return (CHAR8 *) ((UINTN) Image->ImageBase + Address);\r
}\r
\r
-VOID\r
-RelocatePeImageForRuntime (\r
- RUNTIME_IMAGE_RELOCATION_DATA *Image\r
- )\r
-{\r
- CHAR8 *OldBase;\r
- CHAR8 *NewBase;\r
- EFI_IMAGE_DOS_HEADER *DosHdr;\r
- EFI_IMAGE_NT_HEADERS *PeHdr;\r
- UINT32 NumberOfRvaAndSizes;\r
- EFI_IMAGE_DATA_DIRECTORY *DataDirectory;\r
- EFI_IMAGE_DATA_DIRECTORY *RelocDir;\r
- EFI_IMAGE_BASE_RELOCATION *RelocBase;\r
- EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;\r
- UINT16 *Reloc;\r
- UINT16 *RelocEnd;\r
- CHAR8 *Fixup;\r
- CHAR8 *FixupBase;\r
- UINT16 *F16;\r
- UINT32 *F32;\r
- CHAR8 *FixupData;\r
- UINTN Adjust;\r
- EFI_STATUS Status;\r
-\r
- OldBase = (CHAR8 *) ((UINTN) Image->ImageBase);\r
- NewBase = (CHAR8 *) ((UINTN) Image->ImageBase);\r
-\r
- Status = RuntimeDriverConvertPointer (0, (VOID **) &NewBase);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Adjust = (UINTN) NewBase - (UINTN) OldBase;\r
-\r
- //\r
- // Find the image's relocate dir info\r
- //\r
- DosHdr = (EFI_IMAGE_DOS_HEADER *) OldBase;\r
- if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
- //\r
- // Valid DOS header so get address of PE header\r
- //\r
- PeHdr = (EFI_IMAGE_NT_HEADERS *) (((CHAR8 *) DosHdr) + DosHdr->e_lfanew);\r
- } else {\r
- //\r
- // No Dos header so assume image starts with PE header.\r
- //\r
- PeHdr = (EFI_IMAGE_NT_HEADERS *) OldBase;\r
- }\r
-\r
- if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
- //\r
- // Not a valid PE image so Exit\r
- //\r
- return ;\r
- }\r
- //\r
- // Get some data from the PE type dependent data\r
- //\r
- NumberOfRvaAndSizes = PeHdr->OptionalHeader.NumberOfRvaAndSizes;\r
- DataDirectory = &PeHdr->OptionalHeader.DataDirectory[0];\r
-\r
- //\r
- // Find the relocation block\r
- //\r
- // Per the PE/COFF spec, you can't assume that a given data directory\r
- // is present in the image. You have to check the NumberOfRvaAndSizes in\r
- // the optional header to verify a desired directory entry is there.\r
- //\r
- if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
- RelocDir = DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;\r
- RelocBase = RuntimePeImageAddress (Image, RelocDir->VirtualAddress);\r
- RelocBaseEnd = RuntimePeImageAddress (Image, RelocDir->VirtualAddress + RelocDir->Size);\r
- } else {\r
- //\r
- // Cannot find relocations, cannot continue\r
- //\r
- ASSERT (FALSE);\r
- return ;\r
- }\r
-\r
- ASSERT (RelocBase != NULL && RelocBaseEnd != NULL);\r
-\r
- //\r
- // Run the whole relocation block. And re-fixup data that has not been\r
- // modified. The FixupData is used to see if the image has been modified\r
- // since it was relocated. This is so data sections that have been updated\r
- // by code will not be fixed up, since that would set them back to\r
- // defaults.\r
- //\r
- FixupData = Image->RelocationData;\r
- while (RelocBase < RelocBaseEnd) {\r
-\r
- Reloc = (UINT16 *) ((UINT8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));\r
- RelocEnd = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);\r
- FixupBase = (CHAR8 *) ((UINTN) Image->ImageBase) + RelocBase->VirtualAddress;\r
-\r
- //\r
- // Run this relocation record\r
- //\r
- while (Reloc < RelocEnd) {\r
-\r
- Fixup = FixupBase + (*Reloc & 0xFFF);\r
- switch ((*Reloc) >> 12) {\r
-\r
- case EFI_IMAGE_REL_BASED_ABSOLUTE:\r
- break;\r
-\r
- case EFI_IMAGE_REL_BASED_HIGH:\r
- F16 = (UINT16 *) Fixup;\r
- if (*(UINT16 *) FixupData == *F16) {\r
- *F16 = (UINT16) ((*F16 << 16) + ((UINT16) Adjust & 0xffff));\r
- }\r
-\r
- FixupData = FixupData + sizeof (UINT16);\r
- break;\r
-\r
- case EFI_IMAGE_REL_BASED_LOW:\r
- F16 = (UINT16 *) Fixup;\r
- if (*(UINT16 *) FixupData == *F16) {\r
- *F16 = (UINT16) (*F16 + ((UINT16) Adjust & 0xffff));\r
- }\r
-\r
- FixupData = FixupData + sizeof (UINT16);\r
- break;\r
-\r
- case EFI_IMAGE_REL_BASED_HIGHLOW:\r
- F32 = (UINT32 *) Fixup;\r
- FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));\r
- if (*(UINT32 *) FixupData == *F32) {\r
- *F32 = *F32 + (UINT32) Adjust;\r
- }\r
-\r
- FixupData = FixupData + sizeof (UINT32);\r
- break;\r
-\r
- case EFI_IMAGE_REL_BASED_HIGHADJ:\r
- //\r
- // Not implemented, but not used in EFI 1.0\r
- //\r
- ASSERT (FALSE);\r
- break;\r
-\r
- default:\r
- //\r
- // Only Itanium requires ConvertPeImage_Ex\r
- //\r
- Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);\r
- if (EFI_ERROR (Status)) {\r
- return ;\r
- }\r
- }\r
- //\r
- // Next relocation record\r
- //\r
- Reloc += 1;\r
- }\r
- //\r
- // next reloc block\r
- //\r
- RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;\r
- }\r
-\r
- FlushCpuCache (Image->ImageBase, (UINT64) Image->ImageSize);\r
-}\r