flat assembler
Message board for the users of flat assembler.

Index > OS Construction > UEFI PECOFF real specs?

Author
Thread Post new topic Reply to topic
sylware



Joined: 23 Oct 2020
Posts: 461
Location: Marseille/France
sylware 12 Apr 2022, 12:28
I am writing my own UEFI OS loader, and I am very puzzled by the PECOFF constraints which does not seems defined or specified anywhere (like the partial and incomplete specs of the x64 calling convention in UEFI specs).

For instance, if I put the '.text' section below RVA (Relative Virtual Address Space) 0x200, it does not work.
I guess, there would be somewhere in some specs this constraint properly defined. It could be also a "one-liner" in some specs with hundreds of dense pages.
Post 12 Apr 2022, 12:28
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4073
Location: vpcmpistri
bitRAKE 12 Apr 2022, 19:20
AFAIK the lowest valid PE address is 0x10000. The UEFI spec just defers to PE spec in this regard - MS was on the committee. Rolling Eyes

32-bit code has a default load address of 0x40'0000
64-bit code defaults to 0x1'4000'0000
(Although I haven't experienced it, wouldn't surprise me if some BIOS assumed images always have this base.)

There are technical reasons. Some conventions are not spelled out in the specification, afaik.

The 0x200 is probably due to the default alignment being sector size. So, the header load would be a single sector and following sections would be greater than that.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 12 Apr 2022, 19:20
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20445
Location: In your JS exploiting you and your system
revolution 12 Apr 2022, 19:55
The PE format doesn't have these constraints. It is the implementation, or the CPU, that imposes them.

To enumerate them in the PE spec is not correct because later a different implementation using a different CPU may allow the use of address 0x0000 (or whatever).

By convention we use address 0x0000 as a NULL pointer. But this isn't the only choice. For example the Itanium has register tags that allow the use of all addresses as valid and the NULL is an entirely separate tag setting. That is, NULL != 0x0000 in Itanium. In fact NULL != any value. So on an Itanium, with a different BIOS/EFI, addresses from 0x0000 could be used without any issue.
Post 12 Apr 2022, 19:55
View user's profile Send private message Visit poster's website Reply with quote
sylware



Joined: 23 Oct 2020
Posts: 461
Location: Marseille/France
sylware 13 Apr 2022, 01:41
Then where I can find the contraints for a PE+ exe running in UEFI for x86_64/x64?

I was talking about the RVA (Relative Virtual Address from image_base), not the absolute virtual address.

Additionally, there are contradictions: for instance the Linux UEFI OS loader use 0x20 alignment for the virtual address space and the file, even though what I could find on the net seems to say that 0x200 is a minimum.

It is really frustrating, like they provided on purpose actually unusable specs for real implementations... wait... you said microsoft?
Post 13 Apr 2022, 01:41
View user's profile Send private message Reply with quote
Ali.Z



Joined: 08 Jan 2018
Posts: 732
Ali.Z 13 Apr 2022, 03:14
sylware wrote:
It is really frustrating, like they provided on purpose actually unusable specs for real implementations... wait... you said microsoft?


just because it is a real implementation, it doesn't imply that their engineers are capable or there isn't something else...

also as a reminder, microsfot had their agreement with intel since the 80s; so they (microsoft) are the one limiting their software to intel based architectures. (though this is not technically true, as there are some other architectures as well, but that is not the point, the point is they most likely build their specs based on intel architecture)

for Zero address, here are some implications, ... bios/uefi rom ... boot code ... translating physical addresses ... among bunch of other things.

_________________
Asm For Wise Humans
Post 13 Apr 2022, 03:14
View user's profile Send private message Reply with quote
sylware



Joined: 23 Oct 2020
Posts: 461
Location: Marseille/France
sylware 13 Apr 2022, 14:34
I am not looking for excuses here, those are literaly trash specs, microsoft again, period.

Now, I have been reading the official online specs (https://docs.microsoft.com/en-us/windows/win32/debug/pe-format) and linux UEFI Os Loader code.

And I managed to find some of the needles I was looking for in this haystack:


  • https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#section-data
    "There are additional restrictions on image files if the SectionAlignment value in the optional header is less than the page size of the architecture. For such files, the location of section data in the file must match its location in memory when the image is loaded, so that the physical offset for section data is the same as the RVA."

    This means the layout of the file MUST be the image layout in the virtual address space if the section alignment is less than the... "page size". It explains why the sections MUST start after the file headers.

  • https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#other-contents-of-the-file
    "An exception is for images with a SectionAlignment value of less than the page size of the architecture (4 K for Intel x86 and for MIPS, and 8 K for Itanium)"

    Then the "page size" is 4k on x86, then I presume x86_64.

  • https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-windows-specific-fields-image-only
    "The alignment factor (in bytes) that is used to align the raw data of sections in the image file. The value should be a power of 2 between 512 and 64 K, inclusive. The default is 512. If the SectionAlignment is less than the architecture's page size, then FileAlignment must match SectionAlignment."

    In the linux UEFI OS Loader SectionAlignment and FileAlignment are 0x20 then wrong. They should be 0x200. And since they force the section data to start at 0x200 anyway and since UEFI image loaders seem to ignore SectionAlignment and FileAlignment (for now...), lucky us.


I guess I have my answers now. I wonder if I choose a section alignment of 8k and load my sections from RVA 0 (which is specs compliant) what would happen with common UEFI Os Loaders...
Post 13 Apr 2022, 14:34
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8358
Location: Kraków, Poland
Tomasz Grysztar 13 Apr 2022, 15:26
sylware wrote:
And I managed to find some of the needles I was looking for in this haystack
May I suggest taking a look at my executable formats tutorial? I put an effort to describe PE format with focus on the important details like these. The universal template prepared in section 1.6 does handle the non-standard alignment in a compliant way, and this is explained in the text. Also, the flexible templates provided there could be valuable for testing various loader implementations (I did many experiments with them while writing the main text, testing many generations of loaders, including obscure ones like Win32s).
Post 13 Apr 2022, 15:26
View user's profile Send private message Visit poster's website Reply with quote
sylware



Joined: 23 Oct 2020
Posts: 461
Location: Marseille/France
sylware 13 Apr 2022, 19:44
Yep, thx. That's what I was looking for. You found out most of the needles and put them in your documents.

Back to UEFI: I did try with a SectionAlignment of 8192, and tried to load the '.text'/code section at RVA 0, namely at IMAGE_BASE (with an entry point a bit further down since it cannot be 0).

Ofc, the UEFI loader did not accept that, namely only the "special case" of the virtual address space layout = file layout seems accepted.

Ofc, I am unable to locate in the latest UEFI specs anything related to this.

Maybe I did not try hard enough or my UEFI loader is actually garbage.

I did clone tianocore EDK II repo and I am looking for their PECOFF loader code to see if I can get some clues.

Last think I do I guess before continuing on my UEFI OS Loader using the "virtual address space layout = file layout" mode.
Post 13 Apr 2022, 19:44
View user's profile Send private message Reply with quote
sylware



Joined: 23 Oct 2020
Posts: 461
Location: Marseille/France
sylware 13 Apr 2022, 20:46
from tianocore EDK II, in file MdePkg/Library/BasePeCoffLib/BasePeCoff.c:
Code:
      //

      // Section data should bigger than the Pe header.

      //

      if ((SectionHeader.VirtualAddress < ImageContext->SizeOfHeaders) ||

          (SectionHeader.PointerToRawData < ImageContext->SizeOfHeaders))

      {

        ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;

        return RETURN_UNSUPPORTED;

      }
    


This is what I thought: if you try in the virtual address space or in the file to "map a section"/"include a section" below the size of the PECOFF headers, you are toast.

It is obvious in the case of the file, but for the virtual address space, well, not at all (very probably some microsoft legacy trash, because I default those guys as guilty untily proven otherwise).

I guess and I hope I did enough investigation. I'll stick to the "virtual address space layout" = "file layout" mode enabled with SectionAlignment = FileAlignment < 4KiB (I did check, this value is hardcoded in tianocore EDK II).
Post 13 Apr 2022, 20:46
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.