> From: "David N. Arnold" <[email protected]>
> Date: Mon, 10 May 2021 18:28:28 -0400
> 
> System description:
> 
> 13-inch, Mid 2009 MacBook Pro (MacBookPro5,5) with memory upgraded to 8 GB.
> 
> Observed behavior:
> 
> On boot, system immediately hangs at:
> 
>     probing: pc0 mem[
> 
> Steps to reproduce:
> 
>   - Boot from a USB installer of 6.9 (hangs)
>   - Boot from a CD installer of 6.9 (works), install the system, and
> reboot (hangs)
>   - Upgrade from 6.8 to 6.9 and reboot (hangs)
>   - Compile the 6.8 version of the boot code with 6.9 and install on
> the EFI partition (hangs)
> 
> Workaround:
> 
> Copy the BOOTX64.EFI from 6.8 release to the EFI system partition.
> 
> Diagnosis:
> 
> I added some debug printf statements to the code and found that it was
> hanging at this line in src/sys/arch/amd64/stand/efiboot/efiboot.c:
> 
>     (++bm)->type = BIOS_MAP_END;
> 
> This appears to be a buffer overrun on:
> 
>     bios_memmap_t bios_memmap[64];
> 
> Updating to a size of 128 allows the machine to boot.  With some
> additional debug statements, I found that it processes 204 records
> from GetMemoryMap into 74 entries in bios_memmap.

Nice bit of debugging!

> I'm not sure how a fixed size 64 was chosen, since the UEFI memory map
> of the system could be arbitrarily long, so I can't say how long this
> array needs to be to work on every system.  At the very least, it
> should probably be doubled with some assertions and a panic if it runs
> out of room.
> 
> I'm also not quite sure why the 6.8 copy of BOOTX64.EFI works, other
> than it is just happily clobbering memory.  The fact that the 6.8
> version of the code fails when compiled on 6.9 makes me think maybe
> there is some checking added by the 6.9 compiler chain that detects
> the overrun and halts?

Pure luck probably.

Anyway, here is a diff that prevents the overrun and raises the number
of map entries to 128.  Can you try this diff and confirm it works for
you?


Index: arch/amd64/stand/efiboot/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/stand/efiboot/conf.c,v
retrieving revision 1.34
diff -u -p -r1.34 conf.c
--- arch/amd64/stand/efiboot/conf.c     17 Mar 2021 05:41:34 -0000      1.34
+++ arch/amd64/stand/efiboot/conf.c     11 May 2021 20:44:15 -0000
@@ -40,7 +40,7 @@
 #include "efidev.h"
 #include "efipxe.h"
 
-const char version[] = "3.57";
+const char version[] = "3.58";
 
 #ifdef EFI_DEBUG
 int    debug = 0;
Index: arch/amd64/stand/efiboot/efiboot.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/stand/efiboot/efiboot.c,v
retrieving revision 1.36
diff -u -p -r1.36 efiboot.c
--- arch/amd64/stand/efiboot/efiboot.c  30 Oct 2020 19:39:00 -0000      1.36
+++ arch/amd64/stand/efiboot/efiboot.c  11 May 2021 20:44:15 -0000
@@ -281,7 +281,7 @@ efi_device_path_ncmp(EFI_DEVICE_PATH *dp
 /***********************************************************************
  * Memory
  ***********************************************************************/
-bios_memmap_t           bios_memmap[64];
+bios_memmap_t           bios_memmap[128];
 bios_efiinfo_t          bios_efiinfo;
 
 static void
@@ -398,6 +398,8 @@ efi_memprobe_internal(void)
                        *bm = bm0;
                        (++bm)->type = BIOS_MAP_END;
                }
+               if (bm == &bios_memmap[nitems(bios_memmap) - 1])
+                       break;
        }
        for (bm = bios_memmap; bm->type != BIOS_MAP_END; bm++) {
                if (bm->addr < IOM_BEGIN)       /* Below memory hole */


Reply via email to