Am Fri, Mar 26, 2021 at 12:12:44PM +0100 schrieb Mark Kettenis:
> > Date: Fri, 26 Mar 2021 19:43:23 +0900 (JST)
> > From: YASUOKA Masahiko <yasu...@openbsd.org>
> > 
> > Hi,
> > 
> > On Fri, 26 Mar 2021 09:30:43 +0100
> > Jan Klemkow <j.klem...@wemelug.de> wrote:
> > > If you want to boot OpenBSD on an HP EliteBook 830 G7/G8, the bootloader
> > > will hang while loading the kernel.  Because, the UEFI loads the
> > > bootloader on the same place in memory, where the bootloader will copy
> > > the kernel.  We are unable to load the kernel on arbitrary memory.
> > > Thus, the following diff will help you, to get OpenBSD running on these
> > > machines.  It moves the hardcoded Kernel address to a free place.
> > 
> > The openbsd efiboot copies the kernel to that place after
> > ExitBootServices().
> > 
> > sys/arch/amd64/stand/efiboot/exec_i386.c
> >     152         /*
> >     153          * Move the loaded kernel image to the usual place after 
> > calling
> >     154          * ExitBootServices().
> >     155          */
> >     156 #ifdef __amd64__
> >     157         protect_writeable(marks[MARK_START] + delta,
> >     158             marks[MARK_END] - marks[MARK_START]);
> >     159 #endif
> >     160         memmove((void *)marks[MARK_START] + delta, (void 
> > *)marks[MARK_START],
> >     161             marks[MARK_END] - marks[MARK_START]);
> >     162         for (i = 0; i < MARK_MAX; i++)
> >     163                 marks[i] += delta;
> >     164 
> >     165 #ifdef __amd64__
> >     166         (*run_i386)((u_long)run_i386, entry, howto, bootdev, 
> > BOOTARG_APIVER,
> >     167             marks[MARK_END], extmem, cnvmem, ac, (intptr_t)av);
> > 
> > 
> > I think it should work without the ld.script change..
> 
> The (likely) problem is that the memmove() on line 160 is overwriting
> the bootloader code itself.

More than just likely.  We have debugged it, looked at the memory table
etc. and it really is the case that efiboot(8) starts at *the same*
address as where the kernel is supposed to be copied to.  Hence *all*
of efiboot(8) is overwritten, even the code that is currectly doing
the copying.

> There are essentially two ways to fix this:
> 
> 1. Have the bootloader relocate itself to an address that doesn't
>    conflict with the kernel to be loaded.
> 
> 2. Make it possible for the kernel to be loaded at a (somewhat)
>    arbitrary physical address.
> 
> In my view #2 is the way forward.  There are other reasons why that
> would be beneficial as it would make it less predictable at which
> physical address the kernel code lives which could prevent some
> attacks that use the direct map.
> 
> #2 is also the approach taken by the EFIBOOT on armv7 and arm64.  On
> arm64 for example, EFIBOOT loads the kernel into a 64MB memory block
> that is aligned on a 2MB boundary.  The kernel then figures out its
> load address based on that and and patches things up accordingly.
> 
> mlarkin@ was doing some work to change how we load the amd64 kernel.
> His approach was to let the bootloader build the initial page tables
> and jump into the kernel in 64-bit mode with the MMU enabled.  That
> was more focussed on running the kernel at a randomized virtual
> address.  But it should be fairly easy to make it run at a different
> physical address as well this way.  Unfortunately that effort was
> mostly focussed on the legacy bootloader.

I'm also more in favour of #2, but I'm still working on my thesis (==
no time) and x86 isn't my area of expertise.

Reply via email to