I suspect that at some point in the future we'll have to bite the
bullet and call into EFI runtime services on amd64 as well. The diff
below paves the road by passing the necessary information from our
bootloader to the kernel.
There is a potential issue with this diff. The EFI memory map is
stored into the bootloader "heap" which is allocated with the
EfiLoaderData attribute. Memory allocated with that attribute is
treated as Free/Available by the kernel. So this data may be
overwritten and the kernel would need to move it somewhere safe early
in the boot process. It's not clear to me how early though? Can
somebody who is more familiar with the amd64 and kernel and how it
uses physical memory during early bootstrap shed some light on this?
Index: arch/amd64/stand/efiboot/efiboot.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/stand/efiboot/efiboot.c,v
retrieving revision 1.30
diff -u -p -r1.30 efiboot.c
--- arch/amd64/stand/efiboot/efiboot.c 6 Jul 2018 07:55:50 -0000 1.30
+++ arch/amd64/stand/efiboot/efiboot.c 6 Aug 2018 21:22:33 -0000
@@ -279,6 +279,7 @@ efi_device_path_ncmp(EFI_DEVICE_PATH *dp
* Memory
***********************************************************************/
bios_memmap_t bios_memmap[64];
+bios_efiinfo_t bios_efiinfo;
static void
efi_heap_init(void)
@@ -335,6 +336,9 @@ efi_memprobe_internal(void)
cnvmem = extmem = 0;
bios_memmap[0].type = BIOS_MAP_END;
+ if (bios_efiinfo.mmap_start != 0)
+ free((void *)bios_efiinfo.mmap_start, bios_efiinfo.mmap_size);
+
siz = 0;
status = EFI_CALL(BS->GetMemoryMap, &siz, NULL, &mapkey, &mmsiz,
&mmver);
@@ -400,7 +404,11 @@ efi_memprobe_internal(void)
bm->addr / 1024 == extmem + 1024)
extmem += bm->size / 1024;
}
- free(mm0, siz);
+
+ bios_efiinfo.mmap_desc_ver = mmver;
+ bios_efiinfo.mmap_desc_size = mmsiz;
+ bios_efiinfo.mmap_size = siz;
+ bios_efiinfo.mmap_start = (uintptr_t)mm0;
}
/***********************************************************************
@@ -733,22 +741,21 @@ efi_makebootargs(void)
EFI_STATUS status;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*gopi;
- bios_efiinfo_t ei;
+ bios_efiinfo_t *ei = &bios_efiinfo;
int curmode;
UINTN sz, gopsiz, bestsiz = 0;
- memset(&ei, 0, sizeof(ei));
/*
* ACPI, BIOS configuration table
*/
for (i = 0; i < ST->NumberOfTableEntries; i++) {
if (efi_guidcmp(&acpi_guid,
&ST->ConfigurationTable[i].VendorGuid) == 0)
- ei.config_acpi = (intptr_t)
+ ei->config_acpi = (uintptr_t)
ST->ConfigurationTable[i].VendorTable;
else if (efi_guidcmp(&smbios_guid,
&ST->ConfigurationTable[i].VendorGuid) == 0)
- ei.config_smbios = (intptr_t)
+ ei->config_smbios = (uintptr_t)
ST->ConfigurationTable[i].VendorTable;
}
@@ -781,35 +788,44 @@ efi_makebootargs(void)
gopi = gop->Mode->Info;
switch (gopi->PixelFormat) {
case PixelBlueGreenRedReserved8BitPerColor:
- ei.fb_red_mask = 0x00ff0000;
- ei.fb_green_mask = 0x0000ff00;
- ei.fb_blue_mask = 0x000000ff;
- ei.fb_reserved_mask = 0xff000000;
+ ei->fb_red_mask = 0x00ff0000;
+ ei->fb_green_mask = 0x0000ff00;
+ ei->fb_blue_mask = 0x000000ff;
+ ei->fb_reserved_mask = 0xff000000;
break;
case PixelRedGreenBlueReserved8BitPerColor:
- ei.fb_red_mask = 0x000000ff;
- ei.fb_green_mask = 0x0000ff00;
- ei.fb_blue_mask = 0x00ff0000;
- ei.fb_reserved_mask = 0xff000000;
+ ei->fb_red_mask = 0x000000ff;
+ ei->fb_green_mask = 0x0000ff00;
+ ei->fb_blue_mask = 0x00ff0000;
+ ei->fb_reserved_mask = 0xff000000;
break;
case PixelBitMask:
- ei.fb_red_mask = gopi->PixelInformation.RedMask;
- ei.fb_green_mask = gopi->PixelInformation.GreenMask;
- ei.fb_blue_mask = gopi->PixelInformation.BlueMask;
- ei.fb_reserved_mask =
+ ei->fb_red_mask = gopi->PixelInformation.RedMask;
+ ei->fb_green_mask = gopi->PixelInformation.GreenMask;
+ ei->fb_blue_mask = gopi->PixelInformation.BlueMask;
+ ei->fb_reserved_mask =
gopi->PixelInformation.ReservedMask;
break;
default:
break;
}
- ei.fb_addr = gop->Mode->FrameBufferBase;
- ei.fb_size = gop->Mode->FrameBufferSize;
- ei.fb_height = gopi->VerticalResolution;
- ei.fb_width = gopi->HorizontalResolution;
- ei.fb_pixpsl = gopi->PixelsPerScanLine;
+ ei->fb_addr = gop->Mode->FrameBufferBase;
+ ei->fb_size = gop->Mode->FrameBufferSize;
+ ei->fb_height = gopi->VerticalResolution;
+ ei->fb_width = gopi->HorizontalResolution;
+ ei->fb_pixpsl = gopi->PixelsPerScanLine;
}
- addbootarg(BOOTARG_EFIINFO, sizeof(ei), &ei);
+ /*
+ * EFI system table
+ */
+ ei->system_table = (uintptr_t)ST;
+
+#ifdef __amd64__
+ ei->flags |= BEI_64BIT;
+#endif
+
+ addbootarg(BOOTARG_EFIINFO, sizeof(bios_efiinfo), &bios_efiinfo);
}
void
Index: arch/amd64/include/biosvar.h
===================================================================
RCS file: /cvs/src/sys/arch/amd64/include/biosvar.h,v
retrieving revision 1.25
diff -u -p -r1.25 biosvar.h
--- arch/amd64/include/biosvar.h 6 Feb 2018 01:09:17 -0000 1.25
+++ arch/amd64/include/biosvar.h 6 Aug 2018 21:22:33 -0000
@@ -204,6 +204,13 @@ typedef struct _bios_efiinfo {
uint32_t fb_green_mask;
uint32_t fb_blue_mask;
uint32_t fb_reserved_mask;
+ uint32_t flags;
+#define BEI_64BIT 0x00000001 /* 64-bit EFI implementation */
+ uint32_t mmap_desc_ver;
+ uint32_t mmap_desc_size;
+ uint32_t mmap_size;
+ uint64_t mmap_start;
+ uint64_t system_table;
} __packed bios_efiinfo_t;
#define BOOTARG_UCODE 12