Generating EFI binaries is possible under arm via --target pei-arm-little --subsystem efi-app It would be nice if the same was possible via aarch64, but no pei-aarch64.c in bfd makes me thing this hasn't been written yet?
(In reply to Alexander von Gluck IV from comment #0) Hi Alexander, > It would be nice if the same was possible via aarch64, but no pei-aarch64.c > in bfd makes me thing this hasn't been written yet? That is correct. :-( I have no idea when/if such support will be provided, sorry. Cheers Nick
A side note, #26218 is related to this one. while Pe aarch64 doesn't exist in bfd, arm exists... but creates broken coff/non-pe binaries. Interesting that pei-arm literally doesn't create pe binaries :-)
This issue is mentioned in passing at https://sources.debian.org/src/shim-signed/1.36/debian/shim-signed.NEWS/ shim-signed (1.34) unstable; urgency=medium Debian no longer supports UEFI Secure Boot on arm64 systems Shim and other EFI programs have always been difficult to build on arm64, compared to x86 platforms. Binutils for amd64 and i386 includes explicit support for creating programs in the PE/COFF binary format that EFI uses, but this has never been added for arm64.
(In reply to Ed Vielmetti from comment #3) > This issue is mentioned in passing at > https://sources.debian.org/src/shim-signed/1.36/debian/shim-signed.NEWS/ > > shim-signed (1.34) unstable; urgency=medium > > Debian no longer supports UEFI Secure Boot on arm64 systems > > Shim and other EFI programs have always been difficult to build on > arm64, compared to x86 platforms. Binutils for amd64 and i386 > includes explicit support for creating programs in the PE/COFF > binary format that EFI uses, but this has never been added for > arm64. Thanks for the update. Not 100% relevant here since this ticket is around adding native PE/EFI binary support to binutils :-) Shim is just an EFI binary to facilitate loading other EFI binaries. While it may be true few use the secure shim, *lots* of projects use EFI bootloaders on ARM64/aarch64
Adding myself to the CC list - as the person who wrote that text in the Debian shim package, I'd love to see this support added.
FYI I've got a partial implementation here: https://github.com/vathpela/binutils/tree/efi-app-aa64 ; it still needs some work. Among other problems, I'm very not thrilled with the way the common header file is generated, as it's racy and failure prone during the build.
(In reply to pjones@redhat.com from comment #6) > FYI I've got a partial implementation here: > https://github.com/vathpela/binutils/tree/efi-app-aa64 ; it still needs some > work. Among other problems, I'm very not thrilled with the way the common > header file is generated, as it's racy and failure prone during the build. Hi!, Awesome, thanks for getting the ball rolling on this! Unfortunately I can't look at the code to give any feedback until the copyright has been assigned to the FSF. Would it be possible for you to push the branch to the binutils repo on sourceware? Cheers, Tamar
(In reply to Tamar Christina from comment #7) > (In reply to pjones@redhat.com from comment #6) > > FYI I've got a partial implementation here: > > https://github.com/vathpela/binutils/tree/efi-app-aa64 ; it still needs some > > work. Among other problems, I'm very not thrilled with the way the common > > header file is generated, as it's racy and failure prone during the build. > > Hi!, > > Awesome, thanks for getting the ball rolling on this! > > Unfortunately I can't look at the code to give any feedback until the > copyright has been assigned to the FSF. Would it be possible for you to > push the branch to the binutils repo on sourceware? > > Cheers, > Tamar I don't have access push to the binutils repo on sourceware, but Red Hat does have a copyright assignment agreement for this sort of thing. Additionally, there's really nothing here that isn't derived from existing binutils code. From my perspective, in terms of copyright it is safe to assume this is is acceptable for upstream.
Aiming for support for this in the next binutils release.
Does anyone happen to know of an easy(ish) way I can test this? I've downloaded and modified https://sourceforge.net/projects/gnu-efi/ to remove the hacks and fixed up the linker script. I can now produce an efi application from hello world #include <efi.h> #include <efilib.h> EFI_STATUS EFIAPI efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { InitializeLib(ImageHandle, SystemTable); Print(L"Hello, world!\n"); return EFI_SUCCESS; } using the standard makefile but having a real hard time figuring out how to test this with qemu-efi-aarch64. Can't seem to be able to get it to go to the efi shell to begin with.
Hi! Do you have an existing UEFI image (e.g. edk2 AAVMF) to use for testing with?
(In reply to Steve McIntyre from comment #11) > Hi! > > Do you have an existing UEFI image (e.g. edk2 AAVMF) to use for testing with? I have been attempting to use QEMU_EFI.fd from http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/4364/QEMU-AARCH64/RELEASE_GCC5/
Hmmm, OK. That UEFI image (when padded up to 64MiB) starts here and will let me start an OS or go into the shell OK. Are you getting any errors?
(In reply to Steve McIntyre from comment #13) > Hmmm, OK. > > That UEFI image (when padded up to 64MiB) starts here and will let me start > an OS or go into the shell OK. Are you getting any errors? No, QEMU just pretty much hangs, maybe a wrong parameter, I'm doing rm -f flash0.img flash1.img dd if=QEMU_EFI.fd bs=1M of=flash0.img conv=notrunc dd if=/dev/zero bs=1M count=64 of=flash1.img dd if=/dev/zero bs=1M count=64 of=flash0.img mkdir boot cp hello.efi boot/ env DISPLAY=:0 qemu-system-aarch64 -machine virt -monitor stdio -drive file=fat:rw:boot/ -drive file=flash0.img,format=raw,if=pflash -drive file=flash1.img,format=raw,if=pflash flash1.img
Hmmm, OK. That UEFI image (when padded up to 64MiB) starts here and will let me start an OS or go into the shell OK. Are you getting any errors?(In reply to Tamar Christina from comment #14) > (In reply to Steve McIntyre from comment #13) > > Hmmm, OK. > > > > That UEFI image (when padded up to 64MiB) starts here and will let me start > > an OS or go into the shell OK. Are you getting any errors? > > No, QEMU just pretty much hangs, maybe a wrong parameter, I'm doing > > rm -f flash0.img flash1.img > dd if=QEMU_EFI.fd bs=1M of=flash0.img conv=notrunc > dd if=/dev/zero bs=1M count=64 of=flash1.img > dd if=/dev/zero bs=1M count=64 of=flash0.img > mkdir boot > cp hello.efi boot/ > env DISPLAY=:0 qemu-system-aarch64 -machine virt -monitor stdio -drive > file=fat:rw:boot/ -drive file=flash0.img,format=raw,if=pflash -drive > file=flash1.img,format=raw,if=pflash flash1.img Aha! Your command there will totally replace the content of flash0.img, not append to it. :-) Try: $ dd if=/dev/zero bs=1M count=62 >> flash0.img (there are probably other dd options to append, but that command is what I've used successfully)
hmmm It looks like I'm dropped to a QEMU shell. (qemu) info status VM status: running which says running, perhaps I can't do this over SSH and a window has popped up on the desktop? If so I'll check it next week :)
(In reply to Tamar Christina from comment #16) > hmmm It looks like I'm dropped to a QEMU shell. > > (qemu) info status > VM status: running > > which says running, perhaps I can't do this over SSH and a window has popped > up on the desktop? If so I'll check it next week :) Cool, sounds good. You can tell qemu to run without graphics etc. too, that's what I tend to do on my arm64 boxes here so I get text display in the xterm: qemu-system-aarch64 -m 2048 --enable-kvm -vga none -nographic -machine virt,gic-version=host,kernel_irqchip=on -cpu host -pflash aarch64-OVMF.fd -pflash aarch64-storage.fd
(In reply to Steve McIntyre from comment #17) > (In reply to Tamar Christina from comment #16) > qemu-system-aarch64 -m 2048 --enable-kvm -vga none -nographic -machine > virt,gic-version=host,kernel_irqchip=on -cpu host -pflash aarch64-OVMF.fd > -pflash aarch64-storage.fd Found the problem, it seems I needed -cpu cortex-a57, it now drops me to the shell. But when I try to run my hello world I get a rather vague Shell> fs0:hello.efi Command Error Status: Not Found I am 80% sure it's the linkerscript, as binutils is able to read and understand the format as produced by clang+lld fine. > file hello.efi hello.efi: PE32+ executable (EFI application) (stripped to external PDB), for MS Windows > objdump -h hello.efi hello.efi: file format pei-littleaarch64 Sections: Idx Name Size VMA LMA File off Algn 0 .text 00005bb0 0000000000002000 0000000000002000 00000400 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .data 00001d80 0000000000008000 0000000000008000 00006000 2**2 CONTENTS, ALLOC, LOAD, DATA 2 .dynamic 000000f0 000000000000a000 000000000000a000 00007e00 2**2 CONTENTS, ALLOC, LOAD, DATA 3 .rela 00000e58 000000000000b000 000000000000b000 00008000 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .dynsym 00000138 000000000000c000 000000000000c000 00009000 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA But afraid I don't know enough about EFI to debug the script. Is there a tool I can use to validate the binary or figure out what that error means?
Can you share your tree so we can replicate this locally? Aside from that, "objdump -f" or even "objdump -x" would be helpful. My initial suspicion is that it's not seeing your binary as relocatable, and EFI_NOT_FOUND is coming from edk2's GetPeCoffImageFixLoadingAssignedAddress(), indicating that the fixed load address is not available. On other arches we solve this with a dummy .reloc section in crt0-efi-ARCH.S (such as this https://github.com/rhboot/gnu-efi/blob/shim-15.5/gnuefi/crt0-efi-x86_64.S#L65 ), and of course you'll need the .reloc section in the linker script (such as https://github.com/rhboot/gnu-efi/blob/shim-15.5/gnuefi/elf_x86_64_efi.lds#L28 ).
(In reply to pjones@redhat.com from comment #19) > Can you share your tree so we can replicate this locally? Aside from that, > "objdump -f" or even "objdump -x" would be helpful. > Yes, I'll do some cleanup and push it to a branch on binutils. > My initial suspicion is that it's not seeing your binary as relocatable, and > EFI_NOT_FOUND is coming from edk2's > GetPeCoffImageFixLoadingAssignedAddress(), indicating that the fixed load > address is not available. On other arches we solve this with a dummy .reloc > section in crt0-efi-ARCH.S (such as this > https://github.com/rhboot/gnu-efi/blob/shim-15.5/gnuefi/crt0-efi-x86_64. > S#L65 ), and of course you'll need the .reloc section in the linker script > (such as > https://github.com/rhboot/gnu-efi/blob/shim-15.5/gnuefi/elf_x86_64_efi. > lds#L28 ). Ahhhhh that would explain it. I didn't add that part in when I removed the PE creation code from crt0-efi-aarch64.S.
(In reply to pjones@redhat.com from comment #19) > Can you share your tree so we can replicate this locally? I have pushed it to a branch called `users/ARM/efi-aarch64-support-binutils` Would appreciate if you could help test it before I push it for review. With the branch objcopy will recognize `--target=efi-app-aarch64` as an efi app for aarch64.
Created attachment 13739 [details] add aarch64_pei_vec to aarch64-*-linux* as well I had to add the attached patch as well to get the targets we build for to include it. With this, some basic support does appear to be functional, though I'm nowhere near done trying it. One thing I have noticed is that the objdump arch list is... a little surprising. We configure the build as such: ../binutils-2.37/configure --disable-dependency-tracking --disable-silent-rules --enable-checking --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include --libdir=/usr/lib64 --libexecdir=/usr/libexec --localstatedir=/var --sharedstatedir=/var/lib --mandir=/usr/share/man --infodir=/usr/share/info --build=x86_64-redhat-linux-gnu --host=x86_64-redhat-linux-gnu --target=aarch64-linux-gnu --program-prefix=aarch64-linux-gnu- --disable-shared --disable-install_libbfd --with-sysroot=/usr/aarch64-linux-gnu/sys-root --enable-deterministic-archives=no --enable-compressed-debug-sections=none --enable-generate-build-notes=no --enable-lto --enable-64-bit-bfd --enable-targets=x86_64-pep --enable-relro=yes --enable-plugins --with-bugurl=http://bugzilla.redhat.com/bugzilla/ When we do that, we get these targets in "objdump --help": aarch64-linux-gnu-objdump: supported targets: elf64-littleaarch64 elf64-bigaarch64 elf32-littleaarch64 elf32-bigaarch64 elf32-littlearm elf32-bigarm pei-aarch64-little elf64-little elf64-big elf32-little elf32-big pe-x86-64 pei-x86-64 pe-bigobj-x86-64 elf64-x86-64 elf64-l1om elf64-k1om pe-i386 pei-i386 elf32-i386 elf32-iamcu srec symbolsrec verilog tekhex binary ihex plugin It's not surprising to see the x86 targets there (we have --enable-targets=x86_64-pep after all), but I don't see the pe*-aarch64* or efi-* targets here at all, nor do I see them in objcopy. That said, clearly the basic support has *worked* in objdump: random:~/devel/fedora/cross-binutils/f35$ aarch64-linux-gnu-objdump -fh shimaa64.efi shimaa64.efi: file format pei-aarch64-little architecture: aarch64, flags 0x00000103: HAS_RELOC, EXEC_P, D_PAGED start address 0x0000000000001000 Sections: Idx Name Size VMA LMA File off Algn 0 .text 00094000 0000000000001000 0000000000001000 00001000 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .data 000325f0 0000000000095000 0000000000095000 00095000 2**2 CONTENTS, ALLOC, LOAD, DATA That's a big step forward, and I'd support upstreaming the patch as is (plus my minor tweak) just for that. Next I'll try building stuff more like we do on x86_64, but that probably won't happen until next week due to other commitments.
(In reply to pjones@redhat.com from comment #22) > Created attachment 13739 [details] > add aarch64_pei_vec to aarch64-*-linux* as well > > I had to add the attached patch as well to get the targets we build for to > include it. With this, some basic support does appear to be functional, > though I'm nowhere near done trying it. No worries, thanks for checking so far! > > When we do that, we get these targets in "objdump --help": > aarch64-linux-gnu-objdump: supported targets: elf64-littleaarch64 > elf64-bigaarch64 elf32-littleaarch64 elf32-bigaarch64 elf32-littlearm > elf32-bigarm pei-aarch64-little elf64-little elf64-big elf32-little > elf32-big pe-x86-64 pei-x86-64 pe-bigobj-x86-64 elf64-x86-64 elf64-l1om > elf64-k1om pe-i386 pei-i386 elf32-i386 elf32-iamcu srec symbolsrec verilog > tekhex binary ihex plugin > > It's not surprising to see the x86 targets there (we have > --enable-targets=x86_64-pep after all), but I don't see the pe*-aarch64* or > efi-* targets here at all, nor do I see them in objcopy. It's in the list you pasted, `elf32-bigarm pei-aarch64-little elf64-little` the sorting is just a bit weird. > That's a big step forward, and I'd support upstreaming the patch as is (plus > my minor tweak) just for that. Next I'll try building stuff more like we do > on x86_64, but that probably won't happen until next week due to other > commitments. Cheers, I will upstream it and keep the bug open till everything is confirmed workig.
(In reply to Tamar Christina from comment #23) > (In reply to pjones@redhat.com from comment #22) > > When we do that, we get these targets in "objdump --help": > > aarch64-linux-gnu-objdump: supported targets: elf64-littleaarch64 > > elf64-bigaarch64 elf32-littleaarch64 elf32-bigaarch64 elf32-littlearm > > elf32-bigarm pei-aarch64-little elf64-little elf64-big elf32-little > > elf32-big pe-x86-64 pei-x86-64 pe-bigobj-x86-64 elf64-x86-64 elf64-l1om > > elf64-k1om pe-i386 pei-i386 elf32-i386 elf32-iamcu srec symbolsrec verilog > > tekhex binary ihex plugin > > > > It's not surprising to see the x86 targets there (we have > > --enable-targets=x86_64-pep after all), but I don't see the pe*-aarch64* or > > efi-* targets here at all, nor do I see them in objcopy. > > It's in the list you pasted, `elf32-bigarm pei-aarch64-little elf64-little` > the sorting is just a bit weird. Indeed, I guess I got a little blinded by all the chaff while I was looking for efi-*.
> > It's in the list you pasted, `elf32-bigarm pei-aarch64-little elf64-little` > > the sorting is just a bit weird. > > Indeed, I guess I got a little blinded by all the chaff while I was looking > for efi-*. The `efi-*` don't exist as targets in binutils, they're an internal mapping for `objcopy`. So in objcopy you have code that interprets `efi-app-*` etc and maps them to the correct target and subsystem. That's why they don't show up in the help.
The master branch has been updated by Tamar Christina <tnfchris@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b69c9d41e89498442cb5af5287f378b3583dd445 commit b69c9d41e89498442cb5af5287f378b3583dd445 Author: Tamar Christina <tamar.christina@arm.com> Date: Tue Nov 23 09:36:39 2021 +0000 AArch64: Add support for AArch64 EFI (efi-*-aarch64). This adds support for efi-*-aarch64 by virtue of adding a new PEI target pei-aarch64-little. This is not a full target and only exists to support EFI at this time. This means that this target does not support relocation processing and is mostly a container format. This format has been added to elf based aarch64 targets such that efi images can be made natively on Linux. However this target is not valid for use with gas but only with objcopy. With these changes the resulting file is recognized as an efi image by third party tools: > pecli info hello.efi Metadata ================================================================================ MD5: 598c32a778b0f0deebe977fef8578c4e SHA1: 4580121edd5cb4dc40f51b28f171fd15250df84c SHA256: 3154bd7cf42433d1c957f6bf55a17ad8c57ed41b29df2d485703349fd6ff1d5c Imphash: Size: 47561 bytes Type: PE32+ executable (EFI application) (stripped to external PDB), for MS Windows Compile Time: 1970-01-01 00:00:00 (UTC - 0x0 ) Entry point: 0x2000 (section .text) Sections ================================================================================ Name RWX VirtSize VirtAddr RawAddr RawSize Entropy md5 .text R-X 0x5bb0 0x2000 0x400 0x5c00 6.39 551fbc264256a3f387de8a891500ae0d .reloc R-- 0xc 0x8000 0x6000 0x200 0.02 0c45f6d812d079821c1d54c09ab89e1d .data RW- 0x1d88 0x9000 0x6200 0x1e00 4.18 5d1137c09f01289dc62bf754f7290db3 .dynamic RW- 0xf0 0xb000 0x8000 0x200 0.34 5c94ed3206f05a277e6f04fbf131f131 .rela R-- 0xe58 0xc000 0x8200 0x1000 1.87 8b5c6bc30f3acb7ca7bf2e6789d68519 .dynsym R-- 0x138 0xd000 0x9200 0x200 0.96 bdcf5101da51aadc663ca8859f88138c Imports ================================================================================ Any magic number is based on the Microsoft PE specification [1]. [1] https://docs.microsoft.com/en-us/windows/win32/debug/pe-format bfd/ChangeLog: 2021-10-21 Tamar Christina <tamar.christina@arm.com> PR binutils/26206 * .gitignore (pe-aarch64igen.c): New. * Makefile.am (pei-aarch64.lo, pe-aarch64igen.lo, pei-aarch64.c, pe-aarch64igen.c): Add support. * Makefile.in: Likewise. * bfd.c (bfd_get_sign_extend_vma): Add pei-aarch64-little. * coff-aarch64.c: New file. * coffcode.h (coff_set_arch_mach_hook, coff_set_flags, coff_write_object_contents) Add aarch64 (aarch64_pei_vec) support. * config.bfd: Likewise. * configure: Likewise. * configure.ac: Likewise. * libpei.h (GET_OPTHDR_IMAGE_BASE, PUT_OPTHDR_IMAGE_BASE, GET_OPTHDR_SIZE_OF_STACK_RESERVE, PUT_OPTHDR_SIZE_OF_STACK_RESERVE, GET_OPTHDR_SIZE_OF_STACK_COMMIT, PUT_OPTHDR_SIZE_OF_STACK_COMMIT, GET_OPTHDR_SIZE_OF_HEAP_RESERVE, PUT_OPTHDR_SIZE_OF_HEAP_RESERVE, GET_OPTHDR_SIZE_OF_HEAP_COMMIT, PUT_OPTHDR_SIZE_OF_HEAP_COMMIT, GET_PDATA_ENTRY, _bfd_peAArch64_bfd_copy_private_bfd_data_common, _bfd_peAArch64_bfd_copy_private_section_data, _bfd_peAArch64_get_symbol_info, _bfd_peAArch64_only_swap_filehdr_out, _bfd_peAArch64_print_private_bfd_data_common, _bfd_peAArch64i_final_link_postscript, _bfd_peAArch64i_only_swap_filehdr_out, _bfd_peAArch64i_swap_aouthdr_in, _bfd_peAArch64i_swap_aouthdr_out, _bfd_peAArch64i_swap_aux_in, _bfd_peAArch64i_swap_aux_out, _bfd_peAArch64i_swap_lineno_in, _bfd_peAArch64i_swap_lineno_out, _bfd_peAArch64i_swap_scnhdr_out, _bfd_peAArch64i_swap_sym_in, _bfd_peAArch64i_swap_sym_out, _bfd_peAArch64i_swap_debugdir_in, _bfd_peAArch64i_swap_debugdir_out, _bfd_peAArch64i_write_codeview_record, _bfd_peAArch64i_slurp_codeview_record, _bfd_peAArch64_print_ce_compressed_pdata): New. * peXXigen.c (_bfd_XXi_swap_aouthdr_in, _bfd_XXi_swap_aouthdr_out, pe_print_pdata, _bfd_XX_print_private_bfd_data_common, _bfd_XX_bfd_copy_private_section_data, _bfd_XXi_final_link_postscript): Support COFF_WITH_peAArch64, * pei-aarch64.c: New file. * peicode.h (coff_swap_scnhdr_in, pe_ILF_build_a_bfd, pe_ILF_object_p): Support COFF_WITH_peAArch64. (jtab): Add dummy entry that traps. * targets.c (aarch64_pei_vec): New. binutils/ChangeLog: 2021-10-21 Tamar Christina <tamar.christina@arm.com> PR binutils/26206 * NEWS: Add new support. * objcopy.c (convert_efi_target): Add efi-*-aarch64 support. * testsuite/binutils-all/aarch64/pei-aarch64-little.d: New test. * testsuite/binutils-all/aarch64/pei-aarch64-little.s: New test. include/ChangeLog: 2021-10-21 Tamar Christina <tamar.christina@arm.com> PR binutils/26206 * coff/aarch64.h: New file. * coff/pe.h (IMAGE_FILE_MACHINE_ARM64): New.
The master branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d91c67e8730354c43fae86fa98fe593925882365 commit d91c67e8730354c43fae86fa98fe593925882365 Author: Alan Modra <amodra@gmail.com> Date: Tue Dec 7 12:36:31 2021 +1030 Re: Add support for AArch64 EFI (efi-*-aarch64) Commit b69c9d41e8 was broken in multiple ways regarding the realloc of the target string, most notably in that "-little" wasn't actually appended to the input_target or output_target. This caused asan errors and "FAIL: Check if efi app format is recognized". I also noticed that the input_target string wasn't being copied but rather the output_target when dealing with the input target. Fix that too. PR 26206 * objcopy.c (convert_efi_target): Rewrite. Allocate modified target strings here.. (copy_main): ..rather than here. Do handle input_target, not output_target for input.
it looks like this one was done and can be closed? :-) It'll be a little while until we (Haiku) update our binutils to be able to test this. For future lurkers, https://git.haiku-os.org/haiku/tree/src/system/boot/Jamfile#n103 is what controls the "fake pe" linker scripts vs the "real pe" binutils formed pe efi app. All that's left is making arm (32-bit) spit out PE EFI apps instead of doing some weird coff thing. https://sourceware.org/bugzilla/show_bug.cgi?id=26218
(In reply to Alexander von Gluck IV from comment #28) > it looks like this one was done and can be closed? :-) Music to my ears. :-)