diff --git a/ArmVirtPkg/ArmVirtCloudHv.dsc b/ArmVirtPkg/ArmVirtCloudHv.dsc index f3800a7f18..613d2fdca7 100644 --- a/ArmVirtPkg/ArmVirtCloudHv.dsc +++ b/ArmVirtPkg/ArmVirtCloudHv.dsc @@ -155,6 +155,11 @@ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|3 gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize|0x20000 + # + # Firmware volume supports UE, and may require PE. + # + gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv|0x03 + [PcdsFixedAtBuild.AARCH64] # Clearing BIT0 in this PCD prevents installing a 32-bit SMBIOS entry point, # if the entry point version is >= 3.0. AARCH64 OSes cannot assume the diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc index 93829a1042..195285dae9 100644 --- a/ArmVirtPkg/ArmVirtKvmTool.dsc +++ b/ArmVirtPkg/ArmVirtKvmTool.dsc @@ -166,6 +166,11 @@ gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16 gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE + + # + # Firmware volume supports UE, and may require PE. + # + gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv|0x03 [PcdsPatchableInModule.common] # diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc index b42badbe58..0b3cbfbadd 100644 --- a/ArmVirtPkg/ArmVirtQemu.dsc +++ b/ArmVirtPkg/ArmVirtQemu.dsc @@ -231,6 +231,11 @@ # System Memory Size -- 128 MB initially, actual size will be fetched from DT gArmTokenSpaceGuid.PcdSystemMemorySize|0x8000000 + # + # Firmware volume supports UE, and may require PE. + # + gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv|0x03 + [PcdsFixedAtBuild.AARCH64] # Clearing BIT0 in this PCD prevents installing a 32-bit SMBIOS entry point, # if the entry point version is >= 3.0. AARCH64 OSes cannot assume the diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc index 1f134f2cfe..5a40ff334f 100644 --- a/ArmVirtPkg/ArmVirtQemuKernel.dsc +++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc @@ -181,6 +181,11 @@ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|3 gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize|0x20000 + # + # Firmware volume supports UE, and may require PE. + # + gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv|0x03 + [PcdsPatchableInModule.common] # we need to provide a resolution for this PCD that supports PcdSet64() # being called from ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c, diff --git a/ArmVirtPkg/ArmVirtRules.fdf.inc b/ArmVirtPkg/ArmVirtRules.fdf.inc index 5865c2ef31..fbbac1d484 100644 --- a/ArmVirtPkg/ArmVirtRules.fdf.inc +++ b/ArmVirtPkg/ArmVirtRules.fdf.inc @@ -35,61 +35,61 @@ ############################################################################ [Rule.Common.SEC] - FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED FIXED { - PE32 PE32 Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + FILE SEC = $(NAMED_GUID) { + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi } [Rule.Common.SEC.SELF_RELOC] FILE SEC = $(NAMED_GUID) { - PE32 PE32 Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi } [Rule.Common.PEI_CORE] - FILE PEI_CORE = $(NAMED_GUID) FIXED { - PE32 PE32 Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING ="$(MODULE_NAME)" Optional + FILE PEI_CORE = $(NAMED_GUID) { + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional } [Rule.Common.PEIM] - FILE PEIM = $(NAMED_GUID) FIXED { - PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional } [Rule.Common.DXE_CORE] FILE DXE_CORE = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional } [Rule.Common.UEFI_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional } [Rule.Common.DXE_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - RAW ACPI Optional |.acpi - RAW ASL Optional |.aml + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml } [Rule.Common.DXE_RUNTIME_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional } [Rule.Common.UEFI_APPLICATION] FILE APPLICATION = $(NAMED_GUID) { - UI STRING ="$(MODULE_NAME)" Optional - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi } [Rule.Common.UEFI_DRIVER.BINARY] @@ -102,7 +102,7 @@ [Rule.Common.UEFI_APPLICATION.BINARY] FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 |.efi + UE UE |.efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } diff --git a/ArmVirtPkg/ArmVirtXen.dsc b/ArmVirtPkg/ArmVirtXen.dsc index 6bc3fcfcf0..f361cbbbf6 100644 --- a/ArmVirtPkg/ArmVirtXen.dsc +++ b/ArmVirtPkg/ArmVirtXen.dsc @@ -103,6 +103,11 @@ # gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE + # + # Firmware volume supports UE, and may require PE. + # + gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv|0x03 + [PcdsPatchableInModule.common] # we need to provide a resolution for this PCD that supports PcdSet64() # being called from ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c, diff --git a/BaseTools/ImageTool/DynamicBuffer.c b/BaseTools/ImageTool/DynamicBuffer.c index 71ae192737..4ae0a0b1fc 100644 --- a/BaseTools/ImageTool/DynamicBuffer.c +++ b/BaseTools/ImageTool/DynamicBuffer.c @@ -10,7 +10,9 @@ #include "ImageTool.h" #include "DynamicBuffer.h" +#ifndef IMAGE_TOOL_DYNAMIC_BUFFER_GROWTH #define IMAGE_TOOL_DYNAMIC_BUFFER_GROWTH 0x1000 +#endif // IMAGE_TOOL_DYNAMIC_BUFFER_GROWTH void ImageToolBufferInit ( @@ -186,9 +188,11 @@ ImageToolBufferDump ( void *Data; uint32_t DataSize; + // LCOV_EXCL_START if (Buffer->Memory == NULL) { return NULL; } + // LCOV_EXCL_STOP DataSize = ImageToolBufferGetSize (Buffer); diff --git a/BaseTools/ImageTool/GNUmakefile b/BaseTools/ImageTool/GNUmakefile index 2981bc86ac..c7594fa4c9 100644 --- a/BaseTools/ImageTool/GNUmakefile +++ b/BaseTools/ImageTool/GNUmakefile @@ -7,10 +7,10 @@ PROJECT = ImageTool PRODUCT = $(PROJECT)$(INFIX)$(SUFFIX) OBJS = $(PROJECT).o -OBJS += Image.o UefiImageScan.o PeEmit32.o PeEmit64.o PeEmitCommon.o PeScan.o ElfScan32.o ElfScan64.o ElfScanCommon.o BinEmit.o ImageToolEmit.o -OBJS += UefiImageExtraActionLib.o +OBJS += Image.o UefiImageScan.o UeEmit.o UeScan.o PeEmit32.o PeEmit64.o PeEmitCommon.o PeScan.o ElfScan32.o ElfScan64.o ElfScanCommon.o BinEmit.o ImageToolEmit.o +OBJS += UeImageLib.o UefiImageExtraActionLib.o OBJS += PeCoffInit.o PeCoffInfo.o PeCoffLoad.o PeCoffRelocate.o PeCoffHii.o PeCoffDebug.o PeCoffHash.o -OBJS += PeSupport.o UefiImageLib.o CommonSupport.o DynamicBuffer.o +OBJS += PeSupport.o UeSupport.o UefiImageLib.o CommonSupport.o DynamicBuffer.o WERROR = 1 DEBUG = 1 @@ -20,7 +20,8 @@ UDK_PATH = ../.. VPATH += ../../MdePkg/Library/BasePeCoffLib2:$\ ../../MdePkg/Library/BaseUefiImageExtraActionLibNull:$\ - ../../MdePkg/Library/BaseUefiImageLib + ../../MdePkg/Library/BaseUefiImageLib:$\ + ../../MdePkg/Library/BaseUeImageLib include $(OC_USER)/User/Makefile diff --git a/BaseTools/ImageTool/Image.c b/BaseTools/ImageTool/Image.c index 68c913f988..bc2a03d6ce 100644 --- a/BaseTools/ImageTool/Image.c +++ b/BaseTools/ImageTool/Image.c @@ -16,10 +16,12 @@ CheckToolImageSegment ( { bool Overflow; + // LCOV_EXCL_START if (!IS_ALIGNED (Segment->ImageSize, SegmentInfo->SegmentAlignment)) { - DEBUG_RAISE (); + assert (false); return false; } + // LCOV_EXCL_STOP if (Segment->Write && Segment->Execute) { DEBUG_RAISE (); @@ -32,14 +34,16 @@ CheckToolImageSegment ( } Overflow = BaseOverflowAddU32 ( - Segment->ImageAddress, - Segment->ImageSize, - PreviousEndAddress - ); + Segment->ImageAddress, + Segment->ImageSize, + PreviousEndAddress + ); + // LCOV_EXCL_START if (Overflow) { - DEBUG_RAISE (); + assert (false); return false; } + // LCOV_EXCL_STOP return true; } @@ -54,28 +58,32 @@ CheckToolImageSegmentInfo ( uint32_t Index; bool Result; + // LCOV_EXCL_START if (!IS_POW2 (SegmentInfo->SegmentAlignment)) { - DEBUG_RAISE (); + assert (false); return false; } + // LCOV_EXCL_STOP if (SegmentInfo->NumSegments == 0) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_START if (!IS_ALIGNED (SegmentInfo->Segments[0].ImageAddress, SegmentInfo->SegmentAlignment)) { - DEBUG_RAISE (); + assert (false); return false; } + // LCOV_EXCL_STOP *ImageSize = SegmentInfo->Segments[0].ImageAddress; for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) { Result = CheckToolImageSegment ( - SegmentInfo, - &SegmentInfo->Segments[Index], - ImageSize - ); + SegmentInfo, + &SegmentInfo->Segments[Index], + ImageSize + ); if (!Result) { DEBUG_RAISE (); return false; @@ -99,15 +107,19 @@ CheckToolImageHeaderInfo ( return false; } + // LCOV_EXCL_START if (!IS_ALIGNED (HeaderInfo->BaseAddress, SegmentInfo->SegmentAlignment)) { - DEBUG_RAISE (); + assert (false); return false; } + // LCOV_EXCL_STOP + // LCOV_EXCL_START if (HeaderInfo->BaseAddress + ImageSize < HeaderInfo->BaseAddress) { - DEBUG_RAISE (); + assert (false); return false; } + // LCOV_EXCL_STOP return true; } @@ -138,7 +150,9 @@ ToolImageGetRelocSize ( uint8_t Type ) { + // LCOV_EXCL_START switch (Type) { + // LCOV_EXCL_STOP case EFI_IMAGE_REL_BASED_HIGHLOW: { return sizeof (UINT32); @@ -156,11 +170,18 @@ ToolImageGetRelocSize ( } #endif + // LCOV_EXCL_START default: { - return 0; + break; } + // LCOV_EXCL_STOP } + + // LCOV_EXCL_START + assert (false); + return 0; + // LCOV_EXCL_STOP } static @@ -214,9 +235,8 @@ CheckToolImageReloc ( #endif // FIXME: Update drivers? - if ((Image->HeaderInfo.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER || - Image->HeaderInfo.Subsystem == EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER) && - Segment->Write) { + if (Image->HeaderInfo.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER && + Segment->Write) { printf("!!! writable reloc at %x !!!\n", Reloc->Target); //DEBUG_RAISE (); //return false; @@ -243,10 +263,12 @@ CheckToolImageRelocInfo ( return true; } + // LCOV_EXCL_START if (RelocInfo->RelocsStripped) { - DEBUG_RAISE (); + assert (false); return false; } + // LCOV_EXCL_STOP if (RelocInfo->NumRelocs > (MAX_UINT32 / sizeof (UINT16))) { DEBUG_RAISE (); @@ -262,10 +284,12 @@ CheckToolImageRelocInfo ( } RelocSize = ToolImageGetRelocSize (RelocInfo->Relocs[Index].Type); + // LCOV_EXCL_START if (RelocSize == 0) { - DEBUG_RAISE (); + assert (false); return false; } + // LCOV_EXCL_STOP Result = CheckToolImageReloc (Image, &RelocInfo->Relocs[Index], RelocSize); if (!Result) { @@ -357,33 +381,47 @@ ToolImageDestruct ( image_tool_image_info_t *Image ) { - uint8_t Index; + uint16_t Index; + // LCOV_EXCL_START if (Image->SegmentInfo.Segments != NULL) { + // LCOV_EXCL_STOP for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { + // LCOV_EXCL_START if (Image->SegmentInfo.Segments[Index].Name != NULL) { + // LCOV_EXCL_STOP FreePool (Image->SegmentInfo.Segments[Index].Name); } + // LCOV_EXCL_START if (Image->SegmentInfo.Segments[Index].Data != NULL) { + // LCOV_EXCL_STOP FreePool (Image->SegmentInfo.Segments[Index].Data); } } + // LCOV_EXCL_START if (Image->SegmentInfo.Segments != NULL) { + // LCOV_EXCL_STOP FreePool (Image->SegmentInfo.Segments); } } + // LCOV_EXCL_START if (Image->HiiInfo.Data != NULL) { + // LCOV_EXCL_STOP FreePool (Image->HiiInfo.Data); } + // LCOV_EXCL_START if (Image->RelocInfo.Relocs != NULL) { + // LCOV_EXCL_STOP FreePool (Image->RelocInfo.Relocs); } + // LCOV_EXCL_START if (Image->DebugInfo.SymbolsPath != NULL) { + // LCOV_EXCL_STOP FreePool (Image->DebugInfo.SymbolsPath); } @@ -443,7 +481,9 @@ ToolImageRelocate ( ); assert (Segment != NULL); + // LCOV_EXCL_START switch (Reloc->Type) { + // LCOV_EXCL_STOP case EFI_IMAGE_REL_BASED_HIGHLOW: { assert (RemainingSize >= sizeof (UINT32)); @@ -475,11 +515,13 @@ ToolImageRelocate ( } #endif + // LCOV_EXCL_START default: { assert (false); return false; } + // LCOV_EXCL_STOP } } @@ -531,14 +573,14 @@ ToolImageSortRelocs ( bool ToolImageCompare ( - const image_tool_image_info_t *Image1, - const image_tool_image_info_t *Image2 + const image_tool_image_info_t *DestImage, + const image_tool_image_info_t *SourceImage ) { int CmpResult; uint32_t SegIndex; - const char *Name1; - const char *Name2; + const char *DestName; + const char *SourceName; uint32_t NameIndex; // @@ -546,14 +588,16 @@ ToolImageCompare ( // CmpResult = memcmp ( - &Image1->HeaderInfo, - &Image2->HeaderInfo, - sizeof (Image1->HeaderInfo) + &DestImage->HeaderInfo, + &SourceImage->HeaderInfo, + sizeof (DestImage->HeaderInfo) ); + // LCOV_EXCL_START if (CmpResult != 0) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_STOP // // Compare SegmentInfo. @@ -562,55 +606,78 @@ ToolImageCompare ( // CmpResult = memcmp ( - &Image1->SegmentInfo, - &Image2->SegmentInfo, + &DestImage->SegmentInfo, + &SourceImage->SegmentInfo, OFFSET_OF (image_tool_segment_info_t, Segments) ); + // LCOV_EXCL_START if (CmpResult != 0) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_STOP - for (SegIndex = 0; SegIndex < Image1->SegmentInfo.NumSegments; ++SegIndex) { + for (SegIndex = 0; SegIndex < DestImage->SegmentInfo.NumSegments; ++SegIndex) { CmpResult = memcmp ( - &Image1->SegmentInfo.Segments[SegIndex], - &Image2->SegmentInfo.Segments[SegIndex], + &DestImage->SegmentInfo.Segments[SegIndex], + &SourceImage->SegmentInfo.Segments[SegIndex], OFFSET_OF (image_tool_segment_t, Name) ); + // LCOV_EXCL_START if (CmpResult != 0) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_STOP // // Don't assume images generally support arbitrarily long names or names in // general. Check prefix equiality as a best effort. // - Name1 = Image1->SegmentInfo.Segments[SegIndex].Name; - Name2 = Image2->SegmentInfo.Segments[SegIndex].Name; - if (Name1 != NULL && Name2 != NULL) { + DestName = DestImage->SegmentInfo.Segments[SegIndex].Name; + SourceName = SourceImage->SegmentInfo.Segments[SegIndex].Name; + + // LCOV_EXCL_START + if (DestName != NULL && SourceName == NULL) { + assert (false); + return false; + } + // LCOV_EXCL_STOP + + // + // When omitting the debug info, some file formats (e.g., UE) may not + // contain segment names. + // + if (DestName != NULL) { for ( NameIndex = 0; - Name1[NameIndex] != '\0' && Name2[NameIndex] != '\0'; + DestName[NameIndex] != '\0' && + // LCOV_EXCL_START + SourceName[NameIndex] != '\0'; + // LCOV_EXCL_STOP ++NameIndex ) { - if (Name1[NameIndex] != Name2[NameIndex]) { + // LCOV_EXCL_START + if (DestName[NameIndex] != SourceName[NameIndex]) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_STOP } } - if (Image1->SegmentInfo.Segments[SegIndex].ImageSize != 0) { + if (DestImage->SegmentInfo.Segments[SegIndex].ImageSize != 0) { CmpResult = memcmp ( - Image1->SegmentInfo.Segments[SegIndex].Data, - Image2->SegmentInfo.Segments[SegIndex].Data, - Image1->SegmentInfo.Segments[SegIndex].ImageSize + DestImage->SegmentInfo.Segments[SegIndex].Data, + SourceImage->SegmentInfo.Segments[SegIndex].Data, + DestImage->SegmentInfo.Segments[SegIndex].ImageSize ); + // LCOV_EXCL_START if (CmpResult != 0) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_STOP } } @@ -619,25 +686,29 @@ ToolImageCompare ( // CmpResult = memcmp ( - &Image1->RelocInfo, - &Image2->RelocInfo, + &DestImage->RelocInfo, + &SourceImage->RelocInfo, OFFSET_OF (image_tool_reloc_info_t, Relocs) ); + // LCOV_EXCL_START if (CmpResult != 0) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_STOP - if (Image1->RelocInfo.NumRelocs != 0) { + if (DestImage->RelocInfo.NumRelocs != 0) { CmpResult = memcmp ( - Image1->RelocInfo.Relocs, - Image2->RelocInfo.Relocs, - Image1->RelocInfo.NumRelocs * sizeof (*Image1->RelocInfo.Relocs) + DestImage->RelocInfo.Relocs, + SourceImage->RelocInfo.Relocs, + DestImage->RelocInfo.NumRelocs * sizeof (*DestImage->RelocInfo.Relocs) ); + // LCOV_EXCL_START if (CmpResult != 0) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_STOP } // @@ -645,55 +716,65 @@ ToolImageCompare ( // CmpResult = memcmp ( - &Image1->HiiInfo, - &Image2->HiiInfo, + &DestImage->HiiInfo, + &SourceImage->HiiInfo, OFFSET_OF (image_tool_hii_info_t, Data) ); + // LCOV_EXCL_START if (CmpResult != 0) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_STOP - if (Image1->HiiInfo.DataSize != 0) { + // LCOV_EXCL_START + if (DestImage->HiiInfo.DataSize != 0) { CmpResult = memcmp ( - Image1->HiiInfo.Data, - Image2->HiiInfo.Data, - Image1->HiiInfo.DataSize + DestImage->HiiInfo.Data, + SourceImage->HiiInfo.Data, + DestImage->HiiInfo.DataSize ); if (CmpResult != 0) { DEBUG_RAISE (); return false; } } + // LCOV_EXCL_STOP // // Compare DebugInfo. // CmpResult = memcmp ( - &Image1->DebugInfo, - &Image2->DebugInfo, + &DestImage->DebugInfo, + &SourceImage->DebugInfo, OFFSET_OF (image_tool_debug_info_t, SymbolsPath) ); + // LCOV_EXCL_START if (CmpResult != 0) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_STOP - if ((Image1->DebugInfo.SymbolsPath != NULL) != (Image2->DebugInfo.SymbolsPath != NULL)) { + // LCOV_EXCL_START + if ((DestImage->DebugInfo.SymbolsPath != NULL) != (SourceImage->DebugInfo.SymbolsPath != NULL)) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_STOP - if (Image1->DebugInfo.SymbolsPath != NULL) { + if (DestImage->DebugInfo.SymbolsPath != NULL) { CmpResult = strcmp ( - Image1->DebugInfo.SymbolsPath, - Image2->DebugInfo.SymbolsPath + DestImage->DebugInfo.SymbolsPath, + SourceImage->DebugInfo.SymbolsPath ); + // LCOV_EXCL_START if (CmpResult != 0) { DEBUG_RAISE (); return false; } + // LCOV_EXCL_STOP } return true; diff --git a/BaseTools/ImageTool/ImageTool.c b/BaseTools/ImageTool/ImageTool.c index a93192945d..d3a4378e5c 100644 --- a/BaseTools/ImageTool/ImageTool.c +++ b/BaseTools/ImageTool/ImageTool.c @@ -321,11 +321,6 @@ NameToType ( return EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER; } - if ((strcmp (TypeName, "DXE_SAL_DRIVER") == 0) - || (strcmp (TypeName, "SAL_RT_DRIVER") == 0)) { - return EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; - } - return -1; } @@ -335,6 +330,10 @@ NameToFormat ( IN const char *FormatName ) { + if (strcmp (FormatName, "UE") == 0) { + return UefiImageFormatUe; + } + if (strcmp (FormatName, "PE") == 0) { return UefiImageFormatPe; } diff --git a/BaseTools/ImageTool/ImageTool.h b/BaseTools/ImageTool/ImageTool.h index a0382d79d8..5ca3930872 100644 --- a/BaseTools/ImageTool/ImageTool.h +++ b/BaseTools/ImageTool/ImageTool.h @@ -13,8 +13,11 @@ #include #include +#include #include +#include #include +#include #include #include #include @@ -135,12 +138,20 @@ ToolImageGetRelocSize ( uint8_t Type ); +void * +ToolImageEmitUe ( + image_tool_image_info_t *Image, + uint32_t *FileSize, + bool Xip, + bool Strip + ); + RETURN_STATUS ToolContextConstructUefiImage ( OUT image_tool_image_info_t *Image, OUT INT8 *Format, IN const void *File, - IN size_t FileSize + IN uint32_t FileSize ); bool diff --git a/BaseTools/ImageTool/ImageToolEmit.c b/BaseTools/ImageTool/ImageToolEmit.c index b874843532..4f7be6786f 100644 --- a/BaseTools/ImageTool/ImageToolEmit.c +++ b/BaseTools/ImageTool/ImageToolEmit.c @@ -68,20 +68,24 @@ ValidateOutputFile ( } Result = CheckToolImage (&OutputImageInfo); + // LCOV_EXCL_START if (!Result) { assert (false); ToolImageDestruct (&OutputImageInfo); return RETURN_UNSUPPORTED; } + // LCOV_EXCL_STOP Result = ToolImageCompare (&OutputImageInfo, ImageInfo); ToolImageDestruct (&OutputImageInfo); + // LCOV_EXCL_START if (!Result) { assert (false); return RETURN_VOLUME_CORRUPTED; } + // LCOV_EXCL_STOP return RETURN_SUCCESS; } @@ -115,15 +119,18 @@ ToolImageEmit ( SymbolsPath ); + // LCOV_EXCL_START if (SymbolsPath == NULL) { SymbolsPath = ""; } + // LCOV_EXCL_STOP if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Could not parse input file %s - %llx\n", SymbolsPath, (unsigned long long)Status); return NULL; } + // LCOV_EXCL_START if (Format == -1) { Format = SourceFormat; if (Format == -1) { @@ -136,6 +143,7 @@ ToolImageEmit ( if (Type != -1) { ImageInfo.HeaderInfo.Subsystem = (uint16_t)Type; } + // LCOV_EXCL_STOP ToolImageSortRelocs (&ImageInfo); @@ -160,11 +168,18 @@ ToolImageEmit ( } OutputFile = NULL; - if (Format == UefiImageFormatPe) { + // LCOV_EXCL_START + if (Format == UefiImageFormatUe) { + // LCOV_EXCL_STOP + OutputFile = ToolImageEmitUe (&ImageInfo, OutputFileSize, Xip, Strip); + } + // LCOV_EXCL_START + else if (Format == UefiImageFormatPe) { OutputFile = ToolImageEmitPe (&ImageInfo, OutputFileSize, Xip, Strip); } else { assert (false); } + // LCOV_EXCL_STOP if (OutputFile == NULL) { DEBUG_RAISE (); @@ -172,6 +187,11 @@ ToolImageEmit ( return NULL; } + if ((Format == UefiImageFormatUe) && Xip) { + ToolImageDestruct (&ImageInfo); + return OutputFile; + } + Status = ValidateOutputFile (OutputFile, *OutputFileSize, &ImageInfo); ToolImageDestruct (&ImageInfo); diff --git a/BaseTools/ImageTool/Makefile b/BaseTools/ImageTool/Makefile index 3e91a6ecae..ec1dfd28d2 100644 --- a/BaseTools/ImageTool/Makefile +++ b/BaseTools/ImageTool/Makefile @@ -17,10 +17,11 @@ OUT_DIR = .\Windows OV = $(UDK_PATH)\MdePkg\Library\BaseOverflowLib PE = $(UDK_PATH)\MdePkg\Library\BasePeCoffLib2 +UE = $(UDK_PATH)\MdePkg\Library\BaseUeImageLib UA = $(UDK_PATH)\MdePkg\Library\BaseUefiImageExtraActionLibNull -OBJECTS = ImageTool.obj Image.obj PeEmit32.obj PeEmit64.obj PeEmitCommon.obj UefiImageScan.obj PeScan.obj ElfScan32.obj ElfScan64.obj ElfScanCommon.obj BinEmit.obj ImageToolEmit.obj -OBJECTS = $(OBJECTS) {$(OV)}BaseAlignment.obj BaseBitOverflow.obj {$(UA)}UefiImageExtraActionLib.obj DynamicBuffer.obj +OBJECTS = ImageTool.obj Image.obj PeEmit32.obj PeEmit64.obj PeEmitCommon.obj UefiImageScan.obj PeScan.obj UeScan.obj UeEmit.obj ElfScan32.obj ElfScan64.obj ElfScanCommon.obj BinEmit.obj ImageToolEmit.obj +OBJECTS = $(OBJECTS) {$(OV)}BaseAlignment.obj BaseBitOverflow.obj {$(UE)}UeImageLib.obj {$(UA)}UefiImageExtraActionLib.obj DynamicBuffer.obj OBJECTS = $(OBJECTS) {$(PE)}PeCoffInit.obj PeCoffInfo.obj PeCoffRelocate.obj PeCoffLoad.obj PeCoffHii.obj PeCoffDebug.obj PeCoffHash.obj BASE = $(UDK_PATH)\MdePkg\Library\BaseLib @@ -33,7 +34,7 @@ CMEM = $(UDK_PATH)\MdeModulePkg\Library\CommonMemoryAllocationLib USER = $(OC_USER)\User\Library OBJECTS = $(OBJECTS) {$(BASE)}SafeString.obj String.obj SwapBytes16.obj SwapBytes32.obj CpuDeadLoop.obj CheckSum.obj QuickSort.obj LinkedList.obj OBJECTS = $(OBJECTS) {$(OUT)}DebugLib.obj {$(PRIN)}PrintLib.obj PrintLibInternal.obj {$(ERRO)}BaseDebugPrintErrorLevelLib.obj -OBJECTS = $(OBJECTS) {$(UIMG)}UefiImageLib.obj PeSupport.obj CommonSupport.obj +OBJECTS = $(OBJECTS) {$(UIMG)}UefiImageLib.obj UeSupport.obj PeSupport.obj CommonSupport.obj OBJECTS = $(OBJECTS) {$(USER)}UserFile.obj UserBaseMemoryLib.obj UserMath.obj UserPcd.obj UserMisc.obj UserGlobalVar.obj UserBootServices.obj OBJECTS = $(OBJECTS) {$(BMPN)}BaseMemoryProfileLibNull.obj {$(CMEM)}CommonMemoryAllocationLib.obj {$(CMEM)}CommonMemoryAllocationLibEx.obj @@ -73,6 +74,10 @@ cleanall: $(CC) -c $(CFLAGS) $(INC) $< -Fo$@ @move $@ $(OUT_DIR)\ +{$(UE)}.c.obj : + $(CC) -c $(CFLAGS) $(INC) $< -Fo$@ + @move $@ $(OUT_DIR)\ + {$(UA)}.c.obj : $(CC) -c $(CFLAGS) $(INC) $< -Fo$@ @move $@ $(OUT_DIR)\ diff --git a/BaseTools/ImageTool/PeEmit.c b/BaseTools/ImageTool/PeEmit.c index 305f42f945..fb0ea39a52 100644 --- a/BaseTools/ImageTool/PeEmit.c +++ b/BaseTools/ImageTool/PeEmit.c @@ -395,12 +395,14 @@ ToolImageEmitPeSection ( SizeOfRawData = Segment->ImageSize; } - strncpy ( - (char *)SectionHeader->Name, - Segment->Name, - sizeof (SectionHeader->Name) - ); - SectionHeader->Name[ARRAY_SIZE (SectionHeader->Name) - 1] = 0; + if (Segment->Name != NULL) { + strncpy ( + (char *)SectionHeader->Name, + Segment->Name, + sizeof (SectionHeader->Name) + ); + SectionHeader->Name[ARRAY_SIZE (SectionHeader->Name) - 1] = 0; + } SectionHeader->VirtualSize = Segment->ImageSize; SectionHeader->VirtualAddress = Segment->ImageAddress; diff --git a/BaseTools/ImageTool/UeEmit.c b/BaseTools/ImageTool/UeEmit.c new file mode 100644 index 0000000000..9fd42a737c --- /dev/null +++ b/BaseTools/ImageTool/UeEmit.c @@ -0,0 +1,1118 @@ +/** @file + Copyright (c) 2023, Marvin Häuser. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "ImageTool.h" + +#include "DynamicBuffer.h" + +static +uint8_t +AlignmentToExponent ( + uint64_t Alignment + ) +{ + uint8_t Index; + + assert (IS_POW2 (Alignment)); + + for ( + Index = 0; + // LCOV_EXCL_START + Index < 64; + // LCOV_EXCL_STOP + ++Index + ) { + if ((Alignment & (1ULL << Index)) == Alignment) { + return Index; + } + } + + // LCOV_EXCL_START + assert (false); + return 0; + // LCOV_EXCL_STOP +} + +static +bool +ToolImageEmitUeSegmentHeaders ( + image_tool_dynamic_buffer *Buffer, + const image_tool_image_info_t *Image, + bool Xip + ) +{ + uint16_t Index; + uint8_t Permissions; + UE_SEGMENT Segment; + uint32_t Offset; + + for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { + // LCOV_EXCL_START + if (Image->SegmentInfo.Segments[Index].Write && + Image->SegmentInfo.Segments[Index].Execute) { + assert (false); + return false; + } + // LCOV_EXCL_STOP + + if (!Image->SegmentInfo.Segments[Index].Read && + !Image->SegmentInfo.Segments[Index].Write && + Image->SegmentInfo.Segments[Index].Execute) { + Permissions = UeSegmentPermX; + } else if (Image->SegmentInfo.Segments[Index].Read && + !Image->SegmentInfo.Segments[Index].Write && + Image->SegmentInfo.Segments[Index].Execute) { + Permissions = UeSegmentPermRX; + } else if (Image->SegmentInfo.Segments[Index].Read && + Image->SegmentInfo.Segments[Index].Write) { + assert (!Image->SegmentInfo.Segments[Index].Execute); + Permissions = UeSegmentPermRW; + } else if (Image->SegmentInfo.Segments[Index].Read) { + assert (!Image->SegmentInfo.Segments[Index].Write); + assert (!Image->SegmentInfo.Segments[Index].Execute); + Permissions = UeSegmentPermR; + } else { + DEBUG_RAISE (); + return false; + } + + Segment.ImageInfo = Image->SegmentInfo.Segments[Index].ImageSize >> 12U; + Segment.ImageInfo |= Permissions << 20U; + assert (UE_SEGMENT_SIZE (Segment.ImageInfo) == Image->SegmentInfo.Segments[Index].ImageSize); + assert (UE_SEGMENT_PERMISSIONS (Segment.ImageInfo) == Permissions); + + Segment.FileSize = Xip ? Image->SegmentInfo.Segments[Index].ImageSize : Image->SegmentInfo.Segments[Index].UnpaddedSize; + + Offset = ImageToolBufferAppend (Buffer, &Segment, sizeof (Segment)); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + } + + return true; +} + +static +bool +ToolImageUeRelocTableRequired ( + const image_tool_image_info_t *Image + ) +{ + return Image->RelocInfo.NumRelocs != 0; +} + +static +bool +ToolImageUeDebugTableRequired ( + const image_tool_image_info_t *Image + ) +{ + // FIXME: Segment names when symbols are absent? + return Image->DebugInfo.SymbolsPath != NULL; +} + +static +int8_t +InternalGetUeMachine ( + uint16_t Machine + ) +{ + switch (Machine) { + case IMAGE_FILE_MACHINE_I386: + { + return UeMachineI386; + } + + case IMAGE_FILE_MACHINE_X64: + { + return UeMachineX64; + } + + case IMAGE_FILE_MACHINE_ARMTHUMB_MIXED: + { + return UeMachineArmThumbMixed; + } + + case IMAGE_FILE_MACHINE_ARM64: + { + return UeMachineArm64; + } + + case IMAGE_FILE_MACHINE_RISCV32: + { + return UeMachineRiscV32; + } + + case IMAGE_FILE_MACHINE_RISCV64: + { + return UeMachineRiscV64; + } + + case IMAGE_FILE_MACHINE_RISCV128: + { + return UeMachineRiscV128; + } + + default: + { + DEBUG_RAISE (); + return -1; + } + } +} + +static +bool +ToolImageEmitUeSegments ( + image_tool_dynamic_buffer *Buffer, + const image_tool_image_info_t *Image + ) +{ + uint16_t Index; + uint32_t Offset; + + for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { + Offset = ImageToolBufferAppend ( + Buffer, + Image->SegmentInfo.Segments[Index].Data, + Image->SegmentInfo.Segments[Index].UnpaddedSize + ); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + } + + Offset = ImageToolBufferAppendReserveAlign (Buffer, UE_LOAD_TABLE_ALIGNMENT); + return Offset != MAX_UINT32; +} + +static +void +ToolImageEmitUePadChainedRelocs ( + const image_tool_image_info_t *Image + ) +{ + uint16_t SegIndex; + image_tool_segment_t *Segment; + uint32_t RelocIndex; + const image_tool_reloc_t *Reloc; + uint32_t EndOfReloc; + bool HasReloc; + uint32_t LastRelocEnd; + uint32_t EndOfRelocOffset; + + LastRelocEnd = 0; + + RelocIndex = 0; + for (SegIndex = 0; SegIndex < Image->SegmentInfo.NumSegments; ++SegIndex) { + Segment = &Image->SegmentInfo.Segments[SegIndex]; + + HasReloc = false; + for (; RelocIndex < Image->RelocInfo.NumRelocs; ++RelocIndex) { + Reloc = &Image->RelocInfo.Relocs[RelocIndex]; + EndOfReloc = Reloc->Target + ToolImageGetRelocSize (Reloc->Type); + + if (EndOfReloc > Segment->ImageAddress + Segment->ImageSize) { + break; + } + + HasReloc = true; + LastRelocEnd = EndOfReloc; + } + + if (HasReloc) { + assert (Segment->ImageAddress <= LastRelocEnd); + EndOfRelocOffset = LastRelocEnd - Segment->ImageAddress; + + if (Segment->UnpaddedSize < EndOfRelocOffset) { + Segment->UnpaddedSize = EndOfRelocOffset; + } + } + } +} + +static +uint32_t +ToolImageEmitUeGetFileOffset ( + const image_tool_dynamic_buffer *Buffer, + uint32_t SegmentHeadersOffset, + uint32_t SegmentsOffset, + uint16_t NumSegments, + uint32_t Address, + uint32_t *Size + ) +{ + CONST UE_SEGMENT *Segments; + uint16_t Index; + uint32_t SegmentAddress; + uint32_t SegmentSize; + uint32_t SegmentOffset; + uint32_t OffsetInSegment; + + Segments = ImageToolBufferGetPointer (Buffer, SegmentHeadersOffset); + + SegmentAddress = 0; + SegmentOffset = SegmentsOffset; + for ( + Index = 0; + // LCOV_EXCL_START + Index < NumSegments; + // LCOV_EXCL_STOP + ++Index + ) { + // LCOV_EXCL_START + if (SegmentAddress > Address) { + break; + } + // LCOV_EXCL_STOP + + SegmentSize = UE_SEGMENT_SIZE (Segments[Index].ImageInfo); + OffsetInSegment = Address - SegmentAddress; + if (OffsetInSegment < SegmentSize) { + assert (OffsetInSegment < Segments[Index].FileSize); + *Size = Segments[Index].FileSize - OffsetInSegment; + return SegmentOffset + OffsetInSegment; + } + + SegmentAddress += SegmentSize; + SegmentOffset += Segments[Index].FileSize; + } + + // LCOV_EXCL_START + assert (false); + return MAX_UINT32; + // LCOV_EXCL_STOP +} + +static +bool +ToolImageEmitUeRelocTable ( + image_tool_dynamic_buffer *Buffer, + uint32_t LoadTableOffset, + uint32_t SegmentHeadersOffset, + uint32_t SegmentsOffset, + const image_tool_image_info_t *Image, + bool Chaining + ) +{ + uint32_t RelocTableOffset; + uint32_t RelocTableSize; + + UE_FIXUP_ROOT RelocRoot; + + uint32_t EntryFileOffset; + uint32_t PrevEntryFileOffset; + + uint8_t RelocType; + uint32_t RelocTarget; + uint32_t RelocFileOffset; + uint64_t RelocValue; + uint8_t RelocSize; + + uint32_t RelocOffset; + + uint64_t ChainRelocInfo; + uint32_t ChainRelocInfo32; + + uint8_t PrevRelocType; + uint32_t PrevRelocTarget; + uint32_t PrevRelocFileOffset; + uint64_t PrevRelocValue; + uint8_t PrevRelocSize; + + uint64_t PrevChainRelocInfo; + uint32_t PrevChainRelocInfo32; + + bool ChainInProgress; + bool ChainSupported; + + uint16_t Fixup; + + UE_LOAD_TABLE LoadTable; + + uint32_t Index; + uint32_t RemainingSize; + uint32_t Offset; + + assert (Image->RelocInfo.NumRelocs > 0); + + ChainInProgress = false; + + RelocTableOffset = ImageToolBufferGetSize (Buffer); + assert (IS_ALIGNED (RelocTableOffset, UE_LOAD_TABLE_ALIGNMENT)); + + PrevRelocType = 0; + PrevRelocTarget = 0; + PrevRelocFileOffset = 0; + PrevRelocValue = 0; + PrevRelocSize = 0; + + EntryFileOffset = 0; + PrevEntryFileOffset = 0; + + for ( + Index = 0; + Index < Image->RelocInfo.NumRelocs; + ++Index, + PrevRelocType = RelocType, + PrevRelocTarget = RelocTarget, + PrevRelocFileOffset = RelocFileOffset, + PrevRelocValue = RelocValue, + PrevRelocSize = RelocSize, + PrevEntryFileOffset = EntryFileOffset + ) { + // + // Get current UE relocation fixup info. + // + + RelocTarget = Image->RelocInfo.Relocs[Index].Target; + + RelocFileOffset = ToolImageEmitUeGetFileOffset ( + Buffer, + SegmentHeadersOffset, + SegmentsOffset, + Image->SegmentInfo.NumSegments, + RelocTarget, + &RemainingSize + ); + assert (RelocFileOffset != MAX_UINT32); + + // LCOV_EXCL_START + switch (Image->RelocInfo.Relocs[Index].Type) { + // LCOV_EXCL_STOP + case EFI_IMAGE_REL_BASED_HIGHLOW: + { + RelocSize = sizeof (UINT32); + RelocType = UeReloc32; + ChainSupported = Chaining; + break; + } + + case EFI_IMAGE_REL_BASED_DIR64: + { + RelocSize = sizeof (UINT64); + RelocType = UeReloc64; + ChainSupported = Chaining; + break; + } + + // LCOV_EXCL_START + default: + { + assert (false); + return false; + } + // LCOV_EXCL_STOP + } + + // LCOV_EXCL_START + if (RemainingSize < RelocSize) { + assert (false); + return false; + } + // LCOV_EXCL_STOP + + assert (RelocSize <= sizeof (RelocValue)); + + RelocValue = 0; + ImageToolBufferRead (&RelocValue, RelocSize, Buffer, RelocFileOffset); + + assert (RelocTarget >= (PrevRelocTarget + PrevRelocSize)); + RelocOffset = RelocTarget - (PrevRelocTarget + PrevRelocSize); + + // + // Handle UE relocation fixup chaining. + // + + if (ChainInProgress) { + ChainInProgress = ChainSupported && (RelocOffset <= UE_CHAINED_RELOC_FIXUP_MAX_OFFSET) && (PrevRelocType == RelocType); + + if (ChainInProgress && (RelocType == UeReloc32)) { + ChainRelocInfo32 = UE_CHAINED_RELOC_FIXUP_OFFSET_END; + ChainRelocInfo32 |= RelocValue << UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT; + if ((ChainRelocInfo32 >> UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT) != RelocValue) { + ChainInProgress = false; + ChainSupported = false; + RelocType = UeReloc32NoMeta; + } + } + + if (ChainInProgress && (RelocType == UeReloc64)) { + PrevChainRelocInfo = RelocType; + PrevChainRelocInfo |= RelocOffset << 4U; + PrevChainRelocInfo |= PrevRelocValue << 16U; + assert (UE_CHAINED_RELOC_FIXUP_NEXT_OFFSET (PrevChainRelocInfo) == RelocOffset); + assert (UE_CHAINED_RELOC_FIXUP_NEXT_TYPE (PrevChainRelocInfo) == RelocType); + assert (UE_CHAINED_RELOC_FIXUP_VALUE (PrevChainRelocInfo) == PrevRelocValue); + + assert (PrevRelocSize <= sizeof (PrevChainRelocInfo)); + + ImageToolBufferWrite ( + Buffer, + PrevRelocFileOffset, + &PrevChainRelocInfo, + PrevRelocSize + ); + } else if (ChainInProgress && (RelocType == UeReloc32)) { + PrevChainRelocInfo32 = RelocOffset; + PrevChainRelocInfo32 |= PrevRelocValue << UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT; + + assert (PrevRelocSize <= sizeof (PrevChainRelocInfo32)); + + ImageToolBufferWrite ( + Buffer, + PrevRelocFileOffset, + &PrevChainRelocInfo32, + PrevRelocSize + ); + } + } + + if (ChainSupported && (RelocType == UeReloc64)) { + ChainRelocInfo = UE_CHAINED_RELOC_FIXUP_OFFSET_END << 4U; + ChainRelocInfo |= RelocValue << 16U; + if ((ChainRelocInfo >> 16U) != RelocValue) { + DEBUG_RAISE (); + return false; + } + assert (UE_CHAINED_RELOC_FIXUP_NEXT_OFFSET (ChainRelocInfo) == UE_CHAINED_RELOC_FIXUP_OFFSET_END); + assert (UE_CHAINED_RELOC_FIXUP_NEXT_TYPE (ChainRelocInfo) == 0); + assert (UE_CHAINED_RELOC_FIXUP_VALUE (ChainRelocInfo) == RelocValue); + + assert (RelocSize <= sizeof (ChainRelocInfo)); + + ImageToolBufferWrite ( + Buffer, + RelocFileOffset, + &ChainRelocInfo, + RelocSize + ); + + if (ChainInProgress) { + continue; + } + + ChainInProgress = true; + } else if (ChainSupported && (RelocType == UeReloc32)) { + ChainRelocInfo32 = UE_CHAINED_RELOC_FIXUP_OFFSET_END; + ChainRelocInfo32 |= RelocValue << UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT; + if ((ChainRelocInfo32 >> UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT) != RelocValue) { + ChainInProgress = false; + ChainSupported = false; + RelocType = UeReloc32NoMeta; + } else { + assert (RelocSize <= sizeof (ChainRelocInfo32)); + + ImageToolBufferWrite ( + Buffer, + RelocFileOffset, + &ChainRelocInfo32, + RelocSize + ); + + if (ChainInProgress) { + continue; + } + + ChainInProgress = true; + } + } + + if (Index > 0 && RelocOffset <= UE_HEAD_FIXUP_MAX_OFFSET) { + Fixup = PrevRelocType; + Fixup |= RelocOffset << 4U; + assert (UE_RELOC_FIXUP_TYPE (Fixup) == PrevRelocType); + assert (UE_RELOC_FIXUP_OFFSET (Fixup) == RelocOffset); + + ImageToolBufferWrite ( + Buffer, + PrevEntryFileOffset, + &Fixup, + sizeof (Fixup) + ); + } else { + Offset = ImageToolBufferAppendReserveAlign ( + Buffer, + UE_FIXUP_ROOT_ALIGNMENT + ); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + + RelocRoot.FirstOffset = RelocOffset; + + Offset = ImageToolBufferAppend (Buffer, &RelocRoot, sizeof (RelocRoot)); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + } + + Fixup = RelocType; + Fixup |= UE_HEAD_FIXUP_OFFSET_END << 4U; + assert (UE_RELOC_FIXUP_TYPE (Fixup) == RelocType); + assert (UE_RELOC_FIXUP_OFFSET (Fixup) == UE_HEAD_FIXUP_OFFSET_END); + + EntryFileOffset = ImageToolBufferAppend (Buffer, &Fixup, sizeof (Fixup)); + if (EntryFileOffset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + } + + Offset = ImageToolBufferAppendReserveAlign (Buffer, UE_LOAD_TABLE_ALIGNMENT); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + + RelocTableSize = ImageToolBufferGetSize (Buffer) - RelocTableOffset; + + LoadTable.FileInfo = RelocTableSize >> 3U; + LoadTable.FileInfo |= UeLoadTableIdReloc << 29U; + assert (UE_LOAD_TABLE_ID (LoadTable.FileInfo) == UeLoadTableIdReloc); + assert (UE_LOAD_TABLE_SIZE (LoadTable.FileInfo) == RelocTableSize); + + ImageToolBufferWrite ( + Buffer, + LoadTableOffset, + &LoadTable, + sizeof (LoadTable) + ); + + return true; +} + +static +bool +ToolImageEmitUeDebugTable ( + image_tool_dynamic_buffer *Buffer, + uint32_t LoadTableOffset, + const image_tool_image_info_t *Image, + uint32_t BaseAddressSubtrahend + ) +{ + UE_DEBUG_TABLE DebugTable; + uint8_t SymSubtrahendFactor; + uint32_t DebugTableOffset; + uint32_t DebugTableSize; + uint16_t Index; + UE_SEGMENT_NAME SegmentName; + UE_LOAD_TABLE LoadTable; + uint32_t Offset; + + assert (Image->DebugInfo.SymbolsPathLen <= MAX_UINT8); + assert (IS_ALIGNED (BaseAddressSubtrahend, Image->SegmentInfo.SegmentAlignment)); + + SymSubtrahendFactor = (uint8_t)(BaseAddressSubtrahend / Image->SegmentInfo.SegmentAlignment); + if (SymSubtrahendFactor > 0x03) { + DEBUG_RAISE (); + return false; + } + + DebugTable.ImageInfo = SymSubtrahendFactor; + assert (UE_DEBUG_TABLE_IMAGE_INFO_SYM_SUBTRAHEND_FACTOR (DebugTable.ImageInfo) == SymSubtrahendFactor); + assert ((DebugTable.ImageInfo & 0xFCU) == 0); + + DebugTable.SymbolsPathLength = (uint8_t)Image->DebugInfo.SymbolsPathLen; + + DebugTableOffset = ImageToolBufferAppend ( + Buffer, + &DebugTable, + sizeof (DebugTable) + ); + if (DebugTableOffset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + + assert (IS_ALIGNED (DebugTableOffset, UE_LOAD_TABLE_ALIGNMENT)); + + // + // Currently, this condition is always TRUE. However, it is not clear whether + // a debug table cannot make sense when debug symbols are stripped. + // + assert (Image->DebugInfo.SymbolsPath != NULL); + + Offset = ImageToolBufferAppend ( + Buffer, + Image->DebugInfo.SymbolsPath, + Image->DebugInfo.SymbolsPathLen + 1 + ); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + + for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { + memset (&SegmentName, 0, sizeof (SegmentName)); + strncpy ( + (char *)SegmentName, + Image->SegmentInfo.Segments[Index].Name, + sizeof (SegmentName) + ); + SegmentName[ARRAY_SIZE (SegmentName) - 1] = 0; + + Offset = ImageToolBufferAppend (Buffer, SegmentName, sizeof (SegmentName)); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + } + + Offset = ImageToolBufferAppendReserveAlign (Buffer, UE_LOAD_TABLE_ALIGNMENT); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + + DebugTableSize = ImageToolBufferGetSize (Buffer) - DebugTableOffset; + + LoadTable.FileInfo = DebugTableSize >> 3U; + LoadTable.FileInfo |= UeLoadTableIdDebug << 29U; + assert (UE_LOAD_TABLE_ID (LoadTable.FileInfo) == UeLoadTableIdDebug); + assert (UE_LOAD_TABLE_SIZE (LoadTable.FileInfo) == DebugTableSize); + + ImageToolBufferWrite ( + Buffer, + LoadTableOffset, + &LoadTable, + sizeof (LoadTable) + ); + + return true; +} + +static +bool +ToolImageEmitUeLoadTables ( + image_tool_dynamic_buffer *Buffer, + uint32_t LoadTablesOffset, + uint32_t SegmentHeadersOffset, + uint32_t SegmentsOffset, + const image_tool_image_info_t *Image, + uint32_t BaseAddressSubtrahend, + bool Chaining + ) +{ + bool Success; + + if (ToolImageUeRelocTableRequired (Image)) { + Success = ToolImageEmitUeRelocTable ( + Buffer, + LoadTablesOffset, + SegmentHeadersOffset, + SegmentsOffset, + Image, + Chaining + ); + if (!Success) { + DEBUG_RAISE (); + return false; + } + + LoadTablesOffset += sizeof (UE_LOAD_TABLE); + } + + if (ToolImageUeDebugTableRequired (Image)) { + Success = ToolImageEmitUeDebugTable ( + Buffer, + LoadTablesOffset, + Image, + BaseAddressSubtrahend + ); + if (!Success) { + DEBUG_RAISE (); + return false; + } + } + + return true; +} + +static +bool +ToolImageStripEmptyPrefix ( + uint32_t *BaseAddressSubtrahend, + image_tool_image_info_t *Image + ) +{ + bool Success; + uint32_t Subtrahend; + uint32_t Index; + + if (Image->RelocInfo.RelocsStripped) { + DEBUG_RAISE (); + return false; + } + + Subtrahend = Image->SegmentInfo.Segments[0].ImageAddress; + + Success = ToolImageRelocate ( + Image, + Image->HeaderInfo.BaseAddress - Subtrahend, + Subtrahend + ); + // LCOV_EXCL_START + if (!Success) { + DEBUG_RAISE (); + return false; + } + // LCOV_EXCL_STOP + + Image->HeaderInfo.BaseAddress += Subtrahend; + + Image->HeaderInfo.EntryPointAddress -= Subtrahend; + + for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { + Image->SegmentInfo.Segments[Index].ImageAddress -= Subtrahend; + } + + for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) { + Image->RelocInfo.Relocs[Index].Target -= Subtrahend; + } + + *BaseAddressSubtrahend = Subtrahend; + + return true; +} + +static +bool +ToolImageEmitUeFile ( + image_tool_dynamic_buffer *Buffer, + const image_tool_image_info_t *Image, + uint32_t BaseAddressSubtrahend + ) +{ + bool Success; + UE_HEADER UeHdr; + uint8_t AlignmentExponent; + int8_t Machine; + uint8_t Subsystem; + uint8_t LastSegmentIndex; + uint8_t NumLoadTables; + uint32_t Offset; + bool Chaining; + uint32_t SegmentHeadersOffset; + uint32_t LoadTablesOffset; + uint32_t SegmentsOffset; + + assert (Image->SegmentInfo.NumSegments > 0); + + if (Image->SegmentInfo.NumSegments > UE_HEADER_NUM_SEGMENTS_MAX) { + DEBUG_RAISE (); + return false; + } + + if (Image->HiiInfo.DataSize > 0) { + DEBUG_RAISE (); + return false; + } + + AlignmentExponent = AlignmentToExponent (Image->SegmentInfo.SegmentAlignment); + if (12 > AlignmentExponent || AlignmentExponent > 27) { + DEBUG_RAISE (); + return false; + } + + Machine = InternalGetUeMachine (Image->HeaderInfo.Machine); + if (Machine < 0) { + DEBUG_RAISE (); + return false; + } + + NumLoadTables = ToolImageUeRelocTableRequired (Image) ? 1U : 0U; + NumLoadTables += ToolImageUeDebugTableRequired (Image) ? 1U : 0U; + + Subsystem = (uint8_t)(Image->HeaderInfo.Subsystem - 10U); + LastSegmentIndex = (uint8_t)(Image->SegmentInfo.NumSegments - 1U); + + Chaining = Image->HeaderInfo.BaseAddress == 0 && + !Image->HeaderInfo.FixedAddress; + + UeHdr.Magic = UE_HEADER_MAGIC; + + UeHdr.Type = (Machine << 3U) | Subsystem; + assert (UE_HEADER_SUBSYSTEM (UeHdr.Type) == Subsystem); + assert (UE_HEADER_ARCH (UeHdr.Type) == Machine); + + UeHdr.TableCounts = NumLoadTables; + UeHdr.TableCounts |= LastSegmentIndex << 3U; + assert (UE_HEADER_LAST_SEGMENT_INDEX (UeHdr.TableCounts) == LastSegmentIndex); + assert (UE_HEADER_NUM_LOAD_TABLES (UeHdr.TableCounts) == NumLoadTables); + + UeHdr.EntryPointAddress = Image->HeaderInfo.EntryPointAddress; + + UeHdr.ImageInfo = Image->HeaderInfo.BaseAddress >> 12ULL; + UeHdr.ImageInfo |= (uint64_t)Image->HeaderInfo.FixedAddress << 57ULL; + UeHdr.ImageInfo |= (uint64_t)Image->RelocInfo.RelocsStripped << 58ULL; + UeHdr.ImageInfo |= (uint64_t)Chaining << 59ULL; + UeHdr.ImageInfo |= (uint64_t)(AlignmentExponent - 12U) << 60ULL; + assert (UE_HEADER_BASE_ADDRESS (UeHdr.ImageInfo) == Image->HeaderInfo.BaseAddress); + assert ((UeHdr.ImageInfo & (0x1FULL << 52ULL)) == 0); + assert (((UeHdr.ImageInfo & UE_HEADER_IMAGE_INFO_FIXED_ADDRESS) != 0) == Image->HeaderInfo.FixedAddress); + assert (((UeHdr.ImageInfo & UE_HEADER_IMAGE_INFO_RELOCATION_FIXUPS_STRIPPED) != 0) == Image->RelocInfo.RelocsStripped); + assert (((UeHdr.ImageInfo & UE_HEADER_IMAGE_INFO_CHAINED_FIXUPS) != 0) == Chaining); + assert (UE_HEADER_SEGMENT_ALIGNMENT (UeHdr.ImageInfo) == Image->SegmentInfo.SegmentAlignment); + + Offset = ImageToolBufferAppend (Buffer, &UeHdr, sizeof (UeHdr)); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + + SegmentHeadersOffset = ImageToolBufferGetSize (Buffer); + + Success = ToolImageEmitUeSegmentHeaders (Buffer, Image, false); + if (!Success) { + DEBUG_RAISE (); + return false; + } + + LoadTablesOffset = ImageToolBufferAppendReserve ( + Buffer, + NumLoadTables * sizeof (UE_LOAD_TABLE) + ); + if (LoadTablesOffset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + + SegmentsOffset = ImageToolBufferGetSize (Buffer); + + Success = ToolImageEmitUeSegments (Buffer, Image); + if (!Success) { + DEBUG_RAISE (); + return false; + } + + Success = ToolImageEmitUeLoadTables ( + Buffer, + LoadTablesOffset, + SegmentHeadersOffset, + SegmentsOffset, + Image, + BaseAddressSubtrahend, + Chaining + ); + if (!Success) { + DEBUG_RAISE (); + return false; + } + + return true; +} + +// FIXME: Find a better solution. Separate metadata storage? +static +bool +ToolImageEmitUeXipFile ( + image_tool_dynamic_buffer *Buffer, + image_tool_image_info_t *Image, + bool Strip + ) +{ + bool Success; + UE_HEADER UeHdr; + uint8_t AlignmentExponent; + int8_t Machine; + uint8_t Subsystem; + uint8_t LastSegmentIndex; + uint8_t NumLoadTables; + uint32_t Offset; + uint16_t Index; + uint32_t SegmentHeadersOffset; + uint32_t LoadTablesOffset; + uint32_t SegmentsOffset; + + assert (Image->SegmentInfo.NumSegments > 0); + + if (Image->SegmentInfo.NumSegments > UE_HEADER_NUM_SEGMENTS_MAX) { + DEBUG_RAISE (); + return false; + } + + if (Image->HiiInfo.DataSize > 0) { + DEBUG_RAISE (); + return false; + } + + AlignmentExponent = AlignmentToExponent (Image->SegmentInfo.SegmentAlignment); + if (12 > AlignmentExponent || AlignmentExponent > 27) { + DEBUG_RAISE (); + return false; + } + + Machine = InternalGetUeMachine (Image->HeaderInfo.Machine); + if (Machine < 0) { + DEBUG_RAISE (); + return false; + } + + NumLoadTables = (!Strip && ToolImageUeRelocTableRequired (Image)) ? 1U : 0U; + Subsystem = (uint8_t)(Image->HeaderInfo.Subsystem - 10U); + LastSegmentIndex = (uint8_t)(Image->SegmentInfo.NumSegments - 1U); + + UeHdr.Magic = UE_HEADER_MAGIC; + + UeHdr.Type = (Machine << 3U) | Subsystem; + assert (UE_HEADER_SUBSYSTEM (UeHdr.Type) == Subsystem); + assert (UE_HEADER_ARCH (UeHdr.Type) == Machine); + + UeHdr.TableCounts = NumLoadTables; + UeHdr.TableCounts |= LastSegmentIndex << 3U; + assert (UE_HEADER_LAST_SEGMENT_INDEX (UeHdr.TableCounts) == LastSegmentIndex); + assert (UE_HEADER_NUM_LOAD_TABLES (UeHdr.TableCounts) == NumLoadTables); + + UeHdr.ImageInfo = Image->HeaderInfo.BaseAddress >> 12ULL; + UeHdr.ImageInfo |= UE_HEADER_IMAGE_INFO_XIP; + UeHdr.ImageInfo |= (uint64_t)Image->HeaderInfo.FixedAddress << 57ULL; + UeHdr.ImageInfo |= (uint64_t)Strip << 58ULL; + UeHdr.ImageInfo |= (uint64_t)(AlignmentExponent - 12U) << 60ULL; + assert (UE_HEADER_BASE_ADDRESS (UeHdr.ImageInfo) == Image->HeaderInfo.BaseAddress); + assert ((UeHdr.ImageInfo & (0xFULL << 52ULL)) == 0); + assert (((UeHdr.ImageInfo & UE_HEADER_IMAGE_INFO_FIXED_ADDRESS) != 0) == Image->HeaderInfo.FixedAddress); + assert (((UeHdr.ImageInfo & UE_HEADER_IMAGE_INFO_RELOCATION_FIXUPS_STRIPPED) != 0) == Strip); + assert (((UeHdr.ImageInfo & UE_HEADER_IMAGE_INFO_CHAINED_FIXUPS) != 0) == FALSE); + assert (((UeHdr.ImageInfo & UE_HEADER_IMAGE_INFO_XIP) != 0) == TRUE); + assert (UE_HEADER_SEGMENT_ALIGNMENT (UeHdr.ImageInfo) == Image->SegmentInfo.SegmentAlignment); + + Offset = ImageToolBufferAppendReserve (Buffer, sizeof (UeHdr)); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + + SegmentHeadersOffset = ImageToolBufferGetSize (Buffer); + + Success = ToolImageEmitUeSegmentHeaders (Buffer, Image, true); + if (!Success) { + DEBUG_RAISE (); + return false; + } + + LoadTablesOffset = ImageToolBufferAppendReserve ( + Buffer, + NumLoadTables * sizeof (UE_LOAD_TABLE) + ); + if (LoadTablesOffset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + + Offset = ImageToolBufferAppendReserveAlign ( + Buffer, + Image->SegmentInfo.SegmentAlignment + ); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + + SegmentsOffset = ImageToolBufferGetSize (Buffer); + + UeHdr.EntryPointAddress = Image->HeaderInfo.EntryPointAddress + SegmentsOffset; + ImageToolBufferWrite (Buffer, 0, &UeHdr, sizeof (UeHdr)); + + Success = ToolImageRelocate (Image, Image->HeaderInfo.BaseAddress + SegmentsOffset, 0); + if (!Success) { + DEBUG_RAISE (); + return false; + } + + for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { + Offset = ImageToolBufferAppend ( + Buffer, + Image->SegmentInfo.Segments[Index].Data, + Image->SegmentInfo.Segments[Index].UnpaddedSize + ); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + + Offset = ImageToolBufferAppendReserve ( + Buffer, + Image->SegmentInfo.Segments[Index].ImageSize - Image->SegmentInfo.Segments[Index].UnpaddedSize + ); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } + } + + if (!Strip && ToolImageUeRelocTableRequired (Image)) { + Success = ToolImageEmitUeRelocTable ( + Buffer, + LoadTablesOffset, + SegmentHeadersOffset, + SegmentsOffset, + Image, + false + ); + if (!Success) { + DEBUG_RAISE (); + return false; + } + } + + return true; +} + +void * +ToolImageEmitUe ( + image_tool_image_info_t *Image, + uint32_t *FileSize, + bool Xip, + bool Strip + ) +{ + bool Success; + image_tool_dynamic_buffer Buffer; + uint32_t BaseAddressSubtrahend; + void *FileBuffer; + + ImageToolBufferInit (&Buffer); + + ImageInitUnpaddedSize (Image); + ToolImageEmitUePadChainedRelocs (Image); + + if (Xip) { + Success = ToolImageEmitUeXipFile (&Buffer, Image, Strip); + } else { + Success = ToolImageStripEmptyPrefix (&BaseAddressSubtrahend, Image); + if (!Success) { + DEBUG_RAISE (); + return NULL; + } + + if (Strip) { + ToolImageStripRelocs (Image); + } + + Success = ToolImageEmitUeFile (&Buffer, Image, BaseAddressSubtrahend); + } + + if (!Success) { + DEBUG_RAISE (); + ImageToolBufferFree (&Buffer); + return NULL; + } + + FileBuffer = ImageToolBufferDump (FileSize, &Buffer); + + ImageToolBufferFree (&Buffer); + + if (FileBuffer == NULL) { + DEBUG_RAISE (); + return NULL; + } + + return FileBuffer; +} diff --git a/BaseTools/ImageTool/UeEmit.h b/BaseTools/ImageTool/UeEmit.h new file mode 100644 index 0000000000..8133d36b11 --- /dev/null +++ b/BaseTools/ImageTool/UeEmit.h @@ -0,0 +1,10 @@ +#ifndef UE_EMIT_H +#define UE_EMIT_H + +#include + +#include "ImageTool.h" + +void *ToolImageEmitUe(image_tool_image_info_t *Image, uint32_t *FileSize); + +#endif // UE_EMIT_H diff --git a/BaseTools/ImageTool/UeScan.c b/BaseTools/ImageTool/UeScan.c new file mode 100644 index 0000000000..880d8bd02d --- /dev/null +++ b/BaseTools/ImageTool/UeScan.c @@ -0,0 +1,485 @@ +/** @file + Copyright (c) 2021 - 2023, Marvin Häuser. All rights reserved. + Copyright (c) 2022, Mikhail Krichanov. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "ImageTool.h" +#include "UeScan.h" +#include "DynamicBuffer.h" + +typedef union { + UINT32 Value32; + UINT64 Value64; +} UE_RELOC_FIXUP_VALUE; + +static +RETURN_STATUS +InternalProcessRelocChain ( + image_tool_dynamic_buffer *Buffer, + const image_tool_segment_info_t *SegmentInfo, + UINT16 FirstRelocType, + UINT32 *ChainStart + ) +{ + uint32_t OffsetInSegment; + const image_tool_segment_t *Segment; + image_tool_reloc_t Reloc; + uint32_t Offset; + + UINT16 RelocType; + UINT16 RelocOffset; + UINT32 RelocTarget; + + UINT32 RemRelocTargetSize; + + VOID *Fixup; + UE_RELOC_FIXUP_VALUE FixupInfo; + UINT8 FixupSize; + UE_RELOC_FIXUP_VALUE FixupValue; + + memset (&Reloc, 0, sizeof (Reloc)); + + RelocType = FirstRelocType; + RelocTarget = *ChainStart; + + while (TRUE) { + OffsetInSegment = RelocTarget; + Segment = ImageGetSegmentByAddress ( + &OffsetInSegment, + &RemRelocTargetSize, + SegmentInfo + ); + if (Segment == NULL) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + + Fixup = &Segment->Data[OffsetInSegment]; + + Reloc.Target = RelocTarget; + + if (RelocType < UeRelocGenericMax) { + if (RelocType == UeReloc64) { + FixupSize = sizeof (UINT64); + // + // Verify the relocation fixup target is in bounds of the Image buffer. + // + if (FixupSize > RemRelocTargetSize) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + // + // Relocate the target instruction. + // + FixupInfo.Value64 = ReadUnaligned64 (Fixup); + FixupValue.Value64 = UE_CHAINED_RELOC_FIXUP_VALUE (FixupInfo.Value64); + WriteUnaligned64 (Fixup, FixupValue.Value64); + + Reloc.Type = EFI_IMAGE_REL_BASED_DIR64; + } else if (RelocType == UeReloc32) { + FixupSize = sizeof (UINT32); + // + // Verify the image relocation fixup target is in bounds of the image + // buffer. + // + if (FixupSize > RemRelocTargetSize) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + // + // Relocate the target instruction. + // + FixupInfo.Value32 = ReadUnaligned32 (Fixup); + FixupValue.Value32 = UE_CHAINED_RELOC_FIXUP_VALUE_32 (FixupInfo.Value32); + WriteUnaligned32 (Fixup, FixupValue.Value32); + + Reloc.Type = EFI_IMAGE_REL_BASED_HIGHLOW; + // + // Imitate the common header of UE chained relocation fixups, + // as for 32-bit files all relocs have the same type. + // + FixupInfo.Value32 = FixupInfo.Value32 << 4; + FixupInfo.Value32 |= UeReloc32; + } else { + // + // The Image relocation fixup type is unknown, disallow the Image. + // + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + } else { + // + // The Image relocation fixup type is unknown, disallow the Image. + // + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + + RelocTarget += FixupSize; + + Offset = ImageToolBufferAppend (Buffer, &Reloc, sizeof (Reloc)); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return RETURN_OUT_OF_RESOURCES; + } + + RelocOffset = UE_CHAINED_RELOC_FIXUP_NEXT_OFFSET (FixupInfo.Value32); + if (RelocOffset == UE_CHAINED_RELOC_FIXUP_OFFSET_END) { + *ChainStart = RelocTarget; + return RETURN_SUCCESS; + } + // + // It holds that ImageSize mod 4 KiB = 0, thus ImageSize <= 0xFFFFF000. + // Furthermore, it holds that RelocTarget <= ImageSize. + // Finally, it holds that RelocOffset <= 0xFFE. + // It follows that this cannot overflow. + // + RelocTarget += RelocOffset; + assert (RelocOffset <= RelocTarget); + + RelocType = UE_CHAINED_RELOC_FIXUP_NEXT_TYPE (FixupInfo.Value32); + } +} + +STATIC +RETURN_STATUS +InternalApplyRelocation ( + image_tool_dynamic_buffer *Buffer, + const image_tool_segment_info_t *SegmentInfo, + UINT16 RelocType, + UINT32 *RelocTarget + ) +{ + BOOLEAN Overflow; + + const image_tool_segment_t *LastSegment; + uint32_t ImageSize; + UINT32 RemRelocTargetSize; + + UINT32 FixupTarget; + UINT8 FixupSize; + + image_tool_reloc_t Reloc; + uint32_t Offset; + + FixupTarget = *RelocTarget; + + LastSegment = &SegmentInfo->Segments[SegmentInfo->NumSegments - 1]; + ImageSize = LastSegment->ImageAddress + LastSegment->ImageSize; + // + // Verify the relocation fixup target address is in bounds of the image buffer. + // + Overflow = BaseOverflowSubU32 (ImageSize, FixupTarget, &RemRelocTargetSize); + if (Overflow) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + + memset (&Reloc, 0, sizeof (Reloc)); + Reloc.Target = FixupTarget; + // + // Apply the relocation fixup per type. + // + if (RelocType < UeRelocGenericMax) { + if ((RelocType == UeReloc32) || (RelocType == UeReloc32NoMeta)) { + FixupSize = sizeof (UINT32); + Reloc.Type = EFI_IMAGE_REL_BASED_HIGHLOW; + } else { + assert (RelocType == UeReloc64); + + FixupSize = sizeof (UINT64); + Reloc.Type = EFI_IMAGE_REL_BASED_DIR64; + } + } else { + // + // The image relocation fixup type is unknown, disallow the image. + // + fprintf (stderr, "ImageTool: Unknown RelocType = 0x%x\n", RelocType); + ImageToolBufferFree (Buffer); + return RETURN_UNSUPPORTED; + } + // + // Verify the relocation fixup target is in bounds of the image buffer. + // + if (FixupSize > RemRelocTargetSize) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + + Offset = ImageToolBufferAppend (Buffer, &Reloc, sizeof (Reloc)); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + ImageToolBufferFree (Buffer); + return RETURN_OUT_OF_RESOURCES; + } + + *RelocTarget = FixupTarget + FixupSize; + + return RETURN_SUCCESS; +} + +RETURN_STATUS +ScanUeGetRelocInfo ( + OUT image_tool_reloc_info_t *RelocInfo, + IN const image_tool_segment_info_t *SegmentInfo, + IN UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + RETURN_STATUS Status; + BOOLEAN Overflow; + CONST UE_HEADER *UeHdr; + BOOLEAN Chaining; + UINT32 RootOffsetMax; + UINT32 EntryOffsetMax; + UINT32 EndOfRelocTable; + UINT32 TableOffset; + const UE_FIXUP_ROOT *RelocRoot; + UINT16 FixupInfo; + UINT16 RelocType; + UINT16 RelocOffset; + UINT32 RelocTarget; + image_tool_dynamic_buffer Buffer; + uint32_t RelocBufferSize; + UINT32 OldTableOffset; + // + // Verify the Relocation Directory is not empty. + // + if (Context->RelocTableSize == 0) { + return RETURN_SUCCESS; + } + + ImageToolBufferInit (&Buffer); + + UeHdr = (CONST UE_HEADER *)Context->FileBuffer; + Chaining = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_CHAINED_FIXUPS) != 0; + + EndOfRelocTable = Context->LoadTablesFileOffset + Context->RelocTableSize; + + RelocTarget = 0; + + RootOffsetMax = EndOfRelocTable - MIN_SIZE_OF_UE_FIXUP_ROOT; + EntryOffsetMax = EndOfRelocTable - sizeof (*RelocRoot->Heads); + // + // Apply all Base Relocations of the Image. + // + for (TableOffset = Context->LoadTablesFileOffset; TableOffset <= RootOffsetMax;) { + RelocRoot = (CONST UE_FIXUP_ROOT *)( + (CONST UINT8 *)Context->FileBuffer + TableOffset + ); + // + // This cannot overflow due to the TableOffset upper bound. + // + TableOffset += sizeof (*RelocRoot); + + Overflow = BaseOverflowAddU32 ( + RelocTarget, + RelocRoot->FirstOffset, + &RelocTarget + ); + if (Overflow) { + DEBUG_RAISE (); + ImageToolBufferFree (&Buffer); + return RETURN_VOLUME_CORRUPTED; + } + // + // Process all relocation fixups of the current root. + // + while (TRUE) { + FixupInfo = *(CONST UINT16 *)((CONST UINT8 *)Context->FileBuffer + TableOffset); + // + // This cannot overflow due to the upper bound of TableOffset. + // + TableOffset += sizeof (*RelocRoot->Heads); + // + // Apply the image relocation fixup. + // + RelocType = UE_RELOC_FIXUP_TYPE (FixupInfo); + + if (Chaining && (RelocType != UeReloc32NoMeta)) { + Status = InternalProcessRelocChain ( + &Buffer, + SegmentInfo, + RelocType, + &RelocTarget + ); + } else { + Status = InternalApplyRelocation ( + &Buffer, + SegmentInfo, + RelocType, + &RelocTarget + ); + } + + if (RETURN_ERROR (Status)) { + DEBUG_RAISE (); + ImageToolBufferFree (&Buffer); + return Status; + } + + RelocOffset = UE_RELOC_FIXUP_OFFSET (FixupInfo); + if (RelocOffset == UE_HEAD_FIXUP_OFFSET_END) { + break; + } + // + // It holds that ImageSize mod 4 KiB = 0, thus ImageSize <= 0xFFFFF000. + // Furthermore, it holds that RelocTarget <= ImageSize. + // Finally, it holds that RelocOffset <= 0xFFE. + // It follows that this cannot overflow. + // + RelocTarget += RelocOffset; + assert (RelocOffset <= RelocTarget); + + if (TableOffset > EntryOffsetMax) { + DEBUG_RAISE (); + ImageToolBufferFree (&Buffer); + return RETURN_VOLUME_CORRUPTED; + } + } + // + // This cannot overflow due to the TableOffset upper bounds and the + // alignment guarantee of RelocTableSize. + // + OldTableOffset = TableOffset; + TableOffset = ALIGN_VALUE (TableOffset, ALIGNOF (UE_FIXUP_ROOT)); + assert (OldTableOffset <= TableOffset); + } + + RelocInfo->Relocs = ImageToolBufferDump (&RelocBufferSize, &Buffer); + + ImageToolBufferFree (&Buffer); + + if (RelocInfo->Relocs == NULL) { + fprintf (stderr, "ImageTool: Could not allocate memory for Relocs[]\n"); + return RETURN_OUT_OF_RESOURCES; + } + + assert (IS_ALIGNED (RelocBufferSize, sizeof (*RelocInfo->Relocs))); + RelocInfo->NumRelocs = RelocBufferSize / sizeof (*RelocInfo->Relocs); + + return RETURN_SUCCESS; +} + +RETURN_STATUS +ScanUeGetSegmentInfo ( + OUT image_tool_segment_info_t *SegmentInfo, + IN UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + RETURN_STATUS Status; + const UE_SEGMENT *Segment; + uint16_t NumSegments; + image_tool_segment_t *ImageSegment; + const char *ImageBuffer; + uint16_t Index; + uint32_t SegmentAddress; + uint32_t SegmentSize; + uint8_t SegmentPermissions; + const UE_SEGMENT_NAME *SegmentNames; + + NumSegments = UeGetSegments (Context, &Segment); + + STATIC_ASSERT ( + sizeof (*SegmentInfo->Segments) <= MAX_UINT16 / UE_HEADER_NUM_SEGMENTS_MAX, + "The following arithmetics cannot overflow." + ); + + SegmentInfo->Segments = AllocateZeroPool ( + NumSegments * sizeof (*SegmentInfo->Segments) + ); + if (SegmentInfo->Segments == NULL) { + fprintf (stderr, "ImageTool: Could not allocate memory for Segments[]\n"); + return RETURN_OUT_OF_RESOURCES; + } + + Status = UeGetSegmentNames (Context, &SegmentNames); + if (RETURN_ERROR (Status)) { + if (Status != RETURN_NOT_FOUND) { + DEBUG_RAISE (); + return Status; + } + + SegmentNames = NULL; + } + + ImageBuffer = (char *)UeLoaderGetImageAddress (Context); + + SegmentAddress = 0; + ImageSegment = SegmentInfo->Segments; + for (Index = 0; Index < NumSegments; ++Index, ++Segment) { + if (SegmentNames != NULL) { + ImageSegment->Name = AllocateCopyPool ( + sizeof (SegmentNames[Index]), + SegmentNames[Index] + ); + if (ImageSegment->Name == NULL) { + fprintf (stderr, "ImageTool: Could not allocate memory for Segment Name\n"); + return RETURN_OUT_OF_RESOURCES; + } + } else { + assert (ImageSegment->Name == NULL); + } + + SegmentSize = UE_SEGMENT_SIZE (Segment->ImageInfo); + + ImageSegment->Data = AllocateCopyPool ( + SegmentSize, + ImageBuffer + SegmentAddress + ); + if (ImageSegment->Data == NULL) { + fprintf (stderr, "ImageTool: Could not allocate memory for Segment Data\n"); + if (ImageSegment->Name != NULL) { + FreePool (ImageSegment->Name); + } + return RETURN_OUT_OF_RESOURCES; + } + + ImageSegment->ImageAddress = SegmentAddress; + ImageSegment->ImageSize = SegmentSize; + + SegmentPermissions = UE_SEGMENT_PERMISSIONS (Segment->ImageInfo); + switch (SegmentPermissions) { + case UeSegmentPermX: + { + ImageSegment->Execute = true; + assert (!ImageSegment->Read); + assert (!ImageSegment->Write); + break; + } + + case UeSegmentPermRX: + { + ImageSegment->Read = true; + ImageSegment->Execute = true; + assert (!ImageSegment->Write); + break; + } + + case UeSegmentPermRW: + { + ImageSegment->Read = true; + ImageSegment->Write = true; + assert (!ImageSegment->Execute); + break; + } + + default: + case UeSegmentPermR: + { + assert (SegmentPermissions == UeSegmentPermR); + ImageSegment->Read = true; + assert (!ImageSegment->Write); + assert (!ImageSegment->Execute); + break; + } + } + + SegmentAddress += SegmentSize; + + ++SegmentInfo->NumSegments; + ++ImageSegment; + } + + return RETURN_SUCCESS; +} diff --git a/BaseTools/ImageTool/UeScan.h b/BaseTools/ImageTool/UeScan.h new file mode 100644 index 0000000000..aa38cf83bd --- /dev/null +++ b/BaseTools/ImageTool/UeScan.h @@ -0,0 +1,19 @@ +#ifndef UE_SCAN_H +#define UE_SCAN_H + +#include "ImageTool.h" + +RETURN_STATUS +ScanUeGetRelocInfo ( + OUT image_tool_reloc_info_t *RelocInfo, + IN const image_tool_segment_info_t *SegmentInfo, + IN UE_LOADER_IMAGE_CONTEXT *Context + ); + +RETURN_STATUS +ScanUeGetSegmentInfo ( + OUT image_tool_segment_info_t *SegmentInfo, + IN UE_LOADER_IMAGE_CONTEXT *Context + ); + +#endif // UE_SCAN_H diff --git a/BaseTools/ImageTool/UefiImageScan.c b/BaseTools/ImageTool/UefiImageScan.c index 65b7903bff..bbf791f703 100644 --- a/BaseTools/ImageTool/UefiImageScan.c +++ b/BaseTools/ImageTool/UefiImageScan.c @@ -10,6 +10,7 @@ #include #include "PeScan.h" +#include "UeScan.h" static bool @@ -24,7 +25,12 @@ ScanUefiImageGetHeaderInfo ( HeaderInfo->BaseAddress = UefiImageGetBaseAddress (Context); HeaderInfo->EntryPointAddress = UefiImageGetEntryPointAddress (Context); HeaderInfo->Machine = UefiImageGetMachine (Context); - HeaderInfo->Subsystem = UefiImageGetSubsystem (Context); + if (HeaderInfo->Machine == 0xFFFF) { + DEBUG_RAISE (); + return false; + } + + HeaderInfo->Subsystem = UefiImageGetSubsystem (Context); Status = UefiImageGetFixedAddress (Context, &Address); if (!RETURN_ERROR (Status)) { @@ -48,6 +54,7 @@ static RETURN_STATUS ScanUefiImageGetRelocInfo ( OUT image_tool_reloc_info_t *RelocInfo, + IN const image_tool_segment_info_t *SegmentInfo, IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context ) { @@ -61,12 +68,21 @@ ScanUefiImageGetRelocInfo ( return ScanPeGetRelocInfo (RelocInfo, &Context->Ctx.Pe); } + // LCOV_EXCL_START + if (FormatIndex == UefiImageFormatUe) { + // LCOV_EXCL_STOP + return ScanUeGetRelocInfo (RelocInfo, SegmentInfo, &Context->Ctx.Ue); + } + + // LCOV_EXCL_START fprintf ( stderr, "ImageTool: Unsupported UefiImage format %u\n", FormatIndex ); + assert (false); return RETURN_UNSUPPORTED; + // LCOV_EXCL_STOP } static @@ -86,12 +102,21 @@ ScanUefiImageGetSegmentInfo ( return ScanPeGetSegmentInfo (SegmentInfo, &Context->Ctx.Pe); } + // LCOV_EXCL_START + if (FormatIndex == UefiImageFormatUe) { + // LCOV_EXCL_STOP + return ScanUeGetSegmentInfo (SegmentInfo, &Context->Ctx.Ue); + } + + // LCOV_EXCL_START fprintf ( stderr, "ImageTool: Unsupported UefiImage format %u\n", FormatIndex ); + assert (false); return RETURN_UNSUPPORTED; + // LCOV_EXCL_STOP } RETURN_STATUS @@ -166,7 +191,7 @@ ToolContextConstructUefiImage ( OUT image_tool_image_info_t *Image, OUT int8_t *Format, IN const void *File, - IN size_t FileSize + IN uint32_t FileSize ) { RETURN_STATUS Status; @@ -180,11 +205,6 @@ ToolContextConstructUefiImage ( assert (File != NULL || FileSize == 0); - if (FileSize > MAX_UINT32) { - fprintf (stderr, "ImageTool: FileSize is too huge\n"); - return RETURN_UNSUPPORTED; - } - Status = UefiImageInitializeContext ( &Context, File, @@ -209,11 +229,13 @@ ToolContextConstructUefiImage ( } Status = UefiImageLoadImage (&Context, Destination, DestinationSize); + // LCOV_EXCL_START if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Could not Load Image\n"); FreeAlignedPages (Destination, DestinationPages); return Status; } + // LCOV_EXCL_STOP memset (Image, 0, sizeof (*Image)); @@ -233,7 +255,11 @@ ToolContextConstructUefiImage ( return Status; } - Status = ScanUefiImageGetRelocInfo (&Image->RelocInfo, &Context); + Status = ScanUefiImageGetRelocInfo ( + &Image->RelocInfo, + &Image->SegmentInfo, + &Context + ); if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Could not retrieve reloc info\n"); ToolImageDestruct (Image); diff --git a/BaseTools/Source/C/Common/GNUmakefile b/BaseTools/Source/C/Common/GNUmakefile index 5ec953cda0..8c70b90f4e 100644 --- a/BaseTools/Source/C/Common/GNUmakefile +++ b/BaseTools/Source/C/Common/GNUmakefile @@ -37,6 +37,8 @@ OBJECTS += \ $(EDK2_OBJPATH)/BaseTools/ImageTool/ElfScan64.o \ $(EDK2_OBJPATH)/BaseTools/ImageTool/ElfScanCommon.o \ $(EDK2_OBJPATH)/BaseTools/ImageTool/UefiImageScan.o \ + $(EDK2_OBJPATH)/BaseTools/ImageTool/UeScan.o \ + $(EDK2_OBJPATH)/BaseTools/ImageTool/UeEmit.o \ $(EDK2_OBJPATH)/BaseTools/ImageTool/PeScan.o \ $(EDK2_OBJPATH)/BaseTools/ImageTool/PeEmit32.o \ $(EDK2_OBJPATH)/BaseTools/ImageTool/PeEmit64.o \ @@ -121,8 +123,12 @@ OBJECTS += \ $(EDK2_OBJPATH)/MdePkg/Library/BasePeCoffLib2/PeCoffLoad.o \ $(EDK2_OBJPATH)/MdePkg/Library/BasePeCoffLib2/PeCoffRelocate.o +OBJECTS += \ + $(EDK2_OBJPATH)/MdePkg/Library/BaseUeImageLib/UeImageLib.o + OBJECTS += \ $(EDK2_OBJPATH)/MdePkg/Library/BaseUefiImageLib/CommonSupport.o \ + $(EDK2_OBJPATH)/MdePkg/Library/BaseUefiImageLib/UeSupport.o \ $(EDK2_OBJPATH)/MdePkg/Library/BaseUefiImageLib/PeSupport.o \ $(EDK2_OBJPATH)/MdePkg/Library/BaseUefiImageLib/UefiImageLib.o diff --git a/BaseTools/Source/C/Common/Makefile b/BaseTools/Source/C/Common/Makefile index db0198c640..a6cd6f5e9c 100644 --- a/BaseTools/Source/C/Common/Makefile +++ b/BaseTools/Source/C/Common/Makefile @@ -37,6 +37,8 @@ OBJECTS = $(OBJECTS) \ $(EDK2_OBJPATH)\BaseTools\ImageTool\ElfScan64.obj \ $(EDK2_OBJPATH)\BaseTools\ImageTool\ElfScanCommon.obj \ $(EDK2_OBJPATH)\BaseTools\ImageTool\UefiImageScan.obj \ + $(EDK2_OBJPATH)\BaseTools\ImageTool\UeScan.obj \ + $(EDK2_OBJPATH)\BaseTools\ImageTool\UeEmit.obj \ $(EDK2_OBJPATH)\BaseTools\ImageTool\PeScan.obj \ $(EDK2_OBJPATH)\BaseTools\ImageTool\PeEmit32.obj \ $(EDK2_OBJPATH)\BaseTools\ImageTool\PeEmit64.obj \ @@ -120,8 +122,12 @@ OBJECTS = $(OBJECTS) \ $(EDK2_OBJPATH)\MdePkg\Library\BasePeCoffLib2\PeCoffLoad.obj \ $(EDK2_OBJPATH)\MdePkg\Library\BasePeCoffLib2\PeCoffRelocate.obj +OBJECTS = $(OBJECTS) \ + $(EDK2_OBJPATH)\MdePkg\Library\BaseUeImageLib\UeImageLib.obj + OBJECTS = $(OBJECTS) \ $(EDK2_OBJPATH)\MdePkg\Library\BaseUefiImageLib\CommonSupport.obj \ + $(EDK2_OBJPATH)\MdePkg\Library\BaseUefiImageLib\UeSupport.obj \ $(EDK2_OBJPATH)\MdePkg\Library\BaseUefiImageLib\PeSupport.obj \ $(EDK2_OBJPATH)\MdePkg\Library\BaseUefiImageLib\UefiImageLib.obj diff --git a/BaseTools/Source/C/GenFv/GenFvInternalLib.c b/BaseTools/Source/C/GenFv/GenFvInternalLib.c index 43df9819af..1d430115c7 100644 --- a/BaseTools/Source/C/GenFv/GenFvInternalLib.c +++ b/BaseTools/Source/C/GenFv/GenFvInternalLib.c @@ -846,6 +846,8 @@ Returns: fprintf (FvMapFile, "EntryPoint=0x%010llx, ", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint)); if (Format == UefiImageFormatPe) { fprintf (FvMapFile, "Type=PE"); + } else if (Format == UefiImageFormatUe) { + fprintf (FvMapFile, "Type=UE"); } else { assert (FALSE); fprintf (FvMapFile, "Type=Unknown"); @@ -3497,6 +3499,11 @@ Returns: UINT8 ImageFormat; UINT32 RebasedImageSize; VOID *RebasedImage; + UINT32 FfsFileLength; + UINTN FileOffset; + EFI_FFS_INTEGRITY_CHECK *IntegrityCheck; + UINT8 *AfterPePart; + UINT32 AfterPeSize; Index = 0; Cptr = NULL; @@ -3665,6 +3672,7 @@ Returns: UefiImageFileBuffer = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize); UefiImageFileSize = SectPeSize; + FileOffset = (UINTN)UefiImageFileBuffer - (UINTN)(*FfsFile); // // UefiImage has no reloc section. It will try to get reloc data from the original UEFI image. // @@ -3733,7 +3741,7 @@ Returns: NewBaseAddress, NULL, TRUE, - Strip, + ImageFormat == UefiImageFormatUe ? (*FfsFile)->Type == EFI_FV_FILETYPE_SECURITY_CORE : Strip, FALSE ); @@ -3746,37 +3754,112 @@ Returns: return EFI_UNSUPPORTED; } - UefiImageFileBuffer = NULL; - UefiImageFileSize = 0; + if (ImageFormat == UefiImageFormatUe) { + if ((RebasedImageSize + sizeof (EFI_COMMON_SECTION_HEADER)) >= 0x00FFFFFFU) { + Error (NULL, 0, 4001, "Invalid", "rebased file is too large (%s)", FileName); + return EFI_UNSUPPORTED; + } - if (RebasedImageSize > SectPeSize) { - Error (NULL, 0, 4001, "Invalid", "rebased file is too large (%s)", FileName); - return EFI_UNSUPPORTED; - } + AfterPeSize = GetFfsFileLength (*FfsFile) - (FileOffset + SectPeSize); + AfterPePart = calloc (1, AfterPeSize); + if (AfterPePart == NULL) { + fprintf (stderr, "GenFv: Could not allocate memory for AfterPePart\n"); + return EFI_OUT_OF_RESOURCES; + } - memmove ( - (UINT8 *)CurrentPe32Section.Pe32Section + CurSecHdrSize, - RebasedImage, - RebasedImageSize + memmove ( + AfterPePart, + (UINT8 *)((UINTN)(*FfsFile) + FileOffset + SectPeSize), + AfterPeSize + ); + + FfsFileLength = GetFfsFileLength (*FfsFile) - SectPeSize + RebasedImageSize; + *FfsFile = realloc (*FfsFile, FfsFileLength); + if (*FfsFile == NULL) { + fprintf (stderr, "GenFv: Could not reallocate memory for rebased FfsFile\n"); + return EFI_OUT_OF_RESOURCES; + } + *FileSize = FfsFileLength; + + CurrentPe32Section.CommonHeader = (EFI_COMMON_SECTION_HEADER *)((UINTN)(*FfsFile) + FileOffset - CurSecHdrSize); + CurrentPe32Section.CommonHeader->Size[0] = (UINT8)((RebasedImageSize + sizeof (EFI_COMMON_SECTION_HEADER)) & 0x000000FF); + CurrentPe32Section.CommonHeader->Size[1] = (UINT8)(((RebasedImageSize + sizeof (EFI_COMMON_SECTION_HEADER)) & 0x0000FF00) >> 8); + CurrentPe32Section.CommonHeader->Size[2] = (UINT8)(((RebasedImageSize + sizeof (EFI_COMMON_SECTION_HEADER)) & 0x00FF0000) >> 16); + + memmove ( + (UINT8 *)((UINTN)(*FfsFile) + FileOffset), + RebasedImage, + RebasedImageSize + ); + + memmove ( + (UINT8 *)((UINTN)(*FfsFile) + FileOffset + RebasedImageSize), + AfterPePart, + AfterPeSize + ); + + if (FfsHeaderSize > sizeof(EFI_FFS_FILE_HEADER)) { + ((EFI_FFS_FILE_HEADER2 *)(*FfsFile))->ExtendedSize = FfsFileLength; + } else { + (*FfsFile)->Size[0] = (UINT8)(FfsFileLength & 0x000000FF); + (*FfsFile)->Size[1] = (UINT8)((FfsFileLength & 0x0000FF00) >> 8); + (*FfsFile)->Size[2] = (UINT8)((FfsFileLength & 0x00FF0000) >> 16); + } + + // + // Recalculate the FFS header checksum. Instead of setting Header and State + // both to zero, set Header to (UINT8)(-State) so State preserves its original + // value + // + IntegrityCheck = &(*FfsFile)->IntegrityCheck; + IntegrityCheck->Checksum.Header = (UINT8) (0x100 - (*FfsFile)->State); + IntegrityCheck->Checksum.File = 0; + + IntegrityCheck->Checksum.Header = CalculateChecksum8 ( + (UINT8 *)(*FfsFile), FfsHeaderSize + ); + + if ((*FfsFile)->Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Ffs header checksum = zero, so only need to calculate ffs body. + // + IntegrityCheck->Checksum.File = CalculateChecksum8 ( + (UINT8 *)(*FfsFile) + FfsHeaderSize, + FfsFileLength - FfsHeaderSize + ); + } else { + IntegrityCheck->Checksum.File = FFS_FIXED_CHECKSUM; + } + } else { + if (RebasedImageSize > SectPeSize) { + Error (NULL, 0, 4001, "Invalid", "rebased file is too large (%s)", FileName); + return EFI_UNSUPPORTED; + } + + memmove ( + (UINT8 *)CurrentPe32Section.Pe32Section + CurSecHdrSize, + RebasedImage, + RebasedImageSize ); - memset ( - (UINT8 *)CurrentPe32Section.Pe32Section + CurSecHdrSize + RebasedImageSize, - 0, - SectPeSize - RebasedImageSize + memset ( + (UINT8 *)CurrentPe32Section.Pe32Section + CurSecHdrSize + RebasedImageSize, + 0, + SectPeSize - RebasedImageSize ); - // - // Now update file checksum - // - if ((*FfsFile)->Attributes & FFS_ATTRIB_CHECKSUM) { - SavedState = (*FfsFile)->State; - (*FfsFile)->IntegrityCheck.Checksum.File = 0; - (*FfsFile)->State = 0; - (*FfsFile)->IntegrityCheck.Checksum.File = CalculateChecksum8 ( - (UINT8 *) ((UINT8 *)(*FfsFile) + FfsHeaderSize), - GetFfsFileLength (*FfsFile) - FfsHeaderSize - ); - (*FfsFile)->State = SavedState; + // + // Now update file checksum + // + if ((*FfsFile)->Attributes & FFS_ATTRIB_CHECKSUM) { + SavedState = (*FfsFile)->State; + (*FfsFile)->IntegrityCheck.Checksum.File = 0; + (*FfsFile)->State = 0; + (*FfsFile)->IntegrityCheck.Checksum.File = CalculateChecksum8 ( + (UINT8 *) ((UINT8 *)(*FfsFile) + FfsHeaderSize), + GetFfsFileLength (*FfsFile) - FfsHeaderSize + ); + (*FfsFile)->State = SavedState; + } } // @@ -3785,7 +3868,7 @@ Returns: Status = UefiImageInitializeContext ( &ImageContext, - (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize), + (VOID *) ((UINTN)(*FfsFile) + FileOffset), RebasedImageSize, UEFI_IMAGE_SOURCE_FV ); @@ -3802,7 +3885,12 @@ Returns: &ImageContext ); - free (SymbolsPathCpy); + UefiImageFileBuffer = NULL; + UefiImageFileSize = 0; + + if (SymbolsPathCpy != NULL) { + free (SymbolsPathCpy); + } } return EFI_SUCCESS; diff --git a/BaseTools/Source/C/Include/Common/AutoGen.h b/BaseTools/Source/C/Include/Common/AutoGen.h index 52135a9977..8b5f42bd03 100644 --- a/BaseTools/Source/C/Include/Common/AutoGen.h +++ b/BaseTools/Source/C/Include/Common/AutoGen.h @@ -171,7 +171,7 @@ extern UINT64 _gPcd_SkuId_Array[]; //#define _PCD_SET_MODE_8_PcdUefiImageFormatSupportNonFv ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD #define _PCD_TOKEN_PcdUefiImageFormatSupportFv 0U -#define _PCD_VALUE_PcdUefiImageFormatSupportFv 0x01 +#define _PCD_VALUE_PcdUefiImageFormatSupportFv 0x03 #define _PCD_SIZE_PcdUefiImageFormatSupportFv 1 #define _PCD_GET_MODE_SIZE_PcdUefiImageFormatSupportFv _PCD_SIZE_PcdUefiImageFormatSupportFv #define _PCD_GET_MODE_8_PcdUefiImageFormatSupportFv _PCD_VALUE_PcdUefiImageFormatSupportFv diff --git a/BaseTools/Source/C/Makefiles/ms.rule b/BaseTools/Source/C/Makefiles/ms.rule index 5b9a90785c..19d37846db 100644 --- a/BaseTools/Source/C/Makefiles/ms.rule +++ b/BaseTools/Source/C/Makefiles/ms.rule @@ -39,6 +39,10 @@ -@if not exist $(@D)\ mkdir $(@D) $(CC) -c $(CFLAGS) $(EDK2_INC) $< -Fo$@ +{$(EDK2_PATH)\MdePkg\Library\BaseUeImageLib\}.c{$(EDK2_OBJPATH)\MdePkg\Library\BaseUeImageLib\}.obj : + -@if not exist $(@D)\ mkdir $(@D) + $(CC) -c $(CFLAGS) $(EDK2_INC) $< -Fo$@ + {$(EDK2_PATH)\MdePkg\Library\BaseUefiImageLib\}.c{$(EDK2_OBJPATH)\MdePkg\Library\BaseUefiImageLib\}.obj : -@if not exist $(@D)\ mkdir $(@D) $(CC) -c $(CFLAGS) -DUEFI_IMAGE_FORMAT_SUPPORT_SOURCES=0x02 $(EDK2_INC) $< -Fo$@ diff --git a/BaseTools/Source/Python/Common/DataType.py b/BaseTools/Source/Python/Common/DataType.py index fdbcdbc308..51d122858c 100644 --- a/BaseTools/Source/Python/Common/DataType.py +++ b/BaseTools/Source/Python/Common/DataType.py @@ -122,6 +122,7 @@ BINARY_FILE_TYPE_PIC = 'PIC' BINARY_FILE_TYPE_PEI_DEPEX = 'PEI_DEPEX' BINARY_FILE_TYPE_DXE_DEPEX = 'DXE_DEPEX' BINARY_FILE_TYPE_SMM_DEPEX = 'SMM_DEPEX' +BINARY_FILE_TYPE_UE = 'UE' BINARY_FILE_TYPE_VER = 'VER' BINARY_FILE_TYPE_UI = 'UI' BINARY_FILE_TYPE_BIN = 'BIN' diff --git a/BaseTools/Source/Python/GenFds/DataSection.py b/BaseTools/Source/Python/GenFds/DataSection.py index 365f9695bc..3bbbd2f295 100644 --- a/BaseTools/Source/Python/GenFds/DataSection.py +++ b/BaseTools/Source/Python/GenFds/DataSection.py @@ -79,10 +79,10 @@ class DataSection (DataSectionClassObject): CopyLongFilePath(MapFile, CopyMapFile) #Get PE Section alignment when align is set to AUTO - if self.Alignment == 'Auto' and self.SecType in (BINARY_FILE_TYPE_PE32): + if self.Alignment == 'Auto' and self.SecType in (BINARY_FILE_TYPE_PE32, BINARY_FILE_TYPE_UE): self.Alignment = "0" NoStrip = True - if self.SecType in (BINARY_FILE_TYPE_PE32): + if self.SecType in (BINARY_FILE_TYPE_PE32, BINARY_FILE_TYPE_UE): if self.KeepReloc is not None: NoStrip = self.KeepReloc @@ -101,6 +101,16 @@ class DataSection (DataSectionClassObject): ) self.SectFileName = StrippedFile + if self.SecType == BINARY_FILE_TYPE_UE: + UeFile = os.path.join( OutputPath, ModuleName + 'Ue.raw') + GenFdsGlobalVariable.GenerateFirmwareImage( + UeFile, + GenFdsGlobalVariable.MacroExtend(self.SectFileName, Dict), + Format = "UE", + IsMakefile = IsMakefile + ) + self.SectFileName = UeFile + OutputFile = os.path.join (OutputPath, ModuleName + SUP_MODULE_SEC + SecNum + SectionSuffix.get(self.SecType)) OutputFile = os.path.normpath(OutputFile) GenFdsGlobalVariable.GenerateSection(OutputFile, [self.SectFileName], Section.Section.SectionType.get(self.SecType), IsMakefile = IsMakefile) diff --git a/BaseTools/Source/Python/GenFds/EfiSection.py b/BaseTools/Source/Python/GenFds/EfiSection.py index 0315778b08..394bf3239a 100644 --- a/BaseTools/Source/Python/GenFds/EfiSection.py +++ b/BaseTools/Source/Python/GenFds/EfiSection.py @@ -62,7 +62,7 @@ class EfiSection (EfiSectionClassObject): StringData = FfsInf.__ExtendMacro__(self.StringData) ModuleNameStr = FfsInf.__ExtendMacro__('$(MODULE_NAME)') NoStrip = True - if FfsInf.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE) and SectionType in (BINARY_FILE_TYPE_PE32): + if FfsInf.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE) and SectionType in (BINARY_FILE_TYPE_PE32, BINARY_FILE_TYPE_UE): if FfsInf.KeepReloc is not None: NoStrip = FfsInf.KeepReloc elif FfsInf.KeepRelocFromRule is not None: @@ -259,7 +259,7 @@ class EfiSection (EfiSectionClassObject): File = GenFdsGlobalVariable.MacroExtend(File, Dict) #Get PE Section alignment when align is set to AUTO - if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32): + if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_UE): Align = "0" if File[(len(File)-4):] == '.efi' and FfsInf.InfModule.BaseName == os.path.basename(File)[:-4]: MapFile = File.replace('.efi', '.map') @@ -296,6 +296,16 @@ class EfiSection (EfiSectionClassObject): ) File = StrippedFile + if SectionType == BINARY_FILE_TYPE_UE: + UeFile = os.path.join( OutputPath, ModuleName + 'Ue.raw') + GenFdsGlobalVariable.GenerateFirmwareImage( + UeFile, + File, + Format = "UE", + IsMakefile = IsMakefile + ) + File = UeFile + """Call GenSection""" GenFdsGlobalVariable.GenerateSection(OutputFile, [File], diff --git a/BaseTools/Source/Python/GenFds/FdfParser.py b/BaseTools/Source/Python/GenFds/FdfParser.py index cdc448adcc..160fe9c458 100644 --- a/BaseTools/Source/Python/GenFds/FdfParser.py +++ b/BaseTools/Source/Python/GenFds/FdfParser.py @@ -2597,7 +2597,7 @@ class FdfParser: # @staticmethod def _SectionCouldHaveRelocFlag (SectionType): - if SectionType in {BINARY_FILE_TYPE_PE32}: + if SectionType in {BINARY_FILE_TYPE_PE32, BINARY_FILE_TYPE_UE}: return True else: return False @@ -2923,10 +2923,10 @@ class FdfParser: self.SetFileBufferPos(OldPos) return False - if self._Token not in {"COMPAT16", BINARY_FILE_TYPE_PE32, BINARY_FILE_TYPE_PIC, "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,\ + if self._Token not in {"COMPAT16", BINARY_FILE_TYPE_PE32, BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_UE, "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,\ BINARY_FILE_TYPE_UI, "VERSION", BINARY_FILE_TYPE_PEI_DEPEX, "SUBTYPE_GUID", BINARY_FILE_TYPE_SMM_DEPEX}: raise Warning("Unknown section type '%s'" % self._Token, self.FileName, self.CurrentLineNumber) - if AlignValue == 'Auto'and (not self._Token == BINARY_FILE_TYPE_PE32): + if AlignValue == 'Auto'and (not self._Token == BINARY_FILE_TYPE_PE32) and (not self._Token == BINARY_FILE_TYPE_UE): raise Warning("Auto alignment can only be used in PE32 section ", self.FileName, self.CurrentLineNumber) # DataSection @@ -3726,7 +3726,7 @@ class FdfParser: if SectionName not in { "COMPAT16", BINARY_FILE_TYPE_PE32, - BINARY_FILE_TYPE_PIC, "FV_IMAGE", + BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_UE, "FV_IMAGE", "RAW",BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI, BINARY_FILE_TYPE_PEI_DEPEX, "VERSION", "SUBTYPE_GUID", BINARY_FILE_TYPE_SMM_DEPEX}: @@ -3743,7 +3743,7 @@ class FdfParser: if self._GetAlignment(): if self._Token not in ALIGNMENTS: raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber) - if self._Token == 'Auto' and (not SectionName == BINARY_FILE_TYPE_PE32): + if self._Token == 'Auto' and (not SectionName == BINARY_FILE_TYPE_PE32) and (not SectionName == BINARY_FILE_TYPE_UE): raise Warning("Auto alignment can only be used in PE32 section ", self.FileName, self.CurrentLineNumber) SectAlignment = self._Token @@ -3796,7 +3796,7 @@ class FdfParser: if SectionName not in { "COMPAT16", BINARY_FILE_TYPE_PE32, - BINARY_FILE_TYPE_PIC, "FV_IMAGE", + BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_UE, "FV_IMAGE", "RAW",BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI, BINARY_FILE_TYPE_PEI_DEPEX, "VERSION", "SUBTYPE_GUID", BINARY_FILE_TYPE_SMM_DEPEX, BINARY_FILE_TYPE_GUID}: @@ -3843,7 +3843,7 @@ class FdfParser: elif self._GetNextToken(): if self._Token not in { T_CHAR_BRACE_R, "COMPAT16", BINARY_FILE_TYPE_PE32, - BINARY_FILE_TYPE_PIC, + BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_UE, "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI, "VERSION", BINARY_FILE_TYPE_PEI_DEPEX, BINARY_FILE_TYPE_GUID, @@ -3907,7 +3907,7 @@ class FdfParser: if self._GetAlignment(): if self._Token not in ALIGNMENTS: raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber) - if self._Token == 'Auto' and (not SectionName == BINARY_FILE_TYPE_PE32): + if self._Token == 'Auto' and (not SectionName == BINARY_FILE_TYPE_PE32) and (not SectionName == BINARY_FILE_TYPE_UE): raise Warning("Auto alignment can only be used in PE32 section ", self.FileName, self.CurrentLineNumber) EfiSectionObj.Alignment = self._Token @@ -3928,7 +3928,7 @@ class FdfParser: elif self._GetNextToken(): if self._Token not in { T_CHAR_BRACE_R, "COMPAT16", BINARY_FILE_TYPE_PE32, - BINARY_FILE_TYPE_PIC, + BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_UE, "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI, "VERSION", BINARY_FILE_TYPE_PEI_DEPEX, BINARY_FILE_TYPE_GUID, @@ -4020,6 +4020,9 @@ class FdfParser: elif SectionType == BINARY_FILE_TYPE_PIC: if FileType not in {BINARY_FILE_TYPE_PIC, "SEC_PIC"}: raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber) + elif SectionType == BINARY_FILE_TYPE_UE: + if FileType not in {BINARY_FILE_TYPE_UE, "SEC_UE"}: + raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber) elif SectionType == "RAW": if FileType not in {BINARY_FILE_TYPE_BIN, "SEC_BIN", "RAW", "ASL", "ACPI"}: raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber) diff --git a/BaseTools/Source/Python/GenFds/Ffs.py b/BaseTools/Source/Python/GenFds/Ffs.py index 64b031f33f..b54cf33de9 100644 --- a/BaseTools/Source/Python/GenFds/Ffs.py +++ b/BaseTools/Source/Python/GenFds/Ffs.py @@ -33,6 +33,7 @@ FdfFvFileTypeToFileType = { SectionSuffix = { BINARY_FILE_TYPE_PE32 : '.pe32', BINARY_FILE_TYPE_PIC : '.pic', + BINARY_FILE_TYPE_UE : '.pe32', BINARY_FILE_TYPE_DXE_DEPEX : '.dpx', 'VERSION' : '.ver', BINARY_FILE_TYPE_UI : '.ui', diff --git a/BaseTools/Source/Python/GenFds/FfsInfStatement.py b/BaseTools/Source/Python/GenFds/FfsInfStatement.py index fce4ea453e..5eee168edb 100644 --- a/BaseTools/Source/Python/GenFds/FfsInfStatement.py +++ b/BaseTools/Source/Python/GenFds/FfsInfStatement.py @@ -775,7 +775,7 @@ class FfsInfStatement(FfsInfStatementClassObject): File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch) #Get PE Section alignment when align is set to AUTO - if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32): + if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_UE): ImageObj = PeImageClass (File) if ImageObj.SectionAlignment < 0x400: self.Alignment = str (ImageObj.SectionAlignment) @@ -799,6 +799,16 @@ class FfsInfStatement(FfsInfStatementClassObject): ) File = StrippedFile + if SectionType == BINARY_FILE_TYPE_UE: + UeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Ue.raw') + GenFdsGlobalVariable.GenerateFirmwareImage( + UeFile, + File, + Format = "UE", + IsMakefile=IsMakefile + ) + File = UeFile + GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile) OutputFileList.append(OutputFile) else: @@ -809,7 +819,7 @@ class FfsInfStatement(FfsInfStatementClassObject): GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch) #Get PE Section alignment when align is set to AUTO - if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32): + if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_UE): ImageObj = PeImageClass (GenSecInputFile) if ImageObj.SectionAlignment < 0x400: self.Alignment = str (ImageObj.SectionAlignment) @@ -834,6 +844,16 @@ class FfsInfStatement(FfsInfStatementClassObject): ) GenSecInputFile = StrippedFile + if SectionType == BINARY_FILE_TYPE_UE: + UeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Ue.raw') + GenFdsGlobalVariable.GenerateFirmwareImage( + UeFile, + GenSecInputFile, + Format = "UE", + IsMakefile=IsMakefile + ) + GenSecInputFile = UeFile + GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile) OutputFileList.append(OutputFile) diff --git a/BaseTools/Source/Python/GenFds/GenFds.py b/BaseTools/Source/Python/GenFds/GenFds.py index c9cc44d250..0bb8cb0099 100644 --- a/BaseTools/Source/Python/GenFds/GenFds.py +++ b/BaseTools/Source/Python/GenFds/GenFds.py @@ -733,12 +733,12 @@ class GenFds(object): if not os.path.exists(FfsPath[0]): continue MatchDict = {} - ReFileEnds = compile(r'\S+(.ui)$|\S+(fv.sec.txt)$|\S+(.pe32.txt)$|\S+(.pic.txt)$|\S+(.raw.txt)$|\S+(.ffs.txt)$') + ReFileEnds = compile(r'\S+(.ui)$|\S+(fv.sec.txt)$|\S+(.pe32.txt)$|\S+(.ue.txt)$|\S+(.pic.txt)$|\S+(.raw.txt)$|\S+(.ffs.txt)$') FileList = os.listdir(FfsPath[0]) for File in FileList: Match = ReFileEnds.search(File) if Match: - for Index in range(1, 7): + for Index in range(1, 8): if Match.group(Index) and Match.group(Index) in MatchDict: MatchDict[Match.group(Index)].append(File) elif Match.group(Index): @@ -759,6 +759,8 @@ class GenFds(object): FileList = MatchDict['fv.sec.txt'] elif '.pe32.txt' in MatchDict: FileList = MatchDict['.pe32.txt'] + elif '.ue.txt' in MatchDict: + FileList = MatchDict['.ue.txt'] elif '.pic.txt' in MatchDict: FileList = MatchDict['.pic.txt'] elif '.raw.txt' in MatchDict: diff --git a/BaseTools/Source/Python/GenFds/Section.py b/BaseTools/Source/Python/GenFds/Section.py index d05d656417..0156c5ed87 100644 --- a/BaseTools/Source/Python/GenFds/Section.py +++ b/BaseTools/Source/Python/GenFds/Section.py @@ -26,6 +26,7 @@ class Section (SectionClassObject): 'FREEFORM' : 'EFI_SECTION_FREEFORM_SUBTYPE_GUID', BINARY_FILE_TYPE_PE32 : 'EFI_SECTION_PE32', BINARY_FILE_TYPE_PIC : 'EFI_SECTION_PIC', + BINARY_FILE_TYPE_UE : 'EFI_SECTION_PE32', 'FV_IMAGE' : 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE', 'COMPAT16' : 'EFI_SECTION_COMPATIBILITY16', BINARY_FILE_TYPE_DXE_DEPEX : 'EFI_SECTION_DXE_DEPEX', @@ -46,6 +47,7 @@ class Section (SectionClassObject): BINARY_FILE_TYPE_PIC : '.pic', BINARY_FILE_TYPE_PEI_DEPEX : '.depex', 'SEC_PEI_DEPEX' : '.depex', + BINARY_FILE_TYPE_UE : '.pe32', BINARY_FILE_TYPE_UNI_VER : '.ver', BINARY_FILE_TYPE_VER : '.ver', BINARY_FILE_TYPE_UNI_UI : '.ui', @@ -121,7 +123,8 @@ class Section (SectionClassObject): for File in FfsInf.BinFileList: if File.Arch == TAB_ARCH_COMMON or FfsInf.CurrentArch == File.Arch: if File.Type == FileType or (int(FfsInf.PiSpecVersion, 16) >= 0x0001000A \ - and FileType == 'DXE_DPEX' and File.Type == BINARY_FILE_TYPE_SMM_DEPEX): + and FileType == 'DXE_DPEX' and File.Type == BINARY_FILE_TYPE_SMM_DEPEX) \ + or (FileType == BINARY_FILE_TYPE_UE and File.Type == BINARY_FILE_TYPE_PE32): if TAB_STAR in FfsInf.TargetOverrideList or File.Target == TAB_STAR or File.Target in FfsInf.TargetOverrideList or FfsInf.TargetOverrideList == []: FileList.append(FfsInf.PatchEfiFile(File.Path, File.Type)) else: diff --git a/BaseTools/Source/Python/UPT/Library/DataType.py b/BaseTools/Source/Python/UPT/Library/DataType.py index b212786a6d..b69b24f326 100644 --- a/BaseTools/Source/Python/UPT/Library/DataType.py +++ b/BaseTools/Source/Python/UPT/Library/DataType.py @@ -424,6 +424,7 @@ BINARY_FILE_TYPE_PIC = 'PIC' BINARY_FILE_TYPE_PEI_DEPEX = 'PEI_DEPEX' BINARY_FILE_TYPE_DXE_DEPEX = 'DXE_DEPEX' BINARY_FILE_TYPE_SMM_DEPEX = 'SMM_DEPEX' +BINARY_FILE_TYPE_UE = 'UE' BINARY_FILE_TYPE_VER = 'VER' BINARY_FILE_TYPE_UI = 'UI' BINARY_FILE_TYPE_BIN = 'BIN' diff --git a/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c b/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c index 17d9ced288..55ee2c6f9a 100644 --- a/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c +++ b/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c @@ -35,16 +35,16 @@ RelocateImageUnder4GIfNeeded ( IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_STATUS Status; - UINT8 *Buffer; - UINTN BufferSize; - EFI_HANDLE NewImageHandle; - UINT32 ImageSize; - UINT32 ImageAlignment; - UINTN Pages; - EFI_PHYSICAL_ADDRESS FfsBuffer; + EFI_STATUS Status; + UINT8 *Buffer; + UINTN BufferSize; + EFI_HANDLE NewImageHandle; + UINT32 ImageSize; + UINT32 ImageAlignment; + UINTN Pages; + EFI_PHYSICAL_ADDRESS FfsBuffer; UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext; - VOID *Interface; + VOID *Interface; // // If it is already <4G, no need do relocate diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index 513f10beee..8669c1dc6f 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -72,6 +72,7 @@ MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec UefiCpuPkg/UefiCpuPkg.dec + OvmfPkg/OvmfPkg.dec [LibraryClasses] BaseMemoryLib @@ -125,6 +126,7 @@ gEfiMemoryAttributesTableGuid ## SOMETIMES_PRODUCES ## SystemTable gEfiEndOfDxeEventGroupGuid ## SOMETIMES_CONSUMES ## Event gEfiHobMemoryAllocStackGuid ## SOMETIMES_CONSUMES ## SystemTable + gUefiImageLoaderImageContextGuid ## CONSUMES ## HOB [Ppis] gEfiVectorHandoffInfoPpiGuid ## UNDEFINED # HOB diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c index a4c2b6db7e..69297b0a4d 100644 --- a/MdeModulePkg/Core/Dxe/Image/Image.c +++ b/MdeModulePkg/Core/Dxe/Image/Image.c @@ -205,6 +205,8 @@ CoreInitializeImageServices ( UINT64 DxeCoreImageLength; VOID *DxeCoreEntryPoint; EFI_PEI_HOB_POINTERS DxeCoreHob; + EFI_HOB_GUID_TYPE *GuidHob; + HOB_IMAGE_CONTEXT *Hob; // // Searching for image hob @@ -233,20 +235,43 @@ CoreInitializeImageServices ( // Image = &mCorePrivateImage; - // - // FIXME: This is not a proper solution, because DxeCore may not be XIP - // - Status = UefiImageInitializeContext ( - ImageContext, - (VOID *) (UINTN) DxeCoreImageBaseAddress, - (UINT32) DxeCoreImageLength, - UEFI_IMAGE_SOURCE_FV - ); - ASSERT_EFI_ERROR (Status); + GuidHob = GetFirstGuidHob (&gUefiImageLoaderImageContextGuid); + if (GuidHob == NULL) { + DEBUG ((DEBUG_ERROR, "UefiImageLoaderImageContextGuid HOB is missing!\n")); + ASSERT (FALSE); + } + + Hob = (HOB_IMAGE_CONTEXT *)GET_GUID_HOB_DATA (GuidHob); + + ImageContext->FormatIndex = Hob->FormatIndex; - // FIXME: DxeCore is dynamically loaded by DxeIpl, can't it pass the context? if (ImageContext->FormatIndex == UefiImageFormatPe) { - ImageContext->Ctx.Pe.ImageBuffer = (VOID *) ImageContext->Ctx.Pe.FileBuffer; + ImageContext->Ctx.Pe.ImageBuffer = (VOID *)(UINTN)Hob->Ctx.Pe.ImageBuffer; + ImageContext->Ctx.Pe.AddressOfEntryPoint = Hob->Ctx.Pe.AddressOfEntryPoint; + ImageContext->Ctx.Pe.ImageType = Hob->Ctx.Pe.ImageType; + ImageContext->Ctx.Pe.FileBuffer = (CONST VOID *)(UINTN)Hob->Ctx.Pe.FileBuffer; + ImageContext->Ctx.Pe.ExeHdrOffset = Hob->Ctx.Pe.ExeHdrOffset; + ImageContext->Ctx.Pe.SizeOfImage = Hob->Ctx.Pe.SizeOfImage; + ImageContext->Ctx.Pe.FileSize = Hob->Ctx.Pe.FileSize; + ImageContext->Ctx.Pe.Subsystem = Hob->Ctx.Pe.Subsystem; + ImageContext->Ctx.Pe.SectionAlignment = Hob->Ctx.Pe.SectionAlignment; + ImageContext->Ctx.Pe.SectionsOffset = Hob->Ctx.Pe.SectionsOffset; + ImageContext->Ctx.Pe.NumberOfSections = Hob->Ctx.Pe.NumberOfSections; + ImageContext->Ctx.Pe.SizeOfHeaders = Hob->Ctx.Pe.SizeOfHeaders; + } else if (ImageContext->FormatIndex == UefiImageFormatUe) { + ImageContext->Ctx.Ue.ImageBuffer = (VOID *)(UINTN)Hob->Ctx.Ue.ImageBuffer; + ImageContext->Ctx.Ue.FileBuffer = (CONST UINT8 *)(UINTN)Hob->Ctx.Ue.FileBuffer; + ImageContext->Ctx.Ue.EntryPointAddress = Hob->Ctx.Ue.EntryPointAddress; + ImageContext->Ctx.Ue.LoadTablesFileOffset = Hob->Ctx.Ue.LoadTablesFileOffset; + ImageContext->Ctx.Ue.NumLoadTables = Hob->Ctx.Ue.NumLoadTables; + ImageContext->Ctx.Ue.LoadTables = (CONST UE_LOAD_TABLE *)(UINTN)Hob->Ctx.Ue.LoadTables; + ImageContext->Ctx.Ue.Segments = (CONST VOID *)(UINTN)Hob->Ctx.Ue.Segments; + ImageContext->Ctx.Ue.LastSegmentIndex = Hob->Ctx.Ue.LastSegmentIndex; + ImageContext->Ctx.Ue.SegmentAlignment = Hob->Ctx.Ue.SegmentAlignment; + ImageContext->Ctx.Ue.ImageSize = Hob->Ctx.Ue.ImageSize; + ImageContext->Ctx.Ue.Subsystem = Hob->Ctx.Ue.Subsystem; + ImageContext->Ctx.Ue.SegmentImageInfoIterSize = Hob->Ctx.Ue.SegmentImageInfoIterSize; + ImageContext->Ctx.Ue.SegmentsFileOffset = Hob->Ctx.Ue.SegmentsFileOffset; } else { ASSERT (FALSE); } @@ -426,7 +451,7 @@ GetUefiImageFixLoadingAssignedAddress ( Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoadingAddress, ImageDestSize); *LoadAddress = FixLoadingAddress; - DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID *)(UINTN)FixLoadingAddress, Status)); + DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID *)(UINTN)FixLoadingAddress, Status)); return Status; } @@ -715,7 +740,7 @@ CoreLoadPeImage ( // // Get the image entry point. // - Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UefiImageLoaderGetImageEntryPoint (ImageContext)); + Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UefiImageLoaderGetImageEntryPoint (ImageContext)); // // Fill in the image information for the Loaded Image Protocol @@ -1200,7 +1225,7 @@ CoreLoadImageCommon ( &ImageContext, FHand.Source, (UINT32) FHand.SourceSize, - ImageIsFromFv + ImageIsFromFv ? UEFI_IMAGE_SOURCE_FV : UEFI_IMAGE_SOURCE_NON_FV ); if (EFI_ERROR (Status)) { ASSERT (FALSE); @@ -1215,8 +1240,8 @@ CoreLoadImageCommon ( SecurityStatus = gSecurity2->FileAuthentication ( gSecurity2, OriginalFilePath, - &ImageContext, - sizeof (ImageContext), + &ImageContext, + sizeof (ImageContext), BootPolicy ); if (!EFI_ERROR (SecurityStatus) && ImageIsFromFv) { diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf index f1990eac77..1473be8f95 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -51,6 +51,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec [LibraryClasses] PcdLib @@ -73,7 +74,7 @@ gEfiPeiDecompressPpiGuid ## PRODUCES gEfiEndOfPeiSignalPpiGuid ## SOMETIMES_PRODUCES # Not produced on S3 boot path gEfiPeiReadOnlyVariable2PpiGuid ## SOMETIMES_CONSUMES - gEfiPeiLoadFilePpiGuid ## SOMETIMES_CONSUMES + gEfiPeiLoadFileWithHobPpiGuid ## SOMETIMES_CONSUMES gEfiPeiS3Resume2PpiGuid ## SOMETIMES_CONSUMES # Consumed on S3 boot path gEfiPeiRecoveryModulePpiGuid ## SOMETIMES_CONSUMES # Consumed on recovery boot path ## SOMETIMES_CONSUMES @@ -88,6 +89,7 @@ ## SOMETIMES_CONSUMES ## Variable:L"MemoryTypeInformation" ## SOMETIMES_PRODUCES ## HOB gEfiMemoryTypeInformationGuid + gUefiImageLoaderImageContextGuid [FeaturePcd.IA32] gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES @@ -116,7 +118,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES [Depex] - gEfiPeiLoadFilePpiGuid AND gEfiPeiMasterBootModePpiGuid + gEfiPeiLoadFileWithHobPpiGuid AND gEfiPeiMasterBootModePpiGuid # # [BootMode] diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c index 2c19f1a507..c65c94afa7 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c @@ -10,6 +10,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "DxeIpl.h" +#include + // // Module Globals used in the DXE to PEI hand off // These must be module globals, so the stack can be switched @@ -258,7 +260,7 @@ DxeLoadCore ( EFI_BOOT_MODE BootMode; EFI_PEI_FILE_HANDLE FileHandle; EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; - EFI_PEI_LOAD_FILE_PPI *LoadFile; + EFI_PEI_LOAD_FILE_WITH_HOB_PPI *LoadFile; UINTN Instance; UINT32 AuthenticationState; UINTN DataSize; @@ -267,6 +269,7 @@ DxeLoadCore ( EDKII_PEI_CAPSULE_ON_DISK_PPI *PeiCapsuleOnDisk; EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1]; VOID *CapsuleOnDiskModePpi; + HOB_IMAGE_CONTEXT *ImageContext; // // if in S3 Resume, restore configure @@ -399,24 +402,27 @@ DxeLoadCore ( // FileHandle = DxeIplFindDxeCore (); + ImageContext = BuildGuidHob (&gUefiImageLoaderImageContextGuid, sizeof (HOB_IMAGE_CONTEXT)); + ASSERT (ImageContext != NULL); + // // Load the DXE Core from a Firmware Volume. // Instance = 0; do { - Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **)&LoadFile); + Status = PeiServicesLocatePpi (&gEfiPeiLoadFileWithHobPpiGuid, Instance++, NULL, (VOID **)&LoadFile); // // These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully. // ASSERT_EFI_ERROR (Status); Status = LoadFile->LoadFile ( - LoadFile, FileHandle, &DxeCoreAddress, &DxeCoreSize, &DxeCoreEntryPoint, - &AuthenticationState + &AuthenticationState, + ImageContext ); } while (EFI_ERROR (Status)); diff --git a/MdeModulePkg/Core/Pei/Image/Image.c b/MdeModulePkg/Core/Pei/Image/Image.c index 277e2806d7..a32f1b949a 100644 --- a/MdeModulePkg/Core/Pei/Image/Image.c +++ b/MdeModulePkg/Core/Pei/Image/Image.c @@ -12,10 +12,21 @@ EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = { PeiLoadImageLoadImageWrapper }; -EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = { - (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), - &gEfiPeiLoadFilePpiGuid, - &mPeiLoadImagePpi +EFI_PEI_LOAD_FILE_WITH_HOB_PPI mPeiLoadImageWithHobPpi = { + PeiLoadImageLoadImageWithHob +}; + +EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiPeiLoadFileWithHobPpiGuid, + &mPeiLoadImageWithHobPpi + }, + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiLoadFilePpiGuid, + &mPeiLoadImagePpi + } }; /** @@ -154,31 +165,31 @@ GetUefiImageFixLoadingAssignedAddress ( **/ EFI_STATUS LoadAndRelocateUefiImage ( - IN EFI_PEI_FILE_HANDLE FileHandle, - IN VOID *Pe32Data, - IN UINT32 Pe32DataSize, - OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext, - OUT EFI_PHYSICAL_ADDRESS *ImageAddress, - OUT UINTN *DebugBase + IN EFI_PEI_FILE_HANDLE FileHandle, + IN VOID *Pe32Data, + IN UINT32 Pe32DataSize, + OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINTN *DebugBase ) { EFI_STATUS Status; BOOLEAN Success; PEI_CORE_INSTANCE *Private; - UINT32 ImageSize; - UINT32 ImageAlignment; - UINT64 ValueInSectionHeader; + UINT32 ImageSize; + UINT32 ImageAlignment; + UINT64 ValueInSectionHeader; BOOLEAN IsXipImage; EFI_STATUS ReturnStatus; BOOLEAN IsS3Boot; BOOLEAN IsPeiModule; BOOLEAN IsRegisterForShadow; EFI_FV_FILE_INFO FileInfo; - UINT32 DestinationPages; - UINT32 DestinationSize; - EFI_PHYSICAL_ADDRESS Destination; - UINT16 Machine; - BOOLEAN LoadDynamically; + UINT32 DestinationPages; + UINT32 DestinationSize; + EFI_PHYSICAL_ADDRESS Destination; + UINT16 Machine; + BOOLEAN LoadDynamically; Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); @@ -357,12 +368,12 @@ LoadAndRelocateUefiImage ( **/ EFI_STATUS LoadAndRelocateUefiImageInPlace ( - IN VOID *Pe32Data, + IN VOID *Pe32Data, IN VOID *ImageAddress, IN UINT32 ImageSize ) { - EFI_STATUS Status; + EFI_STATUS Status; UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext; ASSERT (Pe32Data != ImageAddress); @@ -455,11 +466,11 @@ PeiLoadImageLoadImage ( OUT UINT32 *AuthenticationState ) { - EFI_STATUS Status; - VOID *Pe32Data; - UINT32 Pe32DataSize; - EFI_PHYSICAL_ADDRESS ImageAddress; - UINTN DebugBase; + EFI_STATUS Status; + VOID *Pe32Data; + UINT32 Pe32DataSize; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINTN DebugBase; UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext; *EntryPoint = 0; @@ -492,12 +503,11 @@ PeiLoadImageLoadImage ( Status = LoadAndRelocateUefiImage ( FileHandle, Pe32Data, - Pe32DataSize, - &ImageContext, - &ImageAddress, - &DebugBase + Pe32DataSize, + &ImageContext, + &ImageAddress, + &DebugBase ); - if (EFI_ERROR (Status)) { return Status; } @@ -541,7 +551,149 @@ PeiLoadImageLoadImage ( EfiFileName, sizeof (EfiFileName) ); + if (!RETURN_ERROR (Status)) { + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); + } + DEBUG_CODE_END (); + + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n")); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PeiLoadImageLoadImageWithHob ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL, + OUT UINT64 *ImageSizeArg OPTIONAL, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState, + OUT HOB_IMAGE_CONTEXT *Hob + ) +{ + EFI_STATUS Status; + VOID *Pe32Data; + UINT32 Pe32DataSize; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINTN DebugBase; + UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext; + + *EntryPoint = 0; + *AuthenticationState = 0; + + // + // Try to find the exe section. + // + Status = PeiServicesFfsFindSectionData4 ( + EFI_SECTION_PE32, + 0, + FileHandle, + &Pe32Data, + &Pe32DataSize, + AuthenticationState + ); + if (EFI_ERROR (Status)) { + // + // PEI core only carry the loader function for PE32 executables + // If this two section does not exist, just return. + // + return Status; + } + + DEBUG ((DEBUG_INFO, "Loading PEIM %g\n", FileHandle)); + + // + // If memory is installed, perform the shadow operations + // + Status = LoadAndRelocateUefiImage ( + FileHandle, + Pe32Data, + Pe32DataSize, + &ImageContext, + &ImageAddress, + &DebugBase + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Save ImageContext into DXE CORE HOB + // + Hob->FormatIndex = ImageContext.FormatIndex; + + if (Hob->FormatIndex == UefiImageFormatPe) { + Hob->Ctx.Pe.ImageBuffer = (UINT32)(UINTN)ImageContext.Ctx.Pe.ImageBuffer; + Hob->Ctx.Pe.AddressOfEntryPoint = ImageContext.Ctx.Pe.AddressOfEntryPoint; + Hob->Ctx.Pe.ImageType = ImageContext.Ctx.Pe.ImageType; + Hob->Ctx.Pe.FileBuffer = (UINT32)(UINTN)ImageContext.Ctx.Pe.FileBuffer; + Hob->Ctx.Pe.ExeHdrOffset = ImageContext.Ctx.Pe.ExeHdrOffset; + Hob->Ctx.Pe.SizeOfImage = ImageContext.Ctx.Pe.SizeOfImage; + Hob->Ctx.Pe.FileSize = ImageContext.Ctx.Pe.FileSize; + Hob->Ctx.Pe.Subsystem = ImageContext.Ctx.Pe.Subsystem; + Hob->Ctx.Pe.SectionAlignment = ImageContext.Ctx.Pe.SectionAlignment; + Hob->Ctx.Pe.SectionsOffset = ImageContext.Ctx.Pe.SectionsOffset; + Hob->Ctx.Pe.NumberOfSections = ImageContext.Ctx.Pe.NumberOfSections; + Hob->Ctx.Pe.SizeOfHeaders = ImageContext.Ctx.Pe.SizeOfHeaders; + } else if (Hob->FormatIndex == UefiImageFormatUe) { + Hob->Ctx.Ue.ImageBuffer = (UINT32)(UINTN)ImageContext.Ctx.Ue.ImageBuffer; + Hob->Ctx.Ue.FileBuffer = (UINT32)(UINTN)ImageContext.Ctx.Ue.FileBuffer; + Hob->Ctx.Ue.EntryPointAddress = ImageContext.Ctx.Ue.EntryPointAddress; + Hob->Ctx.Ue.LoadTablesFileOffset = ImageContext.Ctx.Ue.LoadTablesFileOffset; + Hob->Ctx.Ue.NumLoadTables = ImageContext.Ctx.Ue.NumLoadTables; + Hob->Ctx.Ue.LoadTables = (UINT32)(UINTN)ImageContext.Ctx.Ue.LoadTables; + Hob->Ctx.Ue.Segments = (UINT32)(UINTN)ImageContext.Ctx.Ue.Segments; + Hob->Ctx.Ue.LastSegmentIndex = ImageContext.Ctx.Ue.LastSegmentIndex; + Hob->Ctx.Ue.SegmentAlignment = ImageContext.Ctx.Ue.SegmentAlignment; + Hob->Ctx.Ue.ImageSize = ImageContext.Ctx.Ue.ImageSize; + Hob->Ctx.Ue.Subsystem = ImageContext.Ctx.Ue.Subsystem; + Hob->Ctx.Ue.SegmentImageInfoIterSize = ImageContext.Ctx.Ue.SegmentImageInfoIterSize; + Hob->Ctx.Ue.SegmentsFileOffset = ImageContext.Ctx.Ue.SegmentsFileOffset; + } else { + ASSERT (FALSE); + } + + // + // Got the entry point from the loaded Pe32Data + // + *EntryPoint = UefiImageLoaderGetImageEntryPoint (&ImageContext); + + if (ImageAddressArg != NULL) { + *ImageAddressArg = ImageAddress; + } + + if (ImageSizeArg != NULL) { + *ImageSizeArg =UefiImageGetImageSize (&ImageContext); + } + + DEBUG_CODE_BEGIN (); + CHAR8 EfiFileName[512]; + UINT16 Machine; + + Machine = UefiImageGetMachine (&ImageContext); + + // + // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi + // + if (Machine != EFI_IMAGE_MACHINE_IA64) { + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p DebugBase=0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)DebugBase, (VOID *)(UINTN)*EntryPoint)); + } else { + // + // For IPF Image, the real entry point should be print. + // + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p DebugBase=0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)DebugBase, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint))); + } + + // + // Print Module Name by PeImage PDB file name. + // + Status = UefiImageGetModuleNameFromSymbolsPath ( + &ImageContext, + EfiFileName, + sizeof (EfiFileName) + ); if (!RETURN_ERROR (Status)) { DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); } @@ -748,13 +900,13 @@ InitializeImageServices ( // The first time we are XIP (running from FLASH). We need to remember the // FLASH address so we can reinstall the memory version that runs faster // - PrivateData->XipLoadFile = &gPpiLoadFilePpiList; + PrivateData->XipLoadFile = gPpiLoadFilePpiList; PeiServicesInstallPpi (PrivateData->XipLoadFile); } else { // // 2nd time we are running from memory so replace the XIP version with the // new memory version. // - PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList); + PeiServicesReInstallPpi (PrivateData->XipLoadFile, gPpiLoadFilePpiList); } } diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h index 21322afbf6..f529bd37f0 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.h +++ b/MdeModulePkg/Core/Pei/PeiMain.h @@ -1417,7 +1417,7 @@ InitializeImageServices ( **/ EFI_STATUS LoadAndRelocateUefiImageInPlace ( - IN VOID *Pe32Data, + IN VOID *Pe32Data, IN VOID *ImageAddress, IN UINT32 ImageSize ); @@ -1435,8 +1435,8 @@ LoadAndRelocateUefiImageInPlace ( EFI_STATUS PeiGetPe32Data ( IN EFI_PEI_FILE_HANDLE FileHandle, - OUT VOID **Pe32Data, - OUT UINT32 *Pe32DataSize + OUT VOID **Pe32Data, + OUT UINT32 *Pe32DataSize ); /** @@ -1463,6 +1463,17 @@ PeiLoadImageLoadImageWrapper ( OUT UINT32 *AuthenticationState ); +EFI_STATUS +EFIAPI +PeiLoadImageLoadImageWithHob ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL, + OUT UINT64 *ImageSizeArg OPTIONAL, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState, + OUT HOB_IMAGE_CONTEXT *Hob + ); + /** Provide a callback for when the security PPI is installed. diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf index 04a847e561..7296653884 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.inf +++ b/MdeModulePkg/Core/Pei/PeiMain.inf @@ -94,6 +94,7 @@ ## PRODUCES ## CONSUMES gEfiPeiLoadFilePpiGuid + gEfiPeiLoadFileWithHobPpiGuid gEfiPeiSecurity2PpiGuid ## NOTIFY gEfiTemporaryRamSupportPpiGuid ## SOMETIMES_CONSUMES gEfiTemporaryRamDonePpiGuid ## SOMETIMES_CONSUMES diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h index 71e826e198..73330b8216 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h @@ -1401,4 +1401,15 @@ SmmInsertImageRecord ( IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext ); +/** + Insert image record. + + @param[in] DriverEntry Driver information +**/ +VOID +SmmInsertImageRecord ( + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, + IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext + ); + #endif diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c index 04dd595f79..ef71a3a7e1 100644 --- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c +++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c @@ -317,17 +317,19 @@ ReadyToLockEventNotify ( UEFI_IMAGE_SOURCE_FV ); ASSERT_EFI_ERROR (Status); + ImageSize = UefiImageGetImageSize (&ImageContext); ImageAlignment = UefiImageGetSegmentAlignment (&ImageContext); - Pages = EFI_SIZE_TO_PAGES (ImageSize); - LoadAddress = 0xFFFFFFFF; - Status = AllocateAlignedPagesEx ( - AllocateMaxAddress, - EfiReservedMemoryType, - Pages, - ImageAlignment, - &LoadAddress - ); + Pages = EFI_SIZE_TO_PAGES (ImageSize); + LoadAddress = 0xFFFFFFFF; + + Status = AllocateAlignedPagesEx ( + AllocateMaxAddress, + EfiReservedMemoryType, + Pages, + ImageAlignment, + &LoadAddress + ); ASSERT_EFI_ERROR (Status); // diff --git a/MdePkg/Include/IndustryStandard/UeImage.h b/MdePkg/Include/IndustryStandard/UeImage.h new file mode 100644 index 0000000000..6f1a188bc5 --- /dev/null +++ b/MdePkg/Include/IndustryStandard/UeImage.h @@ -0,0 +1,667 @@ +/** @file + Definitions of the UEFI Executable (UE) file format. + + Copyright (c) 2021 - 2023, Marvin Häuser. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef UE_IMAGE_H_ +#define UE_IMAGE_H_ + +#include + +// +// UE segment definitions. +// + +/// +/// Definition of the UE segment permission configurations. +/// +enum { + UeSegmentPermX = 0, + UeSegmentPermRX = 1, + UeSegmentPermRW = 2, + // + // Read-only is the last value, as this makes it easier to implement it as + // the else/default case. + // + UeSegmentPermR = 3, + UeSegmentPermMax +}; + +/// +/// The minimum alignment requirement, in bytes, of each UE segment in the UE +/// address space. +/// +#define UE_SEGMENT_MIN_ALIGNMENT 0x00001000U + +/// +/// The maximum alignment requirement, in bytes, of each UE segment in the UE +/// address space. +/// +#define UE_SEGMENT_MAX_ALIGNMENT 0x08000000U + +/// +/// Information about the UE segment in the UE address space. +/// +/// [Bits 19:0] The size, in 4-KiB units, of the UE segment in the UE address +/// space. +/// [Bits 21:20] The UE segment permissions. +/// [Bits 31:22] Reserved for future use. Must be zero. +/// +typedef UINT32 UE_SEGMENT_IMAGE_INFO; + +/// +/// Definition of a UE segment header. +/// +typedef struct { + /// + /// Information about the UE segment in the UE address space. + /// + UE_SEGMENT_IMAGE_INFO ImageInfo; + /// + /// The size, in bytes, of the UE segment in the UE file. + /// + UINT32 FileSize; +} UE_SEGMENT; + +STATIC_ASSERT ( + sizeof (UE_SEGMENT) == 8 && ALIGNOF (UE_SEGMENT) == 4, + "The UE segment definition does not meet the specification." + ); + +/// +/// Definition of a UE XIP segment header. +/// +typedef struct { + /// + /// Information about the UE segment in the UE address space. + /// + UE_SEGMENT_IMAGE_INFO ImageInfo; +} UE_SEGMENT_XIP; + +STATIC_ASSERT ( + sizeof (UE_SEGMENT_XIP) == 4 && ALIGNOF (UE_SEGMENT_XIP) == 4, + "The UE XIP segment definition does not meet the specification." + ); + +/** + Retrieve the UE segment memory permissions. + + @param[in] ImageInfo The UE segment image information. +**/ +#define UE_SEGMENT_PERMISSIONS(ImageInfo) \ + ((UINT8)(((ImageInfo) >> 20U) & 0x03U)) + +/** + Retrieve the size, in bytes, of the UE segment in the UE address space. + + @param[in] ImageInfo The UE segment image information. +**/ +#define UE_SEGMENT_SIZE(ImageInfo) ((ImageInfo) << 12U) + +STATIC_ASSERT ( + IS_ALIGNED (UE_SEGMENT_SIZE (0xFFFFFFFF), UE_SEGMENT_MIN_ALIGNMENT), + "The UE segment size definition does not meet the specification." + ); + +// +// UE load table definitions. +// + +/// +/// The alignment, in bytes, of each UE load table in the UE file. +/// +#define UE_LOAD_TABLE_ALIGNMENT 8U + +/// +/// Definition of the UE load table identifiers. +/// +enum { + // + // An array of UE fixup roots. Blocks are ordered ascending by their + // base address. + // + UeLoadTableIdReloc = 0x00, + // + // An instance of the UE debug table.. + // + UeLoadTableIdDebug = 0x01 +}; + +/// +/// Definition of a UE load table header. +/// +typedef struct { + /// + /// Information about the UE load table. + /// + /// [Bits 28:0] The size, in 8-byte units, of the UE load table in the UE + /// file. + /// [Bits 31:29] The identifier of the UE load table. + /// + UINT32 FileInfo; +} UE_LOAD_TABLE; + +STATIC_ASSERT ( + sizeof (UE_LOAD_TABLE) == 4 && ALIGNOF (UE_LOAD_TABLE) == 4, + "The UE load table definition does not meet the specification." + ); + +/** + Retrieves the UE load table identifier. + + @param[in] FileInfo The UE load table file information. +**/ +#define UE_LOAD_TABLE_ID(FileInfo) ((UINT8)((FileInfo) >> 29U)) + +/** + Retrieves the size, in bytes, of the UE load table in the UE file. + + @param[in] FileInfo The UE load table file information. +**/ +#define UE_LOAD_TABLE_SIZE(FileInfo) ((FileInfo) << 3U) + +STATIC_ASSERT ( + IS_ALIGNED (UE_LOAD_TABLE_SIZE (0xFFFFFFFF), UE_LOAD_TABLE_ALIGNMENT), + "The UE load table size definition does not meet the specification." + ); + +// +// UE relocation table definitions. +// + +/// +/// Definitions of the generic UE relocation identifiers. +/// +enum { + UeReloc32 = 0x00, + UeReloc64 = 0x01, + UeReloc32NoMeta = 0x02, + UeRelocGenericMax +}; + +#if 0 +/// +/// Definition of the ARM UE relocation identifiers. +/// +enum { + UeRelocArmMovtMovw = 0x02 +}; +#endif + +/// +/// The alignment requirement for a UE fixup root. +/// +#define UE_FIXUP_ROOT_ALIGNMENT 4U + +STATIC_ASSERT ( + UE_FIXUP_ROOT_ALIGNMENT <= UE_LOAD_TABLE_ALIGNMENT, + "The UE fixup root definition does not meet the specification." + ); + +/// +/// Definition of a UE fixup root. +/// +typedef struct { + /// + /// The offset of the first head fixup, in bytes, from the end of the previous + /// UE relocation fixup (chained or not). The first UE fixup root is + /// relative to 0. + /// + UINT32 FirstOffset; + /// + /// The head fixups of the UE fixup root. + /// + /// [Bits 3:0] The type of the UE relocation fixup. + /// [Bits 15:4] The offset of the next UE head fixup from the end of the last + /// UE relocation fixup in the chain (if chained). If 0x0FFF, the + /// current fixup root is terminated. + /// + UINT16 Heads[]; +} UE_FIXUP_ROOT; + +STATIC_ASSERT ( + sizeof (UE_FIXUP_ROOT) == 4 && ALIGNOF (UE_FIXUP_ROOT) == UE_FIXUP_ROOT_ALIGNMENT, + "The UE fixup root definition does not meet the specification." + ); + +STATIC_ASSERT ( + OFFSET_OF (UE_FIXUP_ROOT, Heads) == sizeof (UE_FIXUP_ROOT), + "The UE fixup root definition does not meet the specification." + ); + +STATIC_ASSERT ( + sizeof (UE_FIXUP_ROOT) <= UE_LOAD_TABLE_ALIGNMENT, + "The UE fixup root definition is misaligned." + ); + +#define MIN_SIZE_OF_UE_FIXUP_ROOT (sizeof (UE_FIXUP_ROOT) + sizeof (UINT16)) + +/// +/// The maximum offset, in bytes, of the next UE head fixup. +/// +#define UE_HEAD_FIXUP_MAX_OFFSET 0x0FFEU + +/// +/// UE head fixup offset that terminates a fixup root. +/// +#define UE_HEAD_FIXUP_OFFSET_END 0x0FFFU + +/** + Retrieves the target offset of the UE relocation fixup. + + @param[in] FixupInfo The UE relocation fixup information. +**/ +#define UE_RELOC_FIXUP_OFFSET(FixupInfo) ((UINT16)((FixupInfo) >> 4U)) + +/** + Retrieves the type of the UE relocation fixup. + + @param[in] FixupInfo The UE relocation fixup information. +**/ +#define UE_RELOC_FIXUP_TYPE(FixupInfo) ((FixupInfo) & 0x000FU) + +/** + Retrieves the offset of the next UE chained relocation fixup. + + @param[in] FixupInfo The UE relocation fixup information. +**/ +#define UE_CHAINED_RELOC_FIXUP_NEXT_OFFSET(FixupInfo) \ + ((UINT16)((UINT16)(FixupInfo) >> 4U) & 0x0FFFU) + +/// +/// The maximum offset, in bytes, of the next UE chained relocation fixup. +/// +#define UE_CHAINED_RELOC_FIXUP_MAX_OFFSET 0x0FFEU + +/// +/// UE chained relocation fixup offset that terminates a chain. +/// +#define UE_CHAINED_RELOC_FIXUP_OFFSET_END 0x0FFFU + +/** + Retrieves the type of the next UE chained relocation fixup. + + @param[in] FixupInfo The UE relocation fixup information. +**/ +#define UE_CHAINED_RELOC_FIXUP_NEXT_TYPE(FixupInfo) \ + ((UINT8)((UINT16)(FixupInfo) & 0x0FU)) + +/// +/// The shift exponent for UE chained relocation fixup values. +/// +#define UE_CHAINED_RELOC_FIXUP_VALUE_SHIFT 16U + +/** + Retrieves the value of the current UE chained relocation fixup. + + @param[in] FixupInfo The UE relocation fixup information. +**/ +#define UE_CHAINED_RELOC_FIXUP_VALUE(FixupInfo) \ + RShiftU64 (FixupInfo, UE_CHAINED_RELOC_FIXUP_VALUE_SHIFT) + +/// +/// Definition of the common header of UE chained relocation fixups. +/// +/// [Bits 3:0] The relocation type of the next chained relocation fixup. Only +/// valid when [Bits 15:4] are not 0x0FFF. +/// [Bits 15:4] The offset to the next chained relocation fixup from the end +/// of the current one. If 0x0FFF, the current chain is terminated. +/// Consult the fixup root for further relocation fixups. +/// +typedef UINT16 UE_RELOC_FIXUP_HDR; + +/// +/// Definition of the generic 64-bit UE chained relocation fixup. +/// +/// [Bits 15:0] The common header of UE chained relocation fixups. +/// [Bits 47:16] The address value to relocate. +/// [Bits 63:48] Must be zero. +/// +typedef UINT64 UE_RELOC_FIXUP_64; + +/// +/// The shift exponent for UE chained 32-bit relocation fixup values. +/// +#define UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT 12U + +/** + Retrieves the value of the current UE chained 32-bit relocation fixup. + + @param[in] FixupInfo The UE relocation fixup information. +**/ +#define UE_CHAINED_RELOC_FIXUP_VALUE_32(FixupInfo) \ + (UINT32)((UINT32)(FixupInfo) >> UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT) + +/// +/// Definition of the generic 32-bit UE chained relocation fixup. +/// +/// [Bits 11:0] The offset to the next chained relocation fixup from the end +/// of the current one. If 0x0FFF, the current chain is terminated. +/// Consult the fixup root for further relocation fixups. +/// [Bits 31:12] The address value to relocate. +/// +typedef UINT32 UE_RELOC_FIXUP_32; + +#if 0 +/// +/// Definition of the ARM Thumb MOVT/MOVW UE chained relocation fixup. +/// +/// [Bits 15:0] The common header of UE chained relocation fixups. +/// [Bits 31:16] The 16-bit immediate value to relocate. +/// +typedef UINT32 UE_RELOC_FIXUP_ARM_MOVT_MOVW; +#endif + +// +// UE debug table definitions. +// +// NOTE: The UE symbols base address offset is required for conversion of +// PE Images that have their first section start after the end of the +// Image headers. As PDBs cannot easily be rebased, store the offset. +// + +/// +/// Definition of a UE segment name. Must be \0-terminated. +/// +typedef UINT8 UE_SEGMENT_NAME[8]; + +STATIC_ASSERT ( + sizeof (UE_SEGMENT_NAME) == 8 && ALIGNOF (UE_SEGMENT_NAME) == 1, + "The UE segment name definition does not meet the specification." + ); + +/// +/// Definition of the UE debug table header. +/// +typedef struct { + /// + /// Information about the image regarding the symbols file. + /// + /// [Bits 1:0] The offset, in image alignment units, to be subtracted from the + /// UE base address in order to retrieve the UE symbols base + /// address. + /// [Bits 7:2] Reserved for future use. Must be zero. + /// + UINT8 ImageInfo; + /// + /// The length, in bytes, of the UE symbols path (excluding the terminator). + /// + UINT8 SymbolsPathLength; + /// + /// The UE symbols path. Must be \0-terminated. + /// + UINT8 SymbolsPath[]; + /// + /// The UE segment name table. The order matches the UE segment table. + /// +//UE_SEGMENT_NAME SegmentNames[]; +} UE_DEBUG_TABLE; + +/// +/// The minimum size, in bytes, of the UE debug table. +/// +#define MIN_SIZE_OF_UE_DEBUG_TABLE \ + (OFFSET_OF (UE_DEBUG_TABLE, SymbolsPath) + 1U) + +/** + Retrieves the UE symbol address subtrahend in SegmentAlignment-units. + + @param[in] ImageInfo The UE debug table image information. +**/ +#define UE_DEBUG_TABLE_IMAGE_INFO_SYM_SUBTRAHEND_FACTOR(ImageInfo) \ + ((UINT8)((ImageInfo) & 0x03U)) + +/** + Retrieves the UE segment name table of a UE debug table. + + @param[in] DebugTable The UE debug table. +**/ +#define UE_DEBUG_TABLE_SEGMENT_NAMES(DebugTable) \ + (CONST UE_SEGMENT_NAME *) ( \ + (DebugTable)->SymbolsPath + (DebugTable)->SymbolsPathLength + 1 \ + ) + +STATIC_ASSERT ( + sizeof (UE_DEBUG_TABLE) == 2 && ALIGNOF (UE_DEBUG_TABLE) == 1, + "The UE debug table definition does not meet the specification." + ); + +STATIC_ASSERT ( + ALIGNOF (UE_DEBUG_TABLE) <= UE_LOAD_TABLE_ALIGNMENT, + "The UE debug table definition is misaligned." + ); + +STATIC_ASSERT ( + OFFSET_OF (UE_DEBUG_TABLE, SymbolsPath) == sizeof (UE_DEBUG_TABLE), + "The UE fixup root definition does not meet the specification." + ); + +// +// UE header definitions. +// + +/// +/// The file magic number of a UE header. +/// +#define UE_HEADER_MAGIC SIGNATURE_16 ('U', 'E') + +/// +/// Definition of the UE machine identifiers. +/// +enum { + UeMachineI386 = 0, + UeMachineX64 = 1, + UeMachineArmThumbMixed = 2, + UeMachineArm64 = 3, + UeMachineRiscV32 = 4, + UeMachineRiscV64 = 5, + UeMachineRiscV128 = 6 +}; + +/// +/// Definition of the UE subsystem identifiers. +/// +enum { + UeSubsystemEfiApplication = 0, + UeSubsystemEfiBootServicesDriver = 1, + UeSubsystemEfiRuntimeDriver = 2 +}; + +/// +/// Definition of a UE file header. +/// +typedef struct { + /// + /// The file magic number to identify the UE file format. Must be 'UE'. + /// + UINT16 Magic; + /// + /// Information about the image kind and supported architectures. + /// + /// [Bits 2:0] Indicates the subsystem. + /// [Bits 7:3] Indicates the supported architectures. + /// + UINT8 Type; + /// + /// Information about the UE load tables and segments. + /// + /// [Bits 2:0] The number of UE load tables. + /// [Bits 7:3] The index of the last segment in the UE segment table. + /// + UINT8 TableCounts; + /// + /// Indicates the offset of the UE entry point in the UE address space. + /// + UINT32 EntryPointAddress; + /// + /// Information about the UE image. + /// + /// [Bits 51:0] The base UEFI page of the UE image, i.e., the base address in + /// 4 KiB units. + /// [Bits 55:52] Reserved for future use. Must be zero. + /// [Bit 56] Indicates whether the UE image is XIP + /// [Bit 57] Indicates whether the UE image is designated for a fixed + /// address. + /// [Bit 58] Indicates whether the UE relocation table has been stripped. + /// [Bit 59] Indicates whether UE chained fixups are used. + /// [Bits 63:60] The shift exponent, offset by -12, for the UE segment + /// alignment in bytes. + /// + UINT64 ImageInfo; + /// + /// The UE segment table. It contains all data of the UE address space. + /// + /// All UE segments are contiguous in the UE address space. + /// The offset of the first UE segment in the UE address space is 0. + /// + /// All UE segments' data are contiguous in the UE file. + /// The offset of the first UE segment in the UE file is the end of the UE + /// file header. + /// + UE_SEGMENT Segments[]; + /// + /// The UE load tables. They contain data useful for UE loading. + /// + /// All UE load tables are contiguous in the UE file. + /// The offset of the first UE load table in the UE file is the end of the last + /// UE segment in the UE file. + /// + /// All UE load tables are ordered ascending by their identifier. + /// +//UE_LOAD_TABLE LoadTables[]; +} UE_HEADER; + +/// +/// The minimum size, in bytes, of a valid UE header. +/// +#define MIN_SIZE_OF_UE_HEADER \ + (OFFSET_OF (UE_HEADER, Segments) + sizeof (UE_SEGMENT)) + +STATIC_ASSERT ( + sizeof (UE_HEADER) == 16 && ALIGNOF (UE_HEADER) == 8, + "The UE header definition does not meet the specification." + ); + +STATIC_ASSERT ( + ALIGNOF (UE_SEGMENT) <= ALIGNOF (UE_LOAD_TABLE), + "The UE header definition is misaligned." + ); + +STATIC_ASSERT ( + OFFSET_OF (UE_HEADER, Segments) == sizeof (UE_HEADER), + "The UE header definition does not meet the specification." + ); + +/** + Retrieves the UE base address. + + @param[in] ImageInfo The UE header image information. +**/ +#define UE_HEADER_BASE_ADDRESS(ImageInfo) LShiftU64 (ImageInfo, 12) + +/** + Retrieves the UE segment alignment, in bytes, as a power of two. + + @param[in] ImageInfo The UE header image information. +**/ +#define UE_HEADER_SEGMENT_ALIGNMENT(ImageInfo) \ + (1U << ((UINT8)RShiftU64 (ImageInfo, 60) + 12U)) + +/// +/// UE header image information bit that indicates whether the image is XIP. +/// +#define UE_HEADER_IMAGE_INFO_XIP 0x0100000000000000ULL + +/// +/// UE header image information bit that indicates whether the image is +/// designated to be loaded to a fixed address. +/// +#define UE_HEADER_IMAGE_INFO_FIXED_ADDRESS 0x0200000000000000ULL + +/// +/// UE header image information bit that indicates whether the relocation fixups +/// have been stripped. +/// +#define UE_HEADER_IMAGE_INFO_RELOCATION_FIXUPS_STRIPPED 0x0400000000000000ULL + +/// +/// UE header image information bit that indicates whether UE relocation fixup +/// chains are utilized. +/// +#define UE_HEADER_IMAGE_INFO_CHAINED_FIXUPS 0x0800000000000000ULL + +/** + Retrieves the UE subsystem. + + @param[in] Type The UE header type information. +**/ +#define UE_HEADER_SUBSYSTEM(Type) ((Type) & 0x07U) + +/** + Retrieves the UE supported architectures. + + @param[in] Type The UE header type information. +**/ +#define UE_HEADER_ARCH(Type) ((Type) >> 3U) + +/// +/// The maximum number of UE load tables. +/// +#define UE_HEADER_NUM_LOAD_TABLES_MAX 7U + +/** + Retrieves the number of UE load tables. + + @param[in] TableCounts The UE header segment and load table information. +**/ +#define UE_HEADER_NUM_LOAD_TABLES(TableCounts) ((TableCounts) & 0x07U) + +STATIC_ASSERT ( + UE_HEADER_NUM_LOAD_TABLES (0xFFU) == UE_HEADER_NUM_LOAD_TABLES_MAX, + "The number of load tables violates the specification." + ); + +/// +/// The maximum number of UE segments. +/// +#define UE_HEADER_NUM_SEGMENTS_MAX 32U + +/** + Retrieves the index of the last UE segment, i.e., their amount minus 1. + + @param[in] TableCounts The UE header segment and load table information. +**/ +#define UE_HEADER_LAST_SEGMENT_INDEX(TableCounts) ((TableCounts) >> 3U) + +STATIC_ASSERT ( + UE_HEADER_LAST_SEGMENT_INDEX (0xFFU) + 1U == UE_HEADER_NUM_SEGMENTS_MAX, + "The number of load tables violates the specification." + ); + +/** + Retrieves the 8 byte aligned UE file size. + + If the file size is larger than this value, the appended data may be the UE + certificate table. + + @param[in] FileInfo The UE header file information. +**/ +#define UE_HEADER_FILE_SIZE(FileInfo) ((FileInfo) << 3U) + +STATIC_ASSERT ( + IS_ALIGNED (UE_HEADER_FILE_SIZE (0xFFFFFFFF), UE_LOAD_TABLE_ALIGNMENT), + "The UE file size definition does not meet the specification." + ); + +/// +/// The maximum size, in bytes, of a valid UE header. +/// +#define MAX_SIZE_OF_UE_HEADER \ + MIN_SIZE_OF_UE_HEADER + \ + UE_HEADER_NUM_SEGMENTS_MAX * sizeof (UE_SEGMENT) + \ + UE_HEADER_NUM_LOAD_TABLES_MAX * sizeof (UE_LOAD_TABLE) + +#endif // UE_IMAGE_H_ diff --git a/MdePkg/Include/Library/UeImageLib.h b/MdePkg/Include/Library/UeImageLib.h new file mode 100644 index 0000000000..850ca6b3df --- /dev/null +++ b/MdePkg/Include/Library/UeImageLib.h @@ -0,0 +1,181 @@ +/** @file + UEFI Image Loader library implementation for UE Images. + + Copyright (c) 2021 - 2023, Marvin Häuser. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef UE_LIB_H_ +#define UE_LIB_H_ + +#include + +typedef struct { + CONST UINT8 *FileBuffer; + UINT32 UnsignedFileSize; + UINT8 Subsystem; + UINT8 Machine; + BOOLEAN FixedAddress; + BOOLEAN XIP; + UINT8 LastSegmentIndex; + UINT32 SegmentsFileOffset; // Unused for XIP + UINT32 SegmentAlignment; + CONST VOID *Segments; + UINT8 SegmentImageInfoIterSize; + BOOLEAN RelocsStripped; + UINT8 NumLoadTables; + UINT32 LoadTablesFileOffset; + UINT32 RelocTableSize; + CONST UE_LOAD_TABLE *LoadTables; + VOID *ImageBuffer; + UINT32 ImageSize; + UINT32 EntryPointAddress; + UINT64 BaseAddress; // Unused for XIP +} UE_LOADER_IMAGE_CONTEXT; + +typedef struct UE_LOADER_RUNTIME_CONTEXT_ UE_LOADER_RUNTIME_CONTEXT; + +/** + Adds the digest of Data to HashContext. This function can be called multiple + times to compute the digest of discontinuous data. + + @param[in,out] HashContext The context of the current hash. + @param[in] Data The data to be hashed. + @param[in] DataSize The size, in Bytes, of Data. + + @returns Whether hashing has been successful. +**/ +typedef +BOOLEAN +(EFIAPI *UE_LOADER_HASH_UPDATE)( + IN OUT VOID *HashContext, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +RETURN_STATUS +UeInitializeContextPreHash ( + OUT UE_LOADER_IMAGE_CONTEXT *Context, + IN CONST VOID *FileBuffer, + IN UINT32 FileSize + ); + +RETURN_STATUS +UeInitializeContextPostHash ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ); + +BOOLEAN +UeHashImageDefault ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context, + IN OUT VOID *HashContext, + IN UE_LOADER_HASH_UPDATE HashUpdate + ); + +RETURN_STATUS +UeLoadImage ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context, + OUT VOID *Destination, + IN UINT32 DestinationSize + ); + +RETURN_STATUS +UeLoaderGetRuntimeContextSize ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context, + OUT UINT32 *Size + ); + +RETURN_STATUS +UeRelocateImage ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context, + IN UINT64 BaseAddress, + OUT UE_LOADER_RUNTIME_CONTEXT *RuntimeContext OPTIONAL, + IN UINT32 RuntimeContextSize + ); + +RETURN_STATUS +UeRelocateImageForRuntime ( + IN OUT VOID *Image, + IN UINT32 ImageSize, + IN CONST UE_LOADER_RUNTIME_CONTEXT *RuntimeContext, + IN UINT64 BaseAddress + ); + +RETURN_STATUS +UeGetSymbolsPath ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context, + OUT CONST CHAR8 **SymbolsPath, + OUT UINT32 *SymbolsPathSize + ); + +UINTN +UeLoaderGetImageDebugAddress ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context + ); + +RETURN_STATUS +UeGetSegmentNames ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context, + OUT CONST UE_SEGMENT_NAME **SegmentNames + ); + +UINT32 +UeGetEntryPointAddress ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context + ); + +UINT16 +UeGetMachine ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ); + +UINT16 +UeGetSubsystem ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ); + +UINT32 +UeGetSegmentAlignment ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ); + +UINT32 +UeGetImageSize ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ); + +UINT64 +UeGetBaseAddress ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ); + +BOOLEAN +UeGetRelocsStripped ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ); + +BOOLEAN +UeGetFixedAddress( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ); + +UINTN +UeLoaderGetImageAddress ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context + ); + +UINT16 +UeGetSegments ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context, + OUT CONST UE_SEGMENT **Segments + ); + +UINT16 +UeGetSegmentImageInfos ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context, + OUT CONST UINT32 **SegmentImageInfos, + OUT UINT8 *SegmentImageInfoIterSize + ); + +#endif // UE_LIB_H_ diff --git a/MdePkg/Include/Library/UefiImageLib.h b/MdePkg/Include/Library/UefiImageLib.h index 7528f3a6eb..957b7f17be 100644 --- a/MdePkg/Include/Library/UefiImageLib.h +++ b/MdePkg/Include/Library/UefiImageLib.h @@ -2,10 +2,12 @@ #ifndef UEFI_IMAGE_LIB_H_ #define UEFI_IMAGE_LIB_H_ +#include #include typedef enum { UefiImageFormatPe = 0, + UefiImageFormatUe = 1, UefiImageFormatMax } UEFI_IMAGE_FORMAT; @@ -14,11 +16,52 @@ typedef enum { #define UEFI_IMAGE_SOURCE_ALL 2U #define UEFI_IMAGE_SOURCE_MAX 3U +// FIXME: Get rid of pointers. +typedef struct { + UINT32 ImageBuffer; + UINT32 AddressOfEntryPoint; + UINT8 ImageType; + UINT32 FileBuffer; + UINT32 ExeHdrOffset; + UINT32 SizeOfImage; + UINT32 FileSize; + UINT16 Subsystem; + UINT32 SectionAlignment; + UINT32 SectionsOffset; + UINT16 NumberOfSections; + UINT32 SizeOfHeaders; +} PE_HOB_IMAGE_CONTEXT; + +typedef struct { + UINT32 ImageBuffer; + UINT32 FileBuffer; + UINT32 EntryPointAddress; + UINT32 LoadTablesFileOffset; + UINT8 NumLoadTables; + UINT32 LoadTables; + UINT32 Segments; + UINT8 LastSegmentIndex; + UINT32 SegmentAlignment; + UINT32 ImageSize; + UINT8 Subsystem; + UINT8 SegmentImageInfoIterSize; + UINT32 SegmentsFileOffset; +} UE_HOB_IMAGE_CONTEXT; + +typedef struct { + UINT8 FormatIndex; + union { + UE_HOB_IMAGE_CONTEXT Ue; + PE_HOB_IMAGE_CONTEXT Pe; + } Ctx; +} HOB_IMAGE_CONTEXT; + typedef UINT8 UEFI_IMAGE_SOURCE; typedef struct { UINT8 FormatIndex; union { + UE_LOADER_IMAGE_CONTEXT Ue; PE_COFF_LOADER_IMAGE_CONTEXT Pe; } Ctx; } UEFI_IMAGE_LOADER_IMAGE_CONTEXT; @@ -574,6 +617,22 @@ UefiImageLoaderGetImageAddress ( IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context ); +/** + Retrieves the Image debug address. Due to post-processing, the debug address + may deviate from the load address. Symbolication must use this address. + + May be called only after UefiImageLoadImage() has succeeded. + + @param[in,out] Context The context describing the Image. Must have been + initialised by UefiImageInitializeContext(). + + @returns The Image debug address. +**/ +UINTN +UefiImageLoaderGetDebugAddress ( + IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ); + /** Retrieve the Image entry point address. diff --git a/MdePkg/Include/Ppi/LoadFile.h b/MdePkg/Include/Ppi/LoadFile.h index 838e3fda90..22c2071191 100644 --- a/MdePkg/Include/Ppi/LoadFile.h +++ b/MdePkg/Include/Ppi/LoadFile.h @@ -12,10 +12,13 @@ #ifndef __LOAD_FILE_PPI_H__ #define __LOAD_FILE_PPI_H__ +#include + #define EFI_PEI_LOAD_FILE_PPI_GUID \ { 0xb9e0abfe, 0x5979, 0x4914, { 0x97, 0x7f, 0x6d, 0xee, 0x78, 0xc2, 0x78, 0xa6 } } typedef struct _EFI_PEI_LOAD_FILE_PPI EFI_PEI_LOAD_FILE_PPI; +typedef struct _EFI_PEI_LOAD_FILE_WITH_HOB_PPI EFI_PEI_LOAD_FILE_WITH_HOB_PPI; /** Loads a PEIM into memory for subsequent execution. @@ -56,6 +59,17 @@ EFI_STATUS OUT UINT32 *AuthenticationState ); +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_LOAD_FILE_WITH_HOB)( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState, + OUT HOB_IMAGE_CONTEXT *Hob + ); + /// /// This PPI is a pointer to the Load File service. /// This service will be published by a PEIM. The PEI Foundation @@ -65,6 +79,11 @@ struct _EFI_PEI_LOAD_FILE_PPI { EFI_PEI_LOAD_FILE LoadFile; }; +struct _EFI_PEI_LOAD_FILE_WITH_HOB_PPI { + EFI_PEI_LOAD_FILE_WITH_HOB LoadFile; +}; + extern EFI_GUID gEfiPeiLoadFilePpiGuid; +extern EFI_GUID gEfiPeiLoadFileWithHobPpiGuid; #endif diff --git a/MdePkg/Library/BaseUeImageLib/BaseUeImageLib.inf b/MdePkg/Library/BaseUeImageLib/BaseUeImageLib.inf new file mode 100644 index 0000000000..557b0961e3 --- /dev/null +++ b/MdePkg/Library/BaseUeImageLib/BaseUeImageLib.inf @@ -0,0 +1,33 @@ +## @file +# UEFI Image Loader library implementation for UE Images. +# +# Copyright (c) 2021, Marvin Häuser. All rights reserved.
+# +# SPDX-License-Identifier: BSD-3-Clause +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UeImageLib + FILE_GUID = 357AD87E-8D6B-468A-B3FA-0D9CC4C725CD + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseUeImageLib + +[Sources] + UeImageLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + BaseOverflowLib + DebugLib + PcdLib + +[FixedPcd] + gEfiMdePkgTokenSpaceGuid.PcdImageLoaderRelocTypePolicy + gEfiMdePkgTokenSpaceGuid.PcdDebugRaisePropertyMask + gEfiMdePkgTokenSpaceGuid.PcdImageLoaderRtRelocAllowTargetMismatch diff --git a/MdePkg/Library/BaseUeImageLib/UeImageLib.c b/MdePkg/Library/BaseUeImageLib/UeImageLib.c new file mode 100644 index 0000000000..f5f6e8720b --- /dev/null +++ b/MdePkg/Library/BaseUeImageLib/UeImageLib.c @@ -0,0 +1,1392 @@ +/** @file + UEFI image loader library implementation for UE images. + + Copyright (c) 2021 - 2023, Marvin Häuser. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct UE_LOADER_RUNTIME_CONTEXT_ { + UINT8 Machine; + UINT8 Reserved[7]; + UINT32 FixupSize; + UINT64 *FixupData; + UINT32 UnchainedRelocsSize; + UINT8 *UnchainedRelocs; +}; + +typedef union { + UINT32 Value32; + UINT64 Value64; +} UE_RELOC_FIXUP_VALUE; + +STATIC +RETURN_STATUS +InternalVerifySegments ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + CONST UE_SEGMENT *Segments; + UINT8 LastSegmentIndex; + UINT8 SegmentIndex; + UINT32 SegmentEndFileOffset; + UINT32 SegmentEndImageAddress; + BOOLEAN Overflow; + UINT32 SegmentImageSize; + + Segments = Context->Segments; + LastSegmentIndex = Context->LastSegmentIndex; + // + // As it holds that SegmentEndFileOffset - Context->SegmentsFileOffset <= SegmentEndImageAddress, + // and it holds that SegmentEndImageAddress % 4 KiB = 0, SegmentEndFileOffset - Context->SegmentsFileOffset + // can be at most 0xFFFFF000. As it holds that Context->SegmentsFileOffset <= MAX_SIZE_OF_UE_HEADER <= 0xFF0, + // this cannot overflow. + // + STATIC_ASSERT ( + MAX_SIZE_OF_UE_HEADER <= BASE_4KB - 8, + "The arithmetic below may overflow." + ); + + SegmentEndFileOffset = Context->SegmentsFileOffset; + // + // The first image segment must begin the image address space. + // + SegmentEndImageAddress = 0; + + for (SegmentIndex = 0; SegmentIndex <= LastSegmentIndex; ++SegmentIndex) { + SegmentImageSize = UE_SEGMENT_SIZE (Segments[SegmentIndex].ImageInfo); + + if (Segments[SegmentIndex].FileSize > SegmentImageSize) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + // + // Verify the image segments are aligned. + // + if (!IS_ALIGNED (SegmentImageSize, Context->SegmentAlignment)) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + // + // Determine the end of the current image segment. + // + Overflow = BaseOverflowAddU32 ( + SegmentEndImageAddress, + SegmentImageSize, + &SegmentEndImageAddress + ); + if (Overflow) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + // + // As it holds that SegmentFileSize <= SegmentImageSize and thus + // SegmentEndFileOffset - Context->SegmentsFileOffset <= SegmentEndImageAddress, + // this cannot overflow (see above). + // + SegmentEndFileOffset += Segments[SegmentIndex].FileSize; + } + // + // As it holds that SegmentEndFileOffset <= 0xFFFFFFF0, this cannot overflow. + // + SegmentEndFileOffset = ALIGN_VALUE ( + SegmentEndFileOffset, + UE_LOAD_TABLE_ALIGNMENT + ); + // + // Verify all image segment data are in bounds of the file buffer. + // + ASSERT (Context->SegmentsFileOffset <= SegmentEndFileOffset); + if (SegmentEndFileOffset > Context->UnsignedFileSize) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + + Context->LoadTablesFileOffset = SegmentEndFileOffset; + Context->ImageSize = SegmentEndImageAddress; + + if (Context->XIP) { + Context->ImageSize += Context->SegmentsFileOffset; + } + + return RETURN_SUCCESS; +} + +STATIC +RETURN_STATUS +InternalVerifyLoadTables ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + BOOLEAN Overflow; + CONST UE_LOAD_TABLE *LoadTable; + UINT8 LoadTableIndex; + INT16 PrevLoadTableId; + UINT32 LoadTableFileOffset; + UINT32 LoadTableFileSize; + UINT8 LoadTableId; + UINT32 LoadTableEndFileOffset; + UINT8 NumLoadTables; + + Context->RelocTableSize = 0; + + LoadTableEndFileOffset = Context->LoadTablesFileOffset; + NumLoadTables = Context->NumLoadTables; + PrevLoadTableId = -1; + + if (0 < NumLoadTables) { + LoadTableIndex = 0; + do { + LoadTable = Context->LoadTables + LoadTableIndex; + LoadTableId = UE_LOAD_TABLE_ID (LoadTable->FileInfo); + + if (PrevLoadTableId >= LoadTableId) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + + LoadTableFileOffset = LoadTableEndFileOffset; + LoadTableFileSize = UE_LOAD_TABLE_SIZE (LoadTable->FileInfo); + + Overflow = BaseOverflowAddU32 ( + LoadTableFileOffset, + LoadTableFileSize, + &LoadTableEndFileOffset + ); + if (Overflow) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + + PrevLoadTableId = LoadTableId; + ++LoadTableIndex; + } while (LoadTableIndex < NumLoadTables); + + if (UE_LOAD_TABLE_ID (Context->LoadTables[0].FileInfo) == UeLoadTableIdReloc) { + if (Context->RelocsStripped) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + + Context->RelocTableSize = UE_LOAD_TABLE_SIZE ( + Context->LoadTables[0].FileInfo + ); + } + } + + if (LoadTableEndFileOffset != Context->UnsignedFileSize) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + + return RETURN_SUCCESS; +} + +RETURN_STATUS +UeInitializeContextPreHash ( + OUT UE_LOADER_IMAGE_CONTEXT *Context, + IN CONST VOID *FileBuffer, + IN UINT32 FileSize + ) +{ + //BOOLEAN Overflow; + CONST UE_HEADER *UeHdr; + //UINT32 UnsignedFileSize; + + ASSERT (Context != NULL); + ASSERT (FileBuffer != NULL || FileSize == 0); + + if (MIN_SIZE_OF_UE_HEADER > FileSize) { + return RETURN_UNSUPPORTED; + } + + UeHdr = (CONST UE_HEADER *) FileBuffer; + + if (UeHdr->Magic != UE_HEADER_MAGIC) { + return RETURN_UNSUPPORTED; + } + + ZeroMem (Context, sizeof (*Context)); + + /*UnsignedFileSize = UE_HEADER_FILE_SIZE (UeHdr->FileInfo); + + Overflow = BaseOverflowSubU32 ( + FileSize, + UnsignedFileSize, + &Context->CertTableSize + ); + if (Overflow) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + }*/ + + Context->FileBuffer = (CONST UINT8 *)UeHdr; + //Context->UnsignedFileSize = UnsignedFileSize; + Context->UnsignedFileSize = FileSize; + + return RETURN_SUCCESS; +} + +BOOLEAN +UeHashImageDefault ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context, + IN OUT VOID *HashContext, + IN UE_LOADER_HASH_UPDATE HashUpdate + ) +{ + BOOLEAN Result; + + ASSERT (Context != NULL); + ASSERT (HashContext != NULL); + ASSERT (HashUpdate != NULL); + + Result = HashUpdate ( + HashContext, + Context->FileBuffer, + Context->UnsignedFileSize + ); + if (!Result) { + DEBUG_RAISE (); + } + + return Result; +} + +STATIC +RETURN_STATUS +InternalInitializeContextLate ( + OUT UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + if (Context->EntryPointAddress > Context->ImageSize) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + + return InternalVerifyLoadTables (Context); +} + +RETURN_STATUS +UeInitializeContextPostHash ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + CONST UE_HEADER *UeHdr; + UINT8 LastSegmentIndex; + UINT8 NumLoadTables; + UINT32 LoadTablesFileOffset; + UINT32 HeaderSize; + UINT64 BaseAddress; + RETURN_STATUS Status; + + ASSERT (Context != NULL); + + UeHdr = (CONST UE_HEADER *)Context->FileBuffer; + + Context->FixedAddress = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_FIXED_ADDRESS) != 0; + Context->RelocsStripped = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_RELOCATION_FIXUPS_STRIPPED) != 0; + Context->XIP = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_XIP) != 0; + + Context->Segments = UeHdr->Segments; + Context->SegmentImageInfoIterSize = sizeof (*UeHdr->Segments); + Context->SegmentAlignment = UE_HEADER_SEGMENT_ALIGNMENT (UeHdr->ImageInfo); + + LastSegmentIndex = UE_HEADER_LAST_SEGMENT_INDEX (UeHdr->TableCounts); + NumLoadTables = UE_HEADER_NUM_LOAD_TABLES (UeHdr->TableCounts); + + LoadTablesFileOffset = MIN_SIZE_OF_UE_HEADER + + (UINT32) LastSegmentIndex * sizeof (UE_SEGMENT); + + HeaderSize = LoadTablesFileOffset + (UINT32) NumLoadTables * sizeof (UE_LOAD_TABLE); + ASSERT (HeaderSize <= MAX_SIZE_OF_UE_HEADER); + if (Context->XIP) { + HeaderSize = ALIGN_VALUE (HeaderSize, Context->SegmentAlignment); + } + + if (HeaderSize > Context->UnsignedFileSize) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + + ASSERT (IS_ALIGNED (LoadTablesFileOffset, ALIGNOF (UE_LOAD_TABLE))); + + Context->LoadTables = (CONST UE_LOAD_TABLE *)( + (CONST UINT8 *) UeHdr + LoadTablesFileOffset + ); + + Context->SegmentsFileOffset = HeaderSize; + Context->LastSegmentIndex = LastSegmentIndex; + Context->NumLoadTables = NumLoadTables; + + BaseAddress = UE_HEADER_BASE_ADDRESS (UeHdr->ImageInfo); + + if (!IS_ALIGNED (BaseAddress, Context->SegmentAlignment)) { + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + + Context->FileBuffer = (CONST UINT8 *)UeHdr; + + Status = InternalVerifySegments (Context); + if (RETURN_ERROR (Status)) { + return Status; + } + + Context->BaseAddress = BaseAddress; + Context->EntryPointAddress = UeHdr->EntryPointAddress; + + Context->Subsystem = UE_HEADER_SUBSYSTEM (UeHdr->Type); + Context->Machine = UE_HEADER_ARCH (UeHdr->Type); + + return InternalInitializeContextLate (Context); +} + +RETURN_STATUS +UeLoadImage ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context, + OUT VOID *Destination, + IN UINT32 DestinationSize + ) +{ + UINT8 SegmentIndex; + UINT32 SegmentFileOffset; + UINT32 SegmentFileSize; + UINT32 SegmentImageAddress; + UINT32 SegmentImageSize; + UINT32 PrevSegmentDataEnd; + + CONST UE_SEGMENT *Segments; + + ASSERT (Context != NULL); + ASSERT (Destination != NULL); + ASSERT (ADDRESS_IS_ALIGNED (Destination, Context->SegmentAlignment)); + + Context->ImageBuffer = Destination; + + // + // Load all image load tables into the address space. + // + Segments = Context->Segments; + + // + // Start zeroing from the start of the destination buffer. + // + PrevSegmentDataEnd = 0; + + SegmentFileOffset = Context->SegmentsFileOffset; + SegmentImageAddress = 0; + + SegmentIndex = 0; + do { + SegmentFileSize = Segments[SegmentIndex].FileSize; + SegmentImageSize = UE_SEGMENT_SIZE (Segments[SegmentIndex].ImageInfo); + // + // Zero from the end of the previous image segment to the start of this + // image segment. + // + ZeroMem ( + (UINT8 *)Destination + PrevSegmentDataEnd, + SegmentImageAddress - PrevSegmentDataEnd + ); + // + // Load the current Image segment into the address space. + // + ASSERT (SegmentFileSize <= SegmentImageSize); + CopyMem ( + (UINT8 *)Destination + SegmentImageAddress, + Context->FileBuffer + SegmentFileOffset, + SegmentFileSize + ); + PrevSegmentDataEnd = SegmentImageAddress + SegmentFileSize; + + SegmentFileOffset += SegmentFileSize; + SegmentImageAddress += SegmentImageSize; + ++SegmentIndex; + } while (SegmentIndex <= Context->LastSegmentIndex); + // + // Zero the trailing data after the last image segment. + // + ZeroMem ( + (UINT8 *)Destination + PrevSegmentDataEnd, + DestinationSize - PrevSegmentDataEnd + ); + + return RETURN_SUCCESS; +} + +RETURN_STATUS +UeLoaderGetRuntimeContextSize ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context, + OUT UINT32 *Size + ) +{ + ASSERT (Context != NULL); + ASSERT (Size != NULL); + + *Size = sizeof (UE_LOADER_RUNTIME_CONTEXT); + return RETURN_SUCCESS; +} + +/** + Apply an image relocation fixup. + + Only a subset of the PE/COFF relocation fixup types are permited. + The relocation fixup target must be in bounds, aligned, and must not overlap + with the Relocation Directory. + + @param[in] Context The context describing the image. Must have been + loaded by PeCoffLoadImage(). + @param[in] RelocIndex The index of the relocation fixup to apply. + @param[in] Adjust The delta to add to the addresses. + + @retval RETURN_SUCCESS The relocation fixup has been applied successfully. + @retval other The relocation fixup could not be applied successfully. +**/ +STATIC +RETURN_STATUS +InternalApplyRelocation ( + IN OUT VOID *Image, + IN UINT32 ImageSize, + IN UINT8 Machine, + IN UINT16 RelocType, + IN UINT32 *RelocTarget, + IN UINT64 Adjust, + IN OUT UINT64 *FixupData, + IN BOOLEAN IsRuntime + ) +{ + BOOLEAN Overflow; + + UINT32 RemFixupTargetSize; + + UINT32 FixupTarget; + VOID *Fixup; + UINT8 FixupSize; + UE_RELOC_FIXUP_VALUE FixupValue; + + ASSERT (FixupData != NULL); + + FixupTarget = *RelocTarget; + // + // Verify the relocation fixup target address is in bounds of the image buffer. + // + Overflow = BaseOverflowSubU32 (ImageSize, FixupTarget, &RemFixupTargetSize); + if (Overflow) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + + Fixup = (UINT8 *)Image + FixupTarget; + // + // Apply the relocation fixup per type. + // + if (RelocType < UeRelocGenericMax) { + if (RelocType == UeReloc32) { + FixupSize = sizeof (UINT32); + // + // Verify the relocation fixup target is in bounds of the image buffer. + // + if (FixupSize > RemFixupTargetSize) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + // + // Relocate the target instruction. + // + FixupValue.Value32 = ReadUnaligned32 (Fixup); + // + // If the Image relocation target value mismatches, skip or abort. + // + if (IsRuntime && (FixupValue.Value32 != (UINT32)*FixupData)) { + if (PcdGetBool (PcdImageLoaderRtRelocAllowTargetMismatch)) { + return RETURN_SUCCESS; + } + + return RETURN_VOLUME_CORRUPTED; + } + + FixupValue.Value32 += (UINT32) Adjust; + WriteUnaligned32 (Fixup, FixupValue.Value32); + } else if (RelocType == UeReloc64) { + FixupSize = sizeof (UINT64); + // + // Verify the image relocation fixup target is in bounds of the image + // buffer. + // + if (FixupSize > RemFixupTargetSize) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + // + // Relocate target the instruction. + // + FixupValue.Value64 = ReadUnaligned64 (Fixup); + // + // If the Image relocation target value mismatches, skip or abort. + // + if (IsRuntime && (FixupValue.Value64 != *FixupData)) { + if (PcdGetBool (PcdImageLoaderRtRelocAllowTargetMismatch)) { + return RETURN_SUCCESS; + } + + return RETURN_VOLUME_CORRUPTED; + } + + FixupValue.Value64 += Adjust; + WriteUnaligned64 (Fixup, FixupValue.Value64); + } else if (RelocType == UeReloc32NoMeta) { + FixupSize = sizeof (UINT32); + // + // Verify the relocation fixup target is in bounds of the image buffer. + // + if (FixupSize > RemFixupTargetSize) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + // + // Relocate the target instruction. + // + FixupValue.Value32 = ReadUnaligned32 (Fixup); + // + // If the Image relocation target value mismatches, skip or abort. + // + if (IsRuntime && (FixupValue.Value32 != (UINT32)*FixupData)) { + if (PcdGetBool (PcdImageLoaderRtRelocAllowTargetMismatch)) { + return RETURN_SUCCESS; + } + + return RETURN_VOLUME_CORRUPTED; + } + + FixupValue.Value32 += (UINT32) Adjust; + WriteUnaligned32 (Fixup, FixupValue.Value32); + + if (!IsRuntime) { + *FixupData = FixupValue.Value32; + } + } else { + // + // The image relocation fixup type is unknown, disallow the image. + // + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + } else { +#if 0 + if (Machine == UeMachineArmThumbMixed) { + switch (RelocType) { + // TODO: MOVW + case (UeMachineArmThumbMixed << 4U) | UeRelocArmMovt: + { + // + // Verify the relocation fixup target is in bounds of the image buffer. + // + if (sizeof (UINT64) > RemFixupTargetSize) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + // + // Verify the relocation fixup target is sufficiently aligned. + // The ARM Thumb instruction pait must start on a 16-bit boundary. + // + if (!IS_ALIGNED (RelocTarget, ALIGNOF (UINT16))) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + // + // Relocate the target instruction. + // + PeCoffThumbMovwMovtImmediateFixup (Fixup, Adjust); + + break; + } + + default: + { + // + // The image relocation fixup type is unknown, disallow the image. + // + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + } + } +#endif + // + // The image relocation fixup type is unknown, disallow the image. + // + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + + *RelocTarget = FixupTarget + FixupSize; + + return RETURN_SUCCESS; +} + +STATIC +RETURN_STATUS +UnchainReloc ( + IN OUT UE_LOADER_RUNTIME_CONTEXT *RuntimeContext OPTIONAL, + IN CONST UINT8 *MetaSource OPTIONAL, + IN UINT32 MetaSize, + IN BOOLEAN IsRuntime, + IN UINT16 RelocOffset, + IN UINT64 *FixupData + ) +{ + UINT32 OldSize; + UINT16 FixupHdr; + UINT32 FixupIndex; + UINT8 Addend; + + if ((RuntimeContext != NULL) && !IsRuntime) { + if (MetaSource == NULL) { + FixupIndex = RuntimeContext->UnchainedRelocsSize - sizeof (UINT16); + + FixupHdr = *(UINT16 *)&RuntimeContext->UnchainedRelocs[FixupIndex]; + FixupHdr = (RelocOffset << 4U) | UE_RELOC_FIXUP_TYPE(FixupHdr); + + *(UINT16 *)&RuntimeContext->UnchainedRelocs[FixupIndex] = FixupHdr; + + Addend = ALIGN_VALUE_ADDEND(RuntimeContext->UnchainedRelocsSize, ALIGNOF(UE_FIXUP_ROOT)); + if ((RelocOffset == UE_HEAD_FIXUP_OFFSET_END) && (Addend != 0)) { + OldSize = RuntimeContext->UnchainedRelocsSize; + RuntimeContext->UnchainedRelocs = ReallocateRuntimePool ( + OldSize, + OldSize + Addend, + RuntimeContext->UnchainedRelocs + ); + if (RuntimeContext->UnchainedRelocs == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + + ZeroMem (RuntimeContext->UnchainedRelocs + OldSize, Addend); + RuntimeContext->UnchainedRelocsSize += Addend; + } + + return RETURN_SUCCESS; + } + + OldSize = RuntimeContext->UnchainedRelocsSize; + RuntimeContext->UnchainedRelocs = ReallocateRuntimePool ( + OldSize, + OldSize + MetaSize, + RuntimeContext->UnchainedRelocs + ); + if (RuntimeContext->UnchainedRelocs == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + + CopyMem (RuntimeContext->UnchainedRelocs + OldSize, MetaSource, MetaSize); + + RuntimeContext->UnchainedRelocsSize += MetaSize; + + if (FixupData != NULL) { + OldSize = RuntimeContext->FixupSize; + RuntimeContext->FixupData = ReallocateRuntimePool ( + OldSize, + OldSize + sizeof (*FixupData), + RuntimeContext->FixupData + ); + if (RuntimeContext->FixupData == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + + CopyMem ((UINT8 *)RuntimeContext->FixupData + OldSize, FixupData, sizeof (*FixupData)); + + RuntimeContext->FixupSize += sizeof (*FixupData); + } + } + + return RETURN_SUCCESS; +} + +STATIC +RETURN_STATUS +InternalProcessRelocChain ( + IN OUT VOID *Image, + IN UINT32 ImageSize, + IN UINT8 Machine, + IN UINT16 FirstRelocType, + IN UINT32 *ChainStart, + IN UINT64 Adjust, + IN OUT UE_LOADER_RUNTIME_CONTEXT *RuntimeContext OPTIONAL + ) +{ + RETURN_STATUS Status; + UINT16 RelocType; + UINT16 RelocOffset; + UINT32 RelocTarget; + + BOOLEAN Overflow; + UINT32 RemFixupTargetSize; + + UINT8 *Fixup; + UE_RELOC_FIXUP_VALUE FixupInfo; + UINT8 FixupSize; + UE_RELOC_FIXUP_VALUE FixupValue; + UINT16 FixupHdr; + UINT64 FixupData; + + RelocType = FirstRelocType; + RelocTarget = *ChainStart; + + while (TRUE) { + Overflow = BaseOverflowSubU32 (ImageSize, RelocTarget, &RemFixupTargetSize); + if (Overflow) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + + Fixup = (UINT8 *)Image + RelocTarget; + + if (RelocType < UeRelocGenericMax) { + if (RelocType == UeReloc64) { + FixupSize = sizeof (UINT64); + // + // Verify the relocation fixup target is in bounds of the image memory. + // + if (FixupSize > RemFixupTargetSize) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + // + // Relocate the target instruction. + // + FixupInfo.Value64 = ReadUnaligned64 ((CONST VOID *)Fixup); + FixupValue.Value64 = UE_CHAINED_RELOC_FIXUP_VALUE (FixupInfo.Value64); + FixupValue.Value64 += Adjust; + WriteUnaligned64 ((VOID *)Fixup, FixupValue.Value64); + + FixupData = FixupValue.Value64; + } else if (RelocType == UeReloc32) { + FixupSize = sizeof (UINT32); + // + // Verify the image relocation fixup target is in bounds of the image + // buffer. + // + if (FixupSize > RemFixupTargetSize) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + // + // Relocate the target instruction. + // + FixupInfo.Value32 = ReadUnaligned32 ((CONST VOID *)Fixup); + FixupValue.Value32 = UE_CHAINED_RELOC_FIXUP_VALUE_32 (FixupInfo.Value32); + FixupValue.Value32 += (UINT32) Adjust; + WriteUnaligned32 ((VOID *)Fixup, FixupValue.Value32); + + FixupData = FixupValue.Value32; + // + // Imitate the common header of UE chained relocation fixups, + // as for 32-bit files all relocs have the same type. + // + FixupInfo.Value32 = FixupInfo.Value32 << 4U; + FixupInfo.Value32 |= UeReloc32; + } else { + // + // The image relocation fixup type is unknown, disallow the image. + // + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + } else { + // + // The image relocation fixup type is unknown, disallow the image. + // + DEBUG_RAISE (); + return RETURN_UNSUPPORTED; + } + + RelocTarget += FixupSize; + + RelocOffset = UE_CHAINED_RELOC_FIXUP_NEXT_OFFSET (FixupInfo.Value32); + FixupHdr = (RelocOffset << 4U) | RelocType; + + Status = UnchainReloc ( + RuntimeContext, + (CONST UINT8 *)&FixupHdr, + sizeof (FixupHdr), + FALSE, + 0, + &FixupData + ); + if (RETURN_ERROR (Status)) { + return Status; + } + + if (RelocOffset == UE_CHAINED_RELOC_FIXUP_OFFSET_END) { + *ChainStart = RelocTarget; + return RETURN_SUCCESS; + } + // + // It holds that ImageSize mod 4 KiB = 0, thus ImageSize <= 0xFFFFF000. + // Furthermore, it holds that RelocTarget <= ImageSize. + // Finally, it holds that RelocOffset <= 0xFFE. + // It follows that this cannot overflow. + // + RelocTarget += RelocOffset; + ASSERT (RelocOffset <= RelocTarget); + + RelocType = UE_CHAINED_RELOC_FIXUP_NEXT_TYPE (FixupInfo.Value32); + } +} + +STATIC +RETURN_STATUS +InternaRelocateImage ( + IN OUT VOID *Image, + IN UINT32 ImageSize, + IN UINT8 Machine, + IN UINT64 OldBaseAddress, + IN CONST VOID *RelocTable, + IN UINT32 RelocTableSize, + IN BOOLEAN Chaining, + IN UINT64 BaseAddress, + OUT UE_LOADER_RUNTIME_CONTEXT *RuntimeContext OPTIONAL, + IN BOOLEAN IsRuntime + ) +{ + RETURN_STATUS Status; + BOOLEAN Overflow; + + UINT64 Adjust; + + UINT32 RootOffsetMax; + UINT32 EntryOffsetMax; + + UINT32 TableOffset; + CONST UE_FIXUP_ROOT *RelocRoot; + + UINT16 FixupInfo; + UINT16 RelocType; + UINT16 RelocOffset; + UINT32 RelocTarget; + + UINT32 OldTableOffset; + UINT64 FixupData; + UINT64 *FixupPointer; + + ASSERT (Image != NULL); + ASSERT (RelocTable != NULL || RelocTableSize == 0); + // + // Verify the Relocation Directory is not empty. + // + if (RelocTableSize == 0) { + return RETURN_SUCCESS; + } + // + // Calculate the image displacement from its prefered load address. + // + Adjust = BaseAddress - OldBaseAddress; + // + // FIXME: RT driver check is removed in the hope we can force no relocs in + // writable segments. + // + // Skip explicit Relocation when the image is already loaded at its base + // address. + // + if (Adjust == 0 && !Chaining) { + return RETURN_SUCCESS; + } + + RelocTarget = 0; + + if (IsRuntime) { + FixupPointer = RuntimeContext->FixupData; + } + + STATIC_ASSERT ( + MIN_SIZE_OF_UE_FIXUP_ROOT <= UE_LOAD_TABLE_ALIGNMENT, + "The following arithmetic may overflow." + ); + + RootOffsetMax = RelocTableSize - MIN_SIZE_OF_UE_FIXUP_ROOT; + EntryOffsetMax = RelocTableSize - sizeof (*RelocRoot->Heads); + // + // Apply all relocation fixups of the Image. + // + for (TableOffset = 0; TableOffset <= RootOffsetMax;) { + RelocRoot = (CONST UE_FIXUP_ROOT *)( + (CONST UINT8 *)RelocTable + TableOffset + ); + TableOffset += sizeof (*RelocRoot); + + Overflow = BaseOverflowAddU32 ( + RelocTarget, + RelocRoot->FirstOffset, + &RelocTarget + ); + if (Overflow) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + + Status = UnchainReloc ( + RuntimeContext, + (CONST UINT8 *)RelocRoot, + sizeof (*RelocRoot), + IsRuntime, + 0, + NULL + ); + if (RETURN_ERROR (Status)) { + return Status; + } + // + // Process all relocation fixups of the current root. + // + while (TRUE) { + FixupInfo = *(CONST UINT16 *)((CONST UINT8 *)RelocTable + TableOffset); + // + // This cannot overflow due to the upper bound of TableOffset. + // + TableOffset += sizeof (*RelocRoot->Heads); + // + // Apply the image relocation fixup. + // + RelocType = UE_RELOC_FIXUP_TYPE (FixupInfo); + + if (Chaining && !IsRuntime && (RelocType != UeReloc32NoMeta)) { + Status = InternalProcessRelocChain ( + Image, + ImageSize, + Machine, + RelocType, + &RelocTarget, + Adjust, + RuntimeContext + ); + } else { + Status = InternalApplyRelocation ( + Image, + ImageSize, + Machine, + RelocType, + &RelocTarget, + Adjust, + IsRuntime ? FixupPointer : &FixupData, + IsRuntime + ); + + if (RETURN_ERROR (Status)) { + return Status; + } + + Status = UnchainReloc ( + RuntimeContext, + (CONST UINT8 *)&FixupInfo, + sizeof (FixupInfo), + IsRuntime, + 0, + &FixupData + ); + + if (IsRuntime) { + ++FixupPointer; + } + } + + if (RETURN_ERROR (Status)) { + return Status; + } + + RelocOffset = UE_RELOC_FIXUP_OFFSET (FixupInfo); + + Status = UnchainReloc ( + RuntimeContext, + NULL, + 0, + IsRuntime, + RelocOffset, + NULL + ); + if (RETURN_ERROR (Status)) { + return Status; + } + + if (RelocOffset == UE_HEAD_FIXUP_OFFSET_END) { + break; + } + // + // It holds that ImageSize mod 4 KiB = 0, thus ImageSize <= 0xFFFFF000. + // Furthermore, it holds that RelocTarget <= ImageSize. + // Finally, it holds that RelocOffset <= 0xFFE. + // It follows that this cannot overflow. + // + RelocTarget += RelocOffset; + ASSERT (RelocOffset <= RelocTarget); + + if (TableOffset > EntryOffsetMax) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + } + // + // This cannot overflow due to the TableOffset upper bounds and the + // alignment guarantee of RelocTableSize. + // + OldTableOffset = TableOffset; + TableOffset = ALIGN_VALUE (TableOffset, ALIGNOF (UE_FIXUP_ROOT)); + ASSERT (OldTableOffset <= TableOffset); + } + + STATIC_ASSERT ( + sizeof (UE_FIXUP_ROOT) <= UE_LOAD_TABLE_ALIGNMENT, + "The following ASSERT may not hold." + ); + + return RETURN_SUCCESS; +} + +RETURN_STATUS +UeRelocateImage ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context, + IN UINT64 BaseAddress, + OUT UE_LOADER_RUNTIME_CONTEXT *RuntimeContext OPTIONAL, + IN UINT32 RuntimeContextSize + ) +{ + CONST UE_HEADER *UeHdr; + BOOLEAN Chaining; + CONST VOID *RelocTable; + + ASSERT (Context != NULL); + ASSERT (IS_ALIGNED (Context->LoadTablesFileOffset, UE_LOAD_TABLE_ALIGNMENT)); + ASSERT (IS_ALIGNED (Context->RelocTableSize, UE_LOAD_TABLE_ALIGNMENT)); + ASSERT (IS_ALIGNED (BaseAddress, Context->SegmentAlignment)); + ASSERT (RuntimeContext != NULL || RuntimeContextSize == 0); + ASSERT (RuntimeContextSize == 0 || sizeof (*RuntimeContext) <= RuntimeContextSize); + + RelocTable = Context->FileBuffer + Context->LoadTablesFileOffset; + + UeHdr = (CONST UE_HEADER *)Context->FileBuffer; + Chaining = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_CHAINED_FIXUPS) != 0; + + if (RuntimeContext != NULL) { + RuntimeContext->Machine = Context->Machine; + } + + if (Context->XIP) { + Context->EntryPointAddress -= Context->SegmentsFileOffset; + } + + return InternaRelocateImage ( + Context->ImageBuffer, + Context->ImageSize, + Context->Machine, + Context->XIP ? (Context->BaseAddress + Context->SegmentsFileOffset) : Context->BaseAddress, + RelocTable, + Context->RelocTableSize, + Chaining, + BaseAddress, + RuntimeContext, + FALSE + ); +} + +RETURN_STATUS +UeRelocateImageForRuntime ( + IN OUT VOID *Image, + IN UINT32 ImageSize, + IN CONST UE_LOADER_RUNTIME_CONTEXT *RuntimeContext, + IN UINT64 BaseAddress + ) +{ + ASSERT (RuntimeContext != NULL); + + return InternaRelocateImage ( + Image, + ImageSize, + RuntimeContext->Machine, + (UINTN)Image, + RuntimeContext->UnchainedRelocs, + RuntimeContext->UnchainedRelocsSize, + FALSE, + BaseAddress, + (UE_LOADER_RUNTIME_CONTEXT *)RuntimeContext, + TRUE + ); +} + +STATIC +RETURN_STATUS +InternalGetDebugTable ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context, + OUT CONST UE_DEBUG_TABLE **DebugTable + ) +{ + BOOLEAN Overflow; + CONST UE_LOAD_TABLE *LoadTable; + UINT8 LoadTableIndex; + UINT8 NumLoadTables; + UINT32 LoadTableFileOffset; + UINT32 LoadTableFileSize; + CONST UE_DEBUG_TABLE *DbgTable; + CONST UE_SEGMENT *Segments; + UINT16 NumSegments; + UINT32 LoadTableExtraSize; + UINT32 MinLoadTableExtraSize; + + ASSERT (Context != NULL); + ASSERT (DebugTable != NULL); + + LoadTableFileOffset = Context->LoadTablesFileOffset; + NumLoadTables = Context->NumLoadTables; + + for (LoadTableIndex = 0; LoadTableIndex < NumLoadTables; ++LoadTableIndex) { + LoadTable = Context->LoadTables + LoadTableIndex; + if (UE_LOAD_TABLE_ID (LoadTable->FileInfo) != UeLoadTableIdDebug) { + LoadTableFileOffset += UE_LOAD_TABLE_SIZE (LoadTable->FileInfo); + continue; + } + + ASSERT (IS_ALIGNED (LoadTableFileOffset, ALIGNOF (UE_DEBUG_TABLE))); + + LoadTableFileSize = UE_LOAD_TABLE_SIZE (LoadTable->FileInfo); + + Overflow = BaseOverflowSubU32 ( + LoadTableFileSize, + MIN_SIZE_OF_UE_DEBUG_TABLE, + &LoadTableExtraSize + ); + if (Overflow) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + + DbgTable = (CONST UE_DEBUG_TABLE *)(CONST VOID *)( + Context->FileBuffer + LoadTableFileOffset + ); + + NumSegments = UeGetSegments (Context, &Segments); + + MinLoadTableExtraSize = DbgTable->SymbolsPathLength + + (UINT32)NumSegments * sizeof (UE_SEGMENT_NAME); + if (MinLoadTableExtraSize > LoadTableExtraSize) { + DEBUG_RAISE (); + return RETURN_VOLUME_CORRUPTED; + } + + *DebugTable = DbgTable; + return RETURN_SUCCESS; + } + + return RETURN_NOT_FOUND; +} + +RETURN_STATUS +UeGetSymbolsPath ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context, + OUT CONST CHAR8 **SymbolsPath, + OUT UINT32 *SymbolsPathSize + ) +{ + RETURN_STATUS Status; + CONST UE_DEBUG_TABLE *DebugTable; + + ASSERT (Context != NULL); + ASSERT (SymbolsPath != NULL); + ASSERT (SymbolsPathSize != NULL); + + Status = InternalGetDebugTable (Context, &DebugTable); + if (RETURN_ERROR (Status)) { + return Status; + } + + if (DebugTable->SymbolsPathLength == 0) { + return RETURN_NOT_FOUND; + } + + if (DebugTable->SymbolsPath[DebugTable->SymbolsPathLength] != 0) { + return RETURN_VOLUME_CORRUPTED; + } + + *SymbolsPath = (CONST CHAR8 *)DebugTable->SymbolsPath; + *SymbolsPathSize = (UINT32)DebugTable->SymbolsPathLength + 1; + return RETURN_SUCCESS; +} + +UINTN +UeLoaderGetImageDebugAddress ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + RETURN_STATUS Status; + CONST UE_DEBUG_TABLE *DebugTable; + UINT8 SymOffsetFactor; + UINT32 SymOffsetSubtrahend; + + ASSERT (Context != NULL); + + SymOffsetSubtrahend = 0; + + Status = InternalGetDebugTable (Context, &DebugTable); + if (!RETURN_ERROR (Status)) { + SymOffsetFactor = UE_DEBUG_TABLE_IMAGE_INFO_SYM_SUBTRAHEND_FACTOR ( + DebugTable->ImageInfo + ); + SymOffsetSubtrahend = (UINT32)SymOffsetFactor * Context->SegmentAlignment; + } + + return UeLoaderGetImageAddress (Context) - SymOffsetSubtrahend; +} + +RETURN_STATUS +UeGetSegmentNames ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context, + OUT CONST UE_SEGMENT_NAME **SegmentNames + ) +{ + RETURN_STATUS Status; + CONST UE_DEBUG_TABLE *DebugTable; + + ASSERT (Context != NULL); + ASSERT (SegmentNames != NULL); + + Status = InternalGetDebugTable (Context, &DebugTable); + if (RETURN_ERROR (Status)) { + return Status; + } + + *SegmentNames = UE_DEBUG_TABLE_SEGMENT_NAMES (DebugTable); + + return RETURN_SUCCESS; +} + +UINT32 +UeGetEntryPointAddress ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + ASSERT (Context != NULL); + + return Context->EntryPointAddress; +} + +UINT16 +UeGetMachine ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + ASSERT (Context != NULL); + + return Context->Machine; +} + +UINT16 +UeGetSubsystem ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + ASSERT (Context != NULL); + + return Context->Subsystem; +} + +UINT32 +UeGetSegmentAlignment ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + ASSERT (Context != NULL); + + return Context->SegmentAlignment; +} + +UINT32 +UeGetImageSize ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + ASSERT (Context != NULL); + + return Context->ImageSize; +} + +UINT64 +UeGetBaseAddress ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + ASSERT (Context != NULL); + + return Context->BaseAddress; +} + +BOOLEAN +UeGetRelocsStripped ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + ASSERT (Context != NULL); + + return Context->RelocsStripped; +} + +BOOLEAN +UeGetFixedAddress( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + ASSERT (Context != NULL); + + return Context->FixedAddress; +} + +UINTN +UeLoaderGetImageAddress ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context + ) +{ + ASSERT (Context != NULL); + + return (UINTN) Context->ImageBuffer; +} + +UINT16 +UeGetSegments ( + IN CONST UE_LOADER_IMAGE_CONTEXT *Context, + OUT CONST UE_SEGMENT **Segments + ) +{ + ASSERT (Context != NULL); + ASSERT (Segments != NULL); + + *Segments = Context->Segments; + return (UINT16)Context->LastSegmentIndex + 1; +} + +UINT16 +UeGetSegmentImageInfos ( + IN OUT UE_LOADER_IMAGE_CONTEXT *Context, + OUT CONST UINT32 **SegmentImageInfos, + OUT UINT8 *SegmentImageInfoIterSize + ) +{ + ASSERT (Context != NULL); + ASSERT (SegmentImageInfos != NULL); + ASSERT (SegmentImageInfoIterSize != NULL); + + ASSERT (IS_ALIGNED (Context->SegmentImageInfoIterSize, ALIGNOF (UINT32))); + + *SegmentImageInfos = Context->Segments; + *SegmentImageInfoIterSize = Context->SegmentImageInfoIterSize; + return (UINT16)Context->LastSegmentIndex + 1; +} diff --git a/MdePkg/Library/BaseUefiImageLib/BaseUefiImageAllLib.inf b/MdePkg/Library/BaseUefiImageLib/BaseUefiImageAllLib.inf index 6ad64cb959..f0640bcd73 100644 --- a/MdePkg/Library/BaseUefiImageLib/BaseUefiImageAllLib.inf +++ b/MdePkg/Library/BaseUefiImageLib/BaseUefiImageAllLib.inf @@ -18,6 +18,7 @@ [Sources] CommonSupport.c ExecutionSupport.c + UeSupport.c PeSupport.c UefiImageLib.c @@ -32,6 +33,7 @@ DebugLib MemoryAllocationLib PeCoffLib2 + UeImageLib UefiImageExtraActionLib [FixedPcd] diff --git a/MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyFvLib.inf b/MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyFvLib.inf index cbdcc58644..f6f1801c6a 100644 --- a/MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyFvLib.inf +++ b/MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyFvLib.inf @@ -18,6 +18,7 @@ [Sources] CommonSupport.c ExecutionSupport.c + UeSupport.c PeSupport.c UefiImageLib.c @@ -32,6 +33,7 @@ DebugLib MemoryAllocationLib PeCoffLib2 + UeImageLib UefiImageExtraActionLib [FixedPcd] diff --git a/MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyNonFvLib.inf b/MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyNonFvLib.inf index 3c8f23e895..9ae93ed4aa 100644 --- a/MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyNonFvLib.inf +++ b/MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyNonFvLib.inf @@ -18,6 +18,7 @@ [Sources] CommonSupport.c ExecutionSupport.c + UeSupport.c PeSupport.c UefiImageLib.c @@ -32,14 +33,14 @@ DebugLib MemoryAllocationLib PeCoffLib2 + UeImageLib UefiImageExtraActionLib [FixedPcd] gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAlignmentPolicy gEfiMdePkgTokenSpaceGuid.PcdImageLoaderLoadHeader - gEfiMdePkgTokenSpaceGuid.PcdImageLoaderRemoveXForWX gEfiMdePkgTokenSpaceGuid.PcdDebugRaisePropertyMask - + gEfiMdePkgTokenSpaceGuid.PcdImageLoaderRemoveXForWX gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportNonFv gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv diff --git a/MdePkg/Library/BaseUefiImageLib/CommonSupport.c b/MdePkg/Library/BaseUefiImageLib/CommonSupport.c index 90124bc7cd..9355719ec2 100644 --- a/MdePkg/Library/BaseUefiImageLib/CommonSupport.c +++ b/MdePkg/Library/BaseUefiImageLib/CommonSupport.c @@ -92,11 +92,7 @@ UefiImageGetModuleNameFromSymbolsPath ( // the debug symbols for the Image. // StartIndex = 0; - for ( - Index = 0; - Index < SymbolsPathSize && SymbolsPath[Index] != '\0'; - ++Index - ) { + for (Index = 0; Index < SymbolsPathSize - 1; ++Index) { if (SymbolsPath[Index] == '\\' || SymbolsPath[Index] == '/') { StartIndex = Index + 1; } @@ -107,7 +103,7 @@ UefiImageGetModuleNameFromSymbolsPath ( // for ( Index = 0; - Index < MIN (ModuleNameSize, SymbolsPathSize); + Index < MIN (ModuleNameSize, SymbolsPathSize) - 1; ++Index ) { ModuleName[Index] = SymbolsPath[Index + StartIndex]; @@ -115,7 +111,7 @@ UefiImageGetModuleNameFromSymbolsPath ( ModuleName[Index] = '.'; } if (ModuleName[Index] == '.') { - if (Index > ModuleNameSize - 3) { + if (Index >= ModuleNameSize - 4) { break; } @@ -139,7 +135,7 @@ UefiImageDebugPrintImageRecord ( IN CONST UEFI_IMAGE_RECORD *ImageRecord ) { - UINT16 SegmentIndex; + UINT32 SegmentIndex; UINTN SegmentAddress; ASSERT (ImageRecord != NULL); diff --git a/MdePkg/Library/BaseUefiImageLib/UeSupport.c b/MdePkg/Library/BaseUefiImageLib/UeSupport.c new file mode 100644 index 0000000000..3e7c35d1ce --- /dev/null +++ b/MdePkg/Library/BaseUefiImageLib/UeSupport.c @@ -0,0 +1,560 @@ +/** @file + UEFI Image Loader library implementation for UE Images. + + Copyright (c) 2023, Marvin Häuser. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "UeSupport.h" + +STATIC CONST UINT16 mPeMachines[] = { + IMAGE_FILE_MACHINE_I386, + IMAGE_FILE_MACHINE_X64, + IMAGE_FILE_MACHINE_ARMTHUMB_MIXED, + IMAGE_FILE_MACHINE_ARM64, + IMAGE_FILE_MACHINE_RISCV32, + IMAGE_FILE_MACHINE_RISCV64, + IMAGE_FILE_MACHINE_RISCV128 +}; + +RETURN_STATUS +UefiImageInitializeContextPreHashUe ( + OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + IN CONST VOID *FileBuffer, + IN UINT32 FileSize + ) +{ + return UeInitializeContextPreHash (&Context->Ctx.Ue, FileBuffer, FileSize); +} + +RETURN_STATUS +UefiImageInitializeContextPostHashUe ( + OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + return UeInitializeContextPostHash (&Context->Ctx.Ue); +} + +BOOLEAN +UefiImageHashImageDefaultUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + IN OUT VOID *HashContext, + IN UEFI_IMAGE_LOADER_HASH_UPDATE HashUpdate + ) +{ + return UeHashImageDefault (&Context->Ctx.Ue, HashContext, HashUpdate); +} + +RETURN_STATUS +UefiImageLoadImageUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + OUT VOID *Destination, + IN UINT32 DestinationSize + ) +{ + return UeLoadImage (&Context->Ctx.Ue, Destination, DestinationSize); +} + +// +// In-place semantics are currently unsupported. +// + +// LCOV_EXCL_START +BOOLEAN +UefiImageImageIsInplaceUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + return FALSE; +} + +RETURN_STATUS +UefiImageLoadImageInplaceUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + ASSERT (Context != NULL); + + if (Context->Ctx.Ue.XIP) { + Context->Ctx.Ue.ImageBuffer = (UINT8 *) Context->Ctx.Ue.FileBuffer; + + return RETURN_SUCCESS; + } + + return RETURN_UNSUPPORTED; +} + +RETURN_STATUS +UefiImageRelocateImageInplaceUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + return RETURN_UNSUPPORTED; +} +// LCOV_EXCL_STOP + +RETURN_STATUS +UefiImageLoaderGetRuntimeContextSizeUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + OUT UINT32 *Size + ) +{ + return UeLoaderGetRuntimeContextSize (&Context->Ctx.Ue, Size); +} + +RETURN_STATUS +UefiImageRelocateImageUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + IN UINT64 BaseAddress, + OUT VOID *RuntimeContext OPTIONAL, + IN UINT32 RuntimeContextSize + ) +{ + return UeRelocateImage ( + &Context->Ctx.Ue, + BaseAddress, + (UE_LOADER_RUNTIME_CONTEXT *)RuntimeContext, + RuntimeContextSize + ); +} + +RETURN_STATUS +UefiImageRuntimeRelocateImageUe ( + IN OUT VOID *Image, + IN UINT32 ImageSize, + IN UINT64 BaseAddress, + IN CONST VOID *RuntimeContext + ) +{ + return UeRelocateImageForRuntime ( + Image, + ImageSize, + (UE_LOADER_RUNTIME_CONTEXT *)RuntimeContext, + BaseAddress + ); +} + +VOID +UefiImageDiscardSegmentsUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + // + // Anything discardable is not loaded in the first place. + // +} + +RETURN_STATUS +UefiImageGetSymbolsPathUe ( + IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + OUT CONST CHAR8 **SymbolsPath, + OUT UINT32 *SymbolsPathSize + ) +{ + return UeGetSymbolsPath (&Context->Ctx.Ue, SymbolsPath, SymbolsPathSize); +} + +// +// UE does not support embedded certificates (yet). +// + +// LCOV_EXCL_START +RETURN_STATUS +UefiImageGetFirstCertificateUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + OUT CONST WIN_CERTIFICATE **Certificate + ) +{ + return RETURN_UNSUPPORTED; +} + +RETURN_STATUS +UefiImageGetNextCertificateUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + IN OUT CONST WIN_CERTIFICATE **Certificate + ) +{ + return RETURN_UNSUPPORTED; +} + +RETURN_STATUS +UefiImageGetHiiDataRvaUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + OUT UINT32 *HiiRva, + OUT UINT32 *HiiSize + ) +{ + // + // UE does not support legacy HII. + // + return RETURN_NOT_FOUND; +} +// LCOV_EXCL_STOP + +UINT32 +UefiImageGetEntryPointAddressUe ( + IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + return UeGetEntryPointAddress (&Context->Ctx.Ue); +} + +UINT16 +UefiImageGetMachineUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + UINT16 UeMachine; + + UeMachine = UeGetMachine (&Context->Ctx.Ue); + if (UeMachine >= ARRAY_SIZE (mPeMachines)) { + DEBUG_RAISE (); + return 0xFFFF; + } + + return mPeMachines[UeMachine]; +} + +UINT16 +UefiImageGetSubsystemUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + return UeGetSubsystem (&Context->Ctx.Ue) + 10; +} + +UINT32 +UefiImageGetSegmentAlignmentUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + return UeGetSegmentAlignment (&Context->Ctx.Ue); +} + +UINT32 +UefiImageGetImageSizeUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + return UeGetImageSize (&Context->Ctx.Ue); +} + +UINT64 +UefiImageGetBaseAddressUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + return UeGetBaseAddress (&Context->Ctx.Ue); +} + +BOOLEAN +UefiImageGetRelocsStrippedUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + return UeGetRelocsStripped (&Context->Ctx.Ue); +} + +UINTN +UefiImageLoaderGetImageAddressUe ( + IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + return UeLoaderGetImageAddress (&Context->Ctx.Ue); +} + +UINTN +UefiImageLoaderGetDebugAddressUe ( + IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + return UeLoaderGetImageDebugAddress (&Context->Ctx.Ue); +} + +STATIC +UINT32 +InternalPermissionsToAttributes ( + IN UINT8 Permissions + ) +{ + switch (Permissions) { + case UeSegmentPermX: + { + return EFI_MEMORY_RP | EFI_MEMORY_RO; + } + + case UeSegmentPermRX: + { + return EFI_MEMORY_RO; + } + + case UeSegmentPermRW: + { + return EFI_MEMORY_XP; + } + + case UeSegmentPermR: + default: + { + ASSERT (Permissions == UeSegmentPermR); + return EFI_MEMORY_XP | EFI_MEMORY_RO; + } + } +} + +UEFI_IMAGE_RECORD * +UefiImageLoaderGetImageRecordUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + UEFI_IMAGE_RECORD *ImageRecord; + UINTN ImageAddress; + UINT32 ImageSize; + UINT32 ImageSizeRecord; + UINT32 NumRecordSegments; + UEFI_IMAGE_RECORD_SEGMENT *RecordSegment; + UINT16 NumSegments; + UINT8 SegmentIterSize; + CONST UINT32 *SegmentImageInfos; + CONST UINT8 *SegmentImageInfoPtr; + UINT32 SegmentImageInfo; + UINT32 SegmentSize; + UINT8 SegmentPermissions; + UINT32 RangeSize; + UINT8 Permissions; + + ASSERT (Context != NULL); + + NumSegments = UeGetSegmentImageInfos ( + &Context->Ctx.Ue, + &SegmentImageInfos, + &SegmentIterSize + ); + + ImageRecord = AllocatePool ( + sizeof (*ImageRecord) + + NumSegments * sizeof (*ImageRecord->Segments) + ); + if (ImageRecord == NULL) { + return NULL; + } + + ImageRecord->Signature = UEFI_IMAGE_RECORD_SIGNATURE; + InitializeListHead (&ImageRecord->Link); + + SegmentImageInfo = *SegmentImageInfos; + + RangeSize = UE_SEGMENT_SIZE (SegmentImageInfo); + Permissions = UE_SEGMENT_PERMISSIONS (SegmentImageInfo); + + ImageSizeRecord = RangeSize; + NumRecordSegments = 0; + + STATIC_ASSERT ( + OFFSET_OF (UE_SEGMENT, ImageInfo) == 0 && + OFFSET_OF (UE_SEGMENT, ImageInfo) == OFFSET_OF (UE_SEGMENT_XIP, ImageInfo), + "Below's logic assumes the given layout." + ); + + for ( + SegmentImageInfoPtr = (CONST UINT8 *) SegmentImageInfos + SegmentIterSize; + SegmentImageInfoPtr < (CONST UINT8 *) SegmentImageInfos + (UINT32) SegmentIterSize * NumSegments; + ImageSizeRecord += SegmentSize, + SegmentImageInfoPtr += SegmentIterSize + ) { + SegmentImageInfo = *(CONST UINT32 *) SegmentImageInfoPtr; + + SegmentSize = UE_SEGMENT_SIZE (SegmentImageInfo); + SegmentPermissions = UE_SEGMENT_PERMISSIONS (SegmentImageInfo); + // + // Skip Image segments with the same memory permissions as the current range + // as they can be merged. + // + if (SegmentPermissions == Permissions) { + RangeSize += SegmentSize; + continue; + } + // + // Create an Image record LoadTable for the current memory permission range. + // + RecordSegment = &ImageRecord->Segments[NumRecordSegments]; + RecordSegment->Size = RangeSize; + RecordSegment->Attributes = InternalPermissionsToAttributes (Permissions); + ++NumRecordSegments; + // + // Start a Image record LoadTable with the current Image LoadTable. + // + RangeSize = SegmentSize; + Permissions = SegmentPermissions; + } + // + // Create an Image record LoadTable for the current memory permission range. + // + RecordSegment = &ImageRecord->Segments[NumRecordSegments]; + RecordSegment->Size = RangeSize; + RecordSegment->Attributes = InternalPermissionsToAttributes (Permissions); + ++NumRecordSegments; + + ImageAddress = UeLoaderGetImageAddress (&Context->Ctx.Ue); + ImageSize = UeGetImageSize (&Context->Ctx.Ue); + ASSERT (ImageSize == ImageSizeRecord); + + ImageRecord->NumSegments = NumRecordSegments; + ImageRecord->StartAddress = ImageAddress; + ImageRecord->EndAddress = ImageAddress + ImageSize; + // + // Zero the remaining array entries to avoid uninitialised data. + // + ZeroMem ( + ImageRecord->Segments + NumRecordSegments, + (NumSegments - NumRecordSegments) * sizeof (*ImageRecord->Segments) + ); + + return ImageRecord; +} + +// LCOV_EXCL_START +RETURN_STATUS +UefiImageDebugLocateImageUe ( + OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + IN UINTN Address + ) +{ + ASSERT (Context != NULL); + (VOID) Address; + // + // UE does not support this feature. + // + return RETURN_NOT_FOUND; +} +// LCOV_EXCL_STOP + +RETURN_STATUS +UefiImageGetFixedAddressUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + OUT UINT64 *Address + ) +{ + BOOLEAN FixedAddress; + + ASSERT (Context != NULL); + ASSERT (Address != NULL); + + FixedAddress = UeGetFixedAddress (&Context->Ctx.Ue); + if (!FixedAddress) { + return RETURN_NOT_FOUND; + } + + *Address = Context->Ctx.Ue.BaseAddress; + return RETURN_SUCCESS; +} + +VOID +UefiImageDebugPrintSegmentsUe ( + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + RETURN_STATUS Status; + CONST CHAR8 *Name; + CONST UE_SEGMENT *Segments; + UINT16 NumSegments; + UINT16 SegmentIndex; + UINT32 SegmentFileOffset; + UINT32 SegmentImageAddress; + CONST UE_SEGMENT_NAME *NameTable; + UINT32 ImageSize; + + NumSegments = UeGetSegments (&Context->Ctx.Ue, &Segments); + + Status = UeGetSegmentNames (&Context->Ctx.Ue, &NameTable); + if (RETURN_ERROR (Status)) { + NameTable = NULL; + } + + SegmentFileOffset = Context->Ctx.Ue.SegmentsFileOffset; + // + // The first Image segment must begin the Image memory space. + // + SegmentImageAddress = 0; + + for (SegmentIndex = 0; SegmentIndex < NumSegments; ++SegmentIndex) { + if (NameTable != NULL) { + Name = (CONST CHAR8 *)NameTable[SegmentIndex]; + } else { + STATIC_ASSERT ( + sizeof (*NameTable) == sizeof ("Unknown"), + "The following may cause prohibited memory accesses." + ); + + Name = "Unknown"; + } + + ImageSize = UE_SEGMENT_SIZE (Segments[SegmentIndex].ImageInfo); + + DEBUG (( + DEBUG_VERBOSE, + " Segment - '%c%c%c%c%c%c%c%c'\n" + " ImageAddress - 0x%08x\n" + " ImageSize - 0x%08x\n" + " FileOffset - 0x%08x\n" + " FileSize - 0x%08x\n" + " Permissions - 0x%08x\n", + Name[0], Name[1], Name[2], Name[3], Name[4], Name[5], Name[6], Name[7], + SegmentImageAddress, + ImageSize, + SegmentFileOffset, + Segments[SegmentIndex].FileSize, + UE_SEGMENT_PERMISSIONS (Segments[SegmentIndex].ImageInfo) + )); + + SegmentImageAddress += ImageSize; + SegmentFileOffset += Segments[SegmentIndex].FileSize; + } +} + +GLOBAL_REMOVE_IF_UNREFERENCED CONST UEFI_IMAGE_FORMAT_SUPPORT mUeSupport = { + UefiImageInitializeContextPreHashUe, + UefiImageHashImageDefaultUe, + UefiImageInitializeContextPostHashUe, + UefiImageLoadImageUe, + UefiImageImageIsInplaceUe, + UefiImageLoadImageInplaceUe, + UefiImageRelocateImageInplaceUe, + UefiImageLoaderGetRuntimeContextSizeUe, + UefiImageRelocateImageUe, + UefiImageRuntimeRelocateImageUe, + UefiImageDiscardSegmentsUe, + UefiImageGetSymbolsPathUe, + UefiImageGetFirstCertificateUe, + UefiImageGetNextCertificateUe, + UefiImageGetHiiDataRvaUe, + UefiImageGetEntryPointAddressUe, + UefiImageGetMachineUe, + UefiImageGetSubsystemUe, + UefiImageGetSegmentAlignmentUe, + UefiImageGetImageSizeUe, + UefiImageGetBaseAddressUe, + UefiImageGetRelocsStrippedUe, + UefiImageLoaderGetImageAddressUe, + UefiImageLoaderGetDebugAddressUe, + UefiImageLoaderGetImageRecordUe, + UefiImageDebugLocateImageUe, + UefiImageGetFixedAddressUe, + UefiImageDebugPrintSegmentsUe +}; diff --git a/MdePkg/Library/BaseUefiImageLib/UeSupport.h b/MdePkg/Library/BaseUefiImageLib/UeSupport.h new file mode 100644 index 0000000000..e62052ebe1 --- /dev/null +++ b/MdePkg/Library/BaseUefiImageLib/UeSupport.h @@ -0,0 +1,16 @@ +/** @file + UEFI Image Loader library implementation for UE Images. + + Copyright (c) 2023, Marvin Häuser. All rights reserved.
+ + SPDX-License-Identifier: BSD-3-Clause +**/ + +#ifndef UE_SUPPORT_H +#define UE_SUPPORT_H + +#include "UefiImageFormat.h" + +extern CONST UEFI_IMAGE_FORMAT_SUPPORT mUeSupport; + +#endif // UE_SUPPORT_H diff --git a/MdePkg/Library/BaseUefiImageLib/UefiImageLib.c b/MdePkg/Library/BaseUefiImageLib/UefiImageLib.c index 18d323f585..9739e50b29 100644 --- a/MdePkg/Library/BaseUefiImageLib/UefiImageLib.c +++ b/MdePkg/Library/BaseUefiImageLib/UefiImageLib.c @@ -20,6 +20,7 @@ #include #include +#include "UeSupport.h" #include "PeSupport.h" STATIC_ASSERT ( @@ -39,34 +40,50 @@ STATIC_ASSERT ( #define UEFI_IMAGE_FORMAT_SUPPORT_FV 0 #endif -#define UEFI_IMAGE_SUPPORT \ +#define UEFI_IMAGE_FORMAT_SUPPORT \ (UEFI_IMAGE_FORMAT_SUPPORT_NON_FV | UEFI_IMAGE_FORMAT_SUPPORT_FV) -#define FORMAT_EQ(FormatIndex, Format) \ - (UEFI_IMAGE_SUPPORT == (1U << (Format)) || \ - ((UEFI_IMAGE_SUPPORT & (1U << (Format))) != 0 && \ +#define FORMAT_EQ(FormatIndex, Format) \ + (UEFI_IMAGE_FORMAT_SUPPORT == (1U << (Format)) || \ + ((UEFI_IMAGE_FORMAT_SUPPORT & (1U << (Format))) != 0 && \ (FormatIndex) == (Format))) #define UEFI_IMAGE_EXEC(Result, FormatIndex, Func, ...) \ do { \ - ASSERT ((FormatIndex) == UefiImageFormatPe); \ - Result = mPeSupport.Func (__VA_ARGS__); \ + if (FORMAT_EQ ((FormatIndex), UefiImageFormatUe)) { \ + ASSERT ((FormatIndex) == UefiImageFormatUe); \ + Result = mUeSupport.Func (__VA_ARGS__); \ + } else { \ + ASSERT ((FormatIndex) == UefiImageFormatPe); \ + Result = mPeSupport.Func (__VA_ARGS__); \ + } \ } while (FALSE) -#define UEFI_IMAGE_EXEC_VOID(FormatIndex, Func, ...) \ - do { \ - ASSERT ((FormatIndex) == UefiImageFormatPe); \ - mPeSupport.Func (__VA_ARGS__); \ +#define UEFI_IMAGE_EXEC_VOID(FormatIndex, Func, ...) \ + do { \ + if (FORMAT_EQ ((FormatIndex), UefiImageFormatUe)) { \ + ASSERT ((FormatIndex) == UefiImageFormatUe); \ + mUeSupport.Func (__VA_ARGS__); \ + } else { \ + ASSERT ((FormatIndex) == UefiImageFormatPe); \ + mPeSupport.Func (__VA_ARGS__); \ + } \ } while (FALSE) STATIC_ASSERT ( - UefiImageFormatPe == UefiImageFormatMax - 1, + UefiImageFormatMax == 2, "Support for more formats needs to be added above." ); -#define FORMAT_SUPPORTED(Format, Source) \ - ((UEFI_IMAGE_SUPPORT & (1U << (Format))) != 0 && \ - (mUefiImageSupportSource[Source] & (1U << (Format))) != 0) +#define FORMAT_SUPPORTED(Format, Source) \ + ((UEFI_IMAGE_FORMAT_SUPPORT & (1U << (Format))) != 0 && \ + (((Source) == UEFI_IMAGE_SOURCE_NON_FV && (UEFI_IMAGE_FORMAT_SUPPORT_NON_FV & (1U << (Format))) != 0) || \ + ((Source) == UEFI_IMAGE_SOURCE_FV && (UEFI_IMAGE_FORMAT_SUPPORT_FV & (1U << (Format))) != 0))) + +STATIC_ASSERT ( + UEFI_IMAGE_SOURCE_MAX == 3, + "Support for more sources needs to be added above." + ); STATIC RETURN_STATUS @@ -99,12 +116,6 @@ UefiImageInitializeContextPreHash ( IN UEFI_IMAGE_SOURCE Source ) { - CONST UINT8 mUefiImageSupportSource[UEFI_IMAGE_SOURCE_MAX] = { - UEFI_IMAGE_FORMAT_SUPPORT_NON_FV, - UEFI_IMAGE_FORMAT_SUPPORT_FV, - UEFI_IMAGE_SUPPORT - }; - RETURN_STATUS Status; #if (UEFI_IMAGE_FORMAT_SUPPORT_SOURCES & (1U << UEFI_IMAGE_SOURCE_NON_FV)) != 0 @@ -124,11 +135,23 @@ UefiImageInitializeContextPreHash ( Status = RETURN_UNSUPPORTED; STATIC_ASSERT ( - UefiImageFormatPe == UefiImageFormatMax - 1, + UefiImageFormatUe == UefiImageFormatMax - 1, "Support for more formats needs to be added above." ); - if (FORMAT_SUPPORTED (UefiImageFormatPe, Source)) { + if (FORMAT_SUPPORTED (UefiImageFormatUe, Source)) { + Status = InternalInitializeContextPreHash ( + Context, + FileBuffer, + FileSize, + UefiImageFormatUe + ); + if (!RETURN_ERROR (Status)) { + Context->FormatIndex = UefiImageFormatUe; + } + } + + if (RETURN_ERROR (Status) && FORMAT_SUPPORTED (UefiImageFormatPe, Source)) { Status = InternalInitializeContextPreHash ( Context, FileBuffer, @@ -137,7 +160,6 @@ UefiImageInitializeContextPreHash ( ); if (!RETURN_ERROR (Status)) { Context->FormatIndex = UefiImageFormatPe; - return RETURN_SUCCESS; } } diff --git a/MdePkg/MdeLibs.dsc.inc b/MdePkg/MdeLibs.dsc.inc index e60c02d2eb..657df0d992 100644 --- a/MdePkg/MdeLibs.dsc.inc +++ b/MdePkg/MdeLibs.dsc.inc @@ -50,6 +50,7 @@ UefiImageOnlyNonFvLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyNonFvLib.inf UefiImageOnlyFvLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyFvLib.inf UefiImageAllLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageAllLib.inf + UeImageLib|MdePkg/Library/BaseUeImageLib/BaseUeImageLib.inf [LibraryClasses.common.USER_DEFINED, LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM, LibraryClasses.common.SMM_CORE, LibraryClasses.common.MM_CORE_STANDALONE, LibraryClasses.common.DXE_SMM_DRIVER, LibraryClasses.common.MM_STANDALONE] UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyFvLib.inf diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index fa30ec88a1..9b686113f9 100644 --- a/MdePkg/MdePkg.dec +++ b/MdePkg/MdePkg.dec @@ -960,6 +960,7 @@ ## Include/Ppi/LoadFile.h gEfiPeiLoadFilePpiGuid = { 0xb9e0abfe, 0x5979, 0x4914, { 0x97, 0x7f, 0x6d, 0xee, 0x78, 0xc2, 0x78, 0xa6 } } + gEfiPeiLoadFileWithHobPpiGuid = { 0x14c2d0d0, 0xccfd, 0x40e5, { 0xae, 0xa7, 0x57, 0x23, 0x58, 0xdd, 0xbf, 0xe8 } } ## Include/Ppi/Decompress.h gEfiPeiDecompressPpiGuid = { 0x1a36e4e7, 0xfab6, 0x476a, { 0x8e, 0x75, 0x69, 0x5a, 0x5, 0x76, 0xfd, 0xd7 } } @@ -2311,13 +2312,21 @@ # @Prompt Remove X permission from WX sections. gEfiMdePkgTokenSpaceGuid.PcdImageLoaderRemoveXForWX|FALSE|BOOLEAN|0x40001021 - ## Indicates the UEFI image file formats supported outside FVs.

+ ## Indicates the UEFI image file formats supported outside FVs. + # UE is experimental and not enabled by default. + # For correct usage in a platform which opts in to UE support, this should + # be overridden globally, not within individual modules.

# BIT0 - PE.
+ # BIT1 - UE.
# @Prompt Supported UEFI image file formats outside FVs. gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportNonFv|0x01|UINT8|0x40002000 - ## Indicates the UEFI image file formats supported inside FVs.

+ ## Indicates the UEFI image file formats supported inside FVs. + # UE is experimental and not enabled by default. + # For correct usage in a platform which opts in to UE support, this should + # be overridden globally, not within individual modules.

# BIT0 - PE.
+ # BIT1 - UE.
# @Prompt Supported UEFI image file formats inside FVs. gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv|0x01|UINT8|0x40002001 diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc index 9762821824..2e792d24b2 100644 --- a/MdePkg/MdePkg.dsc +++ b/MdePkg/MdePkg.dsc @@ -58,6 +58,7 @@ MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.inf MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf MdePkg/Library/BaseArmTrngLibNull/BaseArmTrngLibNull.inf + MdePkg/Library/BaseUeImageLib/BaseUeImageLib.inf MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyNonFvLib.inf MdePkg/Library/BaseUefiImageLib/BaseUefiImageOnlyFvLib.inf diff --git a/OvmfPkg/Include/Fdf/OvmfPkgDefines.fdf.inc b/OvmfPkg/Include/Fdf/OvmfPkgDefines.fdf.inc index a933961464..0c3e551d1f 100644 --- a/OvmfPkg/Include/Fdf/OvmfPkgDefines.fdf.inc +++ b/OvmfPkg/Include/Fdf/OvmfPkgDefines.fdf.inc @@ -62,9 +62,9 @@ DEFINE FW_BLOCKS = 0x400 DEFINE CODE_BASE_ADDRESS = 0xFFC84000 DEFINE CODE_SIZE = 0x0037C000 DEFINE CODE_BLOCKS = 0x37C -DEFINE FVMAIN_SIZE = 0x00345000 -DEFINE SECFV_OFFSET = 0x003C9000 -DEFINE SECFV_SIZE = 0x37000 +DEFINE FVMAIN_SIZE = 0x00342000 +DEFINE SECFV_OFFSET = 0x003C6000 +DEFINE SECFV_SIZE = 0x3a000 !endif SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress = $(FW_BASE_ADDRESS) diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.dsc b/OvmfPkg/IntelTdx/IntelTdxX64.dsc index ac01770284..222d55fba3 100644 --- a/OvmfPkg/IntelTdx/IntelTdxX64.dsc +++ b/OvmfPkg/IntelTdx/IntelTdxX64.dsc @@ -485,6 +485,11 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF45 !endif + # + # Firmware volume is PE. + # + gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv|0x01 + ################################################################################ # # Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 51be9a5959..9217de7026 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -168,6 +168,7 @@ gEfiNonCcFvGuid = {0xae047c6d, 0xbce9, 0x426c, {0xae, 0x03, 0xa6, 0x8e, 0x3b, 0x8a, 0x04, 0x88}} gOvmfVariableGuid = {0x50bea1e5, 0xa2c5, 0x46e9, {0x9b, 0x3a, 0x59, 0x59, 0x65, 0x16, 0xb0, 0x0a}} gQemuFirmwareResourceHobGuid = {0x3cc47b04, 0x0d3e, 0xaa64, {0x06, 0xa6, 0x4b, 0xdc, 0x9a, 0x2c, 0x61, 0x19}} + gUefiImageLoaderImageContextGuid = {0x05cc29cc, 0xfbdf, 0x4cc8, {0x98, 0x25, 0x71, 0x76, 0x08, 0x5b, 0x05, 0x01}} [Ppis] # PPI whose presence in the PPI database signals that the TPM base address diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index fdd28d5716..c2afa6c116 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -593,6 +593,11 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x0 !endif + # + # Firmware volume supports UE, and may require PE. + # + gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv|0x03 + ################################################################################ # # Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf index cb96b13eb8..c066cb1e63 100644 --- a/OvmfPkg/OvmfPkgIa32.fdf +++ b/OvmfPkg/OvmfPkgIa32.fdf @@ -402,57 +402,57 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { [Rule.Common.SEC] FILE SEC = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING ="$(MODULE_NAME)" Optional VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.PEI_CORE] FILE PEI_CORE = $(NAMED_GUID) { - PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING ="$(MODULE_NAME)" Optional VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.PEIM] FILE PEIM = $(NAMED_GUID) { - PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.DXE_CORE] FILE DXE_CORE = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.DXE_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - RAW ACPI Optional |.acpi - RAW ASL Optional |.aml + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml } [Rule.Common.DXE_RUNTIME_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.UEFI_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.UEFI_DRIVER.BINARY] @@ -465,14 +465,14 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { [Rule.Common.UEFI_APPLICATION] FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.UEFI_APPLICATION.BINARY] FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 |.efi + UE UE |.efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } @@ -484,15 +484,15 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { [Rule.Common.SMM_CORE] FILE SMM_CORE = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.DXE_SMM_DRIVER] FILE SMM = $(NAMED_GUID) { - SMM_DEPEX SMM_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + SMM_DEPEX SMM_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index eaa2d2d794..b8e895d04f 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -564,6 +564,11 @@ gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask|0x1 gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x00000003 + # + # Firmware volume supports UE, and may require PE. + # + gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv|0x03 + [PcdsFixedAtBuild.IA32] # # The NumberOfPages values below are ad-hoc. They are updated sporadically at diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf index 5dc2a69fba..1c093f8ddf 100644 --- a/OvmfPkg/OvmfPkgIa32X64.fdf +++ b/OvmfPkg/OvmfPkgIa32X64.fdf @@ -305,7 +305,7 @@ INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf # !if $(E1000_ENABLE) FILE DRIVER = 5D695E11-9B3F-4b83-B25F-4A8D5D69BE07 { - SECTION PE32 = Intel3.5/EFIX64/E3522X2.EFI + SECTION UE = Intel3.5/EFIX64/E3522X2.EFI } !endif !include NetworkPkg/Network.fdf.inc @@ -405,57 +405,57 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { [Rule.Common.SEC] FILE SEC = $(NAMED_GUID) { - PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING ="$(MODULE_NAME)" Optional VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.PEI_CORE] FILE PEI_CORE = $(NAMED_GUID) { - PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING ="$(MODULE_NAME)" Optional VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.PEIM] FILE PEIM = $(NAMED_GUID) { - PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.DXE_CORE] FILE DXE_CORE = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.DXE_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - RAW ACPI Optional |.acpi - RAW ASL Optional |.aml + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml } [Rule.Common.DXE_RUNTIME_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.UEFI_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.UEFI_DRIVER.BINARY] @@ -468,14 +468,14 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { [Rule.Common.UEFI_APPLICATION] FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.UEFI_APPLICATION.BINARY] FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 |.efi + UE UE |.efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } @@ -487,15 +487,15 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { [Rule.Common.SMM_CORE] FILE SMM_CORE = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.DXE_SMM_DRIVER] FILE SMM = $(NAMED_GUID) { - SMM_DEPEX SMM_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + SMM_DEPEX SMM_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index b54445abd2..62c227b792 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -619,6 +619,11 @@ gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|TRUE !endif + # + # Firmware volume supports UE, and may require PE. + # + gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv|0x03 + ################################################################################ # # Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index 7247798034..f5da94c67f 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -336,7 +336,7 @@ INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf # !if $(E1000_ENABLE) FILE DRIVER = 5D695E11-9B3F-4b83-B25F-4A8D5D69BE07 { - SECTION PE32 = Intel3.5/EFIX64/E3522X2.EFI + SECTION UE = Intel3.5/EFIX64/E3522X2.EFI } !endif !include NetworkPkg/Network.fdf.inc @@ -443,57 +443,57 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { [Rule.Common.SEC] FILE SEC = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING ="$(MODULE_NAME)" Optional VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.PEI_CORE] FILE PEI_CORE = $(NAMED_GUID) { - PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING ="$(MODULE_NAME)" Optional VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.PEIM] FILE PEIM = $(NAMED_GUID) { - PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.DXE_CORE] FILE DXE_CORE = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.DXE_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - RAW ACPI Optional |.acpi - RAW ASL Optional |.aml + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml } [Rule.Common.DXE_RUNTIME_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.UEFI_DRIVER] FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.UEFI_DRIVER.BINARY] @@ -506,14 +506,14 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { [Rule.Common.UEFI_APPLICATION] FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.UEFI_APPLICATION.BINARY] FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 |.efi + UE UE |.efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } @@ -525,15 +525,15 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { [Rule.Common.SMM_CORE] FILE SMM_CORE = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.DXE_SMM_DRIVER] FILE SMM = $(NAMED_GUID) { - SMM_DEPEX SMM_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + SMM_DEPEX SMM_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } diff --git a/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm b/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm index c65f5497e6..c1ab35e968 100644 --- a/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm +++ b/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm @@ -150,10 +150,20 @@ getEntryPointOfFfsFileLoopForSections: jmp getEntryPointOfFfsFileLoopForSections getEntryPointOfFfsFileFoundPe32Section: - add eax, 4 ; EAX = Start of PE32 image + add eax, 4 ; EAX = Start of PE or UE image cmp word [eax], 'MZ' + je getEntryPointOfFfsFileFoundPeFile + + cmp word [eax], 'UE' jne getEntryPointOfFfsFileErrorReturn + + ; *EntryPoint = (VOID *)((UINTN)UeData + UeHdr.EntryPointAddress) + mov ebx, dword [eax + 0x4] + add eax, ebx + jmp getEntryPointOfFfsFileReturn + +getEntryPointOfFfsFileFoundPeFile: movzx ebx, word [eax + 0x3c] add ebx, eax @@ -171,4 +181,3 @@ getEntryPointOfFfsFileErrorReturn: getEntryPointOfFfsFileReturn: OneTimeCallRet GetEntryPointOfFfsFile - diff --git a/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c b/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c index ea8599aa4d..1f6abec34b 100644 --- a/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c +++ b/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c @@ -28,13 +28,13 @@ LoadUefiImage ( OUT EFI_PHYSICAL_ADDRESS *EntryPoint ) { - RETURN_STATUS Status; - UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext; - UINT32 ImageSize; - UINT32 ImageAlignment; - UINT32 BufferPages; - UINT32 BufferSize; - VOID *Buffer; + RETURN_STATUS Status; + UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext; + UINT32 ImageSize; + UINT32 ImageAlignment; + UINT32 BufferPages; + UINT32 BufferSize; + VOID *Buffer; Status = UefiImageInitializeContext ( &ImageContext, diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index 48713a3a65..feb5a8192e 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -508,6 +508,11 @@ !endif !endif + # + # Firmware volume supports UE, and may require PE. + # + gEfiMdePkgTokenSpaceGuid.PcdUefiImageFormatSupportFv|0x03 + [PcdsPatchableInModule.X64] !if $(NETWORK_DRIVER_ENABLE) == TRUE gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections|TRUE diff --git a/UefiPayloadPkg/UefiPayloadPkg.fdf b/UefiPayloadPkg/UefiPayloadPkg.fdf index f5af3b7771..db07c3296b 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.fdf +++ b/UefiPayloadPkg/UefiPayloadPkg.fdf @@ -372,7 +372,7 @@ INF ShellPkg/Application/Shell/Shell.inf [Rule.Common.DXE_DRIVER] FILE DRIVER = $(NAMED_GUID) { DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } @@ -380,21 +380,21 @@ INF ShellPkg/Application/Shell/Shell.inf [Rule.Common.DXE_RUNTIME_DRIVER] FILE DRIVER = $(NAMED_GUID) { DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.DXE_SMM_DRIVER] FILE SMM = $(NAMED_GUID) { SMM_DEPEX SMM_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.SMM_CORE] FILE SMM_CORE = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } @@ -402,7 +402,7 @@ INF ShellPkg/Application/Shell/Shell.inf [Rule.Common.UEFI_DRIVER] FILE DRIVER = $(NAMED_GUID) { DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } @@ -410,21 +410,21 @@ INF ShellPkg/Application/Shell/Shell.inf [Rule.Common.UEFI_DRIVER.BINARY] FILE DRIVER = $(NAMED_GUID) { DXE_DEPEX DXE_DEPEX Optional |.depex - PE32 PE32 |.efi + UE UE |.efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.UEFI_APPLICATION] FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } [Rule.Common.UEFI_APPLICATION.BINARY] FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 |.efi + UE UE |.efi UI STRING="$(MODULE_NAME)" Optional VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) } @@ -447,7 +447,7 @@ INF ShellPkg/Application/Shell/Shell.inf [Rule.Common.UEFI_APPLICATION.UI] FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING="Enter Setup" VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) }