> 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. 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.