On Mon, Aug 06, 2018 at 11:38:28PM +0200, Mark Kettenis wrote:
> 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?
>
That's probably me, but I'm a bit backed up at the moment. I'll take a
look this weekend.
-ml
>
> 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
>