mirror of
https://github.com/acidanthera/audk.git
synced 2025-09-22 09:17:39 +02:00
UE: Added support for XIP.
This commit is contained in:
parent
923004dd69
commit
f60c587094
@ -187,6 +187,11 @@ ToolImageEmit (
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((Format == UefiImageFormatUe) && Xip) {
|
||||||
|
ToolImageDestruct (&ImageInfo);
|
||||||
|
return OutputFile;
|
||||||
|
}
|
||||||
|
|
||||||
Status = ValidateOutputFile (OutputFile, *OutputFileSize, &ImageInfo);
|
Status = ValidateOutputFile (OutputFile, *OutputFileSize, &ImageInfo);
|
||||||
|
|
||||||
ToolImageDestruct (&ImageInfo);
|
ToolImageDestruct (&ImageInfo);
|
||||||
|
@ -908,6 +908,136 @@ ToolImageEmitUeFile (
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool
|
||||||
|
ToolImageEmitUeXipFile (
|
||||||
|
image_tool_dynamic_buffer *Buffer,
|
||||||
|
image_tool_image_info_t *Image
|
||||||
|
)
|
||||||
|
{
|
||||||
|
bool Success;
|
||||||
|
UE_HEADER UeHdr;
|
||||||
|
uint8_t AlignmentExponent;
|
||||||
|
int8_t Machine;
|
||||||
|
uint8_t Subsystem;
|
||||||
|
uint8_t LastSegmentIndex;
|
||||||
|
uint8_t NumLoadTables;
|
||||||
|
uint32_t Offset;
|
||||||
|
uint32_t UeHdrOff;
|
||||||
|
bool Chaining;
|
||||||
|
uint16_t Index;
|
||||||
|
uint64_t BaseAddress;
|
||||||
|
|
||||||
|
assert (Image->SegmentInfo.NumSegments > 0);
|
||||||
|
|
||||||
|
if (Image->SegmentInfo.NumSegments > UE_HEADER_NUM_SEGMENTS_MAX) {
|
||||||
|
DEBUG_RAISE ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Image->HiiInfo.DataSize > 0) {
|
||||||
|
DEBUG_RAISE ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseAddress = Image->HeaderInfo.BaseAddress;
|
||||||
|
UeHdrOff = ALIGN_VALUE(sizeof (UeHdr), Image->SegmentInfo.SegmentAlignment);
|
||||||
|
|
||||||
|
Success = ToolImageRelocate (Image, BaseAddress + UeHdrOff, 0);
|
||||||
|
if (!Success) {
|
||||||
|
DEBUG_RAISE ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AlignmentExponent = AlignmentToExponent (Image->SegmentInfo.SegmentAlignment);
|
||||||
|
if (12 > AlignmentExponent || AlignmentExponent > 27) {
|
||||||
|
DEBUG_RAISE ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Machine = InternalGetUeMachine (Image->HeaderInfo.Machine);
|
||||||
|
if (Machine < 0) {
|
||||||
|
DEBUG_RAISE ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NumLoadTables = 0U;
|
||||||
|
Subsystem = (uint8_t)(Image->HeaderInfo.Subsystem - 10U);
|
||||||
|
LastSegmentIndex = (uint8_t)(Image->SegmentInfo.NumSegments - 1U);
|
||||||
|
Chaining = false;
|
||||||
|
|
||||||
|
UeHdr.Magic = UE_HEADER_MAGIC;
|
||||||
|
|
||||||
|
UeHdr.Type = (Machine << 3U) | Subsystem;
|
||||||
|
assert (UE_HEADER_SUBSYSTEM (UeHdr.Type) == Subsystem);
|
||||||
|
assert (UE_HEADER_ARCH (UeHdr.Type) == Machine);
|
||||||
|
|
||||||
|
UeHdr.TableCounts = NumLoadTables;
|
||||||
|
UeHdr.TableCounts |= LastSegmentIndex << 3U;
|
||||||
|
assert (UE_HEADER_LAST_SEGMENT_INDEX (UeHdr.TableCounts) == LastSegmentIndex);
|
||||||
|
assert (UE_HEADER_NUM_LOAD_TABLES (UeHdr.TableCounts) == NumLoadTables);
|
||||||
|
|
||||||
|
UeHdr.EntryPointAddress = Image->HeaderInfo.EntryPointAddress + UeHdrOff;
|
||||||
|
|
||||||
|
UeHdr.ImageInfo = BaseAddress >> 12ULL;
|
||||||
|
UeHdr.ImageInfo |= UE_HEADER_IMAGE_INFO_XIP;
|
||||||
|
UeHdr.ImageInfo |= (uint64_t)Image->HeaderInfo.FixedAddress << 57ULL;
|
||||||
|
UeHdr.ImageInfo |= (uint64_t)Image->RelocInfo.RelocsStripped << 58ULL;
|
||||||
|
UeHdr.ImageInfo |= (uint64_t)Chaining << 59ULL;
|
||||||
|
UeHdr.ImageInfo |= (uint64_t)(AlignmentExponent - 12U) << 60ULL;
|
||||||
|
assert (UE_HEADER_BASE_ADDRESS (UeHdr.ImageInfo) == BaseAddress);
|
||||||
|
assert ((UeHdr.ImageInfo & (0xFULL << 52ULL)) == 0);
|
||||||
|
assert (((UeHdr.ImageInfo & UE_HEADER_IMAGE_INFO_FIXED_ADDRESS) != 0) == Image->HeaderInfo.FixedAddress);
|
||||||
|
assert (((UeHdr.ImageInfo & UE_HEADER_IMAGE_INFO_RELOCATION_FIXUPS_STRIPPED) != 0) == Image->RelocInfo.RelocsStripped);
|
||||||
|
assert (((UeHdr.ImageInfo & UE_HEADER_IMAGE_INFO_CHAINED_FIXUPS) != 0) == Chaining);
|
||||||
|
assert (((UeHdr.ImageInfo & UE_HEADER_IMAGE_INFO_XIP) != 0) == TRUE);
|
||||||
|
assert (UE_HEADER_SEGMENT_ALIGNMENT (UeHdr.ImageInfo) == Image->SegmentInfo.SegmentAlignment);
|
||||||
|
|
||||||
|
Offset = ImageToolBufferAppend (Buffer, &UeHdr, sizeof (UeHdr));
|
||||||
|
if (Offset == MAX_UINT32) {
|
||||||
|
DEBUG_RAISE ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Success = ToolImageEmitUeSegmentHeaders (Buffer, Image);
|
||||||
|
if (!Success) {
|
||||||
|
DEBUG_RAISE ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset = ImageToolBufferAppendReserveAlign (
|
||||||
|
Buffer,
|
||||||
|
Image->SegmentInfo.SegmentAlignment
|
||||||
|
);
|
||||||
|
if (Offset == MAX_UINT32) {
|
||||||
|
DEBUG_RAISE ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
||||||
|
Offset = ImageToolBufferAppend (
|
||||||
|
Buffer,
|
||||||
|
Image->SegmentInfo.Segments[Index].Data,
|
||||||
|
Image->SegmentInfo.Segments[Index].UnpaddedSize
|
||||||
|
);
|
||||||
|
if (Offset == MAX_UINT32) {
|
||||||
|
DEBUG_RAISE ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset = ImageToolBufferAppendReserve (
|
||||||
|
Buffer,
|
||||||
|
Image->SegmentInfo.Segments[Index].ImageSize - Image->SegmentInfo.Segments[Index].UnpaddedSize
|
||||||
|
);
|
||||||
|
if (Offset == MAX_UINT32) {
|
||||||
|
DEBUG_RAISE ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
ToolImageEmitUe (
|
ToolImageEmitUe (
|
||||||
image_tool_image_info_t *Image,
|
image_tool_image_info_t *Image,
|
||||||
@ -921,13 +1051,14 @@ ToolImageEmitUe (
|
|||||||
uint32_t BaseAddressSubtrahend;
|
uint32_t BaseAddressSubtrahend;
|
||||||
void *FileBuffer;
|
void *FileBuffer;
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
ImageToolBufferInit (&Buffer);
|
||||||
if (Xip) {
|
|
||||||
DEBUG_RAISE ();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
|
|
||||||
|
ImageInitUnpaddedSize (Image);
|
||||||
|
ToolImageEmitUePadChainedRelocs (Image);
|
||||||
|
|
||||||
|
if (Xip) {
|
||||||
|
Success = ToolImageEmitUeXipFile (&Buffer, Image);
|
||||||
|
} else {
|
||||||
Success = ToolImageStripEmptyPrefix (&BaseAddressSubtrahend, Image);
|
Success = ToolImageStripEmptyPrefix (&BaseAddressSubtrahend, Image);
|
||||||
if (!Success) {
|
if (!Success) {
|
||||||
DEBUG_RAISE ();
|
DEBUG_RAISE ();
|
||||||
@ -938,12 +1069,9 @@ ToolImageEmitUe (
|
|||||||
ToolImageStripRelocs (Image);
|
ToolImageStripRelocs (Image);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageInitUnpaddedSize (Image);
|
|
||||||
ToolImageEmitUePadChainedRelocs (Image);
|
|
||||||
|
|
||||||
ImageToolBufferInit (&Buffer);
|
|
||||||
|
|
||||||
Success = ToolImageEmitUeFile (&Buffer, Image, BaseAddressSubtrahend);
|
Success = ToolImageEmitUeFile (&Buffer, Image, BaseAddressSubtrahend);
|
||||||
|
}
|
||||||
|
|
||||||
if (!Success) {
|
if (!Success) {
|
||||||
DEBUG_RAISE ();
|
DEBUG_RAISE ();
|
||||||
ImageToolBufferFree (&Buffer);
|
ImageToolBufferFree (&Buffer);
|
||||||
|
@ -3622,6 +3622,9 @@ Returns:
|
|||||||
UINT8 ImageFormat;
|
UINT8 ImageFormat;
|
||||||
UINT32 RebasedImageSize;
|
UINT32 RebasedImageSize;
|
||||||
VOID *RebasedImage;
|
VOID *RebasedImage;
|
||||||
|
UINT32 FfsFileLength;
|
||||||
|
UINTN FileOffset;
|
||||||
|
EFI_FFS_INTEGRITY_CHECK *IntegrityCheck;
|
||||||
|
|
||||||
Index = 0;
|
Index = 0;
|
||||||
Cptr = NULL;
|
Cptr = NULL;
|
||||||
@ -3790,6 +3793,7 @@ Returns:
|
|||||||
|
|
||||||
UefiImageFileBuffer = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize);
|
UefiImageFileBuffer = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize);
|
||||||
UefiImageFileSize = SectPeSize;
|
UefiImageFileSize = SectPeSize;
|
||||||
|
FileOffset = (UINTN)UefiImageFileBuffer - (UINTN)(*FfsFile);
|
||||||
//
|
//
|
||||||
// UefiImage has no reloc section. It will try to get reloc data from the original UEFI image.
|
// UefiImage has no reloc section. It will try to get reloc data from the original UEFI image.
|
||||||
//
|
//
|
||||||
@ -3871,9 +3875,52 @@ Returns:
|
|||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
UefiImageFileBuffer = NULL;
|
if (ImageFormat == UefiImageFormatUe) {
|
||||||
UefiImageFileSize = 0;
|
FfsFileLength = GetFfsFileLength (*FfsFile) - SectPeSize + RebasedImageSize;
|
||||||
|
*FfsFile = realloc (*FfsFile, FfsFileLength);
|
||||||
|
if (*FfsFile == NULL) {
|
||||||
|
fprintf (stderr, "GenFv: Could not reallocate memory for rebased FfsFile\n");
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
*FileSize = FfsFileLength;
|
||||||
|
|
||||||
|
memmove (
|
||||||
|
(UINT8 *)((UINTN)(*FfsFile) + FileOffset),
|
||||||
|
RebasedImage,
|
||||||
|
RebasedImageSize
|
||||||
|
);
|
||||||
|
|
||||||
|
if (FfsHeaderSize > sizeof(EFI_FFS_FILE_HEADER)) {
|
||||||
|
((EFI_FFS_FILE_HEADER2 *)(*FfsFile))->ExtendedSize = FfsFileLength;
|
||||||
|
} else {
|
||||||
|
(*FfsFile)->Size[0] = (UINT8)(FfsFileLength & 0x000000FF);
|
||||||
|
(*FfsFile)->Size[1] = (UINT8)((FfsFileLength & 0x0000FF00) >> 8);
|
||||||
|
(*FfsFile)->Size[2] = (UINT8)((FfsFileLength & 0x00FF0000) >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Recalculate the FFS header checksum. Instead of setting Header and State
|
||||||
|
// both to zero, set Header to (UINT8)(-State) so State preserves its original
|
||||||
|
// value
|
||||||
|
//
|
||||||
|
IntegrityCheck = &(*FfsFile)->IntegrityCheck;
|
||||||
|
IntegrityCheck->Checksum.Header = (UINT8) (0x100 - (*FfsFile)->State);
|
||||||
|
IntegrityCheck->Checksum.File = 0;
|
||||||
|
|
||||||
|
IntegrityCheck->Checksum.Header = CalculateChecksum8 (
|
||||||
|
(UINT8 *)(*FfsFile), FfsHeaderSize);
|
||||||
|
|
||||||
|
if ((*FfsFile)->Attributes & FFS_ATTRIB_CHECKSUM) {
|
||||||
|
//
|
||||||
|
// Ffs header checksum = zero, so only need to calculate ffs body.
|
||||||
|
//
|
||||||
|
IntegrityCheck->Checksum.File = CalculateChecksum8 (
|
||||||
|
(UINT8 *)(*FfsFile) + FfsHeaderSize,
|
||||||
|
FfsFileLength - FfsHeaderSize);
|
||||||
|
} else {
|
||||||
|
IntegrityCheck->Checksum.File = FFS_FIXED_CHECKSUM;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (RebasedImageSize > SectPeSize) {
|
if (RebasedImageSize > SectPeSize) {
|
||||||
Error (NULL, 0, 4001, "Invalid", "rebased file is too large (%s)", FileName);
|
Error (NULL, 0, 4001, "Invalid", "rebased file is too large (%s)", FileName);
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
@ -3903,6 +3950,7 @@ Returns:
|
|||||||
);
|
);
|
||||||
(*FfsFile)->State = SavedState;
|
(*FfsFile)->State = SavedState;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get this module function address from ModulePeMapFile and add them into FvMap file
|
// Get this module function address from ModulePeMapFile and add them into FvMap file
|
||||||
@ -3910,7 +3958,7 @@ Returns:
|
|||||||
|
|
||||||
Status = UefiImageInitializeContext (
|
Status = UefiImageInitializeContext (
|
||||||
&ImageContext,
|
&ImageContext,
|
||||||
(VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize),
|
(VOID *) ((UINTN)(*FfsFile) + FileOffset),
|
||||||
RebasedImageSize,
|
RebasedImageSize,
|
||||||
UEFI_IMAGE_SOURCE_FV
|
UEFI_IMAGE_SOURCE_FV
|
||||||
);
|
);
|
||||||
@ -3927,6 +3975,9 @@ Returns:
|
|||||||
&ImageContext
|
&ImageContext
|
||||||
);
|
);
|
||||||
|
|
||||||
|
UefiImageFileBuffer = NULL;
|
||||||
|
UefiImageFileSize = 0;
|
||||||
|
|
||||||
free (SymbolsPathCpy);
|
free (SymbolsPathCpy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,7 +501,8 @@ typedef struct {
|
|||||||
///
|
///
|
||||||
/// [Bits 51:0] The base UEFI page of the UE image, i.e., the base address in
|
/// [Bits 51:0] The base UEFI page of the UE image, i.e., the base address in
|
||||||
/// 4 KiB units.
|
/// 4 KiB units.
|
||||||
/// [Bits 56:52] Reserved for future use. Must be zero.
|
/// [Bits 55:52] Reserved for future use. Must be zero.
|
||||||
|
/// [Bit 56] Indicates whether the UE image is XIP
|
||||||
/// [Bit 57] Indicates whether the UE image is designated for a fixed
|
/// [Bit 57] Indicates whether the UE image is designated for a fixed
|
||||||
/// address.
|
/// address.
|
||||||
/// [Bit 58] Indicates whether the UE relocation table has been stripped.
|
/// [Bit 58] Indicates whether the UE relocation table has been stripped.
|
||||||
@ -569,6 +570,11 @@ STATIC_ASSERT (
|
|||||||
#define UE_HEADER_SEGMENT_ALIGNMENT(ImageInfo) \
|
#define UE_HEADER_SEGMENT_ALIGNMENT(ImageInfo) \
|
||||||
(1U << ((UINT8)RShiftU64 (ImageInfo, 60) + 12U))
|
(1U << ((UINT8)RShiftU64 (ImageInfo, 60) + 12U))
|
||||||
|
|
||||||
|
///
|
||||||
|
/// UE header image information bit that indicates whether the image is XIP.
|
||||||
|
///
|
||||||
|
#define UE_HEADER_IMAGE_INFO_XIP 0x0100000000000000ULL
|
||||||
|
|
||||||
///
|
///
|
||||||
/// UE header image information bit that indicates whether the image is
|
/// UE header image information bit that indicates whether the image is
|
||||||
/// designated to be loaded to a fixed address.
|
/// designated to be loaded to a fixed address.
|
||||||
|
@ -17,6 +17,7 @@ typedef struct {
|
|||||||
UINT8 Subsystem;
|
UINT8 Subsystem;
|
||||||
UINT8 Machine;
|
UINT8 Machine;
|
||||||
BOOLEAN FixedAddress;
|
BOOLEAN FixedAddress;
|
||||||
|
BOOLEAN XIP;
|
||||||
UINT8 LastSegmentIndex;
|
UINT8 LastSegmentIndex;
|
||||||
UINT32 SegmentsFileOffset; // Unused for XIP
|
UINT32 SegmentsFileOffset; // Unused for XIP
|
||||||
UINT32 SegmentAlignment;
|
UINT32 SegmentAlignment;
|
||||||
|
@ -273,6 +273,10 @@ InternalInitializeContextLate (
|
|||||||
return RETURN_UNSUPPORTED;
|
return RETURN_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Context->XIP) {
|
||||||
|
return RETURN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
return InternalVerifyLoadTables (Context);
|
return InternalVerifyLoadTables (Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,6 +324,7 @@ UeInitializeContextPostHash (
|
|||||||
|
|
||||||
Context->FixedAddress = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_FIXED_ADDRESS) != 0;
|
Context->FixedAddress = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_FIXED_ADDRESS) != 0;
|
||||||
Context->RelocsStripped = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_RELOCATION_FIXUPS_STRIPPED) != 0;
|
Context->RelocsStripped = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_RELOCATION_FIXUPS_STRIPPED) != 0;
|
||||||
|
Context->XIP = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_XIP) != 0;
|
||||||
|
|
||||||
Context->LastSegmentIndex = LastSegmentIndex;
|
Context->LastSegmentIndex = LastSegmentIndex;
|
||||||
Context->NumLoadTables = NumLoadTables;
|
Context->NumLoadTables = NumLoadTables;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user