diff --git a/BaseTools/ImageTool/ElfScan.c b/BaseTools/ImageTool/ElfScan.c index e2a75b694f..233f315991 100644 --- a/BaseTools/ImageTool/ElfScan.c +++ b/BaseTools/ImageTool/ElfScan.c @@ -622,8 +622,7 @@ CreateIntermediate ( memcpy (Segments[SIndex].Name, Name, strlen (Name)); Segments[SIndex].ImageAddress = (uint32_t)(Shdr->sh_addr - BaseAddress); - Segments[SIndex].DataSize = (uint32_t)Shdr->sh_size; - Segments[SIndex].ImageSize = ALIGN_VALUE (Segments[SIndex].DataSize, Context->Alignment); + Segments[SIndex].ImageSize = ALIGN_VALUE ((uint32_t)Shdr->sh_size, Context->Alignment); Segments[SIndex].Read = true; Segments[SIndex].Write = (Shdr->sh_flags & SHF_WRITE) != 0; Segments[SIndex].Execute = (Shdr->sh_flags & SHF_EXECINSTR) != 0; diff --git a/BaseTools/ImageTool/Image.c b/BaseTools/ImageTool/Image.c index 2245521c60..b384c213b8 100644 --- a/BaseTools/ImageTool/Image.c +++ b/BaseTools/ImageTool/Image.c @@ -29,11 +29,6 @@ CheckToolImageSegment ( return false; } - if (Segment->ImageSize < Segment->DataSize) { - raise (); - return false; - } - // FIXME: Expand prior segment if (Segment->ImageAddress != *PreviousEndAddress) { raise (); @@ -223,6 +218,10 @@ CheckToolImageRelocInfo ( RelocInfo = &Image->RelocInfo; + if (RelocInfo->NumRelocs == 0) { + return true; + } + if (RelocInfo->RelocsStripped && (RelocInfo->NumRelocs > 0)) { raise (); return false; @@ -233,7 +232,18 @@ CheckToolImageRelocInfo ( return false; } - for (Index = 0; Index < RelocInfo->NumRelocs; ++Index) { + Result = CheckToolImageReloc (Image, ImageSize, &RelocInfo->Relocs[0]); + if (!Result) { + raise (); + return false; + } + + for (Index = 1; Index < RelocInfo->NumRelocs; ++Index) { + if (RelocInfo->Relocs[Index].Target < RelocInfo->Relocs[Index - 1].Target) { + assert (false); + return false; + } + Result = CheckToolImageReloc (Image, ImageSize, &RelocInfo->Relocs[Index]); if (!Result) { raise (); @@ -294,33 +304,8 @@ CheckToolImage ( return true; } -bool -ImageConvertToXip ( - image_tool_image_info_t *Image - ) -{ - image_tool_segment_info_t *SegmentInfo; - uint64_t Index; - image_tool_segment_t *Segment; - - assert (Image != NULL); - - SegmentInfo = &Image->SegmentInfo; - - for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) { - Segment = &SegmentInfo->Segments[Index]; - - assert (Segment->DataSize <= Segment->ImageSize); - Segment->DataSize = Segment->ImageSize; - } - - Image->HeaderInfo.IsXip = true; - - return true; -} - void -ImageShrinkSegmentData ( +ImageInitUnpaddedSize ( const image_tool_image_info_t *Image ) { @@ -329,8 +314,14 @@ ImageShrinkSegmentData ( for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { Segment = &Image->SegmentInfo.Segments[Index]; - for (; Segment->DataSize > 0; --Segment->DataSize) { - if (Segment->Data[Segment->DataSize - 1] != 0) { + Segment->UnpaddedSize = Segment->ImageSize; + + if (Image->HeaderInfo.IsXip) { + continue; + } + + for (; Segment->UnpaddedSize > 0; --Segment->UnpaddedSize) { + if (Segment->Data[Segment->UnpaddedSize - 1] != 0) { break; } } @@ -348,28 +339,16 @@ ToolImageDestruct ( if (Image->SegmentInfo.Segments != NULL) { for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { - if (Image->SegmentInfo.Segments[Index].Name != NULL) { - free (Image->SegmentInfo.Segments[Index].Name); - } - if (Image->SegmentInfo.Segments[Index].DataSize != 0) { - free (Image->SegmentInfo.Segments[Index].Data); - } + free (Image->SegmentInfo.Segments[Index].Name); + free (Image->SegmentInfo.Segments[Index].Data); } free (Image->SegmentInfo.Segments); } - if (Image->HiiInfo.Data != NULL) { - free (Image->HiiInfo.Data); - } - - if (Image->RelocInfo.Relocs != NULL) { - free (Image->RelocInfo.Relocs); - } - - if (Image->DebugInfo.SymbolsPath != NULL) { - free (Image->DebugInfo.SymbolsPath); - } + free (Image->HiiInfo.Data); + free (Image->RelocInfo.Relocs); + free (Image->DebugInfo.SymbolsPath); memset (Image, 0, sizeof (*Image)); } @@ -451,3 +430,212 @@ ToolImageRelocate ( return true; } + +static +INTN +EFIAPI +ToolImageRelocCompare ( + IN CONST VOID *Buffer1, + IN CONST VOID *Buffer2 + ) +{ + const image_tool_reloc_t *Reloc1; + const image_tool_reloc_t *Reloc2; + + Reloc1 = (const image_tool_reloc_t *)Buffer1; + Reloc2 = (const image_tool_reloc_t *)Buffer2; + + if (Reloc1->Target < Reloc2->Target) { + return -1; + } + + if (Reloc1->Target > Reloc2->Target) { + return 1; + } + + return 0; +} + +void +ToolImageSortRelocs ( + image_tool_image_info_t *Image + ) +{ + image_tool_reloc_t OneElement; + + if (Image->RelocInfo.Relocs == NULL) { + return; + } + + QuickSort ( + Image->RelocInfo.Relocs, + Image->RelocInfo.NumRelocs, + sizeof (*Image->RelocInfo.Relocs), + ToolImageRelocCompare, + &OneElement + ); +} + +bool +ToolImageCompare ( + const image_tool_image_info_t *Image1, + const image_tool_image_info_t *Image2 + ) +{ + int CmpResult; + uint32_t SegIndex; + const char *Name1; + const char *Name2; + uint32_t NameIndex; + + // + // Compare HeaderInfo. + // + + CmpResult = memcmp ( + &Image1->HeaderInfo, + &Image2->HeaderInfo, + sizeof (Image1->HeaderInfo) + ); + if (CmpResult != 0) { + raise (); + return false; + } + + // + // Compare SegmentInfo. + // UnpaddedSize is deliberately omitted, as it's implicit by the equality of + // ImageSize and Data. + // + + CmpResult = memcmp ( + &Image1->SegmentInfo, + &Image2->SegmentInfo, + OFFSET_OF (image_tool_segment_info_t, Segments) + ); + if (CmpResult != 0) { + raise (); + return false; + } + + for (SegIndex = 0; SegIndex < Image1->SegmentInfo.NumSegments; ++SegIndex) { + CmpResult = memcmp ( + &Image1->SegmentInfo.Segments[SegIndex], + &Image2->SegmentInfo.Segments[SegIndex], + OFFSET_OF (image_tool_segment_t, Name) + ); + if (CmpResult != 0) { + raise (); + return false; + } + + // + // Don't assume images generally support arbitrarily long names or names in + // general. Check prefix equiality as a best effort. + // + Name1 = Image1->SegmentInfo.Segments[SegIndex].Name; + Name2 = Image2->SegmentInfo.Segments[SegIndex].Name; + if (Name1 != NULL && Name2 != NULL) { + for ( + NameIndex = 0; + Name1[NameIndex] != '\0' && Name2[NameIndex] != '\0'; + ++NameIndex + ) { + if (Name1[NameIndex] != Name2[NameIndex]) { + 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; + } + } + + // + // Compare RelocInfo. + // + + CmpResult = memcmp ( + &Image1->RelocInfo, + &Image2->RelocInfo, + OFFSET_OF (image_tool_reloc_info_t, Relocs) + ); + if (CmpResult != 0) { + raise (); + return false; + } + + CmpResult = memcmp ( + Image1->RelocInfo.Relocs, + Image2->RelocInfo.Relocs, + Image1->RelocInfo.NumRelocs * sizeof (*Image1->RelocInfo.Relocs) + ); + if (CmpResult != 0) { + raise (); + return false; + } + + // + // Compare HiiInfo. + // + + CmpResult = memcmp ( + &Image1->HiiInfo, + &Image2->HiiInfo, + OFFSET_OF (image_tool_hii_info_t, Data) + ); + if (CmpResult != 0) { + raise (); + return false; + } + + CmpResult = memcmp ( + Image1->HiiInfo.Data, + Image2->HiiInfo.Data, + Image1->HiiInfo.DataSize + ); + if (CmpResult != 0) { + raise (); + return false; + } + + // + // Compare DebugInfo. + // + + CmpResult = memcmp ( + &Image1->DebugInfo, + &Image2->DebugInfo, + OFFSET_OF (image_tool_debug_info_t, SymbolsPath) + ); + if (CmpResult != 0) { + raise (); + return false; + } + + if ((Image1->DebugInfo.SymbolsPath != NULL) != (Image2->DebugInfo.SymbolsPath != NULL)) { + raise (); + return false; + } + + if (Image1->DebugInfo.SymbolsPath != NULL) { + CmpResult = strcmp ( + Image1->DebugInfo.SymbolsPath, + Image2->DebugInfo.SymbolsPath + ); + if (CmpResult != 0) { + raise (); + return false; + } + } + + return true; +} diff --git a/BaseTools/ImageTool/ImageTool.c b/BaseTools/ImageTool/ImageTool.c index 1b7032c887..f78543882b 100644 --- a/BaseTools/ImageTool/ImageTool.c +++ b/BaseTools/ImageTool/ImageTool.c @@ -270,6 +270,43 @@ ImageSetModuleType ( return true; } +static +RETURN_STATUS +ValidateOutputFile ( + void *OutputFile, + uint32_t OutputFileSize, + const image_tool_image_info_t *ImageInfo + ) +{ + RETURN_STATUS Status; + bool Result; + image_tool_image_info_t OutputImageInfo; + + Status = ToolContextConstructPe (&OutputImageInfo, OutputFile, OutputFileSize); + if (EFI_ERROR (Status)) { + assert (false); + return Status; + } + + Result = CheckToolImage (&OutputImageInfo); + if (!Result) { + raise (); + ToolImageDestruct (&OutputImageInfo); + return RETURN_UNSUPPORTED; + } + + Result = ToolImageCompare (&OutputImageInfo, ImageInfo); + + ToolImageDestruct (&OutputImageInfo); + + if (!Result) { + assert (false); + return RETURN_VOLUME_CORRUPTED; + } + + return RETURN_SUCCESS; +} + static RETURN_STATUS GenExecutable ( @@ -331,6 +368,8 @@ GenExecutable ( ImageInfo.HiiInfo.DataSize = HiiFileSize; } + ToolImageSortRelocs (&ImageInfo); + Result = CheckToolImage (&ImageInfo); if (!Result) { ToolImageDestruct (&ImageInfo); @@ -359,10 +398,18 @@ GenExecutable ( assert (false); } + if (OutputFile == NULL) { + ToolImageDestruct (&ImageInfo); + return RETURN_ABORTED; + } + + Status = ValidateOutputFile (OutputFile, OutputFileSize, &ImageInfo); + ToolImageDestruct (&ImageInfo); - if (OutputFile == NULL) { - return RETURN_ABORTED; + if (EFI_ERROR (Status)) { + assert (false); + return Status; } UserWriteFile (OutputFileName, OutputFile, OutputFileSize); diff --git a/BaseTools/ImageTool/ImageTool.h b/BaseTools/ImageTool/ImageTool.h index 02abecbee8..170264ff85 100644 --- a/BaseTools/ImageTool/ImageTool.h +++ b/BaseTools/ImageTool/ImageTool.h @@ -39,40 +39,49 @@ typedef struct { uint32_t EntryPointAddress; uint16_t Machine; uint16_t Subsystem; - bool IsXip; + uint8_t IsXip; + uint8_t Reserved[7]; } image_tool_header_info_t; typedef struct { - char *Name; - uint8_t *Data; - uint32_t DataSize; uint32_t ImageAddress; uint32_t ImageSize; - bool Read; - bool Write; - bool Execute; + uint8_t Read; + uint8_t Write; + uint8_t Execute; + uint8_t Reserved[1]; + + char *Name; + uint8_t *Data; + + uint32_t UnpaddedSize; } image_tool_segment_t; typedef struct { uint32_t SegmentAlignment; uint32_t NumSegments; + image_tool_segment_t *Segments; } image_tool_segment_info_t; typedef struct { uint8_t Type; + uint8_t Reserved[3]; uint32_t Target; } image_tool_reloc_t; typedef struct { uint32_t NumRelocs; - bool RelocsStripped; + uint8_t RelocsStripped; + uint8_t Reserved[3]; + image_tool_reloc_t *Relocs; } image_tool_reloc_info_t; typedef struct { - char *SymbolsPath; uint32_t SymbolsPathLen; + + char *SymbolsPath; } image_tool_debug_info_t; typedef struct { @@ -81,8 +90,9 @@ typedef struct { } image_tool_pe_datadir_info_t; typedef struct { - void *Data; uint32_t DataSize; + + void *Data; } image_tool_hii_info_t; typedef struct { @@ -99,21 +109,27 @@ ToolImageDestruct ( ); void -ImageShrinkSegmentData ( +ImageInitUnpaddedSize ( const image_tool_image_info_t *Image ); -bool -ImageConvertToXip ( - image_tool_image_info_t *Image - ); - bool ToolImageRelocate ( image_tool_image_info_t *Image, uint64_t BaseAddress ); +void +ToolImageSortRelocs ( + image_tool_image_info_t *Image + ); + +bool +ToolImageCompare ( + const image_tool_image_info_t *Image1, + const image_tool_image_info_t *Image2 + ); + RETURN_STATUS ToolContextConstructPe ( OUT image_tool_image_info_t *Image, @@ -128,8 +144,8 @@ CheckToolImage ( void * ToolImageEmitPe ( - const image_tool_image_info_t *Image, - uint32_t *FileSize + image_tool_image_info_t *Image, + uint32_t *FileSize ); RETURN_STATUS diff --git a/BaseTools/ImageTool/Makefile b/BaseTools/ImageTool/Makefile index cadf57d9c9..c09875b183 100644 --- a/BaseTools/ImageTool/Makefile +++ b/BaseTools/ImageTool/Makefile @@ -30,7 +30,7 @@ ERRO = $(UDK_PATH)\MdePkg\Library\BaseDebugPrintErrorLevelLib BMPN = $(UDK_PATH)\MdeModulePkg\Library\BaseMemoryProfileLibNull CMEM = $(UDK_PATH)\MdeModulePkg\Library\CommonMemoryAllocationLib USER = $(OC_USER)\User\Library -OBJECTS = $(OBJECTS) {$(BASE)}SafeString.obj String.obj SwapBytes16.obj SwapBytes32.obj CpuDeadLoop.obj CheckSum.obj +OBJECTS = $(OBJECTS) {$(BASE)}SafeString.obj String.obj SwapBytes16.obj SwapBytes32.obj CpuDeadLoop.obj CheckSum.obj QuickSort.obj OBJECTS = $(OBJECTS) {$(OUT)}DebugLib.obj {$(PRIN)}PrintLib.obj PrintLibInternal.obj {$(ERRO)}BaseDebugPrintErrorLevelLib.obj OBJECTS = $(OBJECTS) {$(USER)}UserFile.obj UserBaseMemoryLib.obj UserMath.obj UserPcd.obj UserMisc.obj UserGlobalVar.obj UserBootServices.obj OBJECTS = $(OBJECTS) {$(BMPN)}BaseMemoryProfileLibNull.obj {$(CMEM)}CommonMemoryAllocationLib.obj {$(CMEM)}CommonMemoryAllocationLibEx.obj diff --git a/BaseTools/ImageTool/PeEmit.c b/BaseTools/ImageTool/PeEmit.c index 440d26ea2c..42197aa143 100644 --- a/BaseTools/ImageTool/PeEmit.c +++ b/BaseTools/ImageTool/PeEmit.c @@ -99,7 +99,7 @@ EmitPeGetSectionsSize ( for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) { Overflow = BaseOverflowAlignUpU32 ( - Image->SegmentInfo.Segments[Index].DataSize, + Image->SegmentInfo.Segments[Index].UnpaddedSize, Context->FileAlignment, &DataSize ); @@ -325,7 +325,7 @@ ToolImageEmitPeSectionHeaders ( Sections[Index].PointerToRawData = SectionOffset; Sections[Index].VirtualAddress = SectionOffset; - Sections[Index].SizeOfRawData = ALIGN_VALUE (Image->SegmentInfo.Segments[Index].DataSize, Context->FileAlignment); + Sections[Index].SizeOfRawData = ALIGN_VALUE (Image->SegmentInfo.Segments[Index].UnpaddedSize, Context->FileAlignment); Sections[Index].VirtualSize = Image->SegmentInfo.Segments[Index].ImageSize; strncpy ( @@ -591,16 +591,16 @@ ToolImageEmitPeSections ( } #endif - assert (Segment->DataSize <= *BufferSize); + assert (Segment->UnpaddedSize <= *BufferSize); - memmove (*Buffer, Segment->Data, Segment->DataSize); + memmove (*Buffer, Segment->Data, Segment->UnpaddedSize); - *BufferSize -= Segment->DataSize; - *Buffer += Segment->DataSize; - SectionsSize += Segment->DataSize; + *BufferSize -= Segment->UnpaddedSize; + *Buffer += Segment->UnpaddedSize; + SectionsSize += Segment->UnpaddedSize; SectionPadding = ALIGN_VALUE_ADDEND ( - Segment->DataSize, + Segment->UnpaddedSize, Context->FileAlignment ); @@ -885,8 +885,8 @@ ToolImageEmitPeExtraSections ( #define ToolImageEmitPe PE_SUFFIX (ToolImageEmitPe) void * ToolImageEmitPe ( - const image_tool_image_info_t *Image, - uint32_t *FileSize + image_tool_image_info_t *Image, + uint32_t *FileSize ) { image_tool_pe_emit_context_t Context; @@ -906,11 +906,9 @@ ToolImageEmitPe ( // FIXME: Non-XIP is not well-supported right now. Context.FileAlignment = Image->SegmentInfo.SegmentAlignment; - Result = ImageConvertToXip ((image_tool_image_info_t *)Image); - if (!Result) { - raise (); - return NULL; - } + Image->HeaderInfo.IsXip = true; + + ImageInitUnpaddedSize (Image); Context.Image = Image; diff --git a/BaseTools/ImageTool/PeEmitCommon.c b/BaseTools/ImageTool/PeEmitCommon.c index 762272c046..eb8b612636 100644 --- a/BaseTools/ImageTool/PeEmitCommon.c +++ b/BaseTools/ImageTool/PeEmitCommon.c @@ -7,8 +7,8 @@ void * ToolImageEmitPe ( - const image_tool_image_info_t *Image, - uint32_t *FileSize + image_tool_image_info_t *Image, + uint32_t *FileSize ) { switch (Image->HeaderInfo.Machine) { diff --git a/BaseTools/ImageTool/PeScan.c b/BaseTools/ImageTool/PeScan.c index 96d7ee0964..121d94661a 100644 --- a/BaseTools/ImageTool/PeScan.c +++ b/BaseTools/ImageTool/PeScan.c @@ -219,7 +219,6 @@ ScanPeGetSegmentInfo ( memmove (ImageSegment->Name, Section->Name, sizeof (Section->Name)); ImageSegment->ImageAddress = Section->VirtualAddress; - ImageSegment->DataSize = MIN (Section->SizeOfRawData, Section->VirtualSize); 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; diff --git a/OpenCorePkg b/OpenCorePkg index 76a69c5486..d185827c70 160000 --- a/OpenCorePkg +++ b/OpenCorePkg @@ -1 +1 @@ -Subproject commit 76a69c5486477a3c3b2ab2924d4b8b288e44ff8e +Subproject commit d185827c701dace24f32f7042ab05a9b0d50d6ec