From: Nick Owens Subject: Re: amd64: allocate efiboot trampoline as EfiLoaderCode To: Mike Larkin Cc: tech@openbsd.org Date: Wed, 30 Sep 2026 13:55:48 -0700 On Wed, Sep 30, 2026 at 9:04 AM Mike Larkin wrote: > > On Wed, Sep 30, 2026 at 08:37:08AM -0700, Nick Owens wrote: > > hi, > > > > amd64 efiboot faults under newer edk2 OVMF, similar to the way riscv64 > > does. see my other mail about it, > > https://marc.info/?l=openbsd-tech&m=178386086560425&w=2 > > > > the secure boot OVMF builds that Fedora, RHEL and Gentoo ship set > > PcdDxeNxMemoryProtectionPolicy to 0xC000000000007FD5, which maps > > EfiLoaderData non-executable. efiboot copies the run_i386 trampoline > > I don't understand this statement. OpenBSD doesn't use "secure boot OVMF > shipped from Fedora, RHEL or Gentoo". I seriously doubt that laptop/desktop > vendors do either. > > We do have an OVMF build that will be coming into play after release for use > with UEFI vmm VMs but A) that isn't enabled yet and B) works fine when it will > be enabled. > > So where is this a problem exactly? i boot openbsd on gentoo with libvirt/qemu. these secureboot builds set this, e.g. https://gitweb.gentoo.org/repo/gentoo.git/tree/sys-firmware/edk2/edk2-202608.ebuild#n193. https://src.fedoraproject.org/rpms/edk2 sets this as well, but i don't use Fedora. so the problem happens if you boot openbsd using a linux host, using libvirt or bare qemu, and you have an edk2/ovmf firmware that protects EfiLoaderData with NX. > > I do understand what you're claiming below, and I'm not generally opposed > to the diff but I don't see where this could be failing today and your mail > isn't clear about the failure mode. > > -ml > > > onto its heap, which is EfiLoaderData, so the call into it takes a page > > fault on instruction fetch right after "entry point at 0x1001000". > > > > give the trampoline its own EfiLoaderCode pages instead. keep them below > > 16MB: after ExitBootServices() the kernel is moved to 16MB and up > > without regard for the memory map. > > > > tested with edk2 202608 secure boot OVMF under qemu and bootx64.efi; bsd > > boots. i did not test bootia32. > > > > diff --git a/sys/arch/amd64/stand/efiboot/efiboot.c b/sys/arch/amd64/stand/efiboot/efiboot.c > > index 0401522e3a8..6b7a21b8da8 100644 > > --- a/sys/arch/amd64/stand/efiboot/efiboot.c > > +++ b/sys/arch/amd64/stand/efiboot/efiboot.c > > @@ -80,6 +80,9 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) > > EFI_DEVICE_PATH *dp0 = NULL, *dp; > > EFI_STATUS status; > > EFI_PHYSICAL_ADDRESS stack; > > +#ifdef __amd64__ > > + EFI_PHYSICAL_ADDRESS addr; > > +#endif > > > > ST = systab; > > BS = ST->BootServices; > > @@ -117,9 +120,17 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) > > } > > > > #ifdef __amd64__ > > - /* allocate run_i386_start() on heap */ > > - if ((run_i386 = alloc(run_i386_size)) == NULL) > > - panic("alloc() failed"); > > + /* > > + * Copy run_i386_start() to its own EfiLoaderCode pages. The heap > > + * is EfiLoaderData, which firmware may map non-executable. Stay > > + * below 16MB, as the kernel is moved to 16MB and up. > > + */ > > + addr = 16 * 1024 * 1024; > > + status = BS->AllocatePages(AllocateMaxAddress, EfiLoaderCode, > > + EFI_SIZE_TO_PAGES(run_i386_size), &addr); > > + if (status != EFI_SUCCESS) > > + panic("BS->AllocatePages()"); > > + run_i386 = (void *)addr; > > memcpy(run_i386, run_i386_start, run_i386_size); > > #endif > > > >