diff options
Diffstat (limited to 'stand/efi/loader/arch')
29 files changed, 589 insertions, 508 deletions
diff --git a/stand/efi/loader/arch/amd64/Makefile.inc b/stand/efi/loader/arch/amd64/Makefile.inc index 0d9e2648cb59..25ff8fa9ce59 100644 --- a/stand/efi/loader/arch/amd64/Makefile.inc +++ b/stand/efi/loader/arch/amd64/Makefile.inc @@ -1,5 +1,3 @@ -# $FreeBSD$ - SRCS+= amd64_tramp.S \ start.S \ elf64_freebsd.c \ diff --git a/stand/efi/loader/arch/amd64/ldscript.amd64 b/stand/efi/loader/arch/amd64/amd64.ldscript index 874df9b08f9e..0e620654ea81 100644 --- a/stand/efi/loader/arch/amd64/ldscript.amd64 +++ b/stand/efi/loader/arch/amd64/amd64.ldscript @@ -1,4 +1,3 @@ -/* $FreeBSD$ */ OUTPUT_FORMAT("elf64-x86-64-freebsd", "elf64-x86-64-freebsd", "elf64-x86-64-freebsd") OUTPUT_ARCH(i386:x86-64) ENTRY(_start) @@ -35,17 +34,6 @@ SECTIONS *(COMMON) } . = ALIGN(4096); - set_Xcommand_set : { - __start_set_Xcommand_set = .; - *(set_Xcommand_set) - __stop_set_Xcommand_set = .; - } - set_Xficl_compile_set : { - __start_set_Xficl_compile_set = .; - *(set_Xficl_compile_set) - __stop_set_Xficl_compile_set = .; - } - . = ALIGN(4096); __gp = .; .sdata : { *(.got.plt .got) diff --git a/stand/efi/loader/arch/amd64/amd64_tramp.S b/stand/efi/loader/arch/amd64/amd64_tramp.S index 877705407f92..515ffc5d784d 100644 --- a/stand/efi/loader/arch/amd64/amd64_tramp.S +++ b/stand/efi/loader/arch/amd64/amd64_tramp.S @@ -1,6 +1,5 @@ /*- * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Benno Rice under sponsorship from * the FreeBSD Foundation. @@ -24,8 +23,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #include <machine/asmacros.h> diff --git a/stand/efi/loader/arch/amd64/elf64_freebsd.c b/stand/efi/loader/arch/amd64/elf64_freebsd.c index 4bdf675cd5a3..35bd4d6c1419 100644 --- a/stand/efi/loader/arch/amd64/elf64_freebsd.c +++ b/stand/efi/loader/arch/amd64/elf64_freebsd.c @@ -25,9 +25,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #define __ELF_WORD_SIZE 64 #include <sys/param.h> #include <sys/exec.h> @@ -43,20 +40,8 @@ __FBSDID("$FreeBSD$"); #include "bootstrap.h" -#include "platform/acfreebsd.h" -#include "acconfig.h" -#define ACPI_SYSTEM_XFACE -#include "actypes.h" -#include "actbl.h" - #include "loader_efi.h" -static EFI_GUID acpi_guid = ACPI_TABLE_GUID; -static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID; - -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); @@ -86,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); @@ -106,9 +89,6 @@ elf64_exec(struct preloaded_file *fp) Elf_Ehdr *ehdr; vm_offset_t modulep, kernend, trampcode, trampstack; int err, i; - ACPI_TABLE_RSDP *rsdp; - char buf[24]; - int revision; bool copy_auto; copy_auto = copy_staging == COPY_STAGING_AUTO; @@ -116,57 +96,12 @@ elf64_exec(struct preloaded_file *fp) copy_staging = fp->f_kernphys_relocatable ? COPY_STAGING_DISABLE : COPY_STAGING_ENABLE; - /* - * Report the RSDP to the kernel. While this can be found with - * a BIOS boot, the RSDP may be elsewhere when booted from UEFI. - * The old code used the 'hints' method to communite this to - * the kernel. However, while convenient, the 'hints' method - * is fragile and does not work when static hints are compiled - * into the kernel. Instead, move to setting different tunables - * that start with acpi. The old 'hints' can be removed before - * we branch for FreeBSD 12. - */ - - rsdp = efi_get_table(&acpi20_guid); - if (rsdp == NULL) { - rsdp = efi_get_table(&acpi_guid); - } - if (rsdp != NULL) { - sprintf(buf, "0x%016llx", (unsigned long long)rsdp); - setenv("hint.acpi.0.rsdp", buf, 1); - setenv("acpi.rsdp", buf, 1); - revision = rsdp->Revision; - if (revision == 0) - revision = 1; - sprintf(buf, "%d", revision); - setenv("hint.acpi.0.revision", buf, 1); - setenv("acpi.revision", buf, 1); - strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); - buf[sizeof(rsdp->OemId)] = '\0'; - setenv("hint.acpi.0.oem", buf, 1); - setenv("acpi.oem", buf, 1); - sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); - setenv("hint.acpi.0.rsdt", buf, 1); - setenv("acpi.rsdt", buf, 1); - if (revision >= 2) { - /* XXX extended checksum? */ - sprintf(buf, "0x%016llx", - (unsigned long long)rsdp->XsdtPhysicalAddress); - setenv("hint.acpi.0.xsdt", buf, 1); - setenv("acpi.xsdt", buf, 1); - sprintf(buf, "%d", rsdp->Length); - setenv("hint.acpi.0.xsdt_length", buf, 1); - setenv("acpi.xsdt_length", buf, 1); - } - } - if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return (EFTYPE); 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)) { @@ -181,7 +116,7 @@ elf64_exec(struct preloaded_file *fp) trampoline = (void *)trampcode; if (copy_staging == COPY_STAGING_ENABLE) { - PT4 = (pml4_entry_t *)0x0000000040000000; + PT4 = (pml4_entry_t *)G(1); err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3, (EFI_PHYSICAL_ADDRESS *)&PT4); if (EFI_ERROR(err)) { @@ -218,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)) { @@ -274,6 +209,12 @@ elf64_exec(struct preloaded_file *fp) trampoline, PT4); printf("Start @ 0x%lx ...\n", ehdr->e_entry); + /* + * we have to cleanup here because net_cleanup() doesn't work after + * we call ExitBootServices + */ + dev_cleanup(); + efi_time_fini(); err = bi_load(fp->f_args, &modulep, &kernend, true); if (err != 0) { @@ -283,8 +224,6 @@ elf64_exec(struct preloaded_file *fp) return (err); } - dev_cleanup(); - trampoline(trampstack, copy_staging == COPY_STAGING_ENABLE ? efi_copy_finish : efi_copy_finish_nop, kernend, modulep, PT4, ehdr->e_entry); diff --git a/stand/efi/loader/arch/amd64/exc.S b/stand/efi/loader/arch/amd64/exc.S index 0035d4a37e20..940bfa160161 100644 --- a/stand/efi/loader/arch/amd64/exc.S +++ b/stand/efi/loader/arch/amd64/exc.S @@ -1,6 +1,5 @@ /*- * Copyright (c) 2016 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Konstantin Belousov under sponsorship * from the FreeBSD Foundation. @@ -25,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ .macro EH N, err=1 diff --git a/stand/efi/loader/arch/amd64/multiboot2.c b/stand/efi/loader/arch/amd64/multiboot2.c index 4d7b2713685d..eb7362293406 100644 --- a/stand/efi/loader/arch/amd64/multiboot2.c +++ b/stand/efi/loader/arch/amd64/multiboot2.c @@ -34,8 +34,6 @@ * https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html */ -#include <sys/cdefs.h> - #include <sys/param.h> #include <sys/exec.h> #include <sys/linker.h> @@ -53,14 +51,13 @@ #include "bootstrap.h" #include "multiboot2.h" #include "loader_efi.h" +#include "modinfo.h" extern int elf32_loadfile_raw(char *filename, uint64_t dest, struct preloaded_file **result, int multiboot); 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); @@ -334,7 +331,7 @@ exec(struct preloaded_file *fp) struct mb2hdr *hdr; - CTASSERT(sizeof(header) <= PAGE_SIZE); + _Static_assert(sizeof(header) <= PAGE_SIZE, "header too big"); if ((md = file_findmetadata(fp, MODINFOMD_NOCOPY | MODINFOMD_MB2HDR)) == NULL) { @@ -440,7 +437,7 @@ exec(struct preloaded_file *fp) * module 0 module 1 */ - fp = file_findfile(NULL, "elf kernel"); + fp = file_findfile(NULL, md_kerntype); if (fp == NULL) { printf("No FreeBSD kernel provided, aborting\n"); error = EINVAL; @@ -502,7 +499,7 @@ obj_loadfile(char *filename, uint64_t dest, struct preloaded_file **result) int error; /* See if there's a multiboot kernel loaded */ - mfp = file_findfile(NULL, "elf multiboot kernel"); + mfp = file_findfile(NULL, md_kerntype_mb); if (mfp == NULL) return (EFTYPE); @@ -510,14 +507,14 @@ obj_loadfile(char *filename, uint64_t dest, struct preloaded_file **result) * We have a multiboot kernel loaded, see if there's a FreeBSD * kernel loaded also. */ - kfp = file_findfile(NULL, "elf kernel"); + kfp = file_findfile(NULL, md_kerntype); if (kfp == NULL) { /* * No kernel loaded, this must be it. The kernel has to * be loaded as a raw file, it will be processed by * Xen and correctly loaded as an ELF file. */ - rfp = file_loadraw(filename, "elf kernel", 0); + rfp = file_loadraw(filename, md_kerntype, 0); if (rfp == NULL) { printf( "Unable to load %s as a multiboot payload kernel\n", diff --git a/stand/efi/loader/arch/amd64/multiboot2.h b/stand/efi/loader/arch/amd64/multiboot2.h index 5693923c014f..a039aa0439aa 100644 --- a/stand/efi/loader/arch/amd64/multiboot2.h +++ b/stand/efi/loader/arch/amd64/multiboot2.h @@ -244,7 +244,7 @@ struct multiboot_tag_mmap multiboot_uint32_t size; multiboot_uint32_t entry_size; multiboot_uint32_t entry_version; - struct multiboot_mmap_entry entries[0]; + struct multiboot_mmap_entry entries[0]; }; struct multiboot_vbe_info_block @@ -388,7 +388,7 @@ struct multiboot_tag_efi_mmap multiboot_uint32_t descr_size; multiboot_uint32_t descr_vers; multiboot_uint8_t efi_mmap[0]; -}; +}; struct multiboot_tag_efi32_ih { diff --git a/stand/efi/loader/arch/amd64/start.S b/stand/efi/loader/arch/amd64/start.S index 774ef4fa7901..34bf166c6501 100644 --- a/stand/efi/loader/arch/amd64/start.S +++ b/stand/efi/loader/arch/amd64/start.S @@ -33,7 +33,6 @@ /* * crt0-efi-x86_64.S - x86_64 EFI startup code. - * $FreeBSD$ */ .text diff --git a/stand/efi/loader/arch/amd64/trap.c b/stand/efi/loader/arch/amd64/trap.c index e8cf188cf22f..61feb76e2dca 100644 --- a/stand/efi/loader/arch/amd64/trap.c +++ b/stand/efi/loader/arch/amd64/trap.c @@ -1,6 +1,5 @@ /*- * Copyright (c) 2016 The FreeBSD Foundation - * All rights reserved. * * This software was developed by Konstantin Belousov under sponsorship * from the FreeBSD Foundation. @@ -27,9 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <stand.h> #include <string.h> #include <sys/param.h> @@ -79,11 +75,21 @@ static uint32_t loader_tss; /* Loader TSS segment */ static struct region_descriptor fw_gdt; /* Descriptor of pristine GDT */ static EFI_PHYSICAL_ADDRESS loader_gdt_pa; /* Address of loader shadow GDT */ +struct frame { + struct frame *fr_savfp; + uintptr_t fr_savpc; +}; + void report_exc(struct trapframe *tf); void report_exc(struct trapframe *tf) { + struct frame *fp; + uintptr_t pc, base; + char buf[80]; + int ret; + base = (uintptr_t)boot_img->ImageBase; /* * printf() depends on loader runtime and UEFI firmware health * to produce the console output, in case of exception, the @@ -109,6 +115,33 @@ report_exc(struct trapframe *tf) tf->tf_rdi, tf->tf_rsi, tf->tf_rdx, tf->tf_rcx, tf->tf_r8, tf->tf_r9, tf->tf_rax, tf->tf_rbx, tf->tf_rbp, tf->tf_r10, tf->tf_r11, tf->tf_r12, tf->tf_r13, tf->tf_r14, tf->tf_r15); + + fp = (struct frame *)tf->tf_rbp; + pc = tf->tf_rip; + + printf("Stack trace:\n"); + pager_open(); + while (fp != NULL || pc != 0) { + char *source = "PC"; + + if (pc >= base && pc < base + boot_img->ImageSize) { + pc -= base; + source = "loader PC"; + } + (void) snprintf(buf, sizeof (buf), "FP %016lx: %s 0x%016lx\n", + (uintptr_t)fp, source, pc); + if (pager_output(buf)) + break; + + if (fp != NULL) + fp = fp->fr_savfp; + + if (fp != NULL) + pc = fp->fr_savpc; + else + pc = 0; + } + pager_close(); printf("Machine stopped.\n"); } @@ -323,7 +356,7 @@ efi_redirect_exceptions(void) PREPARE_EXCEPTION(19); PREPARE_EXCEPTION(20); - exc_rsp = exc_stack_pa + PAGE_SIZE - + exc_rsp = exc_stack_pa + EFI_PAGE_SIZE - (6 /* hw exception frame */ + 3 /* scratch regs */) * 8; /* Find free IST and use it */ @@ -343,7 +376,7 @@ efi_redirect_exceptions(void) if (intercepted[i]) loader_idt_e->gd_ist = ist; } - (&(tss->tss_ist1))[ist - 1] = exc_stack_pa + PAGE_SIZE; + (&(tss->tss_ist1))[ist - 1] = exc_stack_pa + EFI_PAGE_SIZE; /* Switch to new IDT */ rfl = intr_disable(); diff --git a/stand/efi/loader/arch/arm/Makefile.inc b/stand/efi/loader/arch/arm/Makefile.inc index 284e517bfbb8..3d07122530e7 100644 --- a/stand/efi/loader/arch/arm/Makefile.inc +++ b/stand/efi/loader/arch/arm/Makefile.inc @@ -1,7 +1,4 @@ -# $FreeBSD$ - SRCS+= exec.c \ - efiserialio.c \ start.S HAVE_FDT=yes diff --git a/stand/efi/loader/arch/arm/ldscript.arm b/stand/efi/loader/arch/arm/arm.ldscript index 68775a88a9cd..7b5c2af399c9 100644 --- a/stand/efi/loader/arch/arm/ldscript.arm +++ b/stand/efi/loader/arch/arm/arm.ldscript @@ -1,4 +1,3 @@ -/* $FreeBSD$ */ OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS @@ -43,16 +42,6 @@ SECTIONS *(.got.plt .got) *(.sdata*.sdata.* .gnu.linkonce.s.*) } - set_Xcommand_set : { - __start_set_Xcommand_set = .; - *(set_Xcommand_set) - __stop_set_Xcommand_set = .; - } - set_Xficl_compile_set : { - __start_set_Xficl_compile_set = .; - *(set_Xficl_compile_set) - __stop_set_Xficl_compile_set = .; - } __gp = .; .plt : { *(.plt) } .reloc : { *(.reloc) } diff --git a/stand/efi/loader/arch/arm/exec.c b/stand/efi/loader/arch/arm/exec.c index a110f3d07cbc..3963b6c0104b 100644 --- a/stand/efi/loader/arch/arm/exec.c +++ b/stand/efi/loader/arch/arm/exec.c @@ -25,9 +25,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/param.h> #include <sys/linker.h> @@ -43,9 +40,6 @@ __FBSDID("$FreeBSD$"); #include "bootstrap.h" #include "loader_efi.h" -extern vm_offset_t md_load(char *, vm_offset_t *); -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) @@ -80,16 +74,17 @@ __elfN(arm_exec)(struct preloaded_file *fp) printf("Kernel entry at %p...\n", entry); printf("Kernel args: %s\n", fp->f_args); + /* + * we have to cleanup here because net_cleanup() doesn't work after + * we call ExitBootServices + */ + dev_cleanup(); + if ((error = bi_load(fp->f_args, &modulep, &kernend, true)) != 0) { efi_time_init(); return (error); } - /* At this point we've called ExitBootServices, so we can't call - * printf or any other function that uses Boot Services */ - - dev_cleanup(); - (*entry)((void *)modulep); panic("exec returned"); } diff --git a/stand/efi/loader/arch/arm/start.S b/stand/efi/loader/arch/arm/start.S index 5b6182d67d0a..5e4301ec7141 100644 --- a/stand/efi/loader/arch/arm/start.S +++ b/stand/efi/loader/arch/arm/start.S @@ -22,8 +22,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #include <machine/asm.h> @@ -140,6 +138,7 @@ section_table: _end_header: .text + .globl _start _start: /* Save the boot params to the stack */ push {r0, r1} diff --git a/stand/efi/loader/arch/arm64/Makefile.inc b/stand/efi/loader/arch/arm64/Makefile.inc index 9978d9c4ea9c..9474767cf2f2 100644 --- a/stand/efi/loader/arch/arm64/Makefile.inc +++ b/stand/efi/loader/arch/arm64/Makefile.inc @@ -1,9 +1,6 @@ -# $FreeBSD$ - HAVE_FDT=yes SRCS+= exec.c \ - efiserialio.c \ start.S .PATH: ${BOOTSRC}/arm64/libarm64 diff --git a/stand/efi/loader/arch/arm64/ldscript.arm64 b/stand/efi/loader/arch/arm64/arm64.ldscript index d0ed320a319c..889a1bafb9f7 100644 --- a/stand/efi/loader/arch/arm64/ldscript.arm64 +++ b/stand/efi/loader/arch/arm64/arm64.ldscript @@ -1,4 +1,3 @@ -/* $FreeBSD$ */ /* OUTPUT_FORMAT("elf64-aarch64-freebsd", "elf64-aarch64-freebsd", "elf64-aarch64-freebsd") */ @@ -16,7 +15,9 @@ SECTIONS *(.gnu.warning) *(.plt) } =0xD4200000 - . = ALIGN(16); + . = ALIGN(4096); + _etext = .; + __data_start = .; .data : { *(.rodata .rodata.* .gnu.linkonce.r.*) *(.rodata1) @@ -38,17 +39,6 @@ SECTIONS __bss_end = .; } . = ALIGN(16); - set_Xcommand_set : { - __start_set_Xcommand_set = .; - *(set_Xcommand_set) - __stop_set_Xcommand_set = .; - } - set_Xficl_compile_set : { - __start_set_Xficl_compile_set = .; - *(set_Xficl_compile_set) - __stop_set_Xficl_compile_set = .; - } - . = ALIGN(16); __gp = .; .sdata : { *(.got.plt .got) @@ -78,6 +68,7 @@ SECTIONS . = ALIGN(16); .dynsym : { *(.dynsym) } _edata = .; + __data_size = ABSOLUTE(. - __data_start); /* Unused sections */ .interp : { *(.interp) } diff --git a/stand/efi/loader/arch/arm64/exec.c b/stand/efi/loader/arch/arm64/exec.c index 6cf4a4fd8e4d..89e2ad7521a8 100644 --- a/stand/efi/loader/arch/arm64/exec.c +++ b/stand/efi/loader/arch/arm64/exec.c @@ -24,9 +24,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <stand.h> #include <string.h> @@ -42,22 +39,9 @@ __FBSDID("$FreeBSD$"); #include "loader_efi.h" #include "cache.h" -#include "platform/acfreebsd.h" -#include "acconfig.h" -#define ACPI_SYSTEM_XFACE -#define ACPI_USE_SYSTEM_INTTYPES -#include "actypes.h" -#include "actbl.h" - -static EFI_GUID acpi_guid = ACPI_TABLE_GUID; -static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID; - 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 @@ -75,45 +59,22 @@ elf64_exec(struct preloaded_file *fp) vm_offset_t clean_addr; size_t clean_size; struct file_metadata *md; - ACPI_TABLE_RSDP *rsdp; Elf_Ehdr *ehdr; - char buf[24]; - int err, revision; + int err; void (*entry)(vm_offset_t); - rsdp = efi_get_table(&acpi20_guid); - if (rsdp == NULL) { - rsdp = efi_get_table(&acpi_guid); - } - if (rsdp != NULL) { - sprintf(buf, "0x%016llx", (unsigned long long)rsdp); - setenv("hint.acpi.0.rsdp", buf, 1); - revision = rsdp->Revision; - if (revision == 0) - revision = 1; - sprintf(buf, "%d", revision); - setenv("hint.acpi.0.revision", buf, 1); - strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); - buf[sizeof(rsdp->OemId)] = '\0'; - setenv("hint.acpi.0.oem", buf, 1); - sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); - setenv("hint.acpi.0.rsdt", buf, 1); - if (revision >= 2) { - /* XXX extended checksum? */ - sprintf(buf, "0x%016llx", - (unsigned long long)rsdp->XsdtPhysicalAddress); - setenv("hint.acpi.0.xsdt", buf, 1); - sprintf(buf, "%d", rsdp->Length); - setenv("hint.acpi.0.xsdt_length", buf, 1); - } - } - if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return(EFTYPE); ehdr = (Elf_Ehdr *)&(md->md_data); entry = efi_translate(ehdr->e_entry); + /* + * we have to cleanup here because net_cleanup() doesn't work after + * we call ExitBootServices + */ + dev_cleanup(); + efi_time_fini(); err = bi_load(fp->f_args, &modulep, &kernendp, true); if (err != 0) { @@ -121,8 +82,6 @@ elf64_exec(struct preloaded_file *fp) return (err); } - dev_cleanup(); - /* Clean D-cache under kernel area and invalidate whole I-cache */ clean_addr = (vm_offset_t)efi_translate(fp->f_addr); clean_size = (vm_offset_t)efi_translate(kernendp) - clean_addr; diff --git a/stand/efi/loader/arch/arm64/start.S b/stand/efi/loader/arch/arm64/start.S index 675d4e153f36..6e30287453c5 100644 --- a/stand/efi/loader/arch/arm64/start.S +++ b/stand/efi/loader/arch/arm64/start.S @@ -22,8 +22,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ /* @@ -34,11 +32,14 @@ #define IMAGE_FILE_MACHINE_ARM64 0xaa64 +#define IMAGE_FILE_EXECUTABLE 0x0002 + #define IMAGE_SCN_CNT_CODE 0x00000020 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 #define IMAGE_SCN_MEM_EXECUTE 0x20000000 #define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 .section .peheader,"a" efi_start: @@ -60,22 +61,22 @@ coff_head: .long 0 /* No symbol table */ .long 0 /* No symbols */ .short section_table - optional_header /* Optional header size */ - .short 0 /* Characteristics TODO: Fill in */ + .short IMAGE_FILE_EXECUTABLE /* Characteristics */ optional_header: .short 0x020b /* PE32+ (64-bit addressing) */ .byte 0 /* Major linker version */ .byte 0 /* Minor linker version */ - .long _edata - _end_header /* Code size */ - .long 0 /* No initialized data */ + .long _etext - _end_header /* Code size */ + .long __data_size /* Initialized data size */ .long 0 /* No uninitialized data */ .long _start - efi_start /* Entry point */ .long _end_header - efi_start /* Start of code */ optional_windows_header: .quad 0 /* Image base */ - .long 32 /* Section Alignment */ - .long 8 /* File alignment */ + .long 4096 /* Section Alignment */ + .long 512 /* File alignment */ .short 0 /* Major OS version */ .short 0 /* Minor OS version */ .short 0 /* Major image version */ @@ -104,36 +105,37 @@ optional_windows_header: .quad 0 section_table: - /* We need a .reloc section for EFI */ - .ascii ".reloc" + .ascii ".text" + .byte 0 .byte 0 .byte 0 /* Pad to 8 bytes */ - .long 0 /* Virtual size */ - .long 0 /* Virtual address */ - .long 0 /* Size of raw data */ - .long 0 /* Pointer to raw data */ + .long _etext - _end_header /* Virtual size */ + .long _end_header - efi_start /* Virtual address */ + .long _etext - _end_header /* Size of raw data */ + .long _end_header - efi_start /* Pointer to raw data */ .long 0 /* Pointer to relocations */ .long 0 /* Pointer to line numbers */ .short 0 /* Number of relocations */ .short 0 /* Number of line numbers */ - .long (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | \ - IMAGE_SCN_MEM_DISCARDABLE) /* Characteristics */ + .long (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | \ + IMAGE_SCN_MEM_READ) /* Characteristics */ - /* The contents of the loader */ - .ascii ".text" + .ascii ".data" .byte 0 .byte 0 .byte 0 /* Pad to 8 bytes */ - .long _edata - _end_header /* Virtual size */ - .long _end_header - efi_start /* Virtual address */ - .long _edata - _end_header /* Size of raw data */ - .long _end_header - efi_start /* Pointer to raw data */ + .long __data_size /* Virtual size */ + .long __data_start - efi_start /* Virtual address */ + .long __data_size /* Size of raw data */ + .long __data_start - efi_start /* Pointer to raw data */ .long 0 /* Pointer to relocations */ .long 0 /* Pointer to line numbers */ .short 0 /* Number of relocations */ .short 0 /* Number of line numbers */ - .long (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | \ - IMAGE_SCN_MEM_READ) /* Characteristics */ + .long (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_MEM_WRITE) /* Characteristics */ + + .align 12 _end_header: .text diff --git a/stand/efi/loader/arch/i386/Makefile.inc b/stand/efi/loader/arch/i386/Makefile.inc index fcdb6324b2f0..e27b553c6bab 100644 --- a/stand/efi/loader/arch/i386/Makefile.inc +++ b/stand/efi/loader/arch/i386/Makefile.inc @@ -1,13 +1,9 @@ -# $FreeBSD$ +SRCS+= amd64_tramp.S \ + start.S \ + setup.c \ + elf64_freebsd.c -SRCS+= start.S \ - elf32_freebsd.c \ - exec.c - -.PATH: ${BOOTSRC}/i386/libi386 +.PATH: ${BOOTSRC}/i386/libi386 SRCS+= nullconsole.c \ comconsole.c \ spinconsole.c - -CFLAGS+= -fPIC -LDFLAGS+= -Wl,-znocombreloc diff --git a/stand/efi/loader/arch/i386/amd64_tramp.S b/stand/efi/loader/arch/i386/amd64_tramp.S new file mode 100644 index 000000000000..06f9262014b3 --- /dev/null +++ b/stand/efi/loader/arch/i386/amd64_tramp.S @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * Copyright (c) 2023 Ahmad Khalifa <ahmadkhalifa570@gmail.com> + * + * This software was developed by Benno Rice under sponsorship from + * the FreeBSD Foundation. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <machine/asmacros.h> + + .text + .globl amd64_tramp + +/* + * void amd64_tramp(uint32_t stack, void *copy_finish, uint32_t kernend, + * uint32_t modulep, uint32_t pagetable, uint32_t gdtr, uint64_t entry) + */ +amd64_tramp: + cli /* Make sure we don't get interrupted. */ + + calll *8(%esp) /* Call copy_finish so we're all ready to go. */ + + movl %cr0, %eax /* Paging may be enabled, disable it. */ + andl $0x7FFFFFFF, %eax + movl %eax, %cr0 + + movl %cr4, %eax /* PAE may be disabled, enable it. */ + orl $0x20, %eax + movl %eax, %cr4 + + movl 20(%esp), %eax /* Swap page tables. */ + movl %eax, %cr3 + + movl $0xC0000080, %ecx /* Enable long mode. */ + rdmsr + orl $0x100, %eax + wrmsr + + movl 12(%esp), %edi /* Stash the kernel and GDT values for later. */ + movl 16(%esp), %esi + movl 24(%esp), %ebx + movl 28(%esp), %edx + movl 32(%esp), %ebp + + movl 4(%esp), %esp /* Switch to our temporary stack. */ + + movl %cr0, %eax /* Enable paging and enter compatibility mode. */ + orl $0x80000000, %eax + movl %eax, %cr0 + + lgdtl (%ebx) /* Load GDT. */ + + pushl %edi /* Push kernend. */ + pushl %esi /* Push modulep. */ + pushl $0x0 + pushl %ebp /* Push 64-bit entry address. */ + pushl %edx + + calll 0f /* Find the address of ".longmode". */ +0: popl %eax + addl $(.longmode-0b), %eax + + pushl $0x8 /* Push CS. */ + pushl %eax /* Push the address. */ + lretl /* "Return" to 64-bit code. */ + + .code64 + +.longmode: + retq /* "Return" to kernel entry. */ + + .code32 + + ALIGN_TEXT +amd64_tramp_end: + + .data + .globl amd64_tramp_size +amd64_tramp_size: + .long amd64_tramp_end-amd64_tramp diff --git a/stand/efi/loader/arch/i386/elf32_freebsd.c b/stand/efi/loader/arch/i386/elf32_freebsd.c deleted file mode 100644 index 97d114f09610..000000000000 --- a/stand/efi/loader/arch/i386/elf32_freebsd.c +++ /dev/null @@ -1,103 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/exec.h> -#include <sys/linker.h> -#include <string.h> -#include <machine/bootinfo.h> -#include <machine/elf.h> -#include <stand.h> - -#include <efi.h> -#include <efilib.h> - -#include "bootstrap.h" -#include "../libi386/libi386.h" -#include "../btx/lib/btxv86.h" - -extern void __exec(caddr_t addr, ...); -extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, - bool exit_bs); - -static int elf32_exec(struct preloaded_file *amp); -static int elf32_obj_exec(struct preloaded_file *amp); - -struct file_format i386_elf = { elf32_loadfile, elf32_exec }; -struct file_format i386_elf_obj = { elf32_obj_loadfile, elf32_obj_exec }; - -struct file_format *file_formats[] = { - &i386_elf, - &i386_elf_obj, - NULL -}; - -/* - * There is an ELF kernel and one or more ELF modules loaded. - * We wish to start executing the kernel image, so make such - * preparations as are required, and do so. - */ -static int -elf32_exec(struct preloaded_file *fp) -{ - struct file_metadata *md; - Elf_Ehdr *ehdr; - vm_offset_t entry, bootinfop, modulep, kernend; - int boothowto, err, bootdev; - - if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) - return(EFTYPE); - ehdr = (Elf_Ehdr *)&(md->md_data); - - efi_time_fini(); - - entry = ehdr->e_entry & 0xffffff; - - printf("Start @ 0x%x ...\n", entry); - - err = bi_load(fp->f_args, &modulep, &kernend, true); - if (err != 0) { - efi_time_init(); - return(err); - } - - /* At this point we've called ExitBootServices, so we can't call - * printf or any other function that uses Boot Services */ - - dev_cleanup(); - __exec((void *)entry, boothowto, bootdev, 0, 0, 0, bootinfop, modulep, kernend); - - panic("exec returned"); -} - -static int -elf32_obj_exec(struct preloaded_file *fp) -{ - return (EFTYPE); -} diff --git a/stand/efi/loader/arch/i386/elf64_freebsd.c b/stand/efi/loader/arch/i386/elf64_freebsd.c new file mode 100644 index 000000000000..22cdd685ea9b --- /dev/null +++ b/stand/efi/loader/arch/i386/elf64_freebsd.c @@ -0,0 +1,279 @@ +/*- + * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define __ELF_WORD_SIZE 64 +#include <sys/param.h> +#include <sys/linker.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/elf.h> +#include <machine/pmap_pae.h> +#include <machine/segments.h> + +#include <efi.h> +#include <efilib.h> + +#include "bootstrap.h" + +#include "loader_efi.h" + +static int elf64_exec(struct preloaded_file *amp); +static int elf64_obj_exec(struct preloaded_file *amp); + +static struct file_format amd64_elf = { + .l_load = elf64_loadfile, + .l_exec = elf64_exec +}; + +static struct file_format amd64_elf_obj = { + .l_load = elf64_obj_loadfile, + .l_exec = elf64_obj_exec +}; + +struct file_format *file_formats[] = { + &amd64_elf, + &amd64_elf_obj, + NULL +}; + +/* + * 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, void *gdtr, uint64_t entry); + +extern void *amd64_tramp; +extern uint32_t amd64_tramp_size; + +/* + * There is an ELF kernel and one or more ELF modules loaded. + * We wish to start executing the kernel image, so make such + * preparations as are required, and do so. + */ +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; + 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; + + switch (copy_staging) { + case COPY_STAGING_ENABLE: + type = AllocateMaxAddress; + break; + case COPY_STAGING_DISABLE: + type = AllocateAnyPages; + break; + case COPY_STAGING_AUTO: + type = fp->f_kernphys_relocatable ? + AllocateAnyPages : AllocateMaxAddress; + break; + } + + if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) + return (EFTYPE); + ehdr = (Elf_Ehdr *)&(md->md_data); + + ptr = G(1); + err = BS->AllocatePages(type, EfiLoaderCode, + 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; + 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(DATASZ), &ptr); + if (EFI_ERROR(err)) { + printf("Unable to allocate GDT and stack\n"); + BS->FreePages((uintptr_t)trampoline, 1); + return (ENOMEM); + } + + 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 */ + + ptr = G(1); + err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, + EFI_SIZE_TO_PAGES(512 * 3 * 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); + return (ENOMEM); + } + PT4 = (pml4_entry_t *)(uintptr_t)ptr; + + PT3 = &PT4[512]; + PT2 = &PT3[512]; + + /* + * This is kinda brutal, but every single 1GB VM + * memory segment points to the same first 1GB of + * physical memory. But it is more than adequate. + */ + for (i = 0; i < 512; i++) { + /* + * Each slot of the L4 pages points to the + * same L3 page. + */ + PT4[i] = (uintptr_t)PT3 | PG_V | PG_RW; + + /* + * Each slot of the L3 pages points to the + * same L2 page. + */ + PT3[i] = (uintptr_t)PT2 | PG_V | PG_RW; + + /* + * The L2 page slots are mapped with 2MB pages for 1GB. + */ + 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); + return (ENOMEM); + } + PT4 = (pml4_entry_t *)(uintptr_t)ptr; + + PT3_l = &PT4[512]; + PT3_u = &PT3_l[512]; + PT2_l0 = &PT3_u[512]; + PT2_l1 = &PT2_l0[512]; + PT2_l2 = &PT2_l1[512]; + PT2_l3 = &PT2_l2[512]; + PT2_u0 = &PT2_l3[512]; + PT2_u1 = &PT2_u0[512]; + + /* 1:1 mapping of lower 4G */ + PT4[0] = (uintptr_t)PT3_l | PG_V | PG_RW; + PT3_l[0] = (uintptr_t)PT2_l0 | PG_V | PG_RW; + PT3_l[1] = (uintptr_t)PT2_l1 | PG_V | PG_RW; + 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] = ((pd_entry_t)i * M(2)) | PG_V | PG_RW | PG_PS; + } + + /* mapping of kernel 2G below top */ + PT4[511] = (uintptr_t)PT3_u | PG_V | PG_RW; + PT3_u[511] = (uintptr_t)PT2_u1 | PG_V | PG_RW; + PT3_u[510] = (uintptr_t)PT2_u0 | PG_V | PG_RW; + /* compat mapping of phys @0 */ + PT2_u0[0] = PG_PS | PG_V | PG_RW; + /* this maps past staging area */ + for (i = 1; i < 1024; i++) { + PT2_u0[i] = (staging + (i - 1) * M(2)) + | PG_V | PG_RW | PG_PS; + } + } + + printf( + "staging %#llx (%scopying) tramp %p PT4 %p GDT %p\n" + "Start @ %#llx ...\n", staging, + type == AllocateMaxAddress ? "" : "not ", trampoline, PT4, gdt, + ehdr->e_entry + ); + + + /* + * we have to cleanup here because net_cleanup() doesn't work after + * we call ExitBootServices + */ + dev_cleanup(); + + efi_time_fini(); + err = bi_load(fp->f_args, &modulep, &kernend, true); + if (err != 0) { + efi_time_init(); + return (err); + } + + trampoline(trampstack, type == AllocateMaxAddress ? efi_copy_finish : + efi_copy_finish_nop, kernend, modulep, PT4, gdtr, ehdr->e_entry); + + panic("exec returned"); +} + +static int +elf64_obj_exec(struct preloaded_file *fp) +{ + return (EFTYPE); +} diff --git a/stand/efi/loader/arch/i386/exec.c b/stand/efi/loader/arch/i386/exec.c deleted file mode 100644 index 579f5593b24b..000000000000 --- a/stand/efi/loader/arch/i386/exec.c +++ /dev/null @@ -1,49 +0,0 @@ -/*- - * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <machine/elf.h> -#include "../btx/lib/btxv86.h" - -#include "../../common/bootstrap.h" - -uint32_t __base; -struct __v86 __v86; - -void -__v86int() -{ - printf("%s\n", __func__); - exit(1); -} - -void -__exec(caddr_t addr, ...) -{ -} diff --git a/stand/efi/loader/arch/i386/ldscript.i386 b/stand/efi/loader/arch/i386/i386.ldscript index e17212a1bddd..dcbbf1b6d609 100644 --- a/stand/efi/loader/arch/i386/ldscript.i386 +++ b/stand/efi/loader/arch/i386/i386.ldscript @@ -1,4 +1,3 @@ -/* $FreeBSD$ */ OUTPUT_FORMAT("elf32-i386-freebsd", "elf32-i386-freebsd", "elf32-i386-freebsd") OUTPUT_ARCH(i386) ENTRY(_start) @@ -30,17 +29,6 @@ SECTIONS *(COMMON) } . = ALIGN(4096); - set_Xcommand_set : { - __start_set_Xcommand_set = .; - *(set_Xcommand_set) - __stop_set_Xcommand_set = .; - } - set_Xficl_compile_set : { - __start_set_Xficl_compile_set = .; - *(set_Xficl_compile_set) - __stop_set_Xficl_compile_set = .; - } - . = ALIGN(4096); __gp = .; .sdata : { *(.got.plt .got) @@ -53,18 +41,8 @@ SECTIONS .dynamic : { *(.dynamic) } . = ALIGN(4096); .rel.dyn : { - *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) - *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) - *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) - *(.rel.got) - *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) - *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) - *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) - *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) - *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) - *(.rel.plt) + *(.rel.*) *(.relset_*) - *(.rel.dyn .rel.dyn.*) } . = ALIGN(4096); .reloc : { *(.reloc) } diff --git a/stand/efi/loader/arch/i386/i386_copy.c b/stand/efi/loader/arch/i386/setup.c index 2c4b0deb49cf..5d15e499ddb3 100644 --- a/stand/efi/loader/arch/i386/i386_copy.c +++ b/stand/efi/loader/arch/i386/setup.c @@ -1,6 +1,7 @@ /*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * All rights reserved. + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Ahmad Khalifa <ahmadkhalifa570@gmail.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -11,10 +12,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -24,35 +25,27 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +#include <sys/types.h> -/* - * MD primitives supporting placement of module data - * - * XXX should check load address/size against memory top. - */ -#include <stand.h> +#include <efi.h> +#include <efilib.h> -#include "libi386.h" -#include "btxv86.h" +#include <machine/specialreg.h> -ssize_t -i386_copyin(const void *src, vm_offset_t dest, const size_t len) -{ - bcopy(src, PTOV(dest), len); - return(len); -} +/* + * Check for long mode then call efi_main + */ +EFI_STATUS +setup(EFI_HANDLE IH, EFI_SYSTEM_TABLE *ST) { + u_int edx; -ssize_t -i386_copyout(const vm_offset_t src, void *dest, const size_t len) -{ - bcopy(PTOV(src), dest, len); - return(len); -} + asm("cpuid" : "=d"(edx) : "a"(0x80000001) : "ebx", "ecx"); + if ((edx & AMDID_LM) == 0) { + ST->ConOut->OutputString(ST->ConOut, (CHAR16 *) + L"This CPU doesn't support long mode.\r\n" + L"Unable to proceed.\r\n"); + ST->BootServices->Exit(IH, EFI_UNSUPPORTED, 0, NULL); + } -ssize_t -i386_readin(readin_handle_t fd, vm_offset_t dest, const size_t len) -{ - return (VECTX_READ(fd, PTOV(dest), len)); + return (efi_main(IH, ST)); } diff --git a/stand/efi/loader/arch/i386/start.S b/stand/efi/loader/arch/i386/start.S index b597f419d4a1..2754c81e509c 100644 --- a/stand/efi/loader/arch/i386/start.S +++ b/stand/efi/loader/arch/i386/start.S @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2008-2010 Rui Paulo <rpaulo@FreeBSD.org> + * Copyright (C) 1999 Hewlett-Packard Co. + * Contributed by David Mosberger <davidm@hpl.hp.com>. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,59 +11,65 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hewlett-Packard Co. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ + */ + +/* + * crt0-efi-ia32.S - x86 EFI startup code. */ .text + .align 4 -#include <machine/asm.h> + .globl _start +_start: + pushl %ebp + movl %esp, %ebp -#define EFI_SUCCESS 0 + pushl 12(%ebp) + pushl 8(%ebp) -/* - * EFI entry point. - * _start(EFI_IMAGE image_handle, EFI_SYSTEM_TABLE *system_table); - * - * We calculate the base address along with _DYNAMIC, relocate us and finally - * pass control to efi_main. - */ + call 0f +0: popl %eax + movl %eax, %ebx + + addl $ImageBase-0b, %eax + addl $_DYNAMIC-0b, %ebx -ENTRY(_start) - pushl %ebp - movl %esp, %ebp + pushl %ebx + pushl %eax + call self_reloc + popl %ebx + popl %ebx - pushl 12(%ebp) /* image_handle */ - pushl 8(%ebp) /* system_table */ - call 0f -0: popl %eax - movl %eax, %ebx - addl $ImageBase-0b, %eax - addl $_DYNAMIC-0b, %ebx - pushl %ebx /* dynamic */ - pushl %eax /* ImageBase */ - call self_reloc - popl %ebx /* remove ImageBase from the stack */ - popl %ebx /* remove dynamic from the stack */ - call efi_main -1: leave + call setup + +.exit: + leave ret -END(_start) + + /* + * hand-craft a dummy .reloc section so EFI knows it's a relocatable + * executable: + */ .data .section .reloc, "a" - .long 0 - .long 10 - .word 0 + .long 0 + .long 10 + .word 0 diff --git a/stand/efi/loader/arch/riscv/Makefile.inc b/stand/efi/loader/arch/riscv/Makefile.inc index 333b789e935d..e7f7fd8b7f4f 100644 --- a/stand/efi/loader/arch/riscv/Makefile.inc +++ b/stand/efi/loader/arch/riscv/Makefile.inc @@ -1,7 +1,4 @@ -# $FreeBSD$ - HAVE_FDT=yes SRCS+= exec.c \ - efiserialio.c \ start.S diff --git a/stand/efi/loader/arch/riscv/exec.c b/stand/efi/loader/arch/riscv/exec.c index c7d90a4f31d0..a53fbd9442b0 100644 --- a/stand/efi/loader/arch/riscv/exec.c +++ b/stand/efi/loader/arch/riscv/exec.c @@ -2,6 +2,7 @@ * Copyright (c) 2001 Benno Rice <benno@FreeBSD.org> * Copyright (c) 2007 Semihalf, Rafal Jaworowski <raj@semihalf.com> * All rights reserved. + * Copyright (c) 2024 The FreeBSD Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,9 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/param.h> #include <sys/linker.h> @@ -43,7 +41,27 @@ __FBSDID("$FreeBSD$"); #include "bootstrap.h" #include "loader_efi.h" -extern int bi_load(char *, vm_offset_t *, vm_offset_t *, bool); +static void +riscv_set_boot_hart(struct preloaded_file *fp) +{ + EFI_GUID riscvboot = RISCV_EFI_BOOT_PROTOCOL_GUID; + RISCV_EFI_BOOT_PROTOCOL *proto; + EFI_STATUS status = 0; + uint64_t boot_hartid = ULONG_MAX; + + status = BS->LocateProtocol(&riscvboot, NULL, (void **)&proto); + if (EFI_ERROR(status)) { + return; + } + + status = proto->GetBootHartId(proto, &boot_hartid); + if (EFI_ERROR(status)) { + return; + } + + file_addmetadata(fp, MODINFOMD_BOOT_HARTID, sizeof(boot_hartid), + &boot_hartid); +} static int __elfN(exec)(struct preloaded_file *fp) @@ -57,6 +75,8 @@ __elfN(exec)(struct preloaded_file *fp) if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return (EFTYPE); + riscv_set_boot_hart(fp); + e = (Elf_Ehdr *)&fmp->md_data; efi_time_fini(); @@ -66,17 +86,17 @@ __elfN(exec)(struct preloaded_file *fp) printf("Kernel entry at %p...\n", entry); printf("Kernel args: %s\n", fp->f_args); + /* + * we have to cleanup here because net_cleanup() doesn't work after + * we call ExitBootServices + */ + dev_cleanup(); + if ((error = bi_load(fp->f_args, &modulep, &kernend, true)) != 0) { efi_time_init(); return (error); } - /* - * At this point we've called ExitBootServices, so we can't call - * printf or any other function that uses Boot Services - */ - dev_cleanup(); - (*entry)((void *)modulep); panic("exec returned"); } diff --git a/stand/efi/loader/arch/riscv/ldscript.riscv b/stand/efi/loader/arch/riscv/riscv.ldscript index aa736f0d9b2a..63b71c3bd702 100644 --- a/stand/efi/loader/arch/riscv/ldscript.riscv +++ b/stand/efi/loader/arch/riscv/riscv.ldscript @@ -1,4 +1,3 @@ -/* $FreeBSD$ */ OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv") OUTPUT_ARCH(riscv64) ENTRY(_start) @@ -36,17 +35,6 @@ SECTIONS __bss_end = .; } . = ALIGN(16); - set_Xcommand_set : { - __start_set_Xcommand_set = .; - *(set_Xcommand_set) - __stop_set_Xcommand_set = .; - } - set_Xficl_compile_set : { - __start_set_Xficl_compile_set = .; - *(set_Xficl_compile_set) - __stop_set_Xficl_compile_set = .; - } - . = ALIGN(16); .sdata : { /* * u-boot expects the gp register to be untouched by the EFI payload, so we diff --git a/stand/efi/loader/arch/riscv/start.S b/stand/efi/loader/arch/riscv/start.S index e63ce68d86ba..fb7d65f17c99 100644 --- a/stand/efi/loader/arch/riscv/start.S +++ b/stand/efi/loader/arch/riscv/start.S @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020 Mitchell Horne <mhorne@FreeBSD.org> * @@ -23,8 +23,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #include <machine/asm.h> |