> On Oct 5, 2016, at 8:08 AM, valerij zaporogeci <[email protected]> wrote:
> 
> Hi everyone. I have a problem with understanding the description of TE
> files and its relocations.

TE is basically PE/COFF with a smaller header. Unlike ELF (Mach-O, etc.) 
PE/COFF includes the headers in the executable image. The TE header is 
basically the bits required by EFI and the adjustments (so you can calculate 
the location the PE/COFF header would have started, since the sections are 
relative to that in the PE/COFF debug info) needed by the debugger to turn it 
into a PE/COFF. 

The only reason TE exists is to save size in the ROM for XIP code. The build 
tools zero out the unused parts of the PE/COFF header so they tend to compress 
well and TE is not needed. 

> The specifications says this:
> "17.2 XIP Images
> For execute-in-place (XIP) images that do not require relocations,
> loading a TE image simply
> requires that the loader adjust the image’s entry point from the value
> specified in the
> EFI_TE_IMAGE_HEADER. For example, if the image (and thus the TE
> header) resides at memory
> location LoadedImageAddress, then the actual entry for the driver is
> computed as follows:
> EntryPoint = LoadedImageAddress + sizeof (EFI_TE_IMAGE_HEADER)
> +
> ((EFI_TE_IMAGE_HEADER *)LoadedImageAddress)–>
> AddressOfEntryPoint – ((EFI_TE_IMAGE_HEADER *)
> LoadedImageAddress)–>StrippedSize;"
> 
> But it looks not as simple as "simply" adjusting the only
> AddressOfEntryPoint. What "do not require relocations means" here?

PE/COFF images are linked at a specific address and can execute directly if 
they are run from that address. If a PE/COFF image is loaded/executed from a 
different address the relocations must be applied to adjust all the absolute 
references in the image to the new addresses. 

The edk2 links PE/COFF images at zero (or for things like ELF they add a pad 
for the PE/COFF header ~0x220). When an FV is constructed and XIP (SEC, PEIM, 
and PEI CORE) images are placed in the FV these PE/COFF images get relocated to 
the address in the FV (ROM address). 

If the code is XIP then there is no need for relocations as that code can run 
from any address. 

I think this section is making the point that even if the image does not 
contain any relocations (all code is PC relative for example) you still have to 
adjust the EntryPoint to point to ROM address of the entry point. 

> Suppose an Image has ImageBase set to X in its header, and it IS at
> the address X in XIP memory. Will it need relocations?

No. 

> For PE it
> won't, but it seems it is not the case for TE. Since not only
> AddressOfEntryPoint is affected, also CodeBase, sections RVAs and all
> base relocations too. They all are lying not at their RVA in XIP
> memory, because TE has a smaller header and screws up even
> FileAlignment of sections. Doesn't it?

No. The TE header lets you compute the location of the PE/COFF header as this 
is required to make debuggers happy. So part of the TE construction is making 
sure the virtual start of the PE/COFF header is aligned correctly. You also 
need to make sure that the file alignment and section alignment are the same. 
For most toolchains 0x20 is uses as the file and section alignment to save 
space.

Note: 0x20 was picked as that was the smallest value we could get to work with 
Visual Studio "back in the day."

> The adjustment in the quote uses StrippedSize and it is described as
> what was removed from PE:
> 
> "The StrippedSize should be set to the number of bytes removed from
> the start of the original
> image, which will typically include the MS-DOS, COFF, and optional
> headers, as well as the section headers."
> 
> But does it take into account section alignment by FileAlignment?

Yes as I pointed out section alignment and FileAlignment has to be the same for 
XIP to work. 

> (SectionAlignment==FileAlignment in this case). Because for example if
> FileAlignment = 200h, then in PE, section for code would be sitting at
> n*200h from the beginning of the file and from ImageBase in XIP
> memory.
> Here is how specification describes PE->TE tranformation process:
> "• Create an EFI_TE_IMAGE_HEADER in memory
> • Parse the PE/COFF headers in an existing image and extract the
> necessary fields to fill in  the EFI_TE_IMAGE_HEADER
> • Fill in the signature and stripped size fields in the EFI_TE_IMAGE_HEADER
> • Write out the EFI_TE_IMAGE_HEADER to a new binary file
> • Write out the contents of the original image, less the stripped
> headers, to the output file"
> 
> This process would place any section at different file offset
> (dispecting alignment) than in PE, and as a result for XIP - different
> RVA from ImageBase. For XIP this would mean that such a file requires
> relocation, even though its actual ImageBase is exactly what is
> written in the file. For non-XIP it would mean that the loader would
> need section headers to know what displacement to put the section to
> in memory to not break addresses. But they are stripped! Otherwise, if
> it just blindly copies what is after TE header, RVAs would be broken,
> all addresses would be broken, as for XIP.
> In fact this means any TE file loaded at its preferred ImageBase will
> need relocations. And for non-XIP. section header cannot be stripped.
> Then what TE files would not need relocations?

Any TE that executes from the ROM directly does not need relocations. That is 
how it works today. As long as SectionAlignment == FileAlignment then 
everything works from an XIP point of view. 

I guess we could have some bugs in the entire stack (PE/COFF -> TE -> FV) of 
not honoring the original PE/COFF alignment? But as my Niece would say Meh. The 
point of TE is to save space in the ROM vs. PE/COFF so if the section alignment 
is 0x200 there is no point in using TE, you should just use PE/COFF. 

The rules in the FDF file allow you to control if XIP code is TE or PE/COFF. It 
looks like different platforms pick different rules. 
https://github.com/tianocore/edk2/blob/master/QuarkPlatformPkg/QuarkMin.fdf#L517
 
<https://github.com/tianocore/edk2/blob/master/QuarkPlatformPkg/QuarkMin.fdf#L517>
https://github.com/tianocore/edk2/blob/master/OvmfPkg/OvmfPkgX64.fdf#L420 
<https://github.com/tianocore/edk2/blob/master/OvmfPkg/OvmfPkgX64.fdf#L420>

It is also possible to control on a per module basis if an XIP image in TE or 
PE/COFF using RuleOverride in the FDF. 

Thanks,

Andrew Fish

PS. I was looking at the TE Image Header and I was reminded that Vincent Zimmer 
used his initials for the TE signature. I'm sure Vincent will claim this was an 
ode to Mark Zbikowski, since MZ is the signature in the DOS header :). 
 
https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/PeImage.h#L719
 
<https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/PeImage.h#L719>
  UINT16                    Signature;            ///< The signature for TE 
format = "VZ".


> Did I understand right?
> Thank you for answers.
> _______________________________________________
> edk2-devel mailing list
> [email protected]
> https://lists.01.org/mailman/listinfo/edk2-devel

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to