UEFI Haiku boot loader for ARM

gnu-efi is a one big hack: Goodbye Gnu-EFI!. Anyway it currently not working. clang + lld-link can link native EFI modules without link scripts and another hacks, just set subsystem and entry point. I have no plans to fix gnu-efi hacks.

1 Like

We may try to get some inspiration from the FreeBSD version of the header:

There are some relevant things I saw:

  • Extra alignment directives
  • Values filled in where ours has “TODO”
  • An extra .reloc section they say is needed for EFI
1 Like

.reloc section is needed certainly, because you cannot guess where FW is going to load your loader image and it’s not something you fill in manually - it’s base relocations through the whole image - every referrence to an absolute address needs to be fixed and .reloc contains records for every such referrence. using PE generating capable compiler/linker is the only sane path.

1 Like

FreeBSD is not doing it and GNU-EFI is not doing it either. So, yes, it’s the easier path, but not the only one. And binutils decided to go elf-only instead of supporting various formats, making this more difficult. I guess even the binutils team wants us to move to clang, then…

1 Like

@X512, could you run my old readpe tool on your haiku_loader.efi ? (and let me know the output)

> readpe /boot/home/Tests/UEFI-link/bootarm.efi
MZ (dos) header:
  magic: 5A4D
  bytesInLastBlock: 78
  blocksInFile: 1
  numRelocations: 0
  headerParagraphs: 4
  minExtraParagraphs: 0
  maxExtraParagraphs: 0
  ss: 0
  sp: 0
  checksum: 0
  ip: 0
  cs: 0
  relocationTableOffset: 40
  overlayNumber: 0
  reserved[4]: -
  oemID: 0
  oemInfo: 0
  reserved2[10]: -
  lfaNew: 78
PE header:
  magic: 4550
  machine: 1C2
  numberOfSections: 5
  timeDateStamp: 5E78EB9C
  pointerToSymbolTable: 5B000
  numberOfSymbols: 12D5
  sizeOfOptionalHeader: E0
  characteristics: 102
PE optional header: (present)
  magic: 10B
  majorOperatingSystemVersion: 6
  minorOperatingSystemVersion: 0
  majorImageVersion: 0
  minorImageVersion: 0
  majorSubsystemVersion: 6
  minorSubsystemVersion: 0

too fast! I added a few more fields… sorry. Could you re-pull, build, and run again?

(or just post your haiku_loader.efi somewhere :wink: )

This is output of my PE decoder:
image

that works. Interesting! Your section alignment is 4096, while gnu-efi is “32”

> readpe /boot/home/Tests/UEFI-link/bootarm.efi
MZ (dos) header:
  magic: 5A4D
  bytesInLastBlock: 78
  blocksInFile: 1
  numRelocations: 0
  headerParagraphs: 4
  minExtraParagraphs: 0
  maxExtraParagraphs: 0
  ss: 0
  sp: 0
  checksum: 0
  ip: 0
  cs: 0
  relocationTableOffset: 40
  overlayNumber: 0
  reserved[4]: -
  oemID: 0
  oemInfo: 0
  reserved2[10]: -
  lfaNew: 78
PE header:
  magic: 4550
  machine: 1C2
  numberOfSections: 5
  timeDateStamp: 5E78EB9C
  pointerToSymbolTable: 5B000
  numberOfSymbols: 12D5
  sizeOfOptionalHeader: E0
  characteristics: 102
PE optional header: (present)
  magic: 10B
  majorOperatingSystemVersion: 6
  minorOperatingSystemVersion: 0
  majorImageVersion: 0
  minorImageVersion: 0
  majorSubsystemVersion: 6
  minorSubsystemVersion: 0

This are recommended values is PE specification (PE Format - Win32 apps | Microsoft Learn).

Also note that align of each section is 1, this align is only used in object files, it is not used in executable files. Alignment from optional header is used for all sections (segments in ELF terminology).

Sections in PE are different from ELF sections, it matches to LOAD entries of program header in ELF.

Invalid ARM haiku_loader.efi produced by current master for comparison:
image

Issues:

  • Wrong alignment.
  • No relocation directory. Relocation directory should have non 0 address and at least 1 entry.
  • Zero image base.

At least the first two should be fixed by incorporating the changes from FreeBSD (that I linked earlier) to our .S hack. On the IRC channel we’ve been discussing the use of an “elf2efi” tool which may be more reliable than doing things manually in a .S.

Interesting, it seems to generate proper PE modules, I try to use it for ARM haiku_loader.efi.

There are many elf2efi tools:

  1. https://github.com/joyent/ipxe/blob/master/src/util/elf2efi.c
  2. https://github.com/efidroid/modules_elf2efi

First produce “Unsupported” modules, second can produce working modules, but it is not compatible with lld and have same problem as in #15819.

btw, interesting, but empty base relocation directory and missing the corresponding .reloc section not necessarily means error. there are cases, where there is nothing to relocate. :slight_smile: that’s relevant for architectures tending to do pc-relative addressing with big offsets available or just small images doing almost nothing. I just checked this by compiling a tiny “os loader” for x64 and aarch32 (same flags, specifying no relocations stripping - /FIXED:NO for msvc/link), a “hello world” C code, plus printing the address of the entry function (taken directly through its pointer). in the x64, there is no .reloc and the base relocation directory is empty, whereas on aarch32 they are present. but, of course in both cases images got loaded NOT where their image base wanted. (it’s because UEFI uses just 1, identity mapped to the system space, address space and so it can’t guarantee availability of an address A at any given time to any of its applications; plus variety of RAM mappings (and its sizes esp. for VMs)). anyway, for 32 bit ARM, relocations seem to be needed from the beginning, so that image most probably is really broken.

1 Like

Neither work really that well from my early testing. I extracted elf2efi this afternoon. It has quite a few requirements (static elf vs current shared, lots of sections it can’t understand)

Until we support native clang, fixing the gnu-efi hacks is likely going to be easier in the short-term

1 Like

I look for a code Haiku and the methods are exists but code it’s not complete.

I fixed the relocation issue but I can’t test it in QEMU here due to the hard-float everywhere. We should really fix multilib support…

1 Like