From 7bcd510a7b202f9e4e670dab3e209ea370d02420 Mon Sep 17 00:00:00 2001 From: Ahmad Khalifa Date: Fri, 27 Sep 2024 18:32:06 +0300 Subject: [PATCH 1/7] stand: further restrict f_kernphys_relocatable and f_tg_kernel_support f_tg_kernel_support isn't used by any EFI code, and f_kernphys_relocatable isn't used by the non-EFI i386 code. --- stand/common/bootstrap.h | 4 ++-- stand/common/load_elf.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stand/common/bootstrap.h b/stand/common/bootstrap.h index ab1e5249fc2a..37cef2956f40 100644 --- a/stand/common/bootstrap.h +++ b/stand/common/bootstrap.h @@ -239,10 +239,10 @@ struct preloaded_file size_t f_size; /* file size */ struct kernel_module *f_modules; /* list of modules if any */ struct preloaded_file *f_next; /* next file */ -#if defined(__amd64__) || defined(__i386__) +#if defined(__amd64__) || (defined(__i386__) && defined(EFI)) bool f_kernphys_relocatable; #endif -#if defined(__i386__) +#if defined(__i386__) && !defined(EFI) bool f_tg_kernel_support; #endif }; diff --git a/stand/common/load_elf.c b/stand/common/load_elf.c index eaa6bef6ee86..d3775b9f0017 100644 --- a/stand/common/load_elf.c +++ b/stand/common/load_elf.c @@ -217,7 +217,7 @@ static int elf_section_header_convert(const Elf_Ehdr *ehdr, Elf_Shdr *shdr) } #endif -#if defined(__amd64__) || defined(__i386__) +#if defined(__amd64__) || (defined(__i386__) && defined(EFI)) static bool is_kernphys_relocatable(elf_file_t ef) { @@ -491,10 +491,10 @@ __elfN(loadfile_raw)(char *filename, uint64_t dest, /* Load OK, return module pointer */ *result = (struct preloaded_file *)fp; err = 0; -#if defined(__amd64__) || defined(__i386__) +#if defined(__amd64__) || (defined(__i386__) && defined(EFI)) fp->f_kernphys_relocatable = multiboot || is_kernphys_relocatable(&ef); #endif -#ifdef __i386__ +#if defined(__i386__) && !defined(EFI) fp->f_tg_kernel_support = is_tg_kernel_support(fp, &ef); #endif goto out; From caaceed1599414a0065bd3383a1db4406f495723 Mon Sep 17 00:00:00 2001 From: Ahmad Khalifa Date: Fri, 27 Sep 2024 18:38:01 +0300 Subject: [PATCH 2/7] stand: move efi's bi_load into loader_efi.h For kboot, we still have to declare it manually since we don't always include loader_efi.h --- stand/efi/loader/arch/amd64/elf64_freebsd.c | 3 --- stand/efi/loader/arch/amd64/multiboot2.c | 2 -- stand/efi/loader/arch/arm/exec.c | 2 -- stand/efi/loader/arch/arm64/exec.c | 3 --- stand/efi/loader/arch/i386/elf64_freebsd.c | 3 --- stand/efi/loader/arch/riscv/exec.c | 2 -- stand/efi/loader/bootinfo.c | 3 --- stand/efi/loader/loader_efi.h | 3 +++ stand/kboot/kboot/arch/aarch64/exec.c | 3 +++ stand/kboot/kboot/arch/amd64/elf64_freebsd.c | 7 ++++--- 10 files changed, 10 insertions(+), 21 deletions(-) diff --git a/stand/efi/loader/arch/amd64/elf64_freebsd.c b/stand/efi/loader/arch/amd64/elf64_freebsd.c index 91dd979a677e..7413d18aab2a 100644 --- a/stand/efi/loader/arch/amd64/elf64_freebsd.c +++ b/stand/efi/loader/arch/amd64/elf64_freebsd.c @@ -42,9 +42,6 @@ #include "loader_efi.h" -extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, - bool exit_bs); - static int elf64_exec(struct preloaded_file *amp); static int elf64_obj_exec(struct preloaded_file *amp); diff --git a/stand/efi/loader/arch/amd64/multiboot2.c b/stand/efi/loader/arch/amd64/multiboot2.c index 130caa82aa49..d09b01fce1fc 100644 --- a/stand/efi/loader/arch/amd64/multiboot2.c +++ b/stand/efi/loader/arch/amd64/multiboot2.c @@ -57,8 +57,6 @@ extern int elf32_loadfile_raw(char *filename, uint64_t dest, extern int elf64_load_modmetadata(struct preloaded_file *fp, uint64_t dest); extern int elf64_obj_loadfile(char *filename, uint64_t dest, struct preloaded_file **result); -extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, - bool exit_bs); extern void multiboot2_exec(void *entry, uint64_t multiboot_info, uint64_t stack); diff --git a/stand/efi/loader/arch/arm/exec.c b/stand/efi/loader/arch/arm/exec.c index 85a8c26ade30..c2a79523c02a 100644 --- a/stand/efi/loader/arch/arm/exec.c +++ b/stand/efi/loader/arch/arm/exec.c @@ -40,8 +40,6 @@ #include "bootstrap.h" #include "loader_efi.h" -extern int bi_load(char *, vm_offset_t *, vm_offset_t *, bool); - static int __elfN(arm_load)(char *filename, uint64_t dest, struct preloaded_file **result) diff --git a/stand/efi/loader/arch/arm64/exec.c b/stand/efi/loader/arch/arm64/exec.c index 877cff658d1e..91a0503a976f 100644 --- a/stand/efi/loader/arch/arm64/exec.c +++ b/stand/efi/loader/arch/arm64/exec.c @@ -42,9 +42,6 @@ static int elf64_exec(struct preloaded_file *amp); static int elf64_obj_exec(struct preloaded_file *amp); -int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, - bool exit_bs); - static struct file_format arm64_elf = { elf64_loadfile, elf64_exec diff --git a/stand/efi/loader/arch/i386/elf64_freebsd.c b/stand/efi/loader/arch/i386/elf64_freebsd.c index ba5117b37016..b8bc925576e7 100644 --- a/stand/efi/loader/arch/i386/elf64_freebsd.c +++ b/stand/efi/loader/arch/i386/elf64_freebsd.c @@ -37,9 +37,6 @@ #include "loader_efi.h" -extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, - bool exit_bs); - static int elf64_exec(struct preloaded_file *amp); static int elf64_obj_exec(struct preloaded_file *amp); diff --git a/stand/efi/loader/arch/riscv/exec.c b/stand/efi/loader/arch/riscv/exec.c index 3c40517ea968..0fc28cba78c1 100644 --- a/stand/efi/loader/arch/riscv/exec.c +++ b/stand/efi/loader/arch/riscv/exec.c @@ -40,8 +40,6 @@ #include "bootstrap.h" #include "loader_efi.h" -extern int bi_load(char *, vm_offset_t *, vm_offset_t *, bool); - static int __elfN(exec)(struct preloaded_file *fp) { diff --git a/stand/efi/loader/bootinfo.c b/stand/efi/loader/bootinfo.c index 2961b8b97fb7..99a7b1444aca 100644 --- a/stand/efi/loader/bootinfo.c +++ b/stand/efi/loader/bootinfo.c @@ -64,9 +64,6 @@ #include "geliboot.h" #endif -int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, - bool exit_bs); - static int bi_getboothowto(char *kargs) { diff --git a/stand/efi/loader/loader_efi.h b/stand/efi/loader/loader_efi.h index c9dfefcd4c74..8d4e352eec79 100644 --- a/stand/efi/loader/loader_efi.h +++ b/stand/efi/loader/loader_efi.h @@ -55,4 +55,7 @@ void * efi_translate(vm_offset_t ptr); void efi_copy_finish(void); void efi_copy_finish_nop(void); +int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, + bool exit_bs); + #endif /* _LOADER_EFI_COPY_H_ */ diff --git a/stand/kboot/kboot/arch/aarch64/exec.c b/stand/kboot/kboot/arch/aarch64/exec.c index 0aa0e7b8408f..585ccffbd42c 100644 --- a/stand/kboot/kboot/arch/aarch64/exec.c +++ b/stand/kboot/kboot/arch/aarch64/exec.c @@ -70,8 +70,11 @@ extern uint32_t efi_map_size; extern vm_paddr_t efi_map_phys_src; /* From DTB */ extern vm_paddr_t efi_map_phys_dst; /* From our memory map metadata module */ +/* Usually provided by loader_efi.h */ +#ifndef EFI int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs); +#endif static struct file_format arm64_elf = { elf64_loadfile, diff --git a/stand/kboot/kboot/arch/amd64/elf64_freebsd.c b/stand/kboot/kboot/arch/amd64/elf64_freebsd.c index f6574b4cbd0d..8618f132126b 100644 --- a/stand/kboot/kboot/arch/amd64/elf64_freebsd.c +++ b/stand/kboot/kboot/arch/amd64/elf64_freebsd.c @@ -56,6 +56,10 @@ static EFI_GUID acpi_guid = ACPI_TABLE_GUID; static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID; +#else +/* Usually provided by loader_efi.h */ +extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, + bool exit_bs); #endif #ifdef EFI @@ -64,9 +68,6 @@ static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID; #define LOADER_PAGE_SIZE PAGE_SIZE #endif -extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, - bool exit_bs); - static int elf64_exec(struct preloaded_file *amp); static int elf64_obj_exec(struct preloaded_file *amp); From f74bdc375224929a487fa6a82b1bce6667c4ce6a Mon Sep 17 00:00:00 2001 From: Ahmad Khalifa Date: Fri, 27 Sep 2024 18:39:32 +0300 Subject: [PATCH 3/7] kboot/aarch64: remove redundant include --- stand/kboot/kboot/arch/aarch64/exec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/stand/kboot/kboot/arch/aarch64/exec.c b/stand/kboot/kboot/arch/aarch64/exec.c index 585ccffbd42c..59ca4b67a4ab 100644 --- a/stand/kboot/kboot/arch/aarch64/exec.c +++ b/stand/kboot/kboot/arch/aarch64/exec.c @@ -42,7 +42,6 @@ #include "bootstrap.h" #include "kboot.h" -#include "bootstrap.h" #include "platform/acfreebsd.h" #include "acconfig.h" From 2d3b870df08823bbe5e71491b47bdc2aa771d465 Mon Sep 17 00:00:00 2001 From: Ahmad Khalifa Date: Fri, 27 Sep 2024 18:44:14 +0300 Subject: [PATCH 4/7] stand: move 'staging' to loader_efi.h On amd64, we need this to setup the page tables. --- stand/efi/loader/arch/amd64/elf64_freebsd.c | 2 -- stand/efi/loader/arch/i386/elf64_freebsd.c | 2 -- stand/efi/loader/loader_efi.h | 5 +++++ stand/kboot/kboot/arch/amd64/elf64_freebsd.c | 2 -- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/stand/efi/loader/arch/amd64/elf64_freebsd.c b/stand/efi/loader/arch/amd64/elf64_freebsd.c index 7413d18aab2a..3883c309e724 100644 --- a/stand/efi/loader/arch/amd64/elf64_freebsd.c +++ b/stand/efi/loader/arch/amd64/elf64_freebsd.c @@ -71,8 +71,6 @@ static pdp_entry_t *PT3_l, *PT3_u; static pd_entry_t *PT2; static pd_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1; -extern EFI_PHYSICAL_ADDRESS staging; - static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend, uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry); diff --git a/stand/efi/loader/arch/i386/elf64_freebsd.c b/stand/efi/loader/arch/i386/elf64_freebsd.c index b8bc925576e7..2c6be607dc4d 100644 --- a/stand/efi/loader/arch/i386/elf64_freebsd.c +++ b/stand/efi/loader/arch/i386/elf64_freebsd.c @@ -86,8 +86,6 @@ static p2_entry_t *PT2; static p2_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1; static gdt_t *GDT; -extern EFI_PHYSICAL_ADDRESS staging; - static void (*trampoline)(uint32_t stack, void *copy_finish, uint32_t kernend, uint32_t modulep, uint64_t *pagetable, struct gdtr *gdtr, uint64_t entry); diff --git a/stand/efi/loader/loader_efi.h b/stand/efi/loader/loader_efi.h index 8d4e352eec79..b2d7817b87dd 100644 --- a/stand/efi/loader/loader_efi.h +++ b/stand/efi/loader/loader_efi.h @@ -55,6 +55,11 @@ void * efi_translate(vm_offset_t ptr); void efi_copy_finish(void); void efi_copy_finish_nop(void); +#if defined(__amd64__) || defined(__i386__) +/* Need this to setup page tables */ +extern EFI_PHYSICAL_ADDRESS staging; +#endif + int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs); diff --git a/stand/kboot/kboot/arch/amd64/elf64_freebsd.c b/stand/kboot/kboot/arch/amd64/elf64_freebsd.c index 8618f132126b..b0efbfe09629 100644 --- a/stand/kboot/kboot/arch/amd64/elf64_freebsd.c +++ b/stand/kboot/kboot/arch/amd64/elf64_freebsd.c @@ -122,8 +122,6 @@ static pd_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1; static pdp_entry_t *PT3; static pd_entry_t *PT2; -extern EFI_PHYSICAL_ADDRESS staging; - static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend, uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry); #endif From 1a1cec19da534570a0e2ebcbe3b92254a4c6c488 Mon Sep 17 00:00:00 2001 From: Ahmad Khalifa Date: Fri, 27 Sep 2024 19:01:27 +0300 Subject: [PATCH 5/7] stand/efi: move G(x) and M(x) macros to loader_efi.h These are often needed for copying to the staging area or just general page table calculations on amd64. --- stand/efi/loader/arch/amd64/elf64_freebsd.c | 9 ++++----- stand/efi/loader/arch/i386/elf64_freebsd.c | 3 --- stand/efi/loader/copy.c | 3 --- stand/efi/loader/loader_efi.h | 4 ++++ stand/kboot/kboot/arch/amd64/elf64_freebsd.c | 9 ++++----- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/stand/efi/loader/arch/amd64/elf64_freebsd.c b/stand/efi/loader/arch/amd64/elf64_freebsd.c index 3883c309e724..c4265aca035e 100644 --- a/stand/efi/loader/arch/amd64/elf64_freebsd.c +++ b/stand/efi/loader/arch/amd64/elf64_freebsd.c @@ -101,8 +101,7 @@ elf64_exec(struct preloaded_file *fp) ehdr = (Elf_Ehdr *)&(md->md_data); trampcode = copy_staging == COPY_STAGING_ENABLE ? - (vm_offset_t)0x0000000040000000 /* 1G */ : - (vm_offset_t)0x0000000100000000; /* 4G */; + (vm_offset_t)G(1) : (vm_offset_t)G(4); err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1, (EFI_PHYSICAL_ADDRESS *)&trampcode); if (EFI_ERROR(err)) { @@ -117,7 +116,7 @@ elf64_exec(struct preloaded_file *fp) trampoline = (void *)trampcode; if (copy_staging == COPY_STAGING_ENABLE) { - PT4 = (pml4_entry_t *)0x0000000040000000; /* 1G */ + PT4 = (pml4_entry_t *)G(1); err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3, (EFI_PHYSICAL_ADDRESS *)&PT4); if (EFI_ERROR(err)) { @@ -154,11 +153,11 @@ elf64_exec(struct preloaded_file *fp) /* * The L2 page slots are mapped with 2MB pages for 1GB. */ - PT2[i] = (pd_entry_t)i * (2 * 1024 * 1024); + PT2[i] = (pd_entry_t)i * M(2); PT2[i] |= PG_V | PG_RW | PG_PS; } } else { - PT4 = (pml4_entry_t *)0x0000000100000000; /* 4G */ + PT4 = (pml4_entry_t *)G(4); err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 9, (EFI_PHYSICAL_ADDRESS *)&PT4); if (EFI_ERROR(err)) { diff --git a/stand/efi/loader/arch/i386/elf64_freebsd.c b/stand/efi/loader/arch/i386/elf64_freebsd.c index 2c6be607dc4d..0dc16437d905 100644 --- a/stand/efi/loader/arch/i386/elf64_freebsd.c +++ b/stand/efi/loader/arch/i386/elf64_freebsd.c @@ -71,9 +71,6 @@ struct gdtr { #define GDT_RW 0x00020000000000 #define GDT_L 0x20000000000000 -#define M(x) ((x) * 1024 * 1024) -#define G(x) (1ULL * (x) * 1024 * 1024 * 1024) - typedef uint64_t p4_entry_t; typedef uint64_t p3_entry_t; typedef uint64_t p2_entry_t; diff --git a/stand/efi/loader/copy.c b/stand/efi/loader/copy.c index 90a55089ffc4..485ec152ae21 100644 --- a/stand/efi/loader/copy.c +++ b/stand/efi/loader/copy.c @@ -35,9 +35,6 @@ #include "loader_efi.h" -#define M(x) ((x) * 1024 * 1024) -#define G(x) (1ULL * (x) * 1024 * 1024 * 1024) - #if defined(__amd64__) #include #include diff --git a/stand/efi/loader/loader_efi.h b/stand/efi/loader/loader_efi.h index b2d7817b87dd..be991eeb9573 100644 --- a/stand/efi/loader/loader_efi.h +++ b/stand/efi/loader/loader_efi.h @@ -41,6 +41,10 @@ enum { extern int copy_staging; #endif +/* Useful for various calculations */ +#define M(x) ((x) * 1024 * 1024) +#define G(x) (1ULL * (x) * 1024 * 1024 * 1024) + extern EFI_LOADED_IMAGE *boot_img; int efi_autoload(void); diff --git a/stand/kboot/kboot/arch/amd64/elf64_freebsd.c b/stand/kboot/kboot/arch/amd64/elf64_freebsd.c index b0efbfe09629..495c4c0b320e 100644 --- a/stand/kboot/kboot/arch/amd64/elf64_freebsd.c +++ b/stand/kboot/kboot/arch/amd64/elf64_freebsd.c @@ -209,8 +209,7 @@ elf64_exec(struct preloaded_file *fp) #ifdef EFI trampcode = copy_staging == COPY_STAGING_ENABLE ? - (vm_offset_t)0x0000000040000000 /* 1G */ : - (vm_offset_t)0x0000000100000000; /* 4G */; + (vm_offset_t)G(1) : (vm_offset_t)G(4); err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1, (EFI_PHYSICAL_ADDRESS *)&trampcode); if (EFI_ERROR(err)) { @@ -234,7 +233,7 @@ elf64_exec(struct preloaded_file *fp) #ifdef EFI if (copy_staging == COPY_STAGING_ENABLE) { - PT4 = (pml4_entry_t *)0x0000000040000000; /* 1G */ + PT4 = (pml4_entry_t *)G(1); err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3, (EFI_PHYSICAL_ADDRESS *)&PT4); if (EFI_ERROR(err)) { @@ -271,11 +270,11 @@ elf64_exec(struct preloaded_file *fp) /* * The L2 page slots are mapped with 2MB pages for 1GB. */ - PT2[i] = (pd_entry_t)i * (2 * 1024 * 1024); + PT2[i] = (pd_entry_t)i * M(2); PT2[i] |= PG_V | PG_RW | PG_PS; } } else { - PT4 = (pml4_entry_t *)0x0000000100000000; /* 4G */ + PT4 = (pml4_entry_t *)G(4); err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 9, (EFI_PHYSICAL_ADDRESS *)&PT4); if (EFI_ERROR(err)) { From c4b7af53049ca9f718a5ee1e535854d8d239ca8d Mon Sep 17 00:00:00 2001 From: Ahmad Khalifa Date: Fri, 27 Sep 2024 19:08:11 +0300 Subject: [PATCH 6/7] stand/elf64_freebsd.c: use headers instead of doing things ourselves Try our best to use headers instead of doing things ourselves. With i386's headers, there are some holes we need to fill manually. --- stand/efi/loader/arch/i386/elf64_freebsd.c | 104 +++++++++++---------- stand/i386/libi386/elf64_freebsd.c | 24 ++--- stand/userboot/userboot/elf64_freebsd.c | 53 ++++------- 3 files changed, 89 insertions(+), 92 deletions(-) diff --git a/stand/efi/loader/arch/i386/elf64_freebsd.c b/stand/efi/loader/arch/i386/elf64_freebsd.c index 0dc16437d905..b02cda2269bc 100644 --- a/stand/efi/loader/arch/i386/elf64_freebsd.c +++ b/stand/efi/loader/arch/i386/elf64_freebsd.c @@ -28,7 +28,11 @@ #define __ELF_WORD_SIZE 64 #include #include +#include +#include #include +#include +#include #include #include @@ -56,35 +60,14 @@ struct file_format *file_formats[] = { NULL }; -struct gdtr { - uint16_t size; - uint64_t ptr; -} __packed; - -#define PG_V 0x001 -#define PG_RW 0x002 -#define PG_PS 0x080 - -#define GDT_P 0x00800000000000 -#define GDT_E 0x00080000000000 -#define GDT_S 0x00100000000000 -#define GDT_RW 0x00020000000000 -#define GDT_L 0x20000000000000 - -typedef uint64_t p4_entry_t; -typedef uint64_t p3_entry_t; -typedef uint64_t p2_entry_t; -typedef uint64_t gdt_t; - -static p4_entry_t *PT4; -static p3_entry_t *PT3; -static p3_entry_t *PT3_l, *PT3_u; -static p2_entry_t *PT2; -static p2_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1; -static gdt_t *GDT; +/* + * i386's pmap_pae.h doesn't provide this, so + * just typedef our own. + */ +typedef pdpt_entry_t pml4_entry_t; static void (*trampoline)(uint32_t stack, void *copy_finish, uint32_t kernend, - uint32_t modulep, uint64_t *pagetable, struct gdtr *gdtr, uint64_t entry); + uint32_t modulep, uint64_t *pagetable, void *gdtr, uint64_t entry); extern void *amd64_tramp; extern uint32_t amd64_tramp_size; @@ -97,12 +80,23 @@ extern uint32_t amd64_tramp_size; static int elf64_exec(struct preloaded_file *fp) { + /* + * segments.h gives us a 32-bit gdtr, but + * we want a 64-bit one, so define our own. + */ + struct { + uint16_t rd_limit; + uint64_t rd_base; + } __packed *gdtr; EFI_PHYSICAL_ADDRESS ptr; EFI_ALLOCATE_TYPE type; EFI_STATUS err; struct file_metadata *md; - struct gdtr *gdtr; Elf_Ehdr *ehdr; + pml4_entry_t *PT4; + pdpt_entry_t *PT3; + pd_entry_t *PT2; + struct user_segment_descriptor *gdt; vm_offset_t modulep, kernend, trampstack; int i; @@ -123,36 +117,47 @@ elf64_exec(struct preloaded_file *fp) return (EFTYPE); ehdr = (Elf_Ehdr *)&(md->md_data); - /* - * Make our temporary stack 32 bytes big, which is - * a little more than we need. - */ ptr = G(1); err = BS->AllocatePages(type, EfiLoaderCode, - EFI_SIZE_TO_PAGES(amd64_tramp_size + 32), &ptr); + EFI_SIZE_TO_PAGES(amd64_tramp_size), &ptr); if (EFI_ERROR(err)) { printf("Unable to allocate trampoline\n"); return (ENOMEM); } trampoline = (void *)(uintptr_t)ptr; - trampstack = ptr + amd64_tramp_size + 32; bcopy(&amd64_tramp, trampoline, amd64_tramp_size); + /* + * Allocate enough space for the GDTR + two GDT segments + + * our temporary stack (28 bytes). + */ +#define DATASZ (sizeof(*gdtr) + \ + sizeof(struct user_segment_descriptor) * 2 + 28) + ptr = G(1); err = BS->AllocatePages(type, EfiLoaderData, - EFI_SIZE_TO_PAGES(sizeof(struct gdtr) + sizeof(uint64_t) * 2), &ptr); + EFI_SIZE_TO_PAGES(DATASZ), &ptr); if (EFI_ERROR(err)) { - printf("Unable to allocate GDT\n"); + printf("Unable to allocate GDT and stack\n"); BS->FreePages((uintptr_t)trampoline, 1); return (ENOMEM); } - GDT = (gdt_t *)(uintptr_t)ptr; - GDT[1] = GDT_P | GDT_E | GDT_S | GDT_RW | GDT_L; /* CS */ - GDT[0] = 0; - gdtr = (struct gdtr *)&GDT[2]; - gdtr->size = sizeof(uint64_t) * 2 - 1; - gdtr->ptr = (uintptr_t)GDT; + + trampstack = ptr + DATASZ; + +#undef DATASZ + + gdt = (void *)(uintptr_t)ptr; + gdt[0] = (struct user_segment_descriptor) { 0 }; + gdt[1] = (struct user_segment_descriptor) { + .sd_p = 1, .sd_long = 1, .sd_type = SDT_MEMERC + }; + + gdtr = (void *)(uintptr_t)(ptr + + sizeof(struct user_segment_descriptor) * 2); + gdtr->rd_limit = sizeof(struct user_segment_descriptor) * 2 - 1; + gdtr->rd_base = (uintptr_t)gdt; if (type == AllocateMaxAddress) { /* Copy staging enabled */ @@ -163,10 +168,10 @@ elf64_exec(struct preloaded_file *fp) if (EFI_ERROR(err)) { printf("Unable to allocate trampoline page table\n"); BS->FreePages((uintptr_t)trampoline, 1); - BS->FreePages((uintptr_t)GDT, 1); + BS->FreePages((uintptr_t)gdt, 1); return (ENOMEM); } - PT4 = (p4_entry_t *)(uintptr_t)ptr; + PT4 = (pml4_entry_t *)(uintptr_t)ptr; PT3 = &PT4[512]; PT2 = &PT3[512]; @@ -195,15 +200,18 @@ elf64_exec(struct preloaded_file *fp) PT2[i] = (i * M(2)) | PG_V | PG_RW | PG_PS; } } else { + pdpt_entry_t *PT3_l, *PT3_u; + pd_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1; + err = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, EFI_SIZE_TO_PAGES(512 * 9 * sizeof(uint64_t)), &ptr); if (EFI_ERROR(err)) { printf("Unable to allocate trampoline page table\n"); BS->FreePages((uintptr_t)trampoline, 1); - BS->FreePages((uintptr_t)GDT, 1); + BS->FreePages((uintptr_t)gdt, 1); return (ENOMEM); } - PT4 = (p4_entry_t *)(uintptr_t)ptr; + PT4 = (pml4_entry_t *)(uintptr_t)ptr; PT3_l = &PT4[512]; PT3_u = &PT3_l[512]; @@ -221,7 +229,7 @@ elf64_exec(struct preloaded_file *fp) PT3_l[2] = (uintptr_t)PT2_l2 | PG_V | PG_RW; PT3_l[3] = (uintptr_t)PT2_l3 | PG_V | PG_RW; for (i = 0; i < 2048; i++) { - PT2_l0[i] = ((p2_entry_t)i * M(2)) | PG_V | PG_RW | PG_PS; + PT2_l0[i] = ((pd_entry_t)i * M(2)) | PG_V | PG_RW | PG_PS; } /* mapping of kernel 2G below top */ @@ -240,7 +248,7 @@ elf64_exec(struct preloaded_file *fp) printf( "staging %#llx (%scopying) tramp %p PT4 %p GDT %p\n" "Start @ %#llx ...\n", staging, - type == AllocateMaxAddress ? "" : "not ", trampoline, PT4, GDT, + type == AllocateMaxAddress ? "" : "not ", trampoline, PT4, gdt, ehdr->e_entry ); diff --git a/stand/i386/libi386/elf64_freebsd.c b/stand/i386/libi386/elf64_freebsd.c index b1340fd1f2e2..89cc249e9d96 100644 --- a/stand/i386/libi386/elf64_freebsd.c +++ b/stand/i386/libi386/elf64_freebsd.c @@ -28,8 +28,11 @@ #include #include #include +#include +#include #include #include +#include #include #include @@ -43,16 +46,15 @@ static int elf64_obj_exec(struct preloaded_file *amp); struct file_format amd64_elf = { elf64_loadfile, elf64_exec }; struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec }; -#define PG_V 0x001 -#define PG_RW 0x002 -#define PG_PS 0x080 +/* + * i386's pmap_pae.h doesn't provide this, so + * just typedef our own. + */ +typedef pdpt_entry_t pml4_entry_t; -typedef uint64_t p4_entry_t; -typedef uint64_t p3_entry_t; -typedef uint64_t p2_entry_t; -extern p4_entry_t PT4[]; -extern p3_entry_t PT3[]; -extern p2_entry_t PT2[]; +extern pml4_entry_t PT4[]; +extern pdpt_entry_t PT3[]; +extern pd_entry_t PT2[]; uint32_t entry_hi; uint32_t entry_lo; @@ -91,11 +93,11 @@ elf64_exec(struct preloaded_file *fp) */ for (i = 0; i < 512; i++) { /* Each slot of the level 4 pages points to the same level 3 page */ - PT4[i] = (p4_entry_t)VTOP((uintptr_t)&PT3[0]); + PT4[i] = (pml4_entry_t)VTOP((uintptr_t)&PT3[0]); PT4[i] |= PG_V | PG_RW; /* Each slot of the level 3 pages points to the same level 2 page */ - PT3[i] = (p3_entry_t)VTOP((uintptr_t)&PT2[0]); + PT3[i] = (pdpt_entry_t)VTOP((uintptr_t)&PT2[0]); PT3[i] |= PG_V | PG_RW; /* The level 2 page slots are mapped with 2MB pages for 1GB. */ diff --git a/stand/userboot/userboot/elf64_freebsd.c b/stand/userboot/userboot/elf64_freebsd.c index 7f817a44da88..5a63fdb4990c 100644 --- a/stand/userboot/userboot/elf64_freebsd.c +++ b/stand/userboot/userboot/elf64_freebsd.c @@ -31,9 +31,10 @@ #ifdef DEBUG #include #endif -#include -#include +#include +#include #include +#include #include #include "bootstrap.h" @@ -45,35 +46,21 @@ static int elf64_obj_exec(struct preloaded_file *amp); struct file_format amd64_elf = { elf64_loadfile, elf64_exec }; struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec }; -#define MSR_EFER 0xc0000080 -#define EFER_LME 0x00000100 -#define EFER_LMA 0x00000400 /* Long mode active (R) */ -#define CR4_PAE 0x00000020 -#define CR4_VMXE (1UL << 13) -#define CR4_PSE 0x00000010 -#define CR0_PG 0x80000000 -#define CR0_PE 0x00000001 /* Protected mode Enable */ -#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ - -#define PG_V 0x001 -#define PG_RW 0x002 -#define PG_PS 0x080 - -typedef uint64_t p4_entry_t; -typedef uint64_t p3_entry_t; -typedef uint64_t p2_entry_t; - #define GUEST_NULL_SEL 0 #define GUEST_CODE_SEL 1 #define GUEST_DATA_SEL 2 #define GUEST_GDTR_LIMIT (3 * 8 - 1) static void -setup_freebsd_gdt(uint64_t *gdtr) +setup_freebsd_gdt(struct user_segment_descriptor *gdt) { - gdtr[GUEST_NULL_SEL] = 0; - gdtr[GUEST_CODE_SEL] = 0x0020980000000000; - gdtr[GUEST_DATA_SEL] = 0x0000900000000000; + gdt[GUEST_NULL_SEL] = (struct user_segment_descriptor) { 0 }; + gdt[GUEST_CODE_SEL] = (struct user_segment_descriptor) { + .sd_p = 1, .sd_long = 1, .sd_type = SDT_MEME + }; + gdt[GUEST_DATA_SEL] = (struct user_segment_descriptor) { + .sd_p = 1, .sd_type = SDT_MEMRO + }; } /* @@ -90,10 +77,10 @@ elf64_exec(struct preloaded_file *fp) int err; int i; uint32_t stack[1024]; - p4_entry_t PT4[512]; - p3_entry_t PT3[512]; - p2_entry_t PT2[512]; - uint64_t gdtr[3]; + pml4_entry_t PT4[512]; + pdp_entry_t PT3[512]; + pd_entry_t PT2[512]; + struct user_segment_descriptor gdt[3]; if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return(EFTYPE); @@ -122,11 +109,11 @@ elf64_exec(struct preloaded_file *fp) */ for (i = 0; i < 512; i++) { /* Each slot of the level 4 pages points to the same level 3 page */ - PT4[i] = (p4_entry_t) 0x3000; + PT4[i] = (pml4_entry_t) 0x3000; PT4[i] |= PG_V | PG_RW; /* Each slot of the level 3 pages points to the same level 2 page */ - PT3[i] = (p3_entry_t) 0x4000; + PT3[i] = (pdp_entry_t) 0x4000; PT3[i] |= PG_V | PG_RW; /* The level 2 page slots are mapped with 2MB pages for 1GB. */ @@ -154,9 +141,9 @@ elf64_exec(struct preloaded_file *fp) CALLBACK(setcr, 3, 0x2000); CALLBACK(setcr, 0, CR0_PG | CR0_PE | CR0_NE); - setup_freebsd_gdt(gdtr); - CALLBACK(copyin, gdtr, 0x5000, sizeof(gdtr)); - CALLBACK(setgdt, 0x5000, sizeof(gdtr)); + setup_freebsd_gdt(gdt); + CALLBACK(copyin, gdt, 0x5000, sizeof(gdt)); + CALLBACK(setgdt, 0x5000, sizeof(gdt)); CALLBACK(exec, ehdr->e_entry); From 78d6582411ca687bf2b3bd526e4dd563115e6ce2 Mon Sep 17 00:00:00 2001 From: Ahmad Khalifa Date: Mon, 30 Sep 2024 20:31:32 +0300 Subject: [PATCH 7/7] loader: remove check for 2M alignment Instead of listing every arch we support, always define EFI_STAGING_2M_ALIGN to 1. --- stand/efi/loader/copy.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/stand/efi/loader/copy.c b/stand/efi/loader/copy.c index 485ec152ae21..935db3a420ba 100644 --- a/stand/efi/loader/copy.c +++ b/stand/efi/loader/copy.c @@ -178,12 +178,7 @@ out: #define EFI_STAGING_SIZE DEFAULT_EFI_STAGING_SIZE #endif -#if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) || \ - defined(__riscv) || defined(__i386__) #define EFI_STAGING_2M_ALIGN 1 -#else -#define EFI_STAGING_2M_ALIGN 0 -#endif #if defined(__amd64__) || defined(__i386__) #define EFI_STAGING_SLOP M(8)