From ba9aad0b56f2804d9ce3b49419e3119fc1937a08 Mon Sep 17 00:00:00 2001 From: Mikhail Krichanov Date: Fri, 15 Dec 2023 16:28:15 +0300 Subject: [PATCH] ImageTool: Rework PeEmit with dynamically-growing buffers --- BaseTools/Conf/build_rule.template | 10 +- BaseTools/ImageTool/BinEmit.c | 17 +- BaseTools/ImageTool/DynamicBuffer.c | 215 +++ BaseTools/ImageTool/DynamicBuffer.h | 74 + BaseTools/ImageTool/ElfScan.c | 30 +- BaseTools/ImageTool/GNUmakefile | 2 +- BaseTools/ImageTool/Image.c | 375 +++-- BaseTools/ImageTool/ImageTool.c | 56 +- BaseTools/ImageTool/ImageTool.h | 31 +- BaseTools/ImageTool/ImageToolEmit.c | 21 +- BaseTools/ImageTool/ImageToolEmit.h | 1 + BaseTools/ImageTool/Makefile | 2 +- BaseTools/ImageTool/PeEmit.c | 1366 ++++++----------- BaseTools/ImageTool/PeEmitCommon.c | 5 +- BaseTools/ImageTool/PeEmitCommon.h | 6 +- BaseTools/ImageTool/PeScan.c | 159 +- BaseTools/ImageTool/PeScan.h | 4 +- BaseTools/ImageTool/UefiImageScan.c | 90 +- BaseTools/Source/C/Common/GNUmakefile | 1 + BaseTools/Source/C/Common/Makefile | 1 + BaseTools/Source/C/GenFv/GenFvInternalLib.c | 1 + BaseTools/Source/C/VolInfo/VolInfo.c | 1 + BaseTools/Source/Python/GenFds/DataSection.py | 1 + BaseTools/Source/Python/GenFds/EfiSection.py | 1 + .../Source/Python/GenFds/FfsInfStatement.py | 2 + .../Python/GenFds/GenFdsGlobalVariable.py | 4 +- BaseTools/Source/Python/build/BuildReport.py | 2 +- BaseTools/Source/Python/build/build.py | 8 +- MdePkg/Library/BaseUefiImageLib/PeSupport.c | 8 +- .../BaseUefiImageLib/UefiImageFormat.h | 8 +- .../Library/BaseUefiImageLib/UefiImageLib.c | 14 +- 31 files changed, 1246 insertions(+), 1270 deletions(-) create mode 100644 BaseTools/ImageTool/DynamicBuffer.c create mode 100644 BaseTools/ImageTool/DynamicBuffer.h diff --git a/BaseTools/Conf/build_rule.template b/BaseTools/Conf/build_rule.template index a218dad9d8..37e14708e5 100755 --- a/BaseTools/Conf/build_rule.template +++ b/BaseTools/Conf/build_rule.template @@ -134,8 +134,8 @@ "$(CC)" $(DEPS_FLAGS) $(CC_FLAGS) -o ${dst} $(INC) ${src} -## Early stages on ARM/AArch64 execute with strict alignment enabled and will crash, -# when compiler generates misaligned access. +## Early stages on ARM/AArch64 execute with strict alignment enabled and will crash, +# when compiler generates misaligned access. # [C-Code-File.BASE.AARCH64,C-Code-File.SEC.AARCH64,C-Code-File.PEI_CORE.AARCH64,C-Code-File.PEIM.AARCH64,C-Code-File.BASE.ARM,C-Code-File.SEC.ARM,C-Code-File.PEI_CORE.ARM,C-Code-File.PEIM.ARM] @@ -382,7 +382,7 @@ $(OUTPUT_DIR)(+)$(MODULE_NAME).map - ImageTool GenImage -c PE -t $(MODULE_TYPE) -o ${dst} ${src} + ImageTool GenImage -c PE -x -t $(MODULE_TYPE) -o ${dst} ${src} $(CP) ${dst} $(DEBUG_DIR) $(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi -$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR) @@ -392,7 +392,7 @@ $(CP) ${src} $(DEBUG_DIR)(+)$(MODULE_NAME).strip $(OBJCOPY) $(OBJCOPY_STRIPFLAG) $(DEBUG_DIR)(+)$(MODULE_NAME).strip - ImageTool GenImage -c PE -t $(MODULE_TYPE) -o ${dst} $(DEBUG_DIR)(+)$(MODULE_NAME).strip + ImageTool GenImage -c PE -x -t $(MODULE_TYPE) -d ${src} -o ${dst} $(DEBUG_DIR)(+)$(MODULE_NAME).strip $(CP) ${dst} $(DEBUG_DIR) $(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi @@ -403,7 +403,7 @@ "$(MTOC)" -subsystem $(MODULE_TYPE) $(MTOC_FLAGS) ${src} $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff # create symbol file for GDB debug -$(DSYMUTIL) ${src} - ImageTool GenImage -c PE -t $(MODULE_TYPE) -o ${dst} $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff + ImageTool GenImage -c PE -x -t $(MODULE_TYPE) -o ${dst} $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff $(CP) ${dst} $(DEBUG_DIR) $(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi -$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR) diff --git a/BaseTools/ImageTool/BinEmit.c b/BaseTools/ImageTool/BinEmit.c index 828c357a7a..ed459f0caf 100644 --- a/BaseTools/ImageTool/BinEmit.c +++ b/BaseTools/ImageTool/BinEmit.c @@ -19,9 +19,6 @@ CreateEntry ( EFI_IMAGE_RESOURCE_DIRECTORY *RDir; EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *Entry; - assert (HiiSectionHeader != NULL); - assert (HiiSectionOffset != NULL); - RDir = (EFI_IMAGE_RESOURCE_DIRECTORY *)(HiiSectionHeader + *HiiSectionOffset); *HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY); RDir->NumberOfNamedEntries = 1; @@ -49,11 +46,6 @@ CreateStringEntry ( { EFI_IMAGE_RESOURCE_DIRECTORY_STRING *RDStr; - assert (Entry != NULL); - assert (HiiSectionHeader != NULL); - assert (HiiSectionOffset != NULL); - assert (String != NULL); - Entry->u1.s.NameOffset = *HiiSectionOffset; RDStr = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *)(HiiSectionHeader + *HiiSectionOffset); RDStr->Length = (UINT16)StrLen (String); @@ -78,8 +70,6 @@ InitializeHiiResouceSectionHeader ( EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *LangRDirEntry; EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry; - assert (HiiSectionHeader != NULL); - HiiSectionOffset = 0; // // Create Type, Name, Language entries @@ -123,10 +113,6 @@ ConstructHii ( UINT32 FileSize; UINT8 NumberOfFormPackages; - assert (Hii != NULL); - assert (HiiGuid != NULL); - assert (FileNames != NULL); - NumberOfFormPackages = 0; EndPackage.Length = sizeof (EFI_HII_PACKAGE_HEADER); @@ -173,7 +159,7 @@ ConstructHii ( CopyGuid (&HiiPackageListHeader.PackageListGuid, HiiGuid); - HiiPackageData = calloc (1, HiiPackageListHeader.PackageLength); + HiiPackageData = AllocateZeroPool (HiiPackageListHeader.PackageLength); if (HiiPackageData == NULL) { return RETURN_OUT_OF_RESOURCES; } @@ -185,6 +171,7 @@ ConstructHii ( File = UserReadFile (FileNames[Index], &FileSize); if (File == NULL) { fprintf (stderr, "ImageTool: Could not open %s: %s\n", FileNames[Index], strerror (errno)); + free (HiiPackageData); return RETURN_ABORTED; } diff --git a/BaseTools/ImageTool/DynamicBuffer.c b/BaseTools/ImageTool/DynamicBuffer.c new file mode 100644 index 0000000000..71ae192737 --- /dev/null +++ b/BaseTools/ImageTool/DynamicBuffer.c @@ -0,0 +1,215 @@ +#include +#include +#include +#include + +#include + +#include + +#include "ImageTool.h" +#include "DynamicBuffer.h" + +#define IMAGE_TOOL_DYNAMIC_BUFFER_GROWTH 0x1000 + +void +ImageToolBufferInit ( + image_tool_dynamic_buffer *Buffer + ) +{ + memset (Buffer, 0, sizeof (*Buffer)); +} + +static +uint32_t +ImageToolBufferExpand ( + image_tool_dynamic_buffer *Buffer, + uint32_t Size + ) +{ + bool Overflow; + uint32_t NewAllocatedSize; + uint8_t *NewMemory; + uint32_t Offset; + + assert (Buffer->DataSize <= Buffer->AllocatedSize); + assert (IS_ALIGNED (Buffer->AllocatedSize, IMAGE_TOOL_DYNAMIC_BUFFER_GROWTH)); + + if (Buffer->AllocatedSize - Buffer->DataSize < Size) { + Overflow = BaseOverflowAlignUpU32 ( + Size, + IMAGE_TOOL_DYNAMIC_BUFFER_GROWTH, + &NewAllocatedSize + ); + if (Overflow) { + DEBUG_RAISE (); + return MAX_UINT32; + } + + Overflow = BaseOverflowAddU32 ( + NewAllocatedSize, + Buffer->AllocatedSize, + &NewAllocatedSize + ); + if (Overflow) { + DEBUG_RAISE (); + return MAX_UINT32; + } + + NewMemory = AllocatePool (NewAllocatedSize); + if (NewMemory == NULL) { + DEBUG_RAISE (); + return MAX_UINT32; + } + + if (Buffer->Memory != NULL) { + memmove (NewMemory, Buffer->Memory, Buffer->DataSize); + FreePool (Buffer->Memory); + } + + memset ( + NewMemory + Buffer->DataSize, + 0, + NewAllocatedSize - Buffer->DataSize + ); + + Buffer->Memory = NewMemory; + Buffer->AllocatedSize = NewAllocatedSize; + } + + Offset = Buffer->DataSize; + Buffer->DataSize += Size; + + return Offset; +} + +void +ImageToolBufferRead ( + void *Data, + uint32_t Size, + const image_tool_dynamic_buffer *Buffer, + uint32_t Offset + ) +{ + assert (Offset + Size > Offset); + assert (Offset + Size <= Buffer->DataSize); + + memmove (Data, &Buffer->Memory[Offset], Size); +} + +void +ImageToolBufferWrite ( + image_tool_dynamic_buffer *Buffer, + uint32_t Offset, + const void *Data, + uint32_t Size + ) +{ + assert (Offset + Size > Offset); + assert (Offset + Size <= Buffer->DataSize); + + memmove (&Buffer->Memory[Offset], Data, Size); +} + +uint32_t +ImageToolBufferAppend ( + image_tool_dynamic_buffer *Buffer, + const void *Data, + uint32_t Size + ) +{ + uint32_t Offset; + + Offset = ImageToolBufferExpand (Buffer, Size); + if (Offset != MAX_UINT32) { + memmove (&Buffer->Memory[Offset], Data, Size); + } + + return Offset; +} + +uint32_t +ImageToolBufferAppendReserve ( + image_tool_dynamic_buffer *Buffer, + uint32_t Size + ) +{ + uint32_t Offset; + + Offset = ImageToolBufferExpand (Buffer, Size); + if (Offset != MAX_UINT32) { + memset (&Buffer->Memory[Offset], 0, Size); + } + + return Offset; +} + +uint32_t +ImageToolBufferAppendReserveAlign ( + image_tool_dynamic_buffer *Buffer, + uint32_t Alignment + ) +{ + assert (IS_POW2 (Alignment)); + + return ImageToolBufferAppendReserve ( + Buffer, + ALIGN_VALUE_ADDEND (ImageToolBufferGetSize (Buffer), Alignment) + ); +} + +void * +ImageToolBufferGetPointer ( + const image_tool_dynamic_buffer *Buffer, + uint32_t Offset + ) +{ + assert (Offset < Buffer->DataSize); + + return &Buffer->Memory[Offset]; +} + +uint32_t +ImageToolBufferGetSize ( + const image_tool_dynamic_buffer *Buffer + ) +{ + return Buffer->DataSize; +} + +void * +ImageToolBufferDump ( + uint32_t *Size, + image_tool_dynamic_buffer *Buffer + ) +{ + void *Data; + uint32_t DataSize; + + if (Buffer->Memory == NULL) { + return NULL; + } + + DataSize = ImageToolBufferGetSize (Buffer); + + Data = AllocateCopyPool (DataSize, Buffer->Memory); + if (Data == NULL) { + return NULL; + } + + *Size = DataSize; + + return Data; +} + +void +ImageToolBufferFree ( + image_tool_dynamic_buffer *Buffer + ) +{ + if (Buffer->Memory != NULL) { + FreePool (Buffer->Memory); + } + + ImageToolBufferInit (Buffer); +} diff --git a/BaseTools/ImageTool/DynamicBuffer.h b/BaseTools/ImageTool/DynamicBuffer.h new file mode 100644 index 0000000000..d71d106d88 --- /dev/null +++ b/BaseTools/ImageTool/DynamicBuffer.h @@ -0,0 +1,74 @@ +#ifndef DYNAMIC_BUFFER_H +#define DYNAMIC_BUFFER_H + +#include + +typedef struct { + uint32_t AllocatedSize; + uint32_t DataSize; + uint8_t *Memory; +} image_tool_dynamic_buffer; + +void +ImageToolBufferInit ( + image_tool_dynamic_buffer *Buffer + ); + +uint32_t +ImageToolBufferAppend ( + image_tool_dynamic_buffer *Buffer, + const void *Data, + uint32_t Size + ); + +uint32_t +ImageToolBufferAppendReserve ( + image_tool_dynamic_buffer *Buffer, + uint32_t Size + ); + +uint32_t +ImageToolBufferAppendReserveAlign ( + image_tool_dynamic_buffer *Buffer, + uint32_t Alignment + ); + +void +ImageToolBufferRead ( + void *Data, + uint32_t Size, + const image_tool_dynamic_buffer *Buffer, + uint32_t Offset + ); + +void +ImageToolBufferWrite ( + image_tool_dynamic_buffer *Buffer, + uint32_t Offset, + const void *Data, + uint32_t Size + ); + +void * +ImageToolBufferGetPointer ( + const image_tool_dynamic_buffer *Buffer, + uint32_t Offset + ); + +uint32_t +ImageToolBufferGetSize ( + const image_tool_dynamic_buffer *Buffer + ); + +void * +ImageToolBufferDump ( + uint32_t *Size, + image_tool_dynamic_buffer *Buffer + ); + +void +ImageToolBufferFree ( + image_tool_dynamic_buffer *Buffer + ); + +#endif // DYNAMIC_BUFFER_H diff --git a/BaseTools/ImageTool/ElfScan.c b/BaseTools/ImageTool/ElfScan.c index 60fd9184b5..102e795143 100644 --- a/BaseTools/ImageTool/ElfScan.c +++ b/BaseTools/ImageTool/ElfScan.c @@ -103,8 +103,6 @@ IsShdrLoadable ( IN const Elf_Shdr *Shdr ) { - assert (Shdr != NULL); - return (Shdr->sh_flags & SHF_ALLOC) != 0; } @@ -360,7 +358,12 @@ SetRelocs ( // break; default: - fprintf (stderr, "ImageTool: Unsupported ELF EM_X86_64 relocation 0x%llx in %s\n", ELF_R_TYPE(Rel->r_info), ImageInfo->DebugInfo.SymbolsPath); + fprintf ( + stderr, + "ImageTool: Unsupported ELF EM_X86_64 relocation 0x%llx in %s\n", + (unsigned long long)ELF_R_TYPE(Rel->r_info), + ImageInfo->DebugInfo.SymbolsPath + ); return RETURN_INCOMPATIBLE_VERSION; } } else if (Ehdr->e_machine == EM_AARCH64) { @@ -402,7 +405,12 @@ SetRelocs ( break; default: - fprintf (stderr, "ImageTool: Unsupported ELF EM_AARCH64 relocation 0x%llx in %s\n", ELF_R_TYPE(Rel->r_info), ImageInfo->DebugInfo.SymbolsPath); + fprintf ( + stderr, + "ImageTool: Unsupported ELF EM_AARCH64 relocation 0x%llx in %s\n", + (unsigned long long)ELF_R_TYPE(Rel->r_info), + ImageInfo->DebugInfo.SymbolsPath + ); return RETURN_INCOMPATIBLE_VERSION; } } @@ -571,7 +579,7 @@ CreateIntermediate ( return RETURN_VOLUME_CORRUPTED; } - Segments = calloc (1, sizeof (*Segments) * ImageInfo->SegmentInfo.NumSegments); + Segments = AllocateZeroPool (sizeof (*Segments) * ImageInfo->SegmentInfo.NumSegments); if (Segments == NULL) { fprintf (stderr, "ImageTool: Could not allocate memory for Segments\n"); return RETURN_OUT_OF_RESOURCES; @@ -580,7 +588,7 @@ CreateIntermediate ( ImageInfo->SegmentInfo.Segments = Segments; if (NumRelocs != 0) { - Relocs = calloc (1, sizeof (*Relocs) * NumRelocs); + Relocs = AllocateZeroPool (sizeof (*Relocs) * NumRelocs); if (Relocs == NULL) { fprintf (stderr, "ImageTool: Could not allocate memory for Relocs\n"); return RETURN_OUT_OF_RESOURCES; @@ -606,7 +614,7 @@ CreateIntermediate ( return RETURN_VOLUME_CORRUPTED; } - Segments[SIndex].Name = calloc (1, strlen (Name) + 1); + Segments[SIndex].Name = AllocateZeroPool (strlen (Name) + 1); if (Segments[SIndex].Name == NULL) { fprintf (stderr, "ImageTool: Could not allocate memory for Segment #%d Name\n", Index); return RETURN_OUT_OF_RESOURCES; @@ -620,7 +628,7 @@ CreateIntermediate ( Segments[SIndex].Write = (Shdr->sh_flags & SHF_WRITE) != 0; Segments[SIndex].Execute = (Shdr->sh_flags & SHF_EXECINSTR) != 0; - Segments[SIndex].Data = calloc (1, Segments[SIndex].ImageSize); + Segments[SIndex].Data = AllocateZeroPool (Segments[SIndex].ImageSize); if (Segments[SIndex].Data == NULL) { fprintf (stderr, "ImageTool: Could not allocate memory for Segment #%d Data\n", Index); return RETURN_OUT_OF_RESOURCES; @@ -652,7 +660,6 @@ ScanElf ( const Elf_Ehdr *Ehdr; Elf_Addr BaseAddress; - assert (ImageInfo != NULL); assert (File != NULL || FileSize == 0); Status = ParseElfFile (&Context, File, FileSize); @@ -667,7 +674,6 @@ ScanElf ( ImageInfo->HeaderInfo.BaseAddress = BaseAddress; ImageInfo->HeaderInfo.EntryPointAddress = (uint32_t)(Ehdr->e_entry - BaseAddress); - ImageInfo->HeaderInfo.IsXip = true; ImageInfo->SegmentInfo.SegmentAlignment = (uint32_t)Context.Alignment; ImageInfo->RelocInfo.RelocsStripped = false; @@ -698,11 +704,11 @@ ScanElf ( return RETURN_INCOMPATIBLE_VERSION; } - ImageInfo->DebugInfo.SymbolsPath = malloc (ImageInfo->DebugInfo.SymbolsPathLen + 1); + ImageInfo->DebugInfo.SymbolsPath = AllocatePool (ImageInfo->DebugInfo.SymbolsPathLen + 1); if (ImageInfo->DebugInfo.SymbolsPath == NULL) { fprintf (stderr, "ImageTool: Could not allocate memory for Debug Data\n"); return RETURN_OUT_OF_RESOURCES; - }; + } if (SymbolsPath != NULL) { memmove (ImageInfo->DebugInfo.SymbolsPath, SymbolsPath, ImageInfo->DebugInfo.SymbolsPathLen + 1); diff --git a/BaseTools/ImageTool/GNUmakefile b/BaseTools/ImageTool/GNUmakefile index 3765720da8..2981bc86ac 100644 --- a/BaseTools/ImageTool/GNUmakefile +++ b/BaseTools/ImageTool/GNUmakefile @@ -10,7 +10,7 @@ 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 += PeCoffInit.o PeCoffInfo.o PeCoffLoad.o PeCoffRelocate.o PeCoffHii.o PeCoffDebug.o PeCoffHash.o -OBJS += PeSupport.o UefiImageLib.o CommonSupport.o +OBJS += PeSupport.o UefiImageLib.o CommonSupport.o DynamicBuffer.o WERROR = 1 DEBUG = 1 diff --git a/BaseTools/ImageTool/Image.c b/BaseTools/ImageTool/Image.c index 699bd89242..68c913f988 100644 --- a/BaseTools/ImageTool/Image.c +++ b/BaseTools/ImageTool/Image.c @@ -16,22 +16,18 @@ CheckToolImageSegment ( { bool Overflow; - assert (Segment != NULL); - assert (PreviousEndAddress != NULL); - if (!IS_ALIGNED (Segment->ImageSize, SegmentInfo->SegmentAlignment)) { - raise (); + DEBUG_RAISE (); return false; } if (Segment->Write && Segment->Execute) { - raise (); + DEBUG_RAISE (); return false; } - // FIXME: Expand prior segment if (Segment->ImageAddress != *PreviousEndAddress) { - raise (); + DEBUG_RAISE (); return false; } @@ -41,7 +37,7 @@ CheckToolImageSegment ( PreviousEndAddress ); if (Overflow) { - raise (); + DEBUG_RAISE (); return false; } @@ -58,21 +54,18 @@ CheckToolImageSegmentInfo ( uint32_t Index; bool Result; - assert (SegmentInfo != NULL); - assert (ImageSize != NULL); - if (!IS_POW2 (SegmentInfo->SegmentAlignment)) { - raise (); + DEBUG_RAISE (); return false; } if (SegmentInfo->NumSegments == 0) { - raise (); + DEBUG_RAISE (); return false; } if (!IS_ALIGNED (SegmentInfo->Segments[0].ImageAddress, SegmentInfo->SegmentAlignment)) { - raise (); + DEBUG_RAISE (); return false; } @@ -84,7 +77,7 @@ CheckToolImageSegmentInfo ( ImageSize ); if (!Result) { - raise (); + DEBUG_RAISE (); return false; } } @@ -93,6 +86,32 @@ CheckToolImageSegmentInfo ( } static +bool +CheckToolImageHeaderInfo ( + const image_tool_header_info_t *HeaderInfo, + const image_tool_segment_info_t *SegmentInfo, + uint32_t ImageSize + ) +{ + if (SegmentInfo->Segments[0].ImageAddress > HeaderInfo->EntryPointAddress || + HeaderInfo->EntryPointAddress > ImageSize) { + DEBUG_RAISE (); + return false; + } + + if (!IS_ALIGNED (HeaderInfo->BaseAddress, SegmentInfo->SegmentAlignment)) { + DEBUG_RAISE (); + return false; + } + + if (HeaderInfo->BaseAddress + ImageSize < HeaderInfo->BaseAddress) { + DEBUG_RAISE (); + return false; + } + + return true; +} + const image_tool_segment_t * ImageGetSegmentByAddress ( uint32_t *Address, @@ -102,9 +121,6 @@ ImageGetSegmentByAddress ( { uint32_t Index; - assert (Address != NULL); - assert (SegmentInfo != NULL); - for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) { if ((SegmentInfo->Segments[Index].ImageAddress <= *Address) && (*Address < SegmentInfo->Segments[Index].ImageAddress + SegmentInfo->Segments[Index].ImageSize)) { @@ -117,22 +133,52 @@ ImageGetSegmentByAddress ( return NULL; } +uint8_t +ToolImageGetRelocSize ( + uint8_t Type + ) +{ + switch (Type) { + case EFI_IMAGE_REL_BASED_HIGHLOW: + { + return sizeof (UINT32); + } + + case EFI_IMAGE_REL_BASED_DIR64: + { + return sizeof (UINT64); + } + +#if 0 + case EFI_IMAGE_REL_BASED_ARM_MOV32T: + { + return sizeof (UINT32); + } +#endif + + default: + { + return 0; + } + } +} + static bool CheckToolImageReloc ( const image_tool_image_info_t *Image, - uint32_t ImageSize, - const image_tool_reloc_t *Reloc + const image_tool_reloc_t *Reloc, + uint8_t RelocSize ) { uint32_t RelocOffset; uint32_t RemainingSize; const image_tool_segment_t *Segment; + +#if 0 uint16_t MovHigh; uint16_t MovLow; - - assert (Image != NULL); - assert (Reloc != NULL); +#endif RelocOffset = Reloc->Target; Segment = ImageGetSegmentByAddress ( @@ -141,64 +187,40 @@ CheckToolImageReloc ( &Image->SegmentInfo ); if (Segment == NULL) { - raise (); + DEBUG_RAISE (); return false; } - switch (Reloc->Type) { - case EFI_IMAGE_REL_BASED_HIGHLOW: - { - if (RemainingSize < sizeof (UINT32)) { - raise (); - return false; - } + if (RelocSize > RemainingSize) { + DEBUG_RAISE (); + return false; + } - break; +#if 0 + if (Reloc->Type == EFI_IMAGE_REL_BASED_ARM_MOV32T) { + if (!IS_ALIGNED (Reloc->Target, ALIGNOF (UINT16))) { + DEBUG_RAISE (); + return false; } - case EFI_IMAGE_REL_BASED_DIR64: - { - if (RemainingSize < sizeof (UINT64)) { - raise (); - return false; - } - - break; - } - - case EFI_IMAGE_REL_BASED_ARM_MOV32T: - { - if (RemainingSize < sizeof (UINT32)) { - raise (); - return false; - } - - if (!IS_ALIGNED (Reloc->Target, ALIGNOF (UINT16))) { - raise (); - return false; - } - - MovHigh = *(const uint16_t *)&Segment->Data[RelocOffset]; - MovLow = *(const uint16_t *)&Segment->Data[RelocOffset + 2]; - if (((MovHigh & 0xFBF0U) != 0xF200U && (MovHigh & 0xFBF0U) != 0xF2C0U) || - (MovLow & 0x8000U) != 0) { - raise (); - return false; - } - - break; - } - - default: - { - raise (); + MovHigh = *(const uint16_t *)&Segment->Data[RelocOffset]; + MovLow = *(const uint16_t *)&Segment->Data[RelocOffset + 2]; + if (((MovHigh & 0xFBF0U) != 0xF200U && (MovHigh & 0xFBF0U) != 0xF2C0U) || + (MovLow & 0x8000U) != 0) { + DEBUG_RAISE (); return false; } } +#endif - /*if (Segment->Write) { + // FIXME: Update drivers? + if ((Image->HeaderInfo.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER || + Image->HeaderInfo.Subsystem == EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER) && + Segment->Write) { printf("!!! writable reloc at %x !!!\n", Reloc->Target); - }*/ + //DEBUG_RAISE (); + //return false; + } return true; } @@ -206,49 +228,52 @@ CheckToolImageReloc ( static bool CheckToolImageRelocInfo ( - const image_tool_image_info_t *Image, - uint32_t ImageSize + const image_tool_image_info_t *Image ) { const image_tool_reloc_info_t *RelocInfo; + uint8_t RelocSize; + uint32_t MinRelocTarget; uint32_t Index; bool Result; - assert (Image != NULL); - RelocInfo = &Image->RelocInfo; if (RelocInfo->NumRelocs == 0) { return true; } - if (RelocInfo->RelocsStripped && (RelocInfo->NumRelocs > 0)) { - raise (); + if (RelocInfo->RelocsStripped) { + DEBUG_RAISE (); return false; } if (RelocInfo->NumRelocs > (MAX_UINT32 / sizeof (UINT16))) { - raise (); + DEBUG_RAISE (); return false; } - Result = CheckToolImageReloc (Image, ImageSize, &RelocInfo->Relocs[0]); - if (!Result) { - raise (); - return false; - } + MinRelocTarget = 0; - for (Index = 1; Index < RelocInfo->NumRelocs; ++Index) { - if (RelocInfo->Relocs[Index].Target < RelocInfo->Relocs[Index - 1].Target) { - assert (false); + for (Index = 0; Index < RelocInfo->NumRelocs; ++Index) { + if (RelocInfo->Relocs[Index].Target < MinRelocTarget) { + DEBUG_RAISE (); return false; } - Result = CheckToolImageReloc (Image, ImageSize, &RelocInfo->Relocs[Index]); + RelocSize = ToolImageGetRelocSize (RelocInfo->Relocs[Index].Type); + if (RelocSize == 0) { + DEBUG_RAISE (); + return false; + } + + Result = CheckToolImageReloc (Image, &RelocInfo->Relocs[Index], RelocSize); if (!Result) { - raise (); + DEBUG_RAISE (); return false; } + + MinRelocTarget = RelocInfo->Relocs[Index].Target + RelocSize; } return true; @@ -260,14 +285,9 @@ CheckToolImageDebugInfo ( const image_tool_debug_info_t *DebugInfo ) { - assert (DebugInfo != NULL); - - if (DebugInfo->SymbolsPath != NULL) { - // FIXME: UE-only? - if (DebugInfo->SymbolsPathLen > MAX_UINT8) { - raise (); - return false; - } + if (DebugInfo->SymbolsPathLen > MAX_UINT8) { + DEBUG_RAISE (); + return false; } return true; @@ -281,23 +301,31 @@ CheckToolImage ( bool Result; uint32_t ImageSize; - assert (Image != NULL); - Result = CheckToolImageSegmentInfo (&Image->SegmentInfo, &ImageSize); if (!Result) { - raise (); + DEBUG_RAISE (); return false; } - Result = CheckToolImageRelocInfo (Image, ImageSize); + Result = CheckToolImageHeaderInfo ( + &Image->HeaderInfo, + &Image->SegmentInfo, + ImageSize + ); if (!Result) { - raise (); + DEBUG_RAISE (); + return false; + } + + Result = CheckToolImageRelocInfo (Image); + if (!Result) { + DEBUG_RAISE (); return false; } Result = CheckToolImageDebugInfo (&Image->DebugInfo); if (!Result) { - raise (); + DEBUG_RAISE (); return false; } @@ -316,10 +344,6 @@ ImageInitUnpaddedSize ( Segment = &Image->SegmentInfo.Segments[Index]; Segment->UnpaddedSize = Segment->ImageSize; - if (Image->HeaderInfo.IsXip) { - continue; - } - for (; Segment->UnpaddedSize > 0; --Segment->UnpaddedSize) { if (Segment->Data[Segment->UnpaddedSize - 1] != 0) { break; @@ -335,20 +359,33 @@ ToolImageDestruct ( { uint8_t Index; - assert (Image != NULL); - if (Image->SegmentInfo.Segments != NULL) { for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { - free (Image->SegmentInfo.Segments[Index].Name); - free (Image->SegmentInfo.Segments[Index].Data); + if (Image->SegmentInfo.Segments[Index].Name != NULL) { + FreePool (Image->SegmentInfo.Segments[Index].Name); + } + + if (Image->SegmentInfo.Segments[Index].Data != NULL) { + FreePool (Image->SegmentInfo.Segments[Index].Data); + } } - free (Image->SegmentInfo.Segments); + if (Image->SegmentInfo.Segments != NULL) { + FreePool (Image->SegmentInfo.Segments); + } } - free (Image->HiiInfo.Data); - free (Image->RelocInfo.Relocs); - free (Image->DebugInfo.SymbolsPath); + if (Image->HiiInfo.Data != NULL) { + FreePool (Image->HiiInfo.Data); + } + + if (Image->RelocInfo.Relocs != NULL) { + FreePool (Image->RelocInfo.Relocs); + } + + if (Image->DebugInfo.SymbolsPath != NULL) { + FreePool (Image->DebugInfo.SymbolsPath); + } memset (Image, 0, sizeof (*Image)); } @@ -356,9 +393,12 @@ ToolImageDestruct ( bool ToolImageRelocate ( image_tool_image_info_t *Image, - uint64_t BaseAddress + uint64_t BaseAddress, + uint32_t IgnorePrefix ) { + const image_tool_segment_t *LastSegment; + uint32_t ImageSize; uint64_t Adjust; const image_tool_reloc_t *Reloc; uint32_t RelocOffset; @@ -368,10 +408,28 @@ ToolImageRelocate ( uint32_t RelocTarget32; uint64_t RelocTarget64; + if (!IS_ALIGNED (BaseAddress, Image->SegmentInfo.SegmentAlignment)) { + DEBUG_RAISE (); + return false; + } + Adjust = BaseAddress - Image->HeaderInfo.BaseAddress; if (Adjust == 0) { - return TRUE; + return true; + } + + LastSegment = &Image->SegmentInfo.Segments[Image->SegmentInfo.NumSegments - 1]; + ImageSize = LastSegment->ImageAddress + LastSegment->ImageSize; + + // + // When removing the image header prefix, BaseAddress + ImageSize may indeed + // overflow. The important part is that the address starting from the first + // image segment does not. + // + if (BaseAddress + ImageSize < BaseAddress + IgnorePrefix) { + DEBUG_RAISE (); + return false; } for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) { @@ -383,10 +441,7 @@ ToolImageRelocate ( &RemainingSize, &Image->SegmentInfo ); - if (Segment == NULL) { - raise (); - return false; - } + assert (Segment != NULL); switch (Reloc->Type) { case EFI_IMAGE_REL_BASED_HIGHLOW: @@ -409,6 +464,7 @@ ToolImageRelocate ( break; } +#if 0 case EFI_IMAGE_REL_BASED_ARM_MOV32T: { assert (RemainingSize >= sizeof (UINT32)); @@ -417,10 +473,11 @@ ToolImageRelocate ( PeCoffThumbMovwMovtImmediateFixup (&Segment->Data[RelocOffset], Adjust); break; } +#endif default: { - raise (); + assert (false); return false; } } @@ -494,7 +551,7 @@ ToolImageCompare ( sizeof (Image1->HeaderInfo) ); if (CmpResult != 0) { - raise (); + DEBUG_RAISE (); return false; } @@ -510,7 +567,7 @@ ToolImageCompare ( OFFSET_OF (image_tool_segment_info_t, Segments) ); if (CmpResult != 0) { - raise (); + DEBUG_RAISE (); return false; } @@ -521,7 +578,7 @@ ToolImageCompare ( OFFSET_OF (image_tool_segment_t, Name) ); if (CmpResult != 0) { - raise (); + DEBUG_RAISE (); return false; } @@ -538,20 +595,22 @@ ToolImageCompare ( ++NameIndex ) { if (Name1[NameIndex] != Name2[NameIndex]) { - raise (); + DEBUG_RAISE (); return false; } } } - CmpResult = memcmp ( - Image1->SegmentInfo.Segments[SegIndex].Data, - Image2->SegmentInfo.Segments[SegIndex].Data, - Image1->SegmentInfo.Segments[SegIndex].ImageSize - ); - if (CmpResult != 0) { - raise (); - return false; + if (Image1->SegmentInfo.Segments[SegIndex].ImageSize != 0) { + CmpResult = memcmp ( + Image1->SegmentInfo.Segments[SegIndex].Data, + Image2->SegmentInfo.Segments[SegIndex].Data, + Image1->SegmentInfo.Segments[SegIndex].ImageSize + ); + if (CmpResult != 0) { + DEBUG_RAISE (); + return false; + } } } @@ -565,18 +624,20 @@ ToolImageCompare ( OFFSET_OF (image_tool_reloc_info_t, Relocs) ); if (CmpResult != 0) { - raise (); + DEBUG_RAISE (); return false; } - CmpResult = memcmp ( - Image1->RelocInfo.Relocs, - Image2->RelocInfo.Relocs, - Image1->RelocInfo.NumRelocs * sizeof (*Image1->RelocInfo.Relocs) - ); - if (CmpResult != 0) { - raise (); - return false; + if (Image1->RelocInfo.NumRelocs != 0) { + CmpResult = memcmp ( + Image1->RelocInfo.Relocs, + Image2->RelocInfo.Relocs, + Image1->RelocInfo.NumRelocs * sizeof (*Image1->RelocInfo.Relocs) + ); + if (CmpResult != 0) { + DEBUG_RAISE (); + return false; + } } // @@ -589,18 +650,20 @@ ToolImageCompare ( OFFSET_OF (image_tool_hii_info_t, Data) ); if (CmpResult != 0) { - raise (); + DEBUG_RAISE (); return false; } - CmpResult = memcmp ( - Image1->HiiInfo.Data, - Image2->HiiInfo.Data, - Image1->HiiInfo.DataSize - ); - if (CmpResult != 0) { - raise (); - return false; + if (Image1->HiiInfo.DataSize != 0) { + CmpResult = memcmp ( + Image1->HiiInfo.Data, + Image2->HiiInfo.Data, + Image1->HiiInfo.DataSize + ); + if (CmpResult != 0) { + DEBUG_RAISE (); + return false; + } } // @@ -613,12 +676,12 @@ ToolImageCompare ( OFFSET_OF (image_tool_debug_info_t, SymbolsPath) ); if (CmpResult != 0) { - raise (); + DEBUG_RAISE (); return false; } if ((Image1->DebugInfo.SymbolsPath != NULL) != (Image2->DebugInfo.SymbolsPath != NULL)) { - raise (); + DEBUG_RAISE (); return false; } @@ -628,7 +691,7 @@ ToolImageCompare ( Image2->DebugInfo.SymbolsPath ); if (CmpResult != 0) { - raise (); + DEBUG_RAISE (); return false; } } @@ -642,7 +705,11 @@ ToolImageStripRelocs ( ) { Image->RelocInfo.NumRelocs = 0; - free (Image->RelocInfo.Relocs); + + if (Image->RelocInfo.Relocs != NULL) { + FreePool (Image->RelocInfo.Relocs); + } + Image->RelocInfo.Relocs = NULL; Image->RelocInfo.RelocsStripped = TRUE; diff --git a/BaseTools/ImageTool/ImageTool.c b/BaseTools/ImageTool/ImageTool.c index 4a39ab3cab..a93192945d 100644 --- a/BaseTools/ImageTool/ImageTool.c +++ b/BaseTools/ImageTool/ImageTool.c @@ -37,10 +37,6 @@ HiiSrc ( FILE *FilePtr; UINT32 Index; - assert (FileNames != NULL); - assert (HiiName != NULL); - assert (Guid != NULL); - Status = AsciiStrToGuid (Guid, &HiiGuid); if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Invalid GUID - %s\n", Guid); @@ -55,7 +51,7 @@ HiiSrc ( FilePtr = fopen (HiiName, "w"); if (FilePtr == NULL) { - free (Hii); + FreePool (Hii); return RETURN_NO_MEDIA; } @@ -113,7 +109,8 @@ HiiSrc ( " (CONST MODULE_HII_PACKAGE_LIST *)&mModuleHiiPackageList;\n" ); - free (Hii); + fclose (FilePtr); + FreePool (Hii); return RETURN_SUCCESS; } @@ -247,9 +244,6 @@ GetAcpi ( UINT16 Index; UINT32 FileLength; - assert (PeName != NULL); - assert (AcpiName != NULL); - Pe = UserReadFile (PeName, &PeSize); if (Pe == NULL) { fprintf (stderr, "ImageTool: Could not open %s: %s\n", PeName, strerror (errno)); @@ -353,9 +347,11 @@ RETURN_STATUS GenExecutable ( IN const char *OutputFileName, IN const char *InputFileName, + IN const char *SymbolsPath OPTIONAL, IN const char *FormatName, IN const char *TypeName, IN const char *BaseAddress, + IN bool Xip, IN bool Strip, IN bool FixedAddress ) @@ -402,6 +398,10 @@ GenExecutable ( return RETURN_ABORTED; } + if (SymbolsPath == NULL) { + SymbolsPath = InputFileName; + } + OutputFile = ToolImageEmit ( &OutputFileSize, InputFile, @@ -410,18 +410,20 @@ GenExecutable ( Type, BaseAddress != NULL, NewBaseAddress, - InputFileName, + SymbolsPath, + Xip, Strip, FixedAddress ); if (OutputFile == NULL) { + DEBUG_RAISE (); return RETURN_ABORTED; } UserWriteFile (OutputFileName, OutputFile, OutputFileSize); - free (OutputFile); + FreePool (OutputFile); return RETURN_SUCCESS; } @@ -432,16 +434,18 @@ int main (int argc, const char *argv[]) UINT32 NumOfFiles; const char *OutputName; const char *InputName; + const char *SymbolsPath; const char *FormatName; const char *TypeName; const char *BaseAddress; + bool Xip; bool Strip; bool FixedAddress; int ArgIndex; if (argc < 2) { fprintf (stderr, "ImageTool: No command is specified\n"); - raise (); + DEBUG_RAISE (); return -1; } // @@ -452,16 +456,18 @@ int main (int argc, const char *argv[]) if (strcmp (argv[1], "GenImage") == 0) { if (argc < 5) { fprintf (stderr, "ImageTool: Command arguments are missing\n"); - fprintf (stderr, " Usage: ImageTool GenImage [-c Format] [-t ModuleType] [-b BaseAddress] [-s] [-f] -o OutputFile InputFile\n"); - raise (); + fprintf (stderr, " Usage: ImageTool GenImage [-c Format] [-t ModuleType] [-b BaseAddress] [-d SymbolsPath] [-x] [-s] [-f] -o OutputFile InputFile\n"); + DEBUG_RAISE (); return -1; } OutputName = NULL; InputName = NULL; + SymbolsPath = NULL; FormatName = NULL; TypeName = NULL; BaseAddress = NULL; + Xip = false; Strip = false; FixedAddress = false; for (ArgIndex = 2; ArgIndex < argc; ++ArgIndex) { @@ -497,6 +503,16 @@ int main (int argc, const char *argv[]) } BaseAddress = argv[ArgIndex]; + } else if (strcmp (argv[ArgIndex], "-d") == 0) { + ++ArgIndex; + if (ArgIndex == argc) { + fprintf (stderr, "Must specify an argument to -d\n"); + return -1; + } + + SymbolsPath = argv[ArgIndex]; + } else if (strcmp (argv[ArgIndex], "-x") == 0) { + Xip = true; } else if (strcmp (argv[ArgIndex], "-s") == 0) { Strip = true; } else if (strcmp (argv[ArgIndex], "-f") == 0) { @@ -524,21 +540,23 @@ int main (int argc, const char *argv[]) Status = GenExecutable ( OutputName, InputName, + SymbolsPath, FormatName, TypeName, BaseAddress, + Xip, Strip, FixedAddress ); if (RETURN_ERROR (Status)) { - raise (); + DEBUG_RAISE (); return -1; } } else if (strcmp (argv[1], "HiiSrc") == 0) { if (argc < 5 || strcmp (argv[3], "-o") != 0) { fprintf (stderr, "ImageTool: Command arguments are missing\n"); fprintf (stderr, " Usage: ImageTool HiiBin GUID -o OutputFile InputFile1 InputFile2 ...\n"); - raise (); + DEBUG_RAISE (); return -1; } @@ -546,20 +564,20 @@ int main (int argc, const char *argv[]) Status = HiiSrc (argv[4], argv[2], &argv[5], NumOfFiles); if (RETURN_ERROR (Status)) { - raise (); + DEBUG_RAISE (); return -1; } } else if (strcmp (argv[1], "GetAcpi") == 0) { if (argc != 5 || strcmp (argv[2], "-o") != 0) { fprintf (stderr, "ImageTool: Command arguments are missing\n"); fprintf (stderr, " Usage: ImageTool GetAcpi -o OutputFile InputFile\n"); - raise (); + DEBUG_RAISE (); return -1; } Status = GetAcpi (argv[4], argv[3]); if (RETURN_ERROR (Status)) { - raise (); + DEBUG_RAISE (); return -1; } } diff --git a/BaseTools/ImageTool/ImageTool.h b/BaseTools/ImageTool/ImageTool.h index 048579a315..a0382d79d8 100644 --- a/BaseTools/ImageTool/ImageTool.h +++ b/BaseTools/ImageTool/ImageTool.h @@ -18,19 +18,12 @@ #include #include #include +#include #include #include #define MAX_PE_ALIGNMENT 0x10000 -#define raise() assert(false) - -typedef struct { - EFI_IMAGE_DEBUG_DIRECTORY_ENTRY Dir; - EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY Nb10; - char Name[]; -} DebugData; - #define PAGE(x) ((x) & ~4095U) #define PAGE_OFF(x) ((x) & 4095U) @@ -39,9 +32,8 @@ typedef struct { uint32_t EntryPointAddress; uint16_t Machine; uint16_t Subsystem; - uint8_t IsXip; uint8_t FixedAddress; - uint8_t Reserved[6]; + uint8_t Reserved[7]; } image_tool_header_info_t; typedef struct { @@ -60,7 +52,8 @@ typedef struct { typedef struct { uint32_t SegmentAlignment; - uint32_t NumSegments; + uint16_t NumSegments; + uint8_t Reserved[2]; image_tool_segment_t *Segments; } image_tool_segment_info_t; @@ -117,7 +110,8 @@ ImageInitUnpaddedSize ( bool ToolImageRelocate ( image_tool_image_info_t *Image, - uint64_t BaseAddress + uint64_t BaseAddress, + uint32_t IgnorePrefix ); void @@ -136,6 +130,11 @@ ToolImageStripRelocs ( image_tool_image_info_t *Image ); +uint8_t +ToolImageGetRelocSize ( + uint8_t Type + ); + RETURN_STATUS ToolContextConstructUefiImage ( OUT image_tool_image_info_t *Image, @@ -153,6 +152,7 @@ void * ToolImageEmitPe ( image_tool_image_info_t *Image, uint32_t *FileSize, + bool Xip, bool Strip ); @@ -182,4 +182,11 @@ ConstructHii ( OUT UINT32 *HiiSize ); +const image_tool_segment_t * +ImageGetSegmentByAddress ( + uint32_t *Address, + uint32_t *RemainingSize, + const image_tool_segment_info_t *SegmentInfo + ); + #endif // IMAGE_TOOL_H diff --git a/BaseTools/ImageTool/ImageToolEmit.c b/BaseTools/ImageTool/ImageToolEmit.c index 043e949dc2..b874843532 100644 --- a/BaseTools/ImageTool/ImageToolEmit.c +++ b/BaseTools/ImageTool/ImageToolEmit.c @@ -33,9 +33,11 @@ ToolContextConstruct ( File, FileSize ); +#ifndef IMAGE_TOOL_DISABLE_ELF if (Status == RETURN_UNSUPPORTED) { Status = ScanElf (ImageInfo, File, FileSize, SymbolsPath); } +#endif return Status; } @@ -61,13 +63,13 @@ ValidateOutputFile ( NULL ); if (EFI_ERROR (Status)) { - assert (false); + assert (Status == RETURN_OUT_OF_RESOURCES); return Status; } Result = CheckToolImage (&OutputImageInfo); if (!Result) { - raise (); + assert (false); ToolImageDestruct (&OutputImageInfo); return RETURN_UNSUPPORTED; } @@ -94,6 +96,7 @@ ToolImageEmit ( IN bool Relocate, IN uint64_t BaseAddress, IN const char *SymbolsPath OPTIONAL, + IN bool Xip, IN bool Strip, IN bool FixedAddress ) @@ -138,12 +141,13 @@ ToolImageEmit ( Success = CheckToolImage (&ImageInfo); if (!Success) { + DEBUG_RAISE (); ToolImageDestruct (&ImageInfo); return NULL; } if (Relocate) { - Success = ToolImageRelocate (&ImageInfo, BaseAddress); + Success = ToolImageRelocate (&ImageInfo, BaseAddress, 0); if (!Success) { fprintf (stderr, "ImageTool: Failed to relocate input file %s\n", SymbolsPath); ToolImageDestruct (&ImageInfo); @@ -157,17 +161,24 @@ ToolImageEmit ( OutputFile = NULL; if (Format == UefiImageFormatPe) { - OutputFile = ToolImageEmitPe (&ImageInfo, OutputFileSize, Strip); + OutputFile = ToolImageEmitPe (&ImageInfo, OutputFileSize, Xip, Strip); } else { assert (false); } + if (OutputFile == NULL) { + DEBUG_RAISE (); + ToolImageDestruct (&ImageInfo); + return NULL; + } + Status = ValidateOutputFile (OutputFile, *OutputFileSize, &ImageInfo); ToolImageDestruct (&ImageInfo); if (EFI_ERROR (Status)) { - assert (false); + assert (Status == RETURN_OUT_OF_RESOURCES); + FreePool (OutputFile); return NULL; } diff --git a/BaseTools/ImageTool/ImageToolEmit.h b/BaseTools/ImageTool/ImageToolEmit.h index ae803fcd3a..f83c4a6a7a 100644 --- a/BaseTools/ImageTool/ImageToolEmit.h +++ b/BaseTools/ImageTool/ImageToolEmit.h @@ -20,6 +20,7 @@ ToolImageEmit ( IN bool Relocate, IN uint64_t BaseAddress, IN const char *SymbolsPath OPTIONAL, + IN bool Xip, IN bool Strip, IN bool FixedAddress ); diff --git a/BaseTools/ImageTool/Makefile b/BaseTools/ImageTool/Makefile index a6a0b6a48c..3e91a6ecae 100644 --- a/BaseTools/ImageTool/Makefile +++ b/BaseTools/ImageTool/Makefile @@ -20,7 +20,7 @@ PE = $(UDK_PATH)\MdePkg\Library\BasePeCoffLib2 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 +OBJECTS = $(OBJECTS) {$(OV)}BaseAlignment.obj BaseBitOverflow.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 diff --git a/BaseTools/ImageTool/PeEmit.c b/BaseTools/ImageTool/PeEmit.c index ef4ffb30df..910d5125a7 100644 --- a/BaseTools/ImageTool/PeEmit.c +++ b/BaseTools/ImageTool/PeEmit.c @@ -6,14 +6,19 @@ #include "ImageTool.h" +#include "DynamicBuffer.h" +#include "PeEmitCommon.h" + #if PE_ARCH == 32 -#define EFI_IMAGE_NT_HEADERS EFI_IMAGE_NT_HEADERS32 +typedef UINT32 EFI_IMAGE_NT_BASE_ADDRESS; +typedef EFI_IMAGE_NT_HEADERS32 EFI_IMAGE_NT_HEADERS; #define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC #elif PE_ARCH == 64 -#define EFI_IMAGE_NT_HEADERS EFI_IMAGE_NT_HEADERS64 +typedef UINT64 EFI_IMAGE_NT_BASE_ADDRESS; +typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS; #define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC #endif @@ -23,622 +28,117 @@ #define PE_SUFFIX(Name) PE_SUFFIX_ (Name, PE_ARCH) typedef struct { - uint8_t NumExtraSections; - uint32_t SizeOfHeaders; - uint8_t NumberOfRvaAndSizes; - uint16_t SizeOfOptionalHeader; - uint32_t SectionHeadersSize; - uint32_t ExtraSectionHeadersSize; -} image_tool_emit_pe_hdr_info_t; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY Dir; + EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY Nb10; +} image_tool_debug_dir_t; -typedef struct { - const image_tool_image_info_t *Image; - EFI_IMAGE_NT_HEADERS *PeHdr; - image_tool_emit_pe_hdr_info_t HdrInfo; - uint32_t SectionsSize; - uint32_t HiiSectionAddress; - uint32_t ExtraSectionsSize; - uint32_t UnsignedFileSize; - uint32_t RelocTableSize; - uint32_t DebugTableSize; - uint32_t FileAlignment; -} image_tool_pe_emit_context_t; +#define SIZE_OF_DATA_DIRECRORY \ + EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES * sizeof (EFI_IMAGE_DATA_DIRECTORY) + +#define SIZE_OF_OPTIONAL_HEADER \ + sizeof (EFI_IMAGE_NT_HEADERS) - sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR) \ + + SIZE_OF_DATA_DIRECRORY -#define EmitPeGetHeaderSizes PE_SUFFIX (EmitPeGetHeaderSizes) static bool -EmitPeGetHeaderSizes ( - const image_tool_image_info_t *Image, - image_tool_emit_pe_hdr_info_t *HdrInfo +InternalFinalizeExtraSection ( + image_tool_dynamic_buffer *Buffer, + EFI_IMAGE_NT_HEADERS *PeHdr, + EFI_IMAGE_SECTION_HEADER *SectionHeader, + const char *Name, + uint32_t Size, + uint32_t Offset ) { - assert (Image != NULL); - assert (HdrInfo != NULL); + uint32_t BufferOffset; - if (Image->RelocInfo.NumRelocs > 0) { - HdrInfo->ExtraSectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER); - } + assert (Size == ImageToolBufferGetSize (Buffer) - Offset); - if (Image->HiiInfo.DataSize > 0) { - HdrInfo->ExtraSectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER); - } - - if (Image->DebugInfo.SymbolsPath != NULL) { - HdrInfo->ExtraSectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER); - } - - HdrInfo->SectionHeadersSize = (uint32_t)Image->SegmentInfo.NumSegments * sizeof (EFI_IMAGE_SECTION_HEADER); - HdrInfo->NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; - HdrInfo->SizeOfOptionalHeader = sizeof (EFI_IMAGE_NT_HEADERS) - sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR) - + HdrInfo->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY); - HdrInfo->SizeOfHeaders = sizeof (EFI_IMAGE_DOS_HEADER) + sizeof (EFI_IMAGE_NT_HEADERS) - + HdrInfo->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY) - + HdrInfo->SectionHeadersSize + HdrInfo->ExtraSectionHeadersSize; - - return true; -} - -#define EmitPeGetSectionsSize PE_SUFFIX (EmitPeGetSectionsSize) -static -bool -EmitPeGetSectionsSize ( - const image_tool_pe_emit_context_t *Context, - uint32_t *SectionsSize - ) -{ - const image_tool_image_info_t *Image; - uint8_t Index; - uint32_t DataSize; - bool Overflow; - - assert (Context != NULL); - assert (SectionsSize != NULL); - - Image = Context->Image; - *SectionsSize = 0; - - for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { - Overflow = BaseOverflowAlignUpU32 ( - Image->SegmentInfo.Segments[Index].UnpaddedSize, - Context->FileAlignment, - &DataSize - ); - if (Overflow) { - raise (); - return false; - } - - Overflow = BaseOverflowAddU32 (*SectionsSize, DataSize, SectionsSize); - if (Overflow) { - raise (); - return false; - } - } - - return true; -} - -#define EmitPeGetRelocSectionSize PE_SUFFIX (EmitPeGetRelocSectionSize) -static -bool -EmitPeGetRelocSectionSize ( - const image_tool_image_info_t *Image, - uint32_t *RelocsSize - ) -{ - uint32_t RelocTableSize; - uint32_t BlockAddress; - uint32_t BlockSize; - uint32_t Index; - uint32_t RelocAddress; - - assert (Image != NULL); - assert (RelocsSize != NULL); - - if (Image->RelocInfo.NumRelocs == 0) { - *RelocsSize = 0; - return true; - } - - assert (Image->RelocInfo.NumRelocs <= MAX_UINT32); - - RelocTableSize = 0; - BlockAddress = PAGE(Image->RelocInfo.Relocs[0].Target); - BlockSize = sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK); - - for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) { - RelocAddress = PAGE(Image->RelocInfo.Relocs[Index].Target); - if (RelocAddress != BlockAddress) { - BlockSize = ALIGN_VALUE (BlockSize, 4); - - RelocTableSize += BlockSize; - - BlockAddress = RelocAddress; - BlockSize = sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK); - } - - BlockSize += sizeof (UINT16); - } - - BlockSize = ALIGN_VALUE (BlockSize, 4); - RelocTableSize += BlockSize; - - *RelocsSize = RelocTableSize; - - return true; -} - -#define EmitPeGetDebugSectionSize PE_SUFFIX (EmitPeGetDebugSectionSize) -static -void -EmitPeGetDebugSectionSize ( - const image_tool_image_info_t *Image, - uint32_t *DebugSize - ) -{ - uint32_t Size; - - assert (Image != NULL); - assert (DebugSize != NULL); - - Size = 0; - if (Image->DebugInfo.SymbolsPath != NULL) { - Size = sizeof (DebugData) + Image->DebugInfo.SymbolsPathLen + 1; - } - - *DebugSize = Size; -} - -#define EmitPeGetExtraSectionsSize PE_SUFFIX (EmitPeGetExtraSectionsSize) -static -bool -EmitPeGetExtraSectionsSize ( - image_tool_pe_emit_context_t *Context, - uint32_t *SectionsSize - ) -{ - const image_tool_image_info_t *Image; - bool Result; - uint32_t AlignedRelocTableSize; - bool Overflow; - uint32_t AlignedDebugTableSize; - uint32_t AlignedHiiTableSize; - - assert (Context != NULL); - assert (SectionsSize != NULL); - - Image = Context->Image; - - Result = EmitPeGetRelocSectionSize (Image, &Context->RelocTableSize); - if (!Result) { - raise (); - return false; - } - - EmitPeGetDebugSectionSize (Image, &Context->DebugTableSize); - - Overflow = BaseOverflowAlignUpU32 ( - Context->RelocTableSize, - Context->FileAlignment, - &AlignedRelocTableSize + strncpy ( + (char *)SectionHeader->Name, + Name, + sizeof (SectionHeader->Name) ); - if (Overflow) { - raise (); - return false; - } + SectionHeader->Name[ARRAY_SIZE (SectionHeader->Name) - 1] = 0; - Overflow = BaseOverflowAlignUpU32 ( - Context->DebugTableSize, - Context->FileAlignment, - &AlignedDebugTableSize - ); - if (Overflow) { - raise (); - return false; - } + SectionHeader->VirtualSize = ALIGN_VALUE (Size, PeHdr->SectionAlignment); + SectionHeader->VirtualAddress = PeHdr->SizeOfImage; + SectionHeader->SizeOfRawData = ALIGN_VALUE (Size, PeHdr->FileAlignment); + SectionHeader->PointerToRawData = Offset; + SectionHeader->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_READ; - AlignedHiiTableSize = 0; - if (Context->Image->HiiInfo.DataSize > 0) { - Overflow = BaseOverflowAddU32 ( - mHiiResourceSectionHeaderSize, - Context->Image->HiiInfo.DataSize, - &AlignedHiiTableSize - ); + PeHdr->SizeOfInitializedData += SectionHeader->VirtualSize; + PeHdr->SizeOfImage += SectionHeader->VirtualSize; - Overflow |= BaseOverflowAlignUpU32 ( - AlignedHiiTableSize, - Context->FileAlignment, - &AlignedHiiTableSize - ); - if (Overflow) { - raise (); - return false; - } - } - - Overflow = BaseOverflowAddU32 ( - AlignedRelocTableSize, - AlignedDebugTableSize, - SectionsSize - ); - if (Overflow) { - raise (); - return false; - } - - Overflow = BaseOverflowAddU32 ( - *SectionsSize, - AlignedHiiTableSize, - SectionsSize - ); - if (Overflow) { - raise (); - return false; - } - - return true; + BufferOffset = ImageToolBufferAppendReserve ( + Buffer, + SectionHeader->SizeOfRawData - Size + ); + return BufferOffset != MAX_UINT32; } -#define ToolImageEmitPeSectionHeaders PE_SUFFIX (ToolImageEmitPeSectionHeaders) +#define ToolImageEmitPeHiiTable PE_SUFFIX (ToolImageEmitPeHiiTable) static bool -ToolImageEmitPeSectionHeaders ( - const image_tool_pe_emit_context_t *Context, - uint8_t **Buffer, - uint32_t *BufferSize, - uint32_t AlignedHeaderSize +ToolImageEmitPeHiiTable ( + image_tool_dynamic_buffer *Buffer, + EFI_IMAGE_NT_HEADERS *PeHdr, + EFI_IMAGE_SECTION_HEADER *SectionHeader, + const image_tool_image_info_t *Image ) { - const image_tool_image_info_t *Image; - uint16_t SectionHeadersSize; - uint32_t SectionOffset; - EFI_IMAGE_SECTION_HEADER *Sections; - uint8_t Index; + bool Success; + uint32_t HiiTableOffset; + uint32_t HiiTableSize; + void *HiiTable; + uint32_t Offset; - assert (Context != NULL); - assert (Buffer != NULL); - assert (BufferSize != NULL); - - Image = Context->Image; - SectionHeadersSize = (uint16_t) (Image->SegmentInfo.NumSegments * sizeof (EFI_IMAGE_SECTION_HEADER)); - SectionOffset = AlignedHeaderSize; - Sections = (void *) *Buffer; - - assert (SectionHeadersSize <= *BufferSize); - - for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { - assert (Sections[Index].Characteristics == 0); - - if (Image->SegmentInfo.Segments[Index].Read) { - Sections[Index].Characteristics |= EFI_IMAGE_SCN_MEM_READ; - } - - if (Image->SegmentInfo.Segments[Index].Write) { - Sections[Index].Characteristics |= EFI_IMAGE_SCN_MEM_WRITE; - } - - if (Image->SegmentInfo.Segments[Index].Execute) { - Sections[Index].Characteristics |= EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_CNT_CODE; - } else { - Sections[Index].Characteristics |= EFI_IMAGE_SCN_CNT_INITIALIZED_DATA; - } - - Sections[Index].PointerToRawData = SectionOffset; - Sections[Index].VirtualAddress = SectionOffset; - Sections[Index].SizeOfRawData = ALIGN_VALUE (Image->SegmentInfo.Segments[Index].UnpaddedSize, Context->FileAlignment); - Sections[Index].VirtualSize = Image->SegmentInfo.Segments[Index].ImageSize; - - strncpy ( - (char *) Sections[Index].Name, - Image->SegmentInfo.Segments[Index].Name, - sizeof (Sections[Index].Name) - ); - - SectionOffset += Sections[Index].SizeOfRawData; + HiiTableOffset = ImageToolBufferAppendReserve ( + Buffer, + mHiiResourceSectionHeaderSize + ); + if (HiiTableOffset == MAX_UINT32) { + DEBUG_RAISE (); + return false; } - if (Image->HeaderInfo.FixedAddress) { - for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { - if ((Sections[Index].Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) { - WriteUnaligned64 ( - (VOID *)&Sections[Index].PointerToRelocations, - Image->HeaderInfo.BaseAddress - ); - break; - } - } + assert (IS_ALIGNED (HiiTableOffset, PeHdr->FileAlignment)); - if (Index == Image->SegmentInfo.NumSegments) { - raise (); - return false; - } - } - - *BufferSize -= SectionHeadersSize; - *Buffer += SectionHeadersSize; - - assert (SectionHeadersSize == Context->HdrInfo.SectionHeadersSize); - - return true; -} - -#define ToolImageEmitPeExtraSectionHeaders PE_SUFFIX (ToolImageEmitPeExtraSectionHeaders) -static -bool -ToolImageEmitPeExtraSectionHeaders ( - image_tool_pe_emit_context_t *Context, - uint8_t **Buffer, - uint32_t *BufferSize, - uint32_t AlignedHeaderSize - ) -{ - uint32_t SectionHeadersSize; - EFI_IMAGE_SECTION_HEADER *Section; - uint32_t SectionOffset; - uint32_t HiiSectionSize; - - assert (Context != NULL); - assert (Buffer != NULL); - assert (BufferSize != NULL); - - SectionHeadersSize = 0; - SectionOffset = AlignedHeaderSize + Context->SectionsSize; - - if (Context->Image->HiiInfo.DataSize > 0) { - ++Context->PeHdr->CommonHeader.FileHeader.NumberOfSections; - - assert (sizeof (EFI_IMAGE_SECTION_HEADER) <= *BufferSize); - - HiiSectionSize = mHiiResourceSectionHeaderSize + Context->Image->HiiInfo.DataSize; - - Section = (void *) *Buffer; - - strncpy ((char *)Section->Name, ".rsrc", sizeof (Section->Name)); - Section->SizeOfRawData = ALIGN_VALUE (HiiSectionSize, Context->FileAlignment); - Section->VirtualSize = ALIGN_VALUE (HiiSectionSize, Context->Image->SegmentInfo.SegmentAlignment); - Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_READ; - Section->PointerToRawData = SectionOffset; - Section->VirtualAddress = Section->PointerToRawData; - - Context->HiiSectionAddress = SectionOffset; - - SectionOffset += Section->SizeOfRawData; - - Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = HiiSectionSize; - Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = Section->PointerToRawData; - - *BufferSize -= sizeof (EFI_IMAGE_SECTION_HEADER); - *Buffer += sizeof (EFI_IMAGE_SECTION_HEADER); - SectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER); - } - - if (Context->RelocTableSize > 0) { - ++Context->PeHdr->CommonHeader.FileHeader.NumberOfSections; - - assert (sizeof (EFI_IMAGE_SECTION_HEADER) <= *BufferSize); - - Section = (void *) *Buffer; - - strncpy ((char *)Section->Name, ".reloc", sizeof (Section->Name)); - Section->SizeOfRawData = ALIGN_VALUE (Context->RelocTableSize, Context->FileAlignment); - Section->VirtualSize = Section->SizeOfRawData; - Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA - | EFI_IMAGE_SCN_MEM_DISCARDABLE | EFI_IMAGE_SCN_MEM_READ; - Section->PointerToRawData = SectionOffset; - Section->VirtualAddress = Section->PointerToRawData; - - SectionOffset += Section->SizeOfRawData; - - Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Context->RelocTableSize; - Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Section->PointerToRawData; - - *BufferSize -= sizeof (EFI_IMAGE_SECTION_HEADER); - *Buffer += sizeof (EFI_IMAGE_SECTION_HEADER); - SectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER); - } - - if (Context->DebugTableSize > 0) { - ++Context->PeHdr->CommonHeader.FileHeader.NumberOfSections; - - assert (sizeof (EFI_IMAGE_SECTION_HEADER) <= *BufferSize); - - Section = (void *) *Buffer; - - strncpy ((char *)Section->Name, ".debug", sizeof (Section->Name)); - Section->SizeOfRawData = ALIGN_VALUE (Context->DebugTableSize, Context->FileAlignment); - Section->VirtualSize = Section->SizeOfRawData; - Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_READ; - Section->PointerToRawData = SectionOffset; - Section->VirtualAddress = Section->PointerToRawData; - - SectionOffset += Section->SizeOfRawData; - - Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); - Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Section->VirtualAddress; - - *BufferSize -= sizeof (EFI_IMAGE_SECTION_HEADER); - *Buffer += sizeof (EFI_IMAGE_SECTION_HEADER); - SectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER); - } - - assert (SectionHeadersSize == Context->HdrInfo.ExtraSectionHeadersSize); - assert (SectionOffset == Context->UnsignedFileSize); - - return true; -} - -#define ToolImageEmitPeHeaders PE_SUFFIX (ToolImageEmitPeHeaders) -static -bool -ToolImageEmitPeHeaders ( - image_tool_pe_emit_context_t *Context, - uint8_t **Buffer, - uint32_t *BufferSize, - uint32_t AlignedHeaderSize - ) -{ - const image_tool_image_info_t *Image; - EFI_IMAGE_DOS_HEADER *DosHdr; - EFI_IMAGE_NT_HEADERS *PePlusHdr; - bool Result; - uint32_t HeaderPadding; - - assert (Context != NULL); - assert (Buffer != NULL); - assert (BufferSize != NULL); - - assert (sizeof (EFI_IMAGE_DOS_HEADER) <= *BufferSize); - - Image = Context->Image; - DosHdr = (void *) *Buffer; - - DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE; - DosHdr->e_lfanew = sizeof (EFI_IMAGE_DOS_HEADER); - - *BufferSize -= sizeof (EFI_IMAGE_DOS_HEADER); - *Buffer += sizeof (EFI_IMAGE_DOS_HEADER); - - assert (sizeof (EFI_IMAGE_NT_HEADERS) <= *BufferSize); - - PePlusHdr = (EFI_IMAGE_NT_HEADERS *)(VOID *) *Buffer; - - PePlusHdr->CommonHeader.Signature = EFI_IMAGE_NT_SIGNATURE; - PePlusHdr->CommonHeader.FileHeader.Machine = Image->HeaderInfo.Machine; - PePlusHdr->CommonHeader.FileHeader.NumberOfSections = (UINT16)Image->SegmentInfo.NumSegments; - PePlusHdr->CommonHeader.FileHeader.SizeOfOptionalHeader = Context->HdrInfo.SizeOfOptionalHeader; - PePlusHdr->CommonHeader.FileHeader.Characteristics = - EFI_IMAGE_FILE_EXECUTABLE_IMAGE | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED | - EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED | EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE; - - if (Image->RelocInfo.RelocsStripped) { - PePlusHdr->CommonHeader.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED; - } - - PePlusHdr->Magic = EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC; - PePlusHdr->AddressOfEntryPoint = Image->HeaderInfo.EntryPointAddress; - PePlusHdr->SectionAlignment = Image->SegmentInfo.SegmentAlignment; - PePlusHdr->FileAlignment = Context->FileAlignment; - PePlusHdr->SizeOfHeaders = AlignedHeaderSize; - PePlusHdr->SizeOfImage = AlignedHeaderSize; - PePlusHdr->ImageBase = (UINTN)Image->HeaderInfo.BaseAddress; - PePlusHdr->Subsystem = Image->HeaderInfo.Subsystem; - PePlusHdr->NumberOfRvaAndSizes = Context->HdrInfo.NumberOfRvaAndSizes; - - STATIC_ASSERT( - OFFSET_OF(EFI_IMAGE_NT_HEADERS, DataDirectory) == sizeof (EFI_IMAGE_NT_HEADERS), - "The following code needs to be updated to consider padding." + HiiTable = ImageToolBufferGetPointer (Buffer, HiiTableOffset); + InitializeHiiResouceSectionHeader ( + HiiTable, + SectionHeader->VirtualAddress, + Image->HiiInfo.DataSize ); + HiiTable = NULL; - Context->PeHdr = PePlusHdr; - - *BufferSize -= sizeof (EFI_IMAGE_NT_HEADERS) + PePlusHdr->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY); - *Buffer += sizeof (EFI_IMAGE_NT_HEADERS) + PePlusHdr->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY); - - Result = ToolImageEmitPeSectionHeaders (Context, Buffer, BufferSize, AlignedHeaderSize); - if (!Result) { + Offset = ImageToolBufferAppend ( + Buffer, + Image->HiiInfo.Data, + Image->HiiInfo.DataSize + ); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); return false; } - Result = ToolImageEmitPeExtraSectionHeaders (Context, Buffer, BufferSize, AlignedHeaderSize); - if (!Result) { + HiiTableSize = ImageToolBufferGetSize (Buffer) - HiiTableOffset; + + Success = InternalFinalizeExtraSection ( + Buffer, + PeHdr, + SectionHeader, + ".rsrc", + HiiTableSize, + HiiTableOffset + ); + if (!Success) { + DEBUG_RAISE (); return false; } - HeaderPadding = AlignedHeaderSize - Context->HdrInfo.SizeOfHeaders; - - assert (HeaderPadding <= *BufferSize); - - *BufferSize -= HeaderPadding; - *Buffer += HeaderPadding; - - return true; -} - -#define ToolImageEmitPeSections PE_SUFFIX (ToolImageEmitPeSections) -static -bool -ToolImageEmitPeSections ( - const image_tool_pe_emit_context_t *Context, - uint8_t **Buffer, - uint32_t *BufferSize - ) -{ - const image_tool_image_info_t *Image; - uint32_t SectionsSize; - uint8_t Index; - const image_tool_segment_t *Segment; - uint32_t SectionPadding; - bool FirstCode; - -#if PE_ARCH == 32 - bool FirstData; -#endif - - assert (Context != NULL); - assert (Buffer != NULL); - assert (BufferSize != NULL); - - assert (Context->SectionsSize <= *BufferSize); - - Image = Context->Image; - SectionsSize = 0; - FirstCode = true; - -#if PE_ARCH == 32 - FirstData = true; -#endif - - for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { - Segment = &Image->SegmentInfo.Segments[Index]; - - Context->PeHdr->SizeOfImage += Segment->ImageSize; - - if (Segment->Execute) { - if (FirstCode) { - Context->PeHdr->BaseOfCode = Segment->ImageAddress; - FirstCode = false; - } - } -#if PE_ARCH == 32 - else { - if (FirstData) { - Context->PeHdr->BaseOfData = Segment->ImageAddress; - FirstData = false; - } - } -#endif - - assert (Segment->UnpaddedSize <= *BufferSize); - - memmove (*Buffer, Segment->Data, Segment->UnpaddedSize); - - *BufferSize -= Segment->UnpaddedSize; - *Buffer += Segment->UnpaddedSize; - SectionsSize += Segment->UnpaddedSize; - - SectionPadding = ALIGN_VALUE_ADDEND ( - Segment->UnpaddedSize, - Context->FileAlignment - ); - - assert (SectionPadding <= *BufferSize); - - *BufferSize -= SectionPadding; - *Buffer += SectionPadding; - SectionsSize += SectionPadding; - - if (Segment->Execute) { - Context->PeHdr->BaseOfCode = MIN(Context->PeHdr->BaseOfCode, Segment->ImageAddress); - Context->PeHdr->SizeOfCode += Segment->ImageSize; - } else { -#if PE_ARCH == 32 - Context->PeHdr->BaseOfData = MIN(Context->PeHdr->BaseOfData, Segment->ImageAddress); -#endif - Context->PeHdr->SizeOfInitializedData += Segment->ImageSize; - } - } - - assert (SectionsSize == Context->SectionsSize); + PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader->VirtualAddress; + PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = HiiTableSize; return true; } @@ -647,254 +147,496 @@ ToolImageEmitPeSections ( static bool ToolImageEmitPeRelocTable ( - const image_tool_pe_emit_context_t *Context, - uint8_t **Buffer, - uint32_t *BufferSize + image_tool_dynamic_buffer *Buffer, + EFI_IMAGE_NT_HEADERS *PeHdr, + EFI_IMAGE_SECTION_HEADER *SectionHeader, + const image_tool_image_info_t *Image ) { - const image_tool_image_info_t *Image; - uint32_t RelocTableSize; - EFI_IMAGE_BASE_RELOCATION_BLOCK *RelocBlock; - uint32_t BlockAddress; - uint32_t BlockNumRelocs; - uint32_t Index; - uint32_t RelocAddress; - uint32_t RelocTablePadding; + bool Success; + uint32_t RelocTableSize; + EFI_IMAGE_BASE_RELOCATION_BLOCK RelocBlock; + uint32_t BlockAddress; + uint32_t Index; + uint32_t RelocAddress; + uint16_t Relocation; + uint32_t RelocTableOffset; + uint32_t RelocTableEnd; + uint32_t RelocBlockOffset; + uint32_t NewRelocBlockOffset; + uint32_t Offset; - assert (Context != NULL); - assert (Buffer != NULL); - assert (BufferSize != NULL); - - if (Context->RelocTableSize == 0) { - return true; + RelocBlockOffset = ImageToolBufferAppendReserve (Buffer, sizeof (RelocBlock)); + if (RelocBlockOffset == MAX_UINT32) { + DEBUG_RAISE (); + return false; } - Image = Context->Image; + RelocTableOffset = RelocBlockOffset; - Context->PeHdr->SizeOfImage += ALIGN_VALUE (Context->RelocTableSize, Image->SegmentInfo.SegmentAlignment); + assert (IS_ALIGNED (RelocTableOffset, PeHdr->FileAlignment)); - assert (Image->RelocInfo.NumRelocs > 0); - assert (Image->RelocInfo.NumRelocs <= MAX_UINT32); - - assert (sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK) <= *BufferSize); - - RelocTableSize = 0; - RelocBlock = (void *) *Buffer; - BlockAddress = PAGE(Image->RelocInfo.Relocs[0].Target); - BlockNumRelocs = 0; - - RelocBlock->VirtualAddress = BlockAddress; - RelocBlock->SizeOfBlock = sizeof (*RelocBlock); + BlockAddress = PAGE (Image->RelocInfo.Relocs[0].Target); for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) { - RelocAddress = PAGE(Image->RelocInfo.Relocs[Index].Target); + RelocAddress = PAGE (Image->RelocInfo.Relocs[Index].Target); if (RelocAddress != BlockAddress) { - RelocBlock->SizeOfBlock = ALIGN_VALUE (RelocBlock->SizeOfBlock, 4); + Offset = ImageToolBufferAppendReserveAlign ( + Buffer, + ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK) + ); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } - assert (RelocBlock->SizeOfBlock <= *BufferSize); + NewRelocBlockOffset = ImageToolBufferAppendReserve ( + Buffer, + sizeof (RelocBlock) + ); + if (NewRelocBlockOffset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } - *BufferSize -= RelocBlock->SizeOfBlock; - *Buffer += RelocBlock->SizeOfBlock; - RelocTableSize += RelocBlock->SizeOfBlock; + RelocBlock.VirtualAddress = BlockAddress; + RelocBlock.SizeOfBlock = NewRelocBlockOffset - RelocBlockOffset; + ImageToolBufferWrite ( + Buffer, + RelocBlockOffset, + &RelocBlock, + sizeof (RelocBlock) + ); - RelocBlock = (void *) *Buffer; + RelocBlockOffset = NewRelocBlockOffset; - BlockAddress = RelocAddress; - BlockNumRelocs = 0; - - RelocBlock->VirtualAddress = BlockAddress; - RelocBlock->SizeOfBlock = sizeof (*RelocBlock); + BlockAddress = RelocAddress; } - RelocBlock->SizeOfBlock += sizeof (*RelocBlock->Relocations); + Relocation = PAGE_OFF(Image->RelocInfo.Relocs[Index].Target); + Relocation |= ((uint16_t)Image->RelocInfo.Relocs[Index].Type) << 12U; - assert (RelocBlock->SizeOfBlock <= *BufferSize); - - RelocBlock->Relocations[BlockNumRelocs] = PAGE_OFF(Image->RelocInfo.Relocs[Index].Target); - RelocBlock->Relocations[BlockNumRelocs] |= ((uint16_t)Image->RelocInfo.Relocs[Index].Type) << 12U; - - ++BlockNumRelocs; + Offset = ImageToolBufferAppend (Buffer, &Relocation, sizeof (Relocation)); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } } - RelocBlock->SizeOfBlock = ALIGN_VALUE (RelocBlock->SizeOfBlock, 4); + Offset = ImageToolBufferAppendReserveAlign ( + Buffer, + ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK) + ); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } - assert (RelocBlock->SizeOfBlock <= *BufferSize); + RelocTableEnd = ImageToolBufferGetSize (Buffer); - *BufferSize -= RelocBlock->SizeOfBlock; - *Buffer += RelocBlock->SizeOfBlock; - RelocTableSize += RelocBlock->SizeOfBlock; - - assert (RelocTableSize == Context->RelocTableSize); - - RelocTablePadding = ALIGN_VALUE_ADDEND ( - RelocTableSize, - Context->FileAlignment + RelocBlock.VirtualAddress = BlockAddress; + RelocBlock.SizeOfBlock = RelocTableEnd - RelocBlockOffset; + ImageToolBufferWrite ( + Buffer, + RelocBlockOffset, + &RelocBlock, + sizeof (RelocBlock) ); - assert (RelocTablePadding <= *BufferSize); + RelocTableSize = RelocTableEnd - RelocTableOffset; - *BufferSize -= RelocTablePadding; - *Buffer += RelocTablePadding; + Success = InternalFinalizeExtraSection ( + Buffer, + PeHdr, + SectionHeader, + ".reloc", + RelocTableSize, + RelocTableOffset + ); + if (!Success) { + DEBUG_RAISE (); + return false; + } + SectionHeader->Characteristics |= EFI_IMAGE_SCN_MEM_DISCARDABLE; + + PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = SectionHeader->VirtualAddress; + PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = RelocTableSize; return true; } -typedef struct { - EFI_IMAGE_DEBUG_DIRECTORY_ENTRY CodeViewDirEntry; - EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY CodeViewEntry; - uint8_t PdbPath[]; -} image_tool_debug_dir_t; - -STATIC_ASSERT( - OFFSET_OF(image_tool_debug_dir_t, PdbPath) == sizeof (image_tool_debug_dir_t), - "Flexible array aliases padding." - ); - #define ToolImageEmitPeDebugTable PE_SUFFIX (ToolImageEmitPeDebugTable) static bool ToolImageEmitPeDebugTable ( - const image_tool_pe_emit_context_t *Context, - uint8_t **Buffer, - uint32_t *BufferSize + image_tool_dynamic_buffer *Buffer, + EFI_IMAGE_NT_HEADERS *PeHdr, + EFI_IMAGE_SECTION_HEADER *SectionHeader, + const image_tool_image_info_t *Image ) { - const image_tool_image_info_t *Image; - uint32_t DebugTablePadding; - DebugData *Data; + bool Success; + uint32_t DebugDirOffset; + uint32_t DebugDirSize; + image_tool_debug_dir_t *Data; + uint32_t Offset; - assert (Context != NULL); - assert (Buffer != NULL); - assert (BufferSize != NULL); + assert (Image->DebugInfo.SymbolsPath != NULL); - Image = Context->Image; - - if (Context->DebugTableSize == 0) { - return true; + DebugDirOffset = ImageToolBufferAppendReserve (Buffer, sizeof (*Data)); + if (DebugDirOffset == MAX_UINT32) { + DEBUG_RAISE (); + return false; } - Context->PeHdr->SizeOfImage += ALIGN_VALUE (Context->DebugTableSize, Image->SegmentInfo.SegmentAlignment); + assert (IS_ALIGNED (DebugDirOffset, PeHdr->FileAlignment)); - assert (Image->DebugInfo.SymbolsPathLen + 1 <= Context->DebugTableSize); - assert (Context->DebugTableSize <= *BufferSize); + Offset = ImageToolBufferAppend ( + Buffer, + Image->DebugInfo.SymbolsPath, + Image->DebugInfo.SymbolsPathLen + 1 + ); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); + return false; + } - Data = (DebugData *) *Buffer; + DebugDirSize = ImageToolBufferGetSize (Buffer) - DebugDirOffset; + Success = InternalFinalizeExtraSection ( + Buffer, + PeHdr, + SectionHeader, + ".debug", + DebugDirSize, + DebugDirOffset + ); + if (!Success) { + DEBUG_RAISE (); + return false; + } + SectionHeader->Characteristics |= EFI_IMAGE_SCN_MEM_DISCARDABLE; + + PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = SectionHeader->VirtualAddress; + PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (Data->Dir); + + Data = ImageToolBufferGetPointer (Buffer, DebugDirOffset); + + memset (Data, 0, sizeof (*Data)); Data->Dir.Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW; - Data->Dir.SizeOfData = sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Image->DebugInfo.SymbolsPathLen + 1; - Data->Dir.RVA = (Context->UnsignedFileSize - ALIGN_VALUE (Context->DebugTableSize, Context->FileAlignment)) + sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); - Data->Dir.FileOffset = Data->Dir.RVA; - + Data->Dir.SizeOfData = DebugDirSize - OFFSET_OF (image_tool_debug_dir_t, Nb10); + Data->Dir.RVA = SectionHeader->VirtualAddress + OFFSET_OF (image_tool_debug_dir_t, Nb10); + Data->Dir.FileOffset = SectionHeader->PointerToRawData + OFFSET_OF (image_tool_debug_dir_t, Nb10); Data->Nb10.Signature = CODEVIEW_SIGNATURE_NB10; - memmove (Data->Name, Image->DebugInfo.SymbolsPath, Image->DebugInfo.SymbolsPathLen + 1); - assert (sizeof (*Data) + Image->DebugInfo.SymbolsPathLen + 1 == Context->DebugTableSize); - - *BufferSize -= Context->DebugTableSize; - *Buffer += Context->DebugTableSize; - - DebugTablePadding = ALIGN_VALUE_ADDEND( - Context->DebugTableSize, - Context->FileAlignment - ); - - assert (DebugTablePadding <= *BufferSize); - - *BufferSize -= DebugTablePadding; - *Buffer += DebugTablePadding; + Data = NULL; return true; } -#define ToolImageEmitPeHiiTable PE_SUFFIX (ToolImageEmitPeHiiTable) static bool -ToolImageEmitPeHiiTable ( - const image_tool_pe_emit_context_t *Context, - uint8_t **Buffer, - uint32_t *BufferSize +ToolImagePeHiiTableRequired ( + const image_tool_image_info_t *Image ) { - const image_tool_image_info_t *Image; - uint32_t HiiTablePadding; + return Image->HiiInfo.DataSize != 0; +} - assert (Context != NULL); - assert (Buffer != NULL); - assert (BufferSize != NULL); +static +bool +ToolImagePeRelocTableRequired ( + const image_tool_image_info_t *Image + ) +{ + return Image->RelocInfo.NumRelocs != 0; +} - Image = Context->Image; +static +bool +ToolImagePeDebugTableRequired ( + const image_tool_image_info_t *Image + ) +{ + return Image->DebugInfo.SymbolsPath != NULL; +} - if (Image->HiiInfo.DataSize == 0) { - return true; +#define ToolImageEmitPeSection PE_SUFFIX (ToolImageEmitPeSection) +static +bool +ToolImageEmitPeSection ( + image_tool_dynamic_buffer *Buffer, + EFI_IMAGE_NT_HEADERS *PeHdr, + EFI_IMAGE_SECTION_HEADER *SectionHeader, + const image_tool_image_info_t *Image, + bool Xip, + const image_tool_segment_t *Segment + ) +{ + uint32_t SectionOffset; + uint32_t SizeOfRawData; + uint32_t Offset; + + SectionOffset = ImageToolBufferAppend ( + Buffer, + Segment->Data, + Segment->UnpaddedSize + ); + if (SectionOffset == MAX_UINT32) { + DEBUG_RAISE (); + return false; } - Context->PeHdr->SizeOfImage += ALIGN_VALUE (mHiiResourceSectionHeaderSize + Image->HiiInfo.DataSize, Image->SegmentInfo.SegmentAlignment); + assert (IS_ALIGNED (SectionOffset, PeHdr->FileAlignment)); - assert (mHiiResourceSectionHeaderSize <= *BufferSize); + if (!Xip) { + SizeOfRawData = Segment->UnpaddedSize; + } else { + SizeOfRawData = Segment->ImageSize; + } - InitializeHiiResouceSectionHeader ( - *Buffer, - Context->HiiSectionAddress, - Context->Image->HiiInfo.DataSize + strncpy ( + (char *)SectionHeader->Name, + Segment->Name, + sizeof (SectionHeader->Name) ); + SectionHeader->Name[ARRAY_SIZE (SectionHeader->Name) - 1] = 0; - *BufferSize -= mHiiResourceSectionHeaderSize; - *Buffer += mHiiResourceSectionHeaderSize; + SectionHeader->VirtualSize = Segment->ImageSize; + SectionHeader->VirtualAddress = Segment->ImageAddress; + SectionHeader->SizeOfRawData = ALIGN_VALUE (SizeOfRawData, PeHdr->FileAlignment); + SectionHeader->PointerToRawData = SectionOffset; - assert (Image->HiiInfo.DataSize <= *BufferSize); + assert (SectionHeader->Characteristics == 0); - memmove (*Buffer, Image->HiiInfo.Data, Image->HiiInfo.DataSize); + if (Segment->Read) { + SectionHeader->Characteristics |= EFI_IMAGE_SCN_MEM_READ; + } - *BufferSize -= Image->HiiInfo.DataSize; - *Buffer += Image->HiiInfo.DataSize; + if (Segment->Write) { + SectionHeader->Characteristics |= EFI_IMAGE_SCN_MEM_WRITE; + } - HiiTablePadding = ALIGN_VALUE_ADDEND( - mHiiResourceSectionHeaderSize + Image->HiiInfo.DataSize, - Context->FileAlignment - ); + if (Segment->Execute) { + SectionHeader->Characteristics |= EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_CNT_CODE; - assert (HiiTablePadding <= *BufferSize); + PeHdr->SizeOfCode += Segment->ImageSize; + if (PeHdr->BaseOfCode == 0) { + PeHdr->BaseOfCode = Segment->ImageAddress; + } + } else { + SectionHeader->Characteristics |= EFI_IMAGE_SCN_CNT_INITIALIZED_DATA; - *BufferSize -= HiiTablePadding; - *Buffer += HiiTablePadding; + PeHdr->SizeOfInitializedData += Segment->ImageSize; +#if PE_ARCH == 32 + if (PeHdr->BaseOfData == 0) { + PeHdr->BaseOfData = Segment->ImageAddress; + } +#endif + } + + assert (PeHdr->SizeOfImage == SectionHeader->VirtualAddress); + PeHdr->SizeOfImage += SectionHeader->VirtualSize; + + Offset = ImageToolBufferAppendReserve ( + Buffer, + SectionHeader->SizeOfRawData - Segment->UnpaddedSize + ); + return Offset != MAX_UINT32; +} + +#define ToolImageEmitPeSections PE_SUFFIX (ToolImageEmitPeSections) +static +bool +ToolImageEmitPeSections ( + image_tool_dynamic_buffer *Buffer, + EFI_IMAGE_NT_HEADERS *PeHdr, + EFI_IMAGE_SECTION_HEADER *SectionHeaders, + const image_tool_image_info_t *Image, + bool Xip + ) +{ + bool Success; + uint16_t Index; + const image_tool_segment_t *Segment; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + + if (PeHdr->SizeOfImage != Image->SegmentInfo.Segments[0].ImageAddress) { + DEBUG_RAISE (); + return false; + } + + for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { + Segment = &Image->SegmentInfo.Segments[Index]; + SectionHeader = &SectionHeaders[Index]; + + Success = ToolImageEmitPeSection ( + Buffer, + PeHdr, + SectionHeader, + Image, + Xip, + Segment + ); + if (!Success) { + DEBUG_RAISE (); + return false; + } + } + + if (ToolImagePeHiiTableRequired (Image)) { + Success = ToolImageEmitPeHiiTable (Buffer, PeHdr, &SectionHeaders[Index], Image); + if (!Success) { + DEBUG_RAISE (); + return false; + } + + ++Index; + } + + if (ToolImagePeRelocTableRequired (Image)) { + Success = ToolImageEmitPeRelocTable (Buffer, PeHdr, &SectionHeaders[Index], Image); + if (!Success) { + DEBUG_RAISE (); + return false; + } + + ++Index; + } + + if (ToolImagePeDebugTableRequired (Image)) { + Success = ToolImageEmitPeDebugTable (Buffer, PeHdr, &SectionHeaders[Index], Image); + if (!Success) { + DEBUG_RAISE (); + return false; + } + + ++Index; + } + + assert (Index == PeHdr->CommonHeader.FileHeader.NumberOfSections); + + if (Image->HeaderInfo.FixedAddress) { + for (Index = 0; Index < PeHdr->CommonHeader.FileHeader.NumberOfSections; ++Index) { + if ((SectionHeaders[Index].Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) { + WriteUnaligned64 ( + (VOID *)&SectionHeaders[Index].PointerToRelocations, + PeHdr->ImageBase + ); + break; + } + } + + if (Index == PeHdr->CommonHeader.FileHeader.NumberOfSections) { + DEBUG_RAISE (); + return false; + } + } return true; } -#define ToolImageEmitPeExtraSections PE_SUFFIX (ToolImageEmitPeExtraSections) +STATIC CONST EFI_IMAGE_DOS_HEADER mDosHdr = { + .e_magic = EFI_IMAGE_DOS_SIGNATURE, + .e_lfanew = sizeof (mDosHdr) +}; + +#define ToolImageEmitPeFile PE_SUFFIX (ToolImageEmitPeFile) static bool -ToolImageEmitPeExtraSections ( - const image_tool_pe_emit_context_t *Context, - uint8_t **Buffer, - uint32_t *BufferSize +ToolImageEmitPeFile ( + image_tool_dynamic_buffer *Buffer, + const image_tool_image_info_t *Image, + bool Xip ) { - uint32_t OldBufferSize; - bool Result; + bool Success; + uint32_t FileAlignment; + uint32_t PeOffset; + EFI_IMAGE_NT_HEADERS *PeHdr; + uint16_t NumSections; + EFI_IMAGE_SECTION_HEADER *SectionHeaders; + uint32_t SectionHeadersOffset; + uint32_t SectionHeadersSize; + uint32_t SizeOfPeHeaders; + uint32_t SizeOfHeaders; + uint32_t AlignedSizeOfHeaders; + void *BufferPeHdr; + uint32_t Offset; - assert (Context != NULL); - assert (Buffer != NULL); - assert (BufferSize != NULL); + if (!Xip) { + FileAlignment = 64; + } else { + FileAlignment = Image->SegmentInfo.SegmentAlignment; + } - OldBufferSize = *BufferSize; + NumSections = Image->SegmentInfo.NumSegments; + NumSections += ToolImagePeHiiTableRequired (Image) ? 1 : 0; + NumSections += ToolImagePeRelocTableRequired (Image) ? 1 : 0; + NumSections += ToolImagePeDebugTableRequired (Image) ? 1 : 0; - Result = ToolImageEmitPeHiiTable (Context, Buffer, BufferSize); - if (!Result) { + Offset = ImageToolBufferAppend (Buffer, &mDosHdr, sizeof (mDosHdr)); + if (Offset == MAX_UINT32) { + DEBUG_RAISE (); return false; } - Result = ToolImageEmitPeRelocTable (Context, Buffer, BufferSize); - if (!Result) { + SectionHeadersOffset = sizeof (*PeHdr) + SIZE_OF_DATA_DIRECRORY; + SectionHeadersSize = NumSections * sizeof (EFI_IMAGE_SECTION_HEADER); + SizeOfPeHeaders = SectionHeadersOffset + SectionHeadersSize; + SizeOfHeaders = sizeof (mDosHdr) + SizeOfPeHeaders; + AlignedSizeOfHeaders = ALIGN_VALUE (SizeOfHeaders, FileAlignment); + + PeOffset = ImageToolBufferAppendReserve ( + Buffer, + AlignedSizeOfHeaders - sizeof (mDosHdr) + ); + if (PeOffset == MAX_UINT32) { + DEBUG_RAISE (); return false; } - Result = ToolImageEmitPeDebugTable (Context, Buffer, BufferSize); - if (!Result) { + PeHdr = AllocateZeroPool (SizeOfPeHeaders); + if (PeHdr == NULL) { + DEBUG_RAISE (); return false; } - assert ((OldBufferSize - *BufferSize) == Context->ExtraSectionsSize); + SectionHeaders = (EFI_IMAGE_SECTION_HEADER *)((UINT8 *)PeHdr + SectionHeadersOffset); + + PeHdr->CommonHeader.Signature = EFI_IMAGE_NT_SIGNATURE; + PeHdr->CommonHeader.FileHeader.Machine = Image->HeaderInfo.Machine; + PeHdr->CommonHeader.FileHeader.NumberOfSections = NumSections; + PeHdr->CommonHeader.FileHeader.SizeOfOptionalHeader = SIZE_OF_OPTIONAL_HEADER; + PeHdr->CommonHeader.FileHeader.Characteristics = + EFI_IMAGE_FILE_EXECUTABLE_IMAGE | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED | + EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED | EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE; + + if (Image->RelocInfo.RelocsStripped) { + PeHdr->CommonHeader.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED; + } + + PeHdr->Magic = EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC; + PeHdr->AddressOfEntryPoint = Image->HeaderInfo.EntryPointAddress; + PeHdr->ImageBase = (EFI_IMAGE_NT_BASE_ADDRESS)Image->HeaderInfo.BaseAddress; + PeHdr->SectionAlignment = Image->SegmentInfo.SegmentAlignment; + PeHdr->FileAlignment = FileAlignment; + PeHdr->SizeOfImage = ALIGN_VALUE (SizeOfHeaders, PeHdr->SectionAlignment); + PeHdr->SizeOfHeaders = AlignedSizeOfHeaders; + PeHdr->Subsystem = Image->HeaderInfo.Subsystem; + PeHdr->NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; + + Success = ToolImageEmitPeSections (Buffer, PeHdr, SectionHeaders, Image, Xip); + if (!Success) { + FreePool (PeHdr); + DEBUG_RAISE (); + return false; + } + + BufferPeHdr = ImageToolBufferGetPointer (Buffer, PeOffset); + memmove (BufferPeHdr, PeHdr, SizeOfPeHeaders); + FreePool (PeHdr); + BufferPeHdr = NULL; return true; } @@ -902,135 +644,37 @@ ToolImageEmitPeExtraSections ( #define ToolImageEmitPe PE_SUFFIX (ToolImageEmitPe) void * ToolImageEmitPe ( - image_tool_image_info_t *Image, - uint32_t *FileSize + const image_tool_image_info_t *Image, + uint32_t *FileSize, + bool Xip ) { - image_tool_pe_emit_context_t Context; - bool Result; - uint32_t AlignedHeaderSize; - bool Overflow; - uint32_t SectionsOffset; - void *FileBuffer; - uint8_t *Buffer; - uint32_t RemainingSize; - uint32_t ExpectedSize; + bool Success; + image_tool_dynamic_buffer Buffer; + void *FileBuffer; assert (Image != NULL); assert (FileSize != NULL); - memset (&Context, 0, sizeof (Context)); - - // FIXME: Non-XIP is not well-supported right now. - Context.FileAlignment = Image->SegmentInfo.SegmentAlignment; - Image->HeaderInfo.IsXip = true; - ImageInitUnpaddedSize (Image); - Context.Image = Image; + ImageToolBufferInit (&Buffer); - Result = EmitPeGetHeaderSizes (Image, &Context.HdrInfo); - if (!Result) { - raise (); + Success = ToolImageEmitPeFile (&Buffer, Image, Xip); + if (!Success) { + DEBUG_RAISE (); + ImageToolBufferFree (&Buffer); return NULL; } - Overflow = BaseOverflowAlignUpU32 ( - Context.HdrInfo.SizeOfHeaders, - Context.FileAlignment, - &AlignedHeaderSize - ); - if (Overflow) { - raise (); - return NULL; - } + FileBuffer = ImageToolBufferDump (FileSize, &Buffer); - if (AlignedHeaderSize > Image->SegmentInfo.Segments[0].ImageAddress) { - raise (); - return NULL; - } + ImageToolBufferFree (&Buffer); - AlignedHeaderSize = (uint32_t)Image->SegmentInfo.Segments[0].ImageAddress; - - Result = EmitPeGetSectionsSize (&Context, &Context.SectionsSize); - if (!Result) { - raise (); - return NULL; - } - - Overflow = BaseOverflowAddU32 ( - AlignedHeaderSize, - Context.SectionsSize, - &SectionsOffset - ); - if (Overflow) { - raise (); - return NULL; - } - - Result = EmitPeGetExtraSectionsSize (&Context, &Context.ExtraSectionsSize); - if (!Result) { - raise (); - return NULL; - } - - Overflow = BaseOverflowAddU32 ( - SectionsOffset, - Context.ExtraSectionsSize, - &Context.UnsignedFileSize - ); - if (Overflow) { - raise (); - return NULL; - } - - FileBuffer = calloc (1, Context.UnsignedFileSize); if (FileBuffer == NULL) { - raise (); + DEBUG_RAISE (); return NULL; } - Buffer = FileBuffer; - RemainingSize = Context.UnsignedFileSize; - ExpectedSize = Context.UnsignedFileSize; - - Result = ToolImageEmitPeHeaders (&Context, &Buffer, &RemainingSize, AlignedHeaderSize); - if (!Result) { - raise (); - free (FileBuffer); - return NULL; - } - - ExpectedSize -= AlignedHeaderSize; - - assert (RemainingSize == ExpectedSize); - - Result = ToolImageEmitPeSections (&Context, &Buffer, &RemainingSize); - if (!Result) { - raise (); - free (FileBuffer); - return NULL; - } - - ExpectedSize -= Context.SectionsSize; - - assert (RemainingSize == ExpectedSize); - - Result = ToolImageEmitPeExtraSections (&Context, &Buffer, &RemainingSize); - if (!Result) { - raise (); - free (FileBuffer); - return NULL; - } - - ExpectedSize -= Context.ExtraSectionsSize; - - assert (RemainingSize == ExpectedSize); - assert (RemainingSize == 0); - - Context.PeHdr->SizeOfInitializedData += Context.ExtraSectionsSize; - - *FileSize = Context.UnsignedFileSize; - return FileBuffer; } diff --git a/BaseTools/ImageTool/PeEmitCommon.c b/BaseTools/ImageTool/PeEmitCommon.c index c136721a19..9946bdfe11 100644 --- a/BaseTools/ImageTool/PeEmitCommon.c +++ b/BaseTools/ImageTool/PeEmitCommon.c @@ -9,6 +9,7 @@ void * ToolImageEmitPe ( image_tool_image_info_t *Image, uint32_t *FileSize, + bool Xip, bool Strip ) { @@ -20,13 +21,13 @@ ToolImageEmitPe ( case IMAGE_FILE_MACHINE_I386: case IMAGE_FILE_MACHINE_ARMTHUMB_MIXED: { - return ToolImageEmitPe32 (Image, FileSize); + return ToolImageEmitPe32 (Image, FileSize, Xip); } case IMAGE_FILE_MACHINE_X64: case IMAGE_FILE_MACHINE_ARM64: { - return ToolImageEmitPe64 (Image, FileSize); + return ToolImageEmitPe64 (Image, FileSize, Xip); } default: diff --git a/BaseTools/ImageTool/PeEmitCommon.h b/BaseTools/ImageTool/PeEmitCommon.h index a65761f06f..0d28aa96d3 100644 --- a/BaseTools/ImageTool/PeEmitCommon.h +++ b/BaseTools/ImageTool/PeEmitCommon.h @@ -13,13 +13,15 @@ void * ToolImageEmitPe32 ( const image_tool_image_info_t *Image, - uint32_t *FileSize + uint32_t *FileSize, + bool Xip ); void * ToolImageEmitPe64 ( const image_tool_image_info_t *Image, - uint32_t *FileSize + uint32_t *FileSize, + bool Xip ); #endif // PE_EMIT_COMMON_H diff --git a/BaseTools/ImageTool/PeScan.c b/BaseTools/ImageTool/PeScan.c index 8c7585a2a1..42aff03009 100644 --- a/BaseTools/ImageTool/PeScan.c +++ b/BaseTools/ImageTool/PeScan.c @@ -6,11 +6,13 @@ #include "ImageTool.h" +#include "PeScan.h" + #define PE_COFF_SECT_NAME_RELOC ".reloc\0" #define PE_COFF_SECT_NAME_RESRC ".rsrc\0\0" #define PE_COFF_SECT_NAME_DEBUG ".debug\0" -bool +RETURN_STATUS ScanPeGetRelocInfo ( OUT image_tool_reloc_info_t *RelocInfo, IN PE_COFF_LOADER_IMAGE_CONTEXT *Context @@ -29,9 +31,7 @@ ScanPeGetRelocInfo ( const char *ImageBuffer; UINT16 RelocType; UINT16 RelocOffset; - - assert (RelocInfo != NULL); - assert (Context != NULL); + uint32_t ToolRelocsSize; // FIXME: PE/COFF context access RelocBlockRva = Context->RelocDirRva; @@ -40,13 +40,28 @@ ScanPeGetRelocInfo ( // Verify the Relocation Directory is not empty. // if (RelocDirSize == 0) { - return true; + return RETURN_SUCCESS; } - RelocInfo->Relocs = calloc (RelocDirSize / sizeof (UINT16), sizeof (*RelocInfo->Relocs)); + STATIC_ASSERT ( + sizeof (*RelocInfo->Relocs) % sizeof (UINT16) == 0, + "The division below is inaccurate." + ); + + Overflow = BaseOverflowMulU32 ( + RelocDirSize, + sizeof (*RelocInfo->Relocs) / sizeof (UINT16), + &ToolRelocsSize + ); + if (Overflow) { + DEBUG_RAISE (); + return RETURN_OUT_OF_RESOURCES; + } + + RelocInfo->Relocs = AllocateZeroPool (ToolRelocsSize); if (RelocInfo->Relocs == NULL) { fprintf (stderr, "ImageTool: Could not allocate memory for Relocs[]\n"); - return false; + return RETURN_OUT_OF_RESOURCES; } TopOfRelocDir = RelocBlockRva + RelocDirSize; @@ -65,7 +80,7 @@ ScanPeGetRelocInfo ( ); if (Overflow) { fprintf (stderr, "ImageTool: Overflow during TopOfRelocDir calculation\n"); - return false; + return RETURN_VOLUME_CORRUPTED; } // // Apply all Base Relocations of the Image. @@ -83,7 +98,7 @@ ScanPeGetRelocInfo ( ); if (Overflow) { fprintf (stderr, "ImageTool: Overflow during SizeOfRelocs calculation\n"); - return false; + return RETURN_VOLUME_CORRUPTED; } // // Verify the Base Relocation Block is in bounds of the Relocation @@ -91,7 +106,7 @@ ScanPeGetRelocInfo ( // if (SizeOfRelocs > RelocBlockRvaMax - RelocBlockRva) { fprintf (stderr, "ImageTool: Base Relocation Block is out of bounds of the Relocation Directory\n"); - return false; + return RETURN_VOLUME_CORRUPTED; } // // This arithmetic cannot overflow because we know @@ -113,7 +128,6 @@ ScanPeGetRelocInfo ( RelocType = IMAGE_RELOC_TYPE (RelocBlock->Relocations[RelocIndex]); RelocOffset = IMAGE_RELOC_OFFSET (RelocBlock->Relocations[RelocIndex]); - // FIXME: Make separate functions for UE switch (RelocType) { case EFI_IMAGE_REL_BASED_ABSOLUTE: continue; @@ -123,7 +137,7 @@ ScanPeGetRelocInfo ( break; default: fprintf (stderr, "ImageTool: Unknown RelocType = 0x%x\n", RelocType); - return false; + return RETURN_UNSUPPORTED; } RelocInfo->Relocs[RelocInfo->NumRelocs].Target = RelocBlock->VirtualAddress + RelocOffset; @@ -140,13 +154,13 @@ ScanPeGetRelocInfo ( // if (RelocBlockRva != TopOfRelocDir) { fprintf (stderr, "ImageTool: Relocation Directory size does not match the contained data\n"); - return false; + return RETURN_VOLUME_CORRUPTED; } - return true; + return RETURN_SUCCESS; } -bool +RETURN_STATUS ScanPeGetSegmentInfo ( OUT image_tool_segment_info_t *SegmentInfo, IN PE_COFF_LOADER_IMAGE_CONTEXT *Context @@ -158,15 +172,19 @@ ScanPeGetSegmentInfo ( const char *ImageBuffer; uint32_t Index; - assert (SegmentInfo != NULL); - assert (Context != NULL); - NumSections = PeCoffGetSectionTable (Context, &Section); - SegmentInfo->Segments = calloc (NumSections, sizeof (*SegmentInfo->Segments)); + STATIC_ASSERT ( + sizeof (*SegmentInfo->Segments) <= sizeof (*Section), + "The multiplication below may overflow." + ); + + SegmentInfo->Segments = AllocateZeroPool ( + NumSections * sizeof (*SegmentInfo->Segments) + ); if (SegmentInfo->Segments == NULL) { fprintf (stderr, "ImageTool: Could not allocate memory for Segments[]\n"); - return false; + return RETURN_OUT_OF_RESOURCES; } ImageBuffer = (char *)PeCoffLoaderGetImageAddress (Context); @@ -184,112 +202,35 @@ ScanPeGetSegmentInfo ( && memcmp (Section->Name, PE_COFF_SECT_NAME_RELOC, sizeof (Section->Name)) != 0 && memcmp (Section->Name, PE_COFF_SECT_NAME_RESRC, sizeof (Section->Name)) != 0 && memcmp (Section->Name, PE_COFF_SECT_NAME_DEBUG, sizeof (Section->Name)) != 0) { - ImageSegment->Name = calloc (1, sizeof (Section->Name)); + ImageSegment->Name = AllocateCopyPool ( + sizeof (Section->Name), + Section->Name + ); if (ImageSegment->Name == NULL) { fprintf (stderr, "ImageTool: Could not allocate memory for Segment Name\n"); - return false; + return RETURN_OUT_OF_RESOURCES; } - memmove (ImageSegment->Name, Section->Name, sizeof (Section->Name)); - ImageSegment->ImageAddress = Section->VirtualAddress; ImageSegment->ImageSize = ALIGN_VALUE (Section->VirtualSize, SegmentInfo->SegmentAlignment); ImageSegment->Read = (Section->Characteristics & EFI_IMAGE_SCN_MEM_READ) != 0; ImageSegment->Write = (Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0; ImageSegment->Execute = (Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) != 0; - ImageSegment->Data = malloc (ImageSegment->ImageSize); + ImageSegment->Data = AllocateCopyPool ( + ImageSegment->ImageSize, + ImageBuffer + Section->VirtualAddress + ); if (ImageSegment->Data == NULL) { fprintf (stderr, "ImageTool: Could not allocate memory for Segment Data\n"); - free (ImageSegment->Name); - return false; + FreePool (ImageSegment->Name); + return RETURN_OUT_OF_RESOURCES; } - memmove ( - ImageSegment->Data, - ImageBuffer + Section->VirtualAddress, - ImageSegment->ImageSize - ); - ++SegmentInfo->NumSegments; ++ImageSegment; } } - return true; -} - -bool -ScanPeGetDebugInfo ( - OUT image_tool_debug_info_t *DebugInfo, - IN PE_COFF_LOADER_IMAGE_CONTEXT *Context - ) -{ - const CHAR8 *PdbPath; - UINT32 PdbPathSize; - RETURN_STATUS Status; - - assert (DebugInfo != NULL); - assert (Context != NULL); - - Status = PeCoffGetPdbPath (Context, &PdbPath, &PdbPathSize); - if (Status == RETURN_NOT_FOUND) { - return true; - } - if (RETURN_ERROR (Status)) { - fprintf (stderr, "ImageTool: Could not get PdbPath\n"); - return false; - } - - DebugInfo->SymbolsPath = malloc (PdbPathSize); - if (DebugInfo->SymbolsPath == NULL) { - fprintf (stderr, "ImageTool: Could not allocate memory for SymbolsPath\n"); - return false; - } - - memmove (DebugInfo->SymbolsPath, PdbPath, PdbPathSize); - - assert (PdbPathSize >= 1); - assert (DebugInfo->SymbolsPath[PdbPathSize - 1] == '\0'); - - DebugInfo->SymbolsPathLen = PdbPathSize - 1; - - return true; -} - -bool -ScanPeGetHiiInfo ( - OUT image_tool_hii_info_t *HiiInfo, - IN PE_COFF_LOADER_IMAGE_CONTEXT *Context - ) -{ - UINT32 HiiRva; - UINT32 HiiSize; - RETURN_STATUS Status; - const char *ImageBuffer; - - assert (HiiInfo != NULL); - assert (Context != NULL); - - Status = PeCoffGetHiiDataRva (Context, &HiiRva, &HiiSize); - if (Status == RETURN_NOT_FOUND) { - return true; - } - if (RETURN_ERROR (Status)) { - fprintf (stderr, "ImageTool: Could not get HiiRva\n"); - return false; - } - - HiiInfo->Data = calloc (1, HiiSize); - if (HiiInfo->Data == NULL) { - fprintf (stderr, "ImageTool: Could not allocate memory for HiiInfo Data\n"); - return false; - } - - ImageBuffer = (char *)PeCoffLoaderGetImageAddress (Context); - - memmove (HiiInfo->Data, ImageBuffer + HiiRva, HiiSize); - HiiInfo->DataSize = HiiSize; - - return true; + return RETURN_SUCCESS; } diff --git a/BaseTools/ImageTool/PeScan.h b/BaseTools/ImageTool/PeScan.h index bdcf2078f8..2a63ab9be0 100644 --- a/BaseTools/ImageTool/PeScan.h +++ b/BaseTools/ImageTool/PeScan.h @@ -8,13 +8,13 @@ #include "ImageTool.h" -bool +RETURN_STATUS ScanPeGetRelocInfo ( OUT image_tool_reloc_info_t *RelocInfo, IN PE_COFF_LOADER_IMAGE_CONTEXT *Context ); -bool +RETURN_STATUS ScanPeGetSegmentInfo ( OUT image_tool_segment_info_t *SegmentInfo, IN PE_COFF_LOADER_IMAGE_CONTEXT *Context diff --git a/BaseTools/ImageTool/UefiImageScan.c b/BaseTools/ImageTool/UefiImageScan.c index 5180be4407..65b7903bff 100644 --- a/BaseTools/ImageTool/UefiImageScan.c +++ b/BaseTools/ImageTool/UefiImageScan.c @@ -25,8 +25,6 @@ ScanUefiImageGetHeaderInfo ( HeaderInfo->EntryPointAddress = UefiImageGetEntryPointAddress (Context); HeaderInfo->Machine = UefiImageGetMachine (Context); HeaderInfo->Subsystem = UefiImageGetSubsystem (Context); - // FIXME: - HeaderInfo->IsXip = true; Status = UefiImageGetFixedAddress (Context, &Address); if (!RETURN_ERROR (Status)) { @@ -47,7 +45,7 @@ ScanUefiImageGetHeaderInfo ( } static -bool +RETURN_STATUS ScanUefiImageGetRelocInfo ( OUT image_tool_reloc_info_t *RelocInfo, IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context @@ -55,9 +53,6 @@ ScanUefiImageGetRelocInfo ( { UINT8 FormatIndex; - assert (RelocInfo != NULL); - assert (Context != NULL); - FormatIndex = UefiImageGetFormat (Context); RelocInfo->RelocsStripped = UefiImageGetRelocsStripped (Context); @@ -71,11 +66,11 @@ ScanUefiImageGetRelocInfo ( "ImageTool: Unsupported UefiImage format %u\n", FormatIndex ); - return false; + return RETURN_UNSUPPORTED; } static -bool +RETURN_STATUS ScanUefiImageGetSegmentInfo ( OUT image_tool_segment_info_t *SegmentInfo, IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context @@ -83,9 +78,6 @@ ScanUefiImageGetSegmentInfo ( { UINT8 FormatIndex; - assert (SegmentInfo != NULL); - assert (Context != NULL); - FormatIndex = UefiImageGetFormat (Context); SegmentInfo->SegmentAlignment = UefiImageGetSegmentAlignment (Context); @@ -99,10 +91,10 @@ ScanUefiImageGetSegmentInfo ( "ImageTool: Unsupported UefiImage format %u\n", FormatIndex ); - return false; + return RETURN_UNSUPPORTED; } -bool +RETURN_STATUS ScanUefiImageGetDebugInfo ( OUT image_tool_debug_info_t *DebugInfo, IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context @@ -112,35 +104,31 @@ ScanUefiImageGetDebugInfo ( const CHAR8 *SymbolsPath; UINT32 SymbolsPathSize; - assert (DebugInfo != NULL); - assert (Context != NULL); - Status = UefiImageGetSymbolsPath (Context, &SymbolsPath, &SymbolsPathSize); - if (Status == RETURN_NOT_FOUND) { - return true; + if (Status == RETURN_NOT_FOUND || Status == RETURN_UNSUPPORTED) { + return RETURN_SUCCESS; } if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Could not get SymbolsPath\n"); - return false; + return Status; } assert (SymbolsPathSize >= 1); - DebugInfo->SymbolsPath = malloc (SymbolsPathSize + 1); + DebugInfo->SymbolsPath = AllocateCopyPool (SymbolsPathSize, SymbolsPath); if (DebugInfo->SymbolsPath == NULL) { fprintf (stderr, "ImageTool: Could not allocate memory for SymbolsPath\n"); - return false; + return RETURN_OUT_OF_RESOURCES; } - memmove (DebugInfo->SymbolsPath, SymbolsPath, SymbolsPathSize); assert (DebugInfo->SymbolsPath[SymbolsPathSize - 1] == '\0'); DebugInfo->SymbolsPathLen = SymbolsPathSize - 1; - return true; + return RETURN_SUCCESS; } -bool +RETURN_STATUS ScanUefiImageGetHiiInfo ( OUT image_tool_hii_info_t *HiiInfo, IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context @@ -151,30 +139,26 @@ ScanUefiImageGetHiiInfo ( UINT32 HiiSize; const char *ImageBuffer; - assert (HiiInfo != NULL); - assert (Context != NULL); - Status = UefiImageGetHiiDataRva (Context, &HiiRva, &HiiSize); if (Status == RETURN_NOT_FOUND) { - return true; + return RETURN_SUCCESS; } if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Malformed HII data\n"); - return false; - } - - HiiInfo->Data = malloc (HiiSize); - if (HiiInfo->Data == NULL) { - fprintf (stderr, "ImageTool: Could not allocate memory for HiiInfo Data\n"); - return false; + return Status; } ImageBuffer = (char *)UefiImageLoaderGetImageAddress (Context); - memmove (HiiInfo->Data, ImageBuffer + HiiRva, HiiSize); + HiiInfo->Data = AllocateCopyPool (HiiSize, ImageBuffer + HiiRva); + if (HiiInfo->Data == NULL) { + fprintf (stderr, "ImageTool: Could not allocate memory for HiiInfo Data\n"); + return RETURN_OUT_OF_RESOURCES; + } + HiiInfo->DataSize = HiiSize; - return true; + return RETURN_SUCCESS; } RETURN_STATUS @@ -194,7 +178,6 @@ ToolContextConstructUefiImage ( void *Destination; bool Success; - assert (Image != NULL); assert (File != NULL || FileSize == 0); if (FileSize > MAX_UINT32) { @@ -229,7 +212,7 @@ ToolContextConstructUefiImage ( if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Could not Load Image\n"); FreeAlignedPages (Destination, DestinationPages); - return RETURN_VOLUME_CORRUPTED; + return Status; } memset (Image, 0, sizeof (*Image)); @@ -237,36 +220,41 @@ ToolContextConstructUefiImage ( Success = ScanUefiImageGetHeaderInfo (&Image->HeaderInfo, &Context); if (!Success) { fprintf (stderr, "ImageTool: Could not retrieve header info\n"); + ToolImageDestruct (Image); FreeAlignedPages (Destination, DestinationPages); return RETURN_VOLUME_CORRUPTED; } - Success = ScanUefiImageGetSegmentInfo (&Image->SegmentInfo, &Context); - if (!Success) { + Status = ScanUefiImageGetSegmentInfo (&Image->SegmentInfo, &Context); + if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Could not retrieve segment info\n"); + ToolImageDestruct (Image); FreeAlignedPages (Destination, DestinationPages); - return RETURN_VOLUME_CORRUPTED; + return Status; } - Success = ScanUefiImageGetRelocInfo (&Image->RelocInfo, &Context); - if (!Success) { + Status = ScanUefiImageGetRelocInfo (&Image->RelocInfo, &Context); + if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Could not retrieve reloc info\n"); + ToolImageDestruct (Image); FreeAlignedPages (Destination, DestinationPages); - return RETURN_VOLUME_CORRUPTED; + return Status; } - Success = ScanUefiImageGetHiiInfo (&Image->HiiInfo, &Context); - if (!Success) { + Status = ScanUefiImageGetHiiInfo (&Image->HiiInfo, &Context); + if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Could not retrieve HII info\n"); + ToolImageDestruct (Image); FreeAlignedPages (Destination, DestinationPages); - return RETURN_VOLUME_CORRUPTED; + return Status; } - Success = ScanUefiImageGetDebugInfo (&Image->DebugInfo, &Context); - if (!Success) { + Status = ScanUefiImageGetDebugInfo (&Image->DebugInfo, &Context); + if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Could not retrieve debug info\n"); + ToolImageDestruct (Image); FreeAlignedPages (Destination, DestinationPages); - return RETURN_VOLUME_CORRUPTED; + return Status; } FreeAlignedPages (Destination, DestinationPages); diff --git a/BaseTools/Source/C/Common/GNUmakefile b/BaseTools/Source/C/Common/GNUmakefile index 1166736e43..5ec953cda0 100644 --- a/BaseTools/Source/C/Common/GNUmakefile +++ b/BaseTools/Source/C/Common/GNUmakefile @@ -42,6 +42,7 @@ OBJECTS += \ $(EDK2_OBJPATH)/BaseTools/ImageTool/PeEmit64.o \ $(EDK2_OBJPATH)/BaseTools/ImageTool/PeEmitCommon.o \ $(EDK2_OBJPATH)/BaseTools/ImageTool/BinEmit.o \ + $(EDK2_OBJPATH)/BaseTools/ImageTool/DynamicBuffer.o \ $(EDK2_OBJPATH)/OpenCorePkg/User/Library/UserFile.o OBJECTS += \ diff --git a/BaseTools/Source/C/Common/Makefile b/BaseTools/Source/C/Common/Makefile index 03a9e73539..db0198c640 100644 --- a/BaseTools/Source/C/Common/Makefile +++ b/BaseTools/Source/C/Common/Makefile @@ -42,6 +42,7 @@ OBJECTS = $(OBJECTS) \ $(EDK2_OBJPATH)\BaseTools\ImageTool\PeEmit64.obj \ $(EDK2_OBJPATH)\BaseTools\ImageTool\PeEmitCommon.obj \ $(EDK2_OBJPATH)\BaseTools\ImageTool\BinEmit.obj \ + $(EDK2_OBJPATH)\BaseTools\ImageTool\DynamicBuffer.obj \ $(EDK2_OBJPATH)\OpenCorePkg\User\Library\UserFile.obj OBJECTS = $(OBJECTS) \ diff --git a/BaseTools/Source/C/GenFv/GenFvInternalLib.c b/BaseTools/Source/C/GenFv/GenFvInternalLib.c index 2f97c26ef7..ef986d09e1 100644 --- a/BaseTools/Source/C/GenFv/GenFvInternalLib.c +++ b/BaseTools/Source/C/GenFv/GenFvInternalLib.c @@ -3741,6 +3741,7 @@ Returns: true, NewBaseAddress, NULL, + TRUE, Strip, FALSE ); diff --git a/BaseTools/Source/C/VolInfo/VolInfo.c b/BaseTools/Source/C/VolInfo/VolInfo.c index d36b1c83e9..1edc2e375d 100644 --- a/BaseTools/Source/C/VolInfo/VolInfo.c +++ b/BaseTools/Source/C/VolInfo/VolInfo.c @@ -1456,6 +1456,7 @@ Returns: true, NewBaseAddress, NULL, + TRUE, FALSE, TRUE ); diff --git a/BaseTools/Source/Python/GenFds/DataSection.py b/BaseTools/Source/Python/GenFds/DataSection.py index 61d162f31b..365f9695bc 100644 --- a/BaseTools/Source/Python/GenFds/DataSection.py +++ b/BaseTools/Source/Python/GenFds/DataSection.py @@ -95,6 +95,7 @@ class DataSection (DataSectionClassObject): GenFdsGlobalVariable.GenerateFirmwareImage( StrippedFile, GenFdsGlobalVariable.MacroExtend(self.SectFileName, Dict), + Xip=True, Strip=True, IsMakefile = IsMakefile ) diff --git a/BaseTools/Source/Python/GenFds/EfiSection.py b/BaseTools/Source/Python/GenFds/EfiSection.py index 809260651f..6816aeb129 100644 --- a/BaseTools/Source/Python/GenFds/EfiSection.py +++ b/BaseTools/Source/Python/GenFds/EfiSection.py @@ -290,6 +290,7 @@ class EfiSection (EfiSectionClassObject): GenFdsGlobalVariable.GenerateFirmwareImage( StrippedFile, File, + Xip=True, Strip=True, IsMakefile = IsMakefile ) diff --git a/BaseTools/Source/Python/GenFds/FfsInfStatement.py b/BaseTools/Source/Python/GenFds/FfsInfStatement.py index 6fdb295441..1c78b71886 100644 --- a/BaseTools/Source/Python/GenFds/FfsInfStatement.py +++ b/BaseTools/Source/Python/GenFds/FfsInfStatement.py @@ -793,6 +793,7 @@ class FfsInfStatement(FfsInfStatementClassObject): GenFdsGlobalVariable.GenerateFirmwareImage( StrippedFile, File, + Xip=True, Strip=True, IsMakefile=IsMakefile ) @@ -827,6 +828,7 @@ class FfsInfStatement(FfsInfStatementClassObject): GenFdsGlobalVariable.GenerateFirmwareImage( StrippedFile, GenSecInputFile, + Xip=True, Strip=True, IsMakefile=IsMakefile ) diff --git a/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py index 68faace90f..6c78a67ca6 100644 --- a/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py +++ b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py @@ -607,7 +607,7 @@ class GenFdsGlobalVariable: GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV") @staticmethod - def GenerateFirmwareImage(Output, Input, Format="Auto", Strip=False, IsMakefile=False): + def GenerateFirmwareImage(Output, Input, Format="Auto", Xip=False, Strip=False, IsMakefile=False): if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile: return GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) @@ -615,6 +615,8 @@ class GenFdsGlobalVariable: Cmd = ["ImageTool GenImage"] if Format != "Auto": Cmd += ("-c", Format) + if Xip: + Cmd.append("-x") if Strip: Cmd.append("-s") Cmd += ("-o", Output, Input) diff --git a/BaseTools/Source/Python/build/BuildReport.py b/BaseTools/Source/Python/build/BuildReport.py index 7ec6abdf18..1ca78bfc52 100644 --- a/BaseTools/Source/Python/build/BuildReport.py +++ b/BaseTools/Source/Python/build/BuildReport.py @@ -642,7 +642,7 @@ class ModuleReport(object): if os.path.isfile(DefaultEFIfile): Tempfile = os.path.join(OutputDir, self.ModuleName + "_hash.tmp") # rebase the efi image since its base address may not zero - cmd = ["ImageTool GenImage -b 0 -o", Tempfile, DefaultEFIfile] + cmd = ["ImageTool GenImage -x -b 0 -o", Tempfile, DefaultEFIfile] try: PopenObject = subprocess.Popen(' '.join(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) except Exception as X: diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py index ac2c8d6bc4..65ddf7c775 100755 --- a/BaseTools/Source/Python/build/build.py +++ b/BaseTools/Source/Python/build/build.py @@ -1542,16 +1542,16 @@ class Build(): # # Update Image to new BaseAddress by ImageTool tool # - LaunchCommand(["ImageTool", "GenImage", "-b", str(BaseAddress), "-o", ModuleOutputImage, ModuleOutputImage], ModuleInfo.OutputDir) - LaunchCommand(["ImageTool", "GenImage", "-b", str(BaseAddress), "-o", ModuleOutputImage, ModuleOutputImage], ModuleInfo.DebugDir) + LaunchCommand(["ImageTool", "GenImage", "-x", "-b", str(BaseAddress), "-o", ModuleOutputImage, ModuleOutputImage], ModuleInfo.OutputDir) + LaunchCommand(["ImageTool", "GenImage", "-x", "-b", str(BaseAddress), "-o", ModuleOutputImage, ModuleOutputImage], ModuleInfo.DebugDir) ## for SMM module in SMRAM, the SMRAM will be allocated from base to top. else: BaseAddress = AlignUp(BaseAddress, ModuleInfo.Image.SectionAlignment) # # Set new address to the section header only for SMM driver. # - LaunchCommand(["ImageTool", "GenImage", "-f -b", str(BaseAddress), "-o", ModuleOutputImage, ModuleOutputImage], ModuleInfo.OutputDir) - LaunchCommand(["ImageTool", "GenImage", "-f -b", str(BaseAddress), "-o", ModuleOutputImage, ModuleOutputImage], ModuleInfo.DebugDir) + LaunchCommand(["ImageTool", "GenImage", "-x", "-f -b", str(BaseAddress), "-o", ModuleOutputImage, ModuleOutputImage], ModuleInfo.OutputDir) + LaunchCommand(["ImageTool", "GenImage", "-x", "-f -b", str(BaseAddress), "-o", ModuleOutputImage, ModuleOutputImage], ModuleInfo.DebugDir) # # Collect function address from Map file # diff --git a/MdePkg/Library/BaseUefiImageLib/PeSupport.c b/MdePkg/Library/BaseUefiImageLib/PeSupport.c index 0698a60461..b03b85ee25 100644 --- a/MdePkg/Library/BaseUefiImageLib/PeSupport.c +++ b/MdePkg/Library/BaseUefiImageLib/PeSupport.c @@ -96,10 +96,10 @@ UefiImageLoaderGetRuntimeContextSizePe ( RETURN_STATUS UefiImageRelocateImagePe ( - IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, - IN UINT64 BaseAddress, - OUT UEFI_IMAGE_LOADER_RUNTIME_CONTEXT *RuntimeContext OPTIONAL, - IN UINT32 RuntimeContextSize + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + IN UINT64 BaseAddress, + OUT VOID *RuntimeContext OPTIONAL, + IN UINT32 RuntimeContextSize ) { return PeCoffRelocateImage ( diff --git a/MdePkg/Library/BaseUefiImageLib/UefiImageFormat.h b/MdePkg/Library/BaseUefiImageLib/UefiImageFormat.h index f9e96287bf..efe7048891 100644 --- a/MdePkg/Library/BaseUefiImageLib/UefiImageFormat.h +++ b/MdePkg/Library/BaseUefiImageLib/UefiImageFormat.h @@ -71,10 +71,10 @@ RETURN_STATUS typedef RETURN_STATUS (*UEFI_IMAGE_RELOCARE_IMAGE) ( - IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, - IN UINT64 BaseAddress, - OUT UEFI_IMAGE_LOADER_RUNTIME_CONTEXT *RuntimeContext OPTIONAL, - IN UINT32 RuntimeContextSize + IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context, + IN UINT64 BaseAddress, + OUT VOID *RuntimeContext OPTIONAL, + IN UINT32 RuntimeContextSize ); typedef diff --git a/MdePkg/Library/BaseUefiImageLib/UefiImageLib.c b/MdePkg/Library/BaseUefiImageLib/UefiImageLib.c index 1803b49035..6e9eaa9364 100644 --- a/MdePkg/Library/BaseUefiImageLib/UefiImageLib.c +++ b/MdePkg/Library/BaseUefiImageLib/UefiImageLib.c @@ -285,12 +285,16 @@ UefiImageRelocateImage ( ) { RETURN_STATUS Status; + VOID *FormatContext; + UINT32 FormatContextSize; + FormatContext = RuntimeContext; + FormatContextSize = RuntimeContextSize; if (RuntimeContext != NULL) { *(UINT64 *)RuntimeContext = Context->FormatIndex; - RuntimeContext = (UEFI_IMAGE_LOADER_RUNTIME_CONTEXT *)((UINT64 *)RuntimeContext + 1); - ASSERT (RuntimeContextSize >= 8); - RuntimeContextSize -= 8; + FormatContext = (VOID *)((UINT64 *)RuntimeContext + 1); + ASSERT (FormatContextSize >= 8); + FormatContextSize -= 8; } UEFI_IMAGE_EXEC ( @@ -299,8 +303,8 @@ UefiImageRelocateImage ( RelocateImage, Context, BaseAddress, - RuntimeContext, - RuntimeContextSize + FormatContext, + FormatContextSize ); if (!RETURN_ERROR (Status)) {