mirror of
https://github.com/acidanthera/audk.git
synced 2025-09-21 16:57:44 +02:00
UE: Added support for XIP.
This commit is contained in:
parent
923004dd69
commit
f60c587094
@ -187,6 +187,11 @@ ToolImageEmit (
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((Format == UefiImageFormatUe) && Xip) {
|
||||
ToolImageDestruct (&ImageInfo);
|
||||
return OutputFile;
|
||||
}
|
||||
|
||||
Status = ValidateOutputFile (OutputFile, *OutputFileSize, &ImageInfo);
|
||||
|
||||
ToolImageDestruct (&ImageInfo);
|
||||
|
@ -908,6 +908,136 @@ ToolImageEmitUeFile (
|
||||
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 *
|
||||
ToolImageEmitUe (
|
||||
image_tool_image_info_t *Image,
|
||||
@ -921,29 +1051,27 @@ ToolImageEmitUe (
|
||||
uint32_t BaseAddressSubtrahend;
|
||||
void *FileBuffer;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
if (Xip) {
|
||||
DEBUG_RAISE ();
|
||||
return NULL;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
Success = ToolImageStripEmptyPrefix (&BaseAddressSubtrahend, Image);
|
||||
if (!Success) {
|
||||
DEBUG_RAISE ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (Strip) {
|
||||
ToolImageStripRelocs (Image);
|
||||
}
|
||||
ImageToolBufferInit (&Buffer);
|
||||
|
||||
ImageInitUnpaddedSize (Image);
|
||||
ToolImageEmitUePadChainedRelocs (Image);
|
||||
|
||||
ImageToolBufferInit (&Buffer);
|
||||
if (Xip) {
|
||||
Success = ToolImageEmitUeXipFile (&Buffer, Image);
|
||||
} else {
|
||||
Success = ToolImageStripEmptyPrefix (&BaseAddressSubtrahend, Image);
|
||||
if (!Success) {
|
||||
DEBUG_RAISE ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (Strip) {
|
||||
ToolImageStripRelocs (Image);
|
||||
}
|
||||
|
||||
Success = ToolImageEmitUeFile (&Buffer, Image, BaseAddressSubtrahend);
|
||||
}
|
||||
|
||||
Success = ToolImageEmitUeFile (&Buffer, Image, BaseAddressSubtrahend);
|
||||
if (!Success) {
|
||||
DEBUG_RAISE ();
|
||||
ImageToolBufferFree (&Buffer);
|
||||
|
@ -3622,6 +3622,9 @@ Returns:
|
||||
UINT8 ImageFormat;
|
||||
UINT32 RebasedImageSize;
|
||||
VOID *RebasedImage;
|
||||
UINT32 FfsFileLength;
|
||||
UINTN FileOffset;
|
||||
EFI_FFS_INTEGRITY_CHECK *IntegrityCheck;
|
||||
|
||||
Index = 0;
|
||||
Cptr = NULL;
|
||||
@ -3790,6 +3793,7 @@ Returns:
|
||||
|
||||
UefiImageFileBuffer = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize);
|
||||
UefiImageFileSize = SectPeSize;
|
||||
FileOffset = (UINTN)UefiImageFileBuffer - (UINTN)(*FfsFile);
|
||||
//
|
||||
// UefiImage has no reloc section. It will try to get reloc data from the original UEFI image.
|
||||
//
|
||||
@ -3871,37 +3875,81 @@ Returns:
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
UefiImageFileBuffer = NULL;
|
||||
UefiImageFileSize = 0;
|
||||
if (ImageFormat == UefiImageFormatUe) {
|
||||
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;
|
||||
|
||||
if (RebasedImageSize > SectPeSize) {
|
||||
Error (NULL, 0, 4001, "Invalid", "rebased file is too large (%s)", FileName);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
memmove (
|
||||
(UINT8 *)((UINTN)(*FfsFile) + FileOffset),
|
||||
RebasedImage,
|
||||
RebasedImageSize
|
||||
);
|
||||
|
||||
memmove (
|
||||
(UINT8 *)CurrentPe32Section.Pe32Section + CurSecHdrSize,
|
||||
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) {
|
||||
Error (NULL, 0, 4001, "Invalid", "rebased file is too large (%s)", FileName);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
memmove (
|
||||
(UINT8 *)CurrentPe32Section.Pe32Section + CurSecHdrSize,
|
||||
RebasedImage,
|
||||
RebasedImageSize
|
||||
);
|
||||
memset (
|
||||
(UINT8 *)CurrentPe32Section.Pe32Section + CurSecHdrSize + RebasedImageSize,
|
||||
0,
|
||||
SectPeSize - RebasedImageSize
|
||||
memset (
|
||||
(UINT8 *)CurrentPe32Section.Pe32Section + CurSecHdrSize + RebasedImageSize,
|
||||
0,
|
||||
SectPeSize - RebasedImageSize
|
||||
);
|
||||
|
||||
//
|
||||
// Now update file checksum
|
||||
//
|
||||
if ((*FfsFile)->Attributes & FFS_ATTRIB_CHECKSUM) {
|
||||
SavedState = (*FfsFile)->State;
|
||||
(*FfsFile)->IntegrityCheck.Checksum.File = 0;
|
||||
(*FfsFile)->State = 0;
|
||||
(*FfsFile)->IntegrityCheck.Checksum.File = CalculateChecksum8 (
|
||||
(UINT8 *) ((UINT8 *)(*FfsFile) + FfsHeaderSize),
|
||||
GetFfsFileLength (*FfsFile) - FfsHeaderSize
|
||||
);
|
||||
(*FfsFile)->State = SavedState;
|
||||
//
|
||||
// Now update file checksum
|
||||
//
|
||||
if ((*FfsFile)->Attributes & FFS_ATTRIB_CHECKSUM) {
|
||||
SavedState = (*FfsFile)->State;
|
||||
(*FfsFile)->IntegrityCheck.Checksum.File = 0;
|
||||
(*FfsFile)->State = 0;
|
||||
(*FfsFile)->IntegrityCheck.Checksum.File = CalculateChecksum8 (
|
||||
(UINT8 *) ((UINT8 *)(*FfsFile) + FfsHeaderSize),
|
||||
GetFfsFileLength (*FfsFile) - FfsHeaderSize
|
||||
);
|
||||
(*FfsFile)->State = SavedState;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -3910,7 +3958,7 @@ Returns:
|
||||
|
||||
Status = UefiImageInitializeContext (
|
||||
&ImageContext,
|
||||
(VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize),
|
||||
(VOID *) ((UINTN)(*FfsFile) + FileOffset),
|
||||
RebasedImageSize,
|
||||
UEFI_IMAGE_SOURCE_FV
|
||||
);
|
||||
@ -3927,6 +3975,9 @@ Returns:
|
||||
&ImageContext
|
||||
);
|
||||
|
||||
UefiImageFileBuffer = NULL;
|
||||
UefiImageFileSize = 0;
|
||||
|
||||
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
|
||||
/// 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
|
||||
/// address.
|
||||
/// [Bit 58] Indicates whether the UE relocation table has been stripped.
|
||||
@ -569,6 +570,11 @@ STATIC_ASSERT (
|
||||
#define UE_HEADER_SEGMENT_ALIGNMENT(ImageInfo) \
|
||||
(1U << ((UINT8)RShiftU64 (ImageInfo, 60) + 12U))
|
||||
|
||||
///
|
||||
/// UE header image information bit that indicates whether the image is XIP.
|
||||
///
|
||||
#define UE_HEADER_IMAGE_INFO_XIP 0x0100000000000000ULL
|
||||
|
||||
///
|
||||
/// UE header image information bit that indicates whether the image is
|
||||
/// designated to be loaded to a fixed address.
|
||||
|
@ -17,6 +17,7 @@ typedef struct {
|
||||
UINT8 Subsystem;
|
||||
UINT8 Machine;
|
||||
BOOLEAN FixedAddress;
|
||||
BOOLEAN XIP;
|
||||
UINT8 LastSegmentIndex;
|
||||
UINT32 SegmentsFileOffset; // Unused for XIP
|
||||
UINT32 SegmentAlignment;
|
||||
|
@ -273,6 +273,10 @@ InternalInitializeContextLate (
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (Context->XIP) {
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
return InternalVerifyLoadTables (Context);
|
||||
}
|
||||
|
||||
@ -320,6 +324,7 @@ UeInitializeContextPostHash (
|
||||
|
||||
Context->FixedAddress = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_FIXED_ADDRESS) != 0;
|
||||
Context->RelocsStripped = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_RELOCATION_FIXUPS_STRIPPED) != 0;
|
||||
Context->XIP = (UeHdr->ImageInfo & UE_HEADER_IMAGE_INFO_XIP) != 0;
|
||||
|
||||
Context->LastSegmentIndex = LastSegmentIndex;
|
||||
Context->NumLoadTables = NumLoadTables;
|
||||
|
Loading…
x
Reference in New Issue
Block a user