mirror of
https://github.com/opnsense/src.git
synced 2026-02-18 18:20:26 -05:00
stand: Add support for 64-bit machines with 32-bit UEFI implementations
Some machines have 64-bit capable cpus but are stuck on 32-bit uefi firmware. Add support for them by building a new "loader_ia32" with LOADER_DEFAULT_INTERP along with the 64-bit one. The loader can be disabled using MK_LOADER_IA32. Reviewed by: imp Pull Request: https://github.com/freebsd/freebsd-src/pull/1098 (cherry picked from commit f8ca5d45c3c1829759ecd87cb95d53e5ab7d0811)
This commit is contained in:
parent
c6d3271fe0
commit
ce02470205
17 changed files with 621 additions and 23 deletions
|
|
@ -238,7 +238,7 @@ 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 */
|
||||
#ifdef __amd64__
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
bool f_kernphys_relocatable;
|
||||
#endif
|
||||
#if defined(__i386__)
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ static int elf_section_header_convert(const Elf_Ehdr *ehdr, Elf_Shdr *shdr)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef __amd64__
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
static bool
|
||||
is_kernphys_relocatable(elf_file_t ef)
|
||||
{
|
||||
|
|
@ -491,7 +491,7 @@ __elfN(loadfile_raw)(char *filename, uint64_t dest,
|
|||
/* Load OK, return module pointer */
|
||||
*result = (struct preloaded_file *)fp;
|
||||
err = 0;
|
||||
#ifdef __amd64__
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
fp->f_kernphys_relocatable = multiboot || is_kernphys_relocatable(&ef);
|
||||
#endif
|
||||
#ifdef __i386__
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ SUBDIR.yes+= boot1 gptboot
|
|||
|
||||
SUBDIR.${MK_FORTH}+= loader_4th
|
||||
SUBDIR.${MK_LOADER_LUA}+= loader_lua
|
||||
SUBDIR.${MK_LOADER_IA32}+= loader_ia32
|
||||
SUBDIR.yes+= loader_simp
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,11 @@ CFLAGS+= -fPIC
|
|||
.endif
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "amd64"
|
||||
.if ${DO32:U0} == 1
|
||||
EFI_TARGET= efi-app-ia32
|
||||
.else
|
||||
EFI_TARGET= efi-app-x86_64
|
||||
.endif
|
||||
.else
|
||||
EFI_TARGET= binary
|
||||
.endif
|
||||
|
|
|
|||
|
|
@ -7,7 +7,13 @@ LOADER_EXT2FS_SUPPORT?= no
|
|||
|
||||
.include <bsd.init.mk>
|
||||
|
||||
.if ${MACHINE} == "amd64" && ${DO32:U0} == 1
|
||||
__arch= i386
|
||||
LOADER?= loader_ia32
|
||||
.else
|
||||
__arch= ${MACHINE}
|
||||
LOADER?= loader_${LOADER_INTERP}
|
||||
.endif
|
||||
PROG= ${LOADER}.sym
|
||||
INTERNALPROG=
|
||||
WARNS?= 3
|
||||
|
|
@ -53,13 +59,13 @@ CFLAGS.gfx_fb.c += -DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib
|
|||
CWARNFLAGS.main.c+= -Wno-format
|
||||
|
||||
.PATH: ${.CURDIR}/../loader
|
||||
.PATH: ${.CURDIR}/../loader/arch/${MACHINE}
|
||||
.include "${.CURDIR}/../loader/arch/${MACHINE}/Makefile.inc"
|
||||
.PATH: ${.CURDIR}/../loader/arch/${__arch}
|
||||
.include "${.CURDIR}/../loader/arch/${__arch}/Makefile.inc"
|
||||
|
||||
CFLAGS+= -I${.CURDIR}
|
||||
CFLAGS+= -I${.CURDIR}/arch/${MACHINE}
|
||||
CFLAGS+= -I${.CURDIR}/arch/${__arch}
|
||||
CFLAGS+= -I${EFISRC}/include
|
||||
CFLAGS+= -I${EFISRC}/include/${MACHINE}
|
||||
CFLAGS+= -I${EFISRC}/include/${__arch}
|
||||
CFLAGS+= -I${SYSDIR}/contrib/dev/acpica/include
|
||||
CFLAGS+= -I${BOOTSRC}/i386/libi386
|
||||
CFLAGS+= -DEFI
|
||||
|
|
@ -96,11 +102,11 @@ CLEANFILES+= 8x16.c
|
|||
FILES+= ${LOADER}.efi
|
||||
FILESMODE_${LOADER}.efi= ${BINMODE}
|
||||
|
||||
.if ${LOADER_INTERP} == ${LOADER_DEFAULT_INTERP}
|
||||
.if ${LOADER_INTERP} == ${LOADER_DEFAULT_INTERP} && ${__arch} != "i386"
|
||||
LINKS+= ${BINDIR}/${LOADER}.efi ${BINDIR}/loader.efi
|
||||
.endif
|
||||
|
||||
LDSCRIPT= ${.CURDIR}/../loader/arch/${MACHINE}/${MACHINE}.ldscript
|
||||
LDSCRIPT= ${.CURDIR}/../loader/arch/${__arch}/${__arch}.ldscript
|
||||
LDFLAGS+= -Wl,-T${LDSCRIPT},-Bsymbolic,-znotext -pie
|
||||
.if ${LINKER_TYPE} == "bfd" && ${LINKER_VERSION} >= 23400
|
||||
LDFLAGS+= -Wl,--no-dynamic-linker
|
||||
|
|
@ -133,8 +139,14 @@ ${LOADER}.efi: ${PROG}
|
|||
--output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
|
||||
|
||||
LIBEFI= ${BOOTOBJ}/efi/libefi/libefi.a
|
||||
LIBEFI32= ${BOOTOBJ}/efi/libefi32/libefi.a
|
||||
|
||||
.if ${__arch} == "i386"
|
||||
DPADD= ${LDR_INTERP32} ${LIBEFI32} ${LIBSA32} ${LDSCRIPT}
|
||||
LDADD= ${LDR_INTERP32} ${LIBEFI32} ${LIBSA32}
|
||||
.else
|
||||
DPADD= ${LDR_INTERP} ${LIBEFI} ${LIBSAFDT} ${LIBEFI_FDT} ${LIBSA} ${LDSCRIPT}
|
||||
LDADD= ${LDR_INTERP} ${LIBEFI} ${LIBSAFDT} ${LIBEFI_FDT} ${LIBSA}
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
|
|
|||
9
stand/efi/loader/arch/i386/Makefile.inc
Normal file
9
stand/efi/loader/arch/i386/Makefile.inc
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
SRCS+= amd64_tramp.S \
|
||||
start.S \
|
||||
setup.c \
|
||||
elf64_freebsd.c
|
||||
|
||||
.PATH: ${BOOTSRC}/i386/libi386
|
||||
SRCS+= nullconsole.c \
|
||||
comconsole.c \
|
||||
spinconsole.c
|
||||
100
stand/efi/loader/arch/i386/amd64_tramp.S
Normal file
100
stand/efi/loader/arch/i386/amd64_tramp.S
Normal file
|
|
@ -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
|
||||
274
stand/efi/loader/arch/i386/elf64_freebsd.c
Normal file
274
stand/efi/loader/arch/i386/elf64_freebsd.c
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
/*-
|
||||
* 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 <machine/elf.h>
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
|
||||
#include "bootstrap.h"
|
||||
|
||||
#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);
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
#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;
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS ptr;
|
||||
EFI_ALLOCATE_TYPE type;
|
||||
EFI_STATUS err;
|
||||
struct file_metadata *md;
|
||||
struct gdtr *gdtr;
|
||||
Elf_Ehdr *ehdr;
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
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);
|
||||
|
||||
ptr = G(1);
|
||||
err = BS->AllocatePages(type, EfiLoaderData,
|
||||
EFI_SIZE_TO_PAGES(sizeof(struct gdtr) + sizeof(uint64_t) * 2), &ptr);
|
||||
if (EFI_ERROR(err)) {
|
||||
printf("Unable to allocate GDT\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;
|
||||
|
||||
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 = (p4_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 {
|
||||
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 = (p4_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] = ((p2_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
|
||||
);
|
||||
|
||||
efi_time_fini();
|
||||
err = bi_load(fp->f_args, &modulep, &kernend, true);
|
||||
if (err != 0) {
|
||||
efi_time_init();
|
||||
return (err);
|
||||
}
|
||||
|
||||
dev_cleanup();
|
||||
|
||||
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);
|
||||
}
|
||||
55
stand/efi/loader/arch/i386/i386.ldscript
Normal file
55
stand/efi/loader/arch/i386/i386.ldscript
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
OUTPUT_FORMAT("elf32-i386-freebsd", "elf32-i386-freebsd", "elf32-i386-freebsd")
|
||||
OUTPUT_ARCH(i386)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = 0;
|
||||
ImageBase = .;
|
||||
. = SIZEOF_HEADERS;
|
||||
. = ALIGN(4096);
|
||||
.text : {
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.plt)
|
||||
} =0xCCCCCCCC
|
||||
. = ALIGN(4096);
|
||||
.data : {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
|
||||
*(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
|
||||
*(.opd)
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.plabel)
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
__gp = .;
|
||||
.sdata : {
|
||||
*(.got.plt .got)
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
*(dynsbss)
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
.dynamic : { *(.dynamic) }
|
||||
. = ALIGN(4096);
|
||||
.rel.dyn : {
|
||||
*(.rel.*)
|
||||
*(.relset_*)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
.reloc : { *(.reloc) }
|
||||
. = ALIGN(4096);
|
||||
.hash : { *(.hash) }
|
||||
. = ALIGN(4096);
|
||||
.dynsym : { *(.dynsym) }
|
||||
. = ALIGN(4096);
|
||||
.dynstr : { *(.dynstr) }
|
||||
}
|
||||
51
stand/efi/loader/arch/i386/setup.c
Normal file
51
stand/efi/loader/arch/i386/setup.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*-
|
||||
* 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
|
||||
* 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 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 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)
|
||||
* 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/types.h>
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
/*
|
||||
* Check for long mode then call efi_main
|
||||
*/
|
||||
EFI_STATUS
|
||||
setup(EFI_HANDLE IH, EFI_SYSTEM_TABLE *ST) {
|
||||
u_int edx;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return (efi_main(IH, ST));
|
||||
}
|
||||
75
stand/efi/loader/arch/i386/start.S
Normal file
75
stand/efi/loader/arch/i386/start.S
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*-
|
||||
* 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
|
||||
* 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.
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* crt0-efi-ia32.S - x86 EFI startup code.
|
||||
*/
|
||||
|
||||
.text
|
||||
.align 4
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
|
||||
pushl 12(%ebp)
|
||||
pushl 8(%ebp)
|
||||
|
||||
call 0f
|
||||
0: popl %eax
|
||||
movl %eax, %ebx
|
||||
|
||||
addl $ImageBase-0b, %eax
|
||||
addl $_DYNAMIC-0b, %ebx
|
||||
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
call self_reloc
|
||||
popl %ebx
|
||||
popl %ebx
|
||||
|
||||
call setup
|
||||
|
||||
.exit:
|
||||
leave
|
||||
ret
|
||||
|
||||
/*
|
||||
* hand-craft a dummy .reloc section so EFI knows it's a relocatable
|
||||
* executable:
|
||||
*/
|
||||
|
||||
.data
|
||||
.section .reloc, "a"
|
||||
.long 0
|
||||
.long 10
|
||||
.word 0
|
||||
|
|
@ -185,7 +185,7 @@ bi_load_efi_data(struct preloaded_file *kfp, bool exit_bs)
|
|||
struct efi_map_header *efihdr;
|
||||
bool do_vmap;
|
||||
|
||||
#if defined(__amd64__) || defined(__aarch64__)
|
||||
#if defined(__amd64__) || defined(__aarch64__) || defined(__i386__)
|
||||
struct efi_fb efifb;
|
||||
|
||||
efifb.fb_addr = gfx_state.tg_fb.fb_addr;
|
||||
|
|
@ -339,7 +339,16 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs)
|
|||
vm_offset_t size;
|
||||
char *rootdevname;
|
||||
int howto;
|
||||
#ifdef __i386__
|
||||
/*
|
||||
* The 32-bit UEFI loader is used to
|
||||
* boot the 64-bit kernel on machines
|
||||
* that support it.
|
||||
*/
|
||||
bool is64 = true;
|
||||
#else
|
||||
bool is64 = sizeof(long) == 8;
|
||||
#endif
|
||||
#if defined(LOADER_FDT_SUPPORT)
|
||||
vm_offset_t dtbp;
|
||||
int dtb_size;
|
||||
|
|
@ -438,7 +447,7 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs)
|
|||
module = *modulep;
|
||||
file_addmetadata(kfp, MODINFOMD_MODULEP, sizeof(module), &module);
|
||||
#endif
|
||||
#ifdef EFI
|
||||
#if defined(EFI) && !defined(__i386__)
|
||||
file_addmetadata(kfp, MODINFOMD_FW_HANDLE, sizeof(ST), &ST);
|
||||
#endif
|
||||
#ifdef LOADER_GELI_SUPPORT
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ extern struct console eficom;
|
|||
/* Hack for backward compatibility -- but only for a while */
|
||||
extern struct console comconsole;
|
||||
#endif
|
||||
#if defined(__amd64__)
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
extern struct console comconsole;
|
||||
extern struct console nullconsole;
|
||||
extern struct console spinconsole;
|
||||
|
|
@ -94,7 +94,7 @@ struct console *consoles[] = {
|
|||
#if defined(__aarch64__) && __FreeBSD_version < 1500000
|
||||
&comconsole,
|
||||
#endif
|
||||
#if defined(__amd64__)
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
&comconsole,
|
||||
&nullconsole,
|
||||
&spinconsole,
|
||||
|
|
|
|||
|
|
@ -182,13 +182,13 @@ out:
|
|||
#endif
|
||||
|
||||
#if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) || \
|
||||
defined(__riscv)
|
||||
defined(__riscv) || defined(__i386__)
|
||||
#define EFI_STAGING_2M_ALIGN 1
|
||||
#else
|
||||
#define EFI_STAGING_2M_ALIGN 0
|
||||
#endif
|
||||
|
||||
#if defined(__amd64__)
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
#define EFI_STAGING_SLOP M(8)
|
||||
#else
|
||||
#define EFI_STAGING_SLOP 0
|
||||
|
|
@ -209,7 +209,7 @@ efi_copy_free(void)
|
|||
stage_offset = 0;
|
||||
}
|
||||
|
||||
#ifdef __amd64__
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
int copy_staging = COPY_STAGING_AUTO;
|
||||
|
||||
static int
|
||||
|
|
@ -281,7 +281,7 @@ command_staging_slop(int argc, char *argv[])
|
|||
COMMAND_SET(staging_slop, "staging_slop", "set staging slop",
|
||||
command_staging_slop);
|
||||
|
||||
#if defined(__amd64__)
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
/*
|
||||
* The staging area must reside in the first 1GB or 4GB physical
|
||||
* memory: see elf64_exec() in
|
||||
|
|
@ -320,7 +320,8 @@ efi_copy_init(void)
|
|||
*/
|
||||
if (running_on_hyperv())
|
||||
efi_verify_staging_size(&nr_pages);
|
||||
|
||||
#endif
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
staging = get_staging_max();
|
||||
#endif
|
||||
status = BS->AllocatePages(EFI_ALLOC_METHOD, EfiLoaderCode,
|
||||
|
|
@ -380,9 +381,10 @@ efi_check_space(vm_offset_t end)
|
|||
end += staging_slop;
|
||||
|
||||
nr_pages = EFI_SIZE_TO_PAGES(end - staging_end);
|
||||
#if defined(__amd64__)
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
/*
|
||||
* amd64 needs all memory to be allocated under the 1G or 4G boundary.
|
||||
* The amd64 kernel needs all memory to be allocated under the 1G or
|
||||
* 4G boundary.
|
||||
*/
|
||||
if (end > get_staging_max())
|
||||
goto before_staging;
|
||||
|
|
@ -427,7 +429,7 @@ expand:
|
|||
#if EFI_STAGING_2M_ALIGN
|
||||
nr_pages += M(2) / EFI_PAGE_SIZE;
|
||||
#endif
|
||||
#if defined(__amd64__)
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
new_base = get_staging_max();
|
||||
#endif
|
||||
status = BS->AllocatePages(EFI_ALLOC_METHOD, EfiLoaderCode,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include <readin.h>
|
||||
#include <efi.h>
|
||||
|
||||
#ifdef __amd64__
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
enum {
|
||||
COPY_STAGING_ENABLE,
|
||||
COPY_STAGING_DISABLE,
|
||||
|
|
|
|||
|
|
@ -966,7 +966,7 @@ main(int argc, CHAR16 *argv[])
|
|||
archsw.arch_getdev = efi_getdev;
|
||||
archsw.arch_copyin = efi_copyin;
|
||||
archsw.arch_copyout = efi_copyout;
|
||||
#ifdef __amd64__
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
archsw.arch_hypervisor = x86_hypervisor;
|
||||
#endif
|
||||
archsw.arch_readin = efi_readin;
|
||||
|
|
|
|||
6
stand/efi/loader_ia32/Makefile
Normal file
6
stand/efi/loader_ia32/Makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
DO32=1
|
||||
INSTALL_LOADER_HELP_FILE=no
|
||||
|
||||
NEWVERSWHAT?= "EFI loader" amd64-ia32
|
||||
|
||||
.include "../loader/Makefile"
|
||||
Loading…
Reference in a new issue