Skip to content

Commit

Permalink
BaseTools, BaseUeImageLib: Added support for 32-bit chaining relocati…
Browse files Browse the repository at this point in the history
…ons.

Fixed Windows 10 BlueScreen issue for IA32.
  • Loading branch information
Mikhail Krichanov committed Sep 8, 2023
1 parent b8d3519 commit 7797818
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 18 deletions.
44 changes: 40 additions & 4 deletions BaseTools/ImageTool/UeEmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ ToolImageEmitUeRelocTable (
uint32_t RelocOffset;

uint64_t ChainRelocInfo;
uint32_t ChainRelocInfo32;

uint8_t PrevRelocType;
uint32_t PrevRelocTarget;
Expand All @@ -323,6 +324,7 @@ ToolImageEmitUeRelocTable (
uint8_t PrevRelocSize;

uint64_t PrevChainRelocInfo;
uint32_t PrevChainRelocInfo32;

bool ChainInProgress;
bool ChainSupported;
Expand Down Expand Up @@ -385,7 +387,7 @@ ToolImageEmitUeRelocTable (
{
RelocSize = sizeof (UINT32);
RelocType = UeReloc32;
ChainSupported = false;
ChainSupported = Chaining;
break;
}

Expand Down Expand Up @@ -426,9 +428,9 @@ ToolImageEmitUeRelocTable (
//

if (ChainInProgress) {
ChainInProgress = ChainSupported && RelocOffset <= UE_CHAINED_RELOC_FIXUP_MAX_OFFSET;
ChainInProgress = ChainSupported && (RelocOffset <= UE_CHAINED_RELOC_FIXUP_MAX_OFFSET) && (PrevRelocType == RelocType);

if (ChainInProgress) {
if (ChainInProgress && (RelocType == UeReloc64)) {
PrevChainRelocInfo = RelocType;
PrevChainRelocInfo |= RelocOffset << 4U;
PrevChainRelocInfo |= PrevRelocValue << 16U;
Expand All @@ -444,10 +446,22 @@ ToolImageEmitUeRelocTable (
&PrevChainRelocInfo,
PrevRelocSize
);
} else if (ChainInProgress && (RelocType == UeReloc32)) {
PrevChainRelocInfo32 = RelocOffset;
PrevChainRelocInfo32 |= PrevRelocValue << UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT;

assert (PrevRelocSize <= sizeof (PrevChainRelocInfo32));

ImageToolBufferWrite (
Buffer,
PrevRelocFileOffset,
&PrevChainRelocInfo32,
PrevRelocSize
);
}
}

if (ChainSupported) {
if (ChainSupported && (RelocType == UeReloc64)) {
ChainRelocInfo = UE_CHAINED_RELOC_FIXUP_OFFSET_END << 4U;
ChainRelocInfo |= RelocValue << 16U;
if ((ChainRelocInfo >> 16U) != RelocValue) {
Expand All @@ -471,6 +485,28 @@ ToolImageEmitUeRelocTable (
continue;
}

ChainInProgress = true;
} else if (ChainSupported && (RelocType == UeReloc32)) {
ChainRelocInfo32 = UE_CHAINED_RELOC_FIXUP_OFFSET_END;
ChainRelocInfo32 |= RelocValue << UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT;
if ((ChainRelocInfo32 >> UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT) != RelocValue) {
DEBUG_RAISE ();
return false;
}

assert (RelocSize <= sizeof (ChainRelocInfo32));

ImageToolBufferWrite (
Buffer,
RelocFileOffset,
&ChainRelocInfo32,
RelocSize
);

if (ChainInProgress) {
continue;
}

ChainInProgress = true;
}

Expand Down
26 changes: 25 additions & 1 deletion BaseTools/ImageTool/UeScan.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,30 @@ InternalProcessRelocChain (
WriteUnaligned64 (Fixup, FixupValue.Value64);

Reloc.Type = EFI_IMAGE_REL_BASED_DIR64;
} else if (RelocType == UeReloc32) {
FixupSize = sizeof (UINT32);
//
// Verify the image relocation fixup target is in bounds of the image
// buffer.
//
if (FixupSize > RemRelocTargetSize) {
DEBUG_RAISE ();
return RETURN_VOLUME_CORRUPTED;
}
//
// Relocate the target instruction.
//
FixupInfo.Value32 = ReadUnaligned32 (Fixup);
FixupValue.Value32 = UE_CHAINED_RELOC_FIXUP_VALUE_32 (FixupInfo.Value32);
WriteUnaligned32 (Fixup, FixupValue.Value32);

Reloc.Type = EFI_IMAGE_REL_BASED_HIGHLOW;
//
// Imitate the common header of UE chained relocation fixups,
// as for 32-bit files all relocs have the same type.
//
FixupInfo.Value32 = FixupInfo.Value32 << 4;
FixupInfo.Value32 |= UeReloc32;
} else {
//
// The Image relocation fixup type is unknown, disallow the Image.
Expand Down Expand Up @@ -272,7 +296,7 @@ ScanUeGetRelocInfo (
//
RelocType = UE_RELOC_FIXUP_TYPE (FixupInfo);

if (Chaining && RelocType != UeReloc32) {
if (Chaining) {
Status = InternalProcessRelocChain (
&Buffer,
SegmentInfo,
Expand Down
23 changes: 23 additions & 0 deletions MdePkg/Include/IndustryStandard/UeImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,29 @@ typedef UINT16 UE_RELOC_FIXUP_HDR;
///
typedef UINT64 UE_RELOC_FIXUP_64;

///
/// The shift exponent for UE chained 32-bit relocation fixup values.
///
#define UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT 12U

/**
Retrieves the value of the current UE chained 32-bit relocation fixup.
@param[in] FixupInfo The UE relocation fixup information.
**/
#define UE_CHAINED_RELOC_FIXUP_VALUE_32(FixupInfo) \
(UINT32)((UINT32)(FixupInfo) >> UE_CHAINED_RELOC_FIXUP_VALUE_32_SHIFT)

///
/// Definition of the generic 32-bit UE chained relocation fixup.
///
/// [Bits 11:0] The offset to the next chained relocation fixup from the end
/// of the current one. If 0x0FFF, the current chain is terminated.
/// Consult the fixup root for further relocation fixups.
/// [Bits 31:12] The address value to relocate.
///
typedef UINT32 UE_RELOC_FIXUP_32;

#if 0
///
/// Definition of the ARM Thumb MOVT/MOVW UE chained relocation fixup.
Expand Down
47 changes: 35 additions & 12 deletions MdePkg/Library/BaseUeImageLib/UeImageLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,20 +505,20 @@ InternalApplyRelocation (
//
// If the Image relocation target value mismatches, skip or abort.
//
// if (IsRuntime && (FixupValue.Value32 != (UINT32)*FixupData)) {
// if (PcdGetBool (PcdImageLoaderRtRelocAllowTargetMismatch)) {
// return RETURN_SUCCESS;
// }
//
// return RETURN_VOLUME_CORRUPTED;
// }
if (IsRuntime && (FixupValue.Value64 != *FixupData)) {
if (PcdGetBool (PcdImageLoaderRtRelocAllowTargetMismatch)) {
return RETURN_SUCCESS;
}

return RETURN_VOLUME_CORRUPTED;
}

FixupValue.Value32 += (UINT32) Adjust;
WriteUnaligned32 (Fixup, FixupValue.Value32);

// if (!IsRuntime) {
// *FixupData = FixupValue.Value32;
// }
if (!IsRuntime) {
*FixupData = FixupValue.Value64;
}
} else {
ASSERT (RelocType == UeReloc64);

Expand Down Expand Up @@ -657,7 +657,30 @@ InternalProcessRelocChain (
FixupInfo.Value64 = ReadUnaligned64 ((CONST VOID *)Fixup);
FixupValue.Value64 = UE_CHAINED_RELOC_FIXUP_VALUE (FixupInfo.Value64);
FixupValue.Value64 += Adjust;
WriteUnaligned64 ((VOID *) Fixup, FixupValue.Value64);
WriteUnaligned64 ((VOID *)Fixup, FixupValue.Value64);
} else if (RelocType == UeReloc32) {
FixupSize = sizeof (UINT32);
//
// Verify the image relocation fixup target is in bounds of the image
// buffer.
//
if (FixupSize > RemFixupTargetSize) {
DEBUG_RAISE ();
return RETURN_VOLUME_CORRUPTED;
}
//
// Relocate the target instruction.
//
FixupInfo.Value32 = ReadUnaligned32 ((CONST VOID *)Fixup);
FixupValue.Value32 = UE_CHAINED_RELOC_FIXUP_VALUE_32 (FixupInfo.Value32);
FixupValue.Value32 += (UINT32) Adjust;
WriteUnaligned32 ((VOID *)Fixup, FixupValue.Value32);
//
// Imitate the common header of UE chained relocation fixups,
// as for 32-bit files all relocs have the same type.
//
FixupInfo.Value32 = FixupInfo.Value32 << 4;
FixupInfo.Value32 |= UeReloc32;
} else {
//
// The image relocation fixup type is unknown, disallow the image.
Expand Down Expand Up @@ -790,7 +813,7 @@ InternaRelocateImage (
//
RelocType = UE_RELOC_FIXUP_TYPE (FixupInfo);

if (Chaining && RelocType != UeReloc32) {
if (Chaining) {
Status = InternalProcessRelocChain (
Image,
ImageSize,
Expand Down
2 changes: 1 addition & 1 deletion OvmfPkg/OvmfPkgIa32.fdf
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
[Rule.Common.DXE_RUNTIME_DRIVER]
FILE DRIVER = $(NAMED_GUID) {
DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
UE UE $(INF_OUTPUT)/$(MODULE_NAME).efi
UI STRING="$(MODULE_NAME)" Optional
VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
}
Expand Down

0 comments on commit 7797818

Please sign in to comment.