Haiku's ARM efi bootloader


Alexander von Gluck IV
 

Good morning!

I'm getting a bit desperate, so posting here for any ideas :-)
I've been working on porting Haiku's x86_64 EFI bootloader over to ARM.

We're super close, but have been hung up for a while with the following.

We can successfully make a call to EFI's runtime services (printing hello for example)
However, the second call to EFI always hangs with similar errors.

In the example below i'm booting as a cd, but sd card, etc suffer the same fate.

qemu boot:
qemu-system-arm -bios /usr/share/edk2/arm/QEMU_EFI.fd -M virt -cdrom haiku-mmc.image -m 2048

[Bds]Booting UEFI Misc Device 2
BlockSize : 512
LastBlock : A5FFF
FatDiskIo: Cache Page OutBound occurred!
FSOpen: Open '\EFI\BOOT\BOOTARM.EFI' Success
[Bds] Expand PciRoot(0x0)/Pci(0x2,0x0) -> PciRoot(0x0)/Pci(0x2,0x0)/HD(1,MBR,0x00000000,0x9FF6,0x1D394)/\EFI\BOOT\BOOTARM.EFI
BdsDxe: loading Boot0002 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x2,0x0)
[Security] 3rd party image[0] can be loaded after EndOfDxe: PciRoot(0x0)/Pci(0x2,0x0)/HD(1,MBR,0x00000000,0x9FF6,0x1D394)/\EFI\BOOT\BOOTARM.EFI.
InstallProtocolInterface: 5B1B31A1-9562-11D2-8E3F-00A0C969723B BD994928
Loading driver at 0x000BC570000 EntryPoint=0x000BC570138
Loading driver at 0x000BC570000 EntryPoint=0x000BC570138
InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF BEFFD290
ProtectUefiImageCommon - 0xBD994928
- 0x00000000BC570000 - 0x000000000004A4E4
!!!!!!!! ProtectUefiImageCommon - Section Alignment(0x20) is incorrect !!!!!!!!
BdsDxe: starting Boot0002 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x2,0x0)

Data Abort Exception PC at 0xBC570D34 CPSR 0x60000013
Data Abort Exception PC at 0xBC570D34 CPSR 0x60000013 nZCveaift_svc

R0 0xBFA58F10 R1 0x00043028 R2 0x0003C088 R3 0x00800080
R4 0xBFA58010 R5 0xBD994790 R6 0xBC5AC088 R7 0x00043030
R8 0x00000001 R9 0xBEFFD4D8 R10 0x00000000 R11 0x00000000
R12 0xBFA9ACC0 SP 0xBFA7A9F8 LR 0xBC5709A4 PC 0xBC570D34
DFSR 0x00000005 DFAR 0x008000AC IFSR 0x00000000 IFAR 0x00000000
Translation fault on Section: read from 0x008000AC

ASSERT [ArmCpuDxe] /builddir/build/BUILD/edk2-edk2-stable202002/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c(267): ((BOOLEAN)(0==1))



$ ~/Code/efi_analyzer/efianalyze ./objects/haiku/arm/release/system/boot/efi/haiku_loader.efi
Offset to PE: 0x40
Machine type: 0x01c2, ARM or Thumb ("interworking")
NumberOfSymbols should be 0.
Characteristics: 0x0306
* The file is executable.
* COFF line numbers were stripped from the file.
* The computer supports 32-bit words.
* Debugging information was removed.
Image type: PE32
Size of optional header: 0x90 != 0xe0
Subsystem: EFI application
ImageBase: 0x0
SectionAlignment: 0x20
SizeOfImage: 0x4a4e4
.reloc.address: 0x0
.reloc.size: 0x0
BaseOfCode: 0x138
AddressOfEntryPoint: 0x138
Number of sections: 2
Section[0]: .reloc
Virtual size: 0x0
Virtual address: 0x0
Size of raw data: 0x0
Pointer to raw data: 0x0
End of raw data: 0x0
Characteristics: 0x42100040
* The section contains initialized data.
* Align data on a 1-byte boundary.
* The section can be discarded as needed.
* The section can be read.
Section[1]: .text
Virtual size: 0x4a300
Virtual address: 0x138
Size of raw data: 0x4a3ac
Pointer to raw data: 0x138
End of raw data: 0x4a4e4
Characteristics: 0xe0500020
* The section contains executable code.
* Align data on a 1-byte boundary.
* Align data on a 8-byte boundary.
* The section can be executed as code.
* The section can be read.
* The section can be written to.



Relevant sources:

Linker script:
https://git.haiku-os.org/haiku/tree/src/system/ldscripts/arm/boot_loader_efi.ld
Our "fake" Pe:
https://git.haiku-os.org/haiku/tree/src/system/boot/platform/efi/arch/arm/crt0-efi-arm.S
Relocations:
https://git.haiku-os.org/haiku/tree/src/system/boot/platform/efi/arch/arm/relocation_func.cpp
Our efi_main:
https://git.haiku-os.org/haiku/tree/src/system/boot/platform/efi/start.cpp#n171



Nightly ARM build with latest compiled code (it will autoboot in qemu due to EFI/BOOT/BOOTARM.EFI)
https://s3.wasabisys.com/haiku-nightly/arm/haiku-master-hrev54358-arm-mmc.zip


Any help (no matter how minor) would be appreciated!

Thanks!

-- Alex


valerij zaporogeci
 

"fake" PE... it's no wonder it works this way.

base is BC570000, abort PC is BC570D34. take you "fake" PE and look at
the offset of D34 (or 0xD34 - 0x138 from the .text), what it does.
it's hard to say, it can be anything. it's a broken image, what do you
expect? it's 32 bit ARM and not a single relocation? really? you do
have .data section? so, say, there is some variable X in the data
section. your code references it, and, on 32 bit ARM literal pool
pointers are accessed a PC relative way, but the pointer to X itself
is NOT. where the relocation for it? it's NULL. here, enough reason to
abort, - dereferencing inaccessible address.

.text
LDR r6, [pc, #(LP_X - . - 8)] @ this way r6, holds X address and
can reference it
...
LiteralPool @ it's inside .text section
LP_X: .long X @ X resides inside .data, and LP_X holds its address,
@ it's a subject for base relocations


virtual size of text section is LESS than the size of raw data...
section alignment is 0x20. why?

using appropriate compilers could save you from getting "desperate".


Alexander von Gluck IV
 

July 5, 2020 6:39 PM, "valerij zaporogeci" <vlrzprgts@gmail.com> wrote:

base is BC570000, abort PC is BC570D34. take you "fake" PE and look at
the offset of D34 (or 0xD34 - 0x138 from the .text), what it does.
it's hard to say, it can be anything. it's a broken image, what do you
expect? it's 32 bit ARM and not a single relocation? really? you do
have .data section? so, say, there is some variable X in the data
section. your code references it, and, on 32 bit ARM literal pool
pointers are accessed a PC relative way, but the pointer to X itself
is NOT. where the relocation for it? it's NULL. here, enough reason to
abort, - dereferencing inaccessible address.

.text
LDR r6, [pc, #(LP_X - . - 8)] @ this way r6, holds X address and
can reference it
...
LiteralPool @ it's inside .text section
LP_X: .long X @ X resides inside .data, and LP_X holds its address,
@ it's a subject for base relocations
Thanks! We actually figured it out, just missing our .reloc sections.

virtual size of text section is LESS than the size of raw data...
section alignment is 0x20. why?

using appropriate compilers could save you from getting "desperate".
gnu-efi does it this way because of the *really* inconsistent support in
binutils bfd.

Things seem to be getting a bit better, but documentation is pretty poor
still.

For anyone reading this, semi-recent versions of binutils now support Pe
EFI binaries as long as the Pe target formats are enabled.

objcopy --output-target=pei-x86-64 --subsystem efi-app ...
objcopy --output-target=pei-arm --subsystem efi-app ...

This stuff doesn't seem documented *anywhere*, and everyone is using the
"outdated" efi-app-x86_64 output target.


Maybe tianocore/edk2 should document some real world tool chain examples
generating efi bootloaders? ipxe has literally written their own elf2efi
conversion application due to the inconsistent support and poor documentation.

"fake" PE... it's no wonder it works this way.
There are also no alternatives for aarch64. binutils bfd doesn't have any
code to support Pe aarch64.

-- Alex