2009-05-03 Bean <bean123ch@gmail.com> Vladimir Serbinenko <phcoder@gmail.com>
FreeBSD 64-bit support * conf/i386-pc.rmk (bsd_mod_SOURCES): add loader/i386/bsd_helper.S and loader/i386/bsd_trampoline.S (bsd_mod_ASFLAGS): new variable * include/grub/i386/bsd.h (FREEBSD_MODINFOMD_SMAP): new definition (FREEBSD_MODTYPE_KERNEL64): likewise (grub_bsd64_trampoline_start): likewise (grub_bsd64_trampoline_end): likewise (grub_bsd64_trampoline_selfjump): likewise (grub_bsd64_trampoline_gdt): likewise * include/grub/i386/loader.h (grub_unix_real_boot): moved from here ... * include/grub/i386/bsd.h (grub_unix_real_boot): ... moved here * kern/i386/loader.S (grub_unix_real_boot): moved from here ... * loader/i386/bsd_helper.S (grub_unix_real_boot): moved here * include/grub/gpt_partition.h (grub_gpt_partentry): Corrected the type of "attrib" member * loader/i386/bsd_pagetable.c: new file * loader/i386/bsd_trampoline.S: likewise * loader/i386/bsd.c (ALIGN_QWORD): new macro (ALIGN_VAR): likewise (entry_hi): new variable (kern_end_mdofs): likewise (is_64bit): likewise (grub_freebsd_add_meta): use ALIGN_VAR (grub_e820_mmap): new declaration (grub_freebsd_add_mmap): new function (grub_freebsd_add_meta_module): support 64 bit kernels (grub_freebsd_list_modules): use ALIGN_VAR (gdt_descriptor): new declaration (grub_freebsd_boot): support 64 bit kernels (grub_bsd_elf64_hook): new function (grub_bsd_load_elf): support elf64
This commit is contained in:
parent
038c5720de
commit
cef17233d4
6 changed files with 310 additions and 39 deletions
36
ChangeLog
36
ChangeLog
|
@ -1,3 +1,39 @@
|
||||||
|
2009-05-03 Bean <bean123ch@gmail.com> Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
FreeBSD 64-bit support
|
||||||
|
|
||||||
|
* conf/i386-pc.rmk (bsd_mod_SOURCES): add loader/i386/bsd_helper.S
|
||||||
|
and loader/i386/bsd_trampoline.S
|
||||||
|
(bsd_mod_ASFLAGS): new variable
|
||||||
|
* include/grub/i386/bsd.h (FREEBSD_MODINFOMD_SMAP): new definition
|
||||||
|
(FREEBSD_MODTYPE_KERNEL64): likewise
|
||||||
|
(grub_bsd64_trampoline_start): likewise
|
||||||
|
(grub_bsd64_trampoline_end): likewise
|
||||||
|
(grub_bsd64_trampoline_selfjump): likewise
|
||||||
|
(grub_bsd64_trampoline_gdt): likewise
|
||||||
|
* include/grub/i386/loader.h (grub_unix_real_boot): moved from here ...
|
||||||
|
* include/grub/i386/bsd.h (grub_unix_real_boot): ... moved here
|
||||||
|
* kern/i386/loader.S (grub_unix_real_boot): moved from here ...
|
||||||
|
* loader/i386/bsd_helper.S (grub_unix_real_boot): moved here
|
||||||
|
* include/grub/gpt_partition.h (grub_gpt_partentry): Corrected the type
|
||||||
|
of "attrib" member
|
||||||
|
* loader/i386/bsd_pagetable.c: new file
|
||||||
|
* loader/i386/bsd_trampoline.S: likewise
|
||||||
|
* loader/i386/bsd.c (ALIGN_QWORD): new macro
|
||||||
|
(ALIGN_VAR): likewise
|
||||||
|
(entry_hi): new variable
|
||||||
|
(kern_end_mdofs): likewise
|
||||||
|
(is_64bit): likewise
|
||||||
|
(grub_freebsd_add_meta): use ALIGN_VAR
|
||||||
|
(grub_e820_mmap): new declaration
|
||||||
|
(grub_freebsd_add_mmap): new function
|
||||||
|
(grub_freebsd_add_meta_module): support 64 bit kernels
|
||||||
|
(grub_freebsd_list_modules): use ALIGN_VAR
|
||||||
|
(gdt_descriptor): new declaration
|
||||||
|
(grub_freebsd_boot): support 64 bit kernels
|
||||||
|
(grub_bsd_elf64_hook): new function
|
||||||
|
(grub_bsd_load_elf): support elf64
|
||||||
|
|
||||||
2009-05-03 Bean <bean123ch@gmail.com>
|
2009-05-03 Bean <bean123ch@gmail.com>
|
||||||
|
|
||||||
* script/sh/execute.c (grub_script_execute_cmdif): Reset grub_errno
|
* script/sh/execute.c (grub_script_execute_cmdif): Reset grub_errno
|
||||||
|
|
|
@ -313,9 +313,10 @@ aout_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
# For bsd.mod
|
# For bsd.mod
|
||||||
bsd_mod_SOURCES = loader/i386/bsd.c
|
bsd_mod_SOURCES = loader/i386/bsd.c loader/i386/bsd_helper.S loader/i386/bsd_trampoline.S
|
||||||
bsd_mod_CFLAGS = $(COMMON_CFLAGS)
|
bsd_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
bsd_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
||||||
|
|
||||||
# For usb.mod
|
# For usb.mod
|
||||||
usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c
|
usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c
|
||||||
|
|
|
@ -80,9 +80,12 @@
|
||||||
#define FREEBSD_MODINFOMD_SHDR 0x0009 /* section header table */
|
#define FREEBSD_MODINFOMD_SHDR 0x0009 /* section header table */
|
||||||
#define FREEBSD_MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */
|
#define FREEBSD_MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */
|
||||||
|
|
||||||
|
#define FREEBSD_MODINFOMD_SMAP 0x1001
|
||||||
|
|
||||||
#define FREEBSD_MODINFOMD_DEPLIST (0x4001 | FREEBSD_MODINFOMD_NOCOPY) /* depends on */
|
#define FREEBSD_MODINFOMD_DEPLIST (0x4001 | FREEBSD_MODINFOMD_NOCOPY) /* depends on */
|
||||||
|
|
||||||
#define FREEBSD_MODTYPE_KERNEL "elf kernel"
|
#define FREEBSD_MODTYPE_KERNEL "elf kernel"
|
||||||
|
#define FREEBSD_MODTYPE_KERNEL64 "elf64 kernel"
|
||||||
#define FREEBSD_MODTYPE_MODULE "elf module"
|
#define FREEBSD_MODTYPE_MODULE "elf module"
|
||||||
#define FREEBSD_MODTYPE_RAW "raw"
|
#define FREEBSD_MODTYPE_RAW "raw"
|
||||||
|
|
||||||
|
@ -224,4 +227,11 @@ struct grub_netbsd_btinfo_bootdisk
|
||||||
int partition;
|
int partition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void grub_unix_real_boot (grub_addr_t entry, ...)
|
||||||
|
__attribute__ ((cdecl,noreturn));
|
||||||
|
|
||||||
|
extern grub_uint8_t grub_bsd64_trampoline_start, grub_bsd64_trampoline_end;
|
||||||
|
extern grub_uint32_t grub_bsd64_trampoline_selfjump;
|
||||||
|
extern grub_uint32_t grub_bsd64_trampoline_gdt;
|
||||||
|
|
||||||
#endif /* ! GRUB_BSD_CPU_HEADER */
|
#endif /* ! GRUB_BSD_CPU_HEADER */
|
||||||
|
|
|
@ -32,7 +32,4 @@ extern grub_size_t EXPORT_VAR(grub_os_area_size);
|
||||||
|
|
||||||
grub_err_t EXPORT_FUNC(grub_linux16_boot) (void);
|
grub_err_t EXPORT_FUNC(grub_linux16_boot) (void);
|
||||||
|
|
||||||
void EXPORT_FUNC(grub_unix_real_boot) (grub_addr_t entry, ...)
|
|
||||||
__attribute__ ((cdecl,noreturn));
|
|
||||||
|
|
||||||
#endif /* ! GRUB_LOADER_CPU_HEADER */
|
#endif /* ! GRUB_LOADER_CPU_HEADER */
|
||||||
|
|
|
@ -118,25 +118,3 @@ linux_setup_seg:
|
||||||
.word 0
|
.word 0
|
||||||
.code32
|
.code32
|
||||||
|
|
||||||
/*
|
|
||||||
* Use cdecl calling convention for *BSD kernels.
|
|
||||||
*/
|
|
||||||
|
|
||||||
FUNCTION(grub_unix_real_boot)
|
|
||||||
|
|
||||||
call EXT_C(grub_dl_unload_all)
|
|
||||||
|
|
||||||
/* Interrupts should be disabled. */
|
|
||||||
cli
|
|
||||||
|
|
||||||
/* Discard `grub_unix_real_boot' return address. */
|
|
||||||
popl %eax
|
|
||||||
|
|
||||||
/* Fetch `entry' address ... */
|
|
||||||
popl %eax
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ... and put our return address in its place. The kernel will
|
|
||||||
* ignore it, but it expects %esp to point to it.
|
|
||||||
*/
|
|
||||||
call *%eax
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* GRUB -- GRand Unified Bootloader
|
* GRUB -- GRand Unified Bootloader
|
||||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
* Copyright (C) 2008, 2009 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* GRUB is free software: you can redistribute it and/or modify
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -21,6 +21,8 @@
|
||||||
#include <grub/cpu/bsd.h>
|
#include <grub/cpu/bsd.h>
|
||||||
#include <grub/machine/init.h>
|
#include <grub/machine/init.h>
|
||||||
#include <grub/machine/memory.h>
|
#include <grub/machine/memory.h>
|
||||||
|
#include <grub/memory.h>
|
||||||
|
#include <grub/machine/machine.h>
|
||||||
#include <grub/file.h>
|
#include <grub/file.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
|
@ -33,17 +35,19 @@
|
||||||
#include <grub/command.h>
|
#include <grub/command.h>
|
||||||
|
|
||||||
#define ALIGN_DWORD(a) ALIGN_UP (a, 4)
|
#define ALIGN_DWORD(a) ALIGN_UP (a, 4)
|
||||||
|
#define ALIGN_QWORD(a) ALIGN_UP (a, 8)
|
||||||
|
#define ALIGN_VAR(a) ((is_64bit) ? (ALIGN_QWORD(a)) : (ALIGN_DWORD(a)))
|
||||||
#define ALIGN_PAGE(a) ALIGN_UP (a, 4096)
|
#define ALIGN_PAGE(a) ALIGN_UP (a, 4096)
|
||||||
|
|
||||||
#define MOD_BUF_ALLOC_UNIT 4096
|
#define MOD_BUF_ALLOC_UNIT 4096
|
||||||
|
|
||||||
static int kernel_type;
|
static int kernel_type;
|
||||||
static grub_dl_t my_mod;
|
static grub_dl_t my_mod;
|
||||||
static grub_addr_t entry, kern_start, kern_end;
|
static grub_addr_t entry, entry_hi, kern_start, kern_end;
|
||||||
static grub_uint32_t bootflags;
|
static grub_uint32_t bootflags;
|
||||||
static char *mod_buf;
|
static char *mod_buf;
|
||||||
static grub_uint32_t mod_buf_len, mod_buf_max;
|
static grub_uint32_t mod_buf_len, mod_buf_max, kern_end_mdofs;
|
||||||
static int is_elf_kernel;
|
static int is_elf_kernel, is_64bit;
|
||||||
|
|
||||||
static const char freebsd_opts[] = "DhaCcdgmnpqrsv";
|
static const char freebsd_opts[] = "DhaCcdgmnpqrsv";
|
||||||
static const grub_uint32_t freebsd_flags[] =
|
static const grub_uint32_t freebsd_flags[] =
|
||||||
|
@ -135,11 +139,121 @@ grub_freebsd_add_meta (grub_uint32_t type, void *data, grub_uint32_t len)
|
||||||
if (len)
|
if (len)
|
||||||
grub_memcpy (mod_buf + mod_buf_len, data, len);
|
grub_memcpy (mod_buf + mod_buf_len, data, len);
|
||||||
|
|
||||||
mod_buf_len = ALIGN_DWORD (mod_buf_len + len);
|
mod_buf_len = ALIGN_VAR (mod_buf_len + len);
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct grub_e820_mmap
|
||||||
|
{
|
||||||
|
grub_uint64_t addr;
|
||||||
|
grub_uint64_t size;
|
||||||
|
grub_uint32_t type;
|
||||||
|
} __attribute__((packed));
|
||||||
|
#define GRUB_E820_RAM 1
|
||||||
|
#define GRUB_E820_RESERVED 2
|
||||||
|
#define GRUB_E820_ACPI 3
|
||||||
|
#define GRUB_E820_NVS 4
|
||||||
|
#define GRUB_E820_EXEC_CODE 5
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_freebsd_add_mmap (void)
|
||||||
|
{
|
||||||
|
grub_size_t len = 0;
|
||||||
|
struct grub_e820_mmap *mmap_buf = 0;
|
||||||
|
struct grub_e820_mmap *mmap = 0;
|
||||||
|
int isfirstrun = 1;
|
||||||
|
|
||||||
|
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
|
||||||
|
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
|
||||||
|
grub_uint32_t type)
|
||||||
|
{
|
||||||
|
/* FreeBSD assumes that first 64KiB are available.
|
||||||
|
Not always true but try to prevent panic somehow. */
|
||||||
|
if (isfirstrun && addr != 0)
|
||||||
|
{
|
||||||
|
if (mmap)
|
||||||
|
{
|
||||||
|
mmap->addr = 0;
|
||||||
|
mmap->size = (addr < 0x10000) ? addr : 0x10000;
|
||||||
|
mmap->type = GRUB_E820_RAM;
|
||||||
|
mmap++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
len += sizeof (struct grub_e820_mmap);
|
||||||
|
}
|
||||||
|
isfirstrun = 0;
|
||||||
|
if (mmap)
|
||||||
|
{
|
||||||
|
mmap->addr = addr;
|
||||||
|
mmap->size = size;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case GRUB_MACHINE_MEMORY_AVAILABLE:
|
||||||
|
mmap->type = GRUB_E820_RAM;
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_MEMORY_ACPI
|
||||||
|
case GRUB_MACHINE_MEMORY_ACPI:
|
||||||
|
mmap->type = GRUB_E820_ACPI;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_MEMORY_NVS
|
||||||
|
case GRUB_MACHINE_MEMORY_NVS:
|
||||||
|
mmap->type = GRUB_E820_NVS;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
#ifdef GRUB_MACHINE_MEMORY_CODE
|
||||||
|
case GRUB_MACHINE_MEMORY_CODE:
|
||||||
|
#endif
|
||||||
|
#ifdef GRUB_MACHINE_MEMORY_RESERVED
|
||||||
|
case GRUB_MACHINE_MEMORY_RESERVED:
|
||||||
|
#endif
|
||||||
|
mmap->type = GRUB_E820_RESERVED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Merge regions if possible. */
|
||||||
|
if (mmap != mmap_buf && mmap->type == mmap[-1].type &&
|
||||||
|
mmap->addr == mmap[-1].addr + mmap[-1].size)
|
||||||
|
mmap[-1].size += mmap->size;
|
||||||
|
else
|
||||||
|
mmap++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
len += sizeof (struct grub_e820_mmap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_mmap_iterate (hook);
|
||||||
|
mmap_buf = mmap = grub_malloc (len);
|
||||||
|
if (! mmap)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
isfirstrun = 1;
|
||||||
|
grub_mmap_iterate (hook);
|
||||||
|
|
||||||
|
len = (mmap - mmap_buf) * sizeof (struct grub_e820_mmap);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < mmap - mmap_buf; i++)
|
||||||
|
grub_dprintf ("bsd", "smap %d, %d:%llx - %llx\n", i,
|
||||||
|
mmap_buf[i].type,
|
||||||
|
(unsigned long long) mmap_buf[i].addr,
|
||||||
|
(unsigned long long) mmap_buf[i].size);
|
||||||
|
|
||||||
|
grub_dprintf ("bsd", "%d entries in smap\n", mmap - mmap_buf);
|
||||||
|
grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
|
||||||
|
FREEBSD_MODINFOMD_SMAP, mmap_buf, len);
|
||||||
|
|
||||||
|
grub_free (mmap_buf);
|
||||||
|
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_freebsd_add_meta_module (int is_kern, int argc, char **argv,
|
grub_freebsd_add_meta_module (int is_kern, int argc, char **argv,
|
||||||
grub_addr_t addr, grub_uint32_t size)
|
grub_addr_t addr, grub_uint32_t size)
|
||||||
|
@ -166,13 +280,31 @@ grub_freebsd_add_meta_module (int is_kern, int argc, char **argv,
|
||||||
argv++;
|
argv++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
type = (is_kern) ? FREEBSD_MODTYPE_KERNEL : FREEBSD_MODTYPE_RAW;
|
type = ((is_kern) ?
|
||||||
|
((is_64bit) ? FREEBSD_MODTYPE_KERNEL64 : FREEBSD_MODTYPE_KERNEL)
|
||||||
|
: FREEBSD_MODTYPE_RAW);
|
||||||
|
|
||||||
if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type,
|
if (is_64bit)
|
||||||
|
{
|
||||||
|
grub_uint64_t addr64 = addr, size64 = size;
|
||||||
|
if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type,
|
||||||
grub_strlen (type) + 1)) ||
|
grub_strlen (type) + 1)) ||
|
||||||
(grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr, sizeof (addr))) ||
|
(grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr64,
|
||||||
(grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size, sizeof (size))))
|
sizeof (addr64))) ||
|
||||||
return grub_errno;
|
(grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size64,
|
||||||
|
sizeof (size64))))
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type,
|
||||||
|
grub_strlen (type) + 1)) ||
|
||||||
|
(grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr,
|
||||||
|
sizeof (addr))) ||
|
||||||
|
(grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size,
|
||||||
|
sizeof (size))))
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
if (argc)
|
if (argc)
|
||||||
{
|
{
|
||||||
|
@ -202,6 +334,23 @@ grub_freebsd_add_meta_module (int is_kern, int argc, char **argv,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_kern)
|
||||||
|
{
|
||||||
|
int len = (is_64bit) ? 8 : 4;
|
||||||
|
grub_uint64_t data = 0;
|
||||||
|
|
||||||
|
if ((grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
|
||||||
|
FREEBSD_MODINFOMD_HOWTO, &data, 4)) ||
|
||||||
|
(grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
|
||||||
|
FREEBSD_MODINFOMD_ENVP, &data, len)) ||
|
||||||
|
(grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
|
||||||
|
FREEBSD_MODINFOMD_KERNEND, &data, len)))
|
||||||
|
return grub_errno;
|
||||||
|
kern_end_mdofs = mod_buf_len - len;
|
||||||
|
|
||||||
|
return grub_freebsd_add_mmap ();
|
||||||
|
}
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,10 +390,19 @@ grub_freebsd_list_modules (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = ALIGN_DWORD (pos + size);
|
pos = ALIGN_VAR (pos + size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function would be here but it's under different licence. */
|
||||||
|
#include "bsd_pagetable.c"
|
||||||
|
|
||||||
|
struct gdt_descriptor
|
||||||
|
{
|
||||||
|
grub_uint16_t limit;
|
||||||
|
void *base;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_freebsd_boot (void)
|
grub_freebsd_boot (void)
|
||||||
{
|
{
|
||||||
|
@ -291,6 +449,9 @@ grub_freebsd_boot (void)
|
||||||
|
|
||||||
if (is_elf_kernel)
|
if (is_elf_kernel)
|
||||||
{
|
{
|
||||||
|
grub_addr_t md_ofs;
|
||||||
|
int ofs;
|
||||||
|
|
||||||
if (grub_freebsd_add_meta (FREEBSD_MODINFO_END, 0, 0))
|
if (grub_freebsd_add_meta (FREEBSD_MODINFO_END, 0, 0))
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
|
@ -298,12 +459,70 @@ grub_freebsd_boot (void)
|
||||||
bi.bi_modulep = kern_end;
|
bi.bi_modulep = kern_end;
|
||||||
|
|
||||||
kern_end = ALIGN_PAGE (kern_end + mod_buf_len);
|
kern_end = ALIGN_PAGE (kern_end + mod_buf_len);
|
||||||
|
|
||||||
|
if (is_64bit)
|
||||||
|
kern_end += 4096 * 4;
|
||||||
|
|
||||||
|
md_ofs = bi.bi_modulep + kern_end_mdofs;
|
||||||
|
ofs = (is_64bit) ? 16 : 12;
|
||||||
|
*((grub_uint32_t *) md_ofs) = kern_end;
|
||||||
|
md_ofs -= ofs;
|
||||||
|
*((grub_uint32_t *) md_ofs) = bi.bi_envp;
|
||||||
|
md_ofs -= ofs;
|
||||||
|
*((grub_uint32_t *) md_ofs) = bootflags;
|
||||||
}
|
}
|
||||||
|
|
||||||
bi.bi_kernend = kern_end;
|
bi.bi_kernend = kern_end;
|
||||||
|
|
||||||
grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev,
|
if (is_64bit)
|
||||||
0, 0, 0, &bi, bi.bi_modulep, kern_end);
|
{
|
||||||
|
grub_uint32_t *gdt;
|
||||||
|
grub_uint8_t *trampoline;
|
||||||
|
void (*launch_trampoline) (grub_addr_t entry, ...)
|
||||||
|
__attribute__ ((cdecl, regparm (0)));
|
||||||
|
grub_uint8_t *pagetable;
|
||||||
|
|
||||||
|
struct gdt_descriptor *gdtdesc;
|
||||||
|
|
||||||
|
pagetable = (grub_uint8_t *) (kern_end - 16384);
|
||||||
|
fill_bsd64_pagetable (pagetable);
|
||||||
|
|
||||||
|
/* Create GDT. */
|
||||||
|
gdt = (grub_uint32_t *) (kern_end - 4096);
|
||||||
|
gdt[0] = 0;
|
||||||
|
gdt[1] = 0;
|
||||||
|
gdt[2] = 0;
|
||||||
|
gdt[3] = 0x00209800;
|
||||||
|
gdt[4] = 0;
|
||||||
|
gdt[5] = 0x00008000;
|
||||||
|
|
||||||
|
/* Create GDT descriptor. */
|
||||||
|
gdtdesc = (struct gdt_descriptor *) (kern_end - 4096 + 24);
|
||||||
|
gdtdesc->limit = 24;
|
||||||
|
gdtdesc->base = gdt;
|
||||||
|
|
||||||
|
/* Prepare trampoline. */
|
||||||
|
trampoline = (grub_uint8_t *) (kern_end - 4096 + 24
|
||||||
|
+ sizeof (struct gdt_descriptor));
|
||||||
|
launch_trampoline = (void __attribute__ ((cdecl, regparm (0)))
|
||||||
|
(*) (grub_addr_t entry, ...)) trampoline;
|
||||||
|
grub_bsd64_trampoline_gdt = (grub_uint32_t) gdtdesc;
|
||||||
|
grub_bsd64_trampoline_selfjump
|
||||||
|
= (grub_uint32_t) (trampoline + 6
|
||||||
|
+ ((grub_uint8_t *) &grub_bsd64_trampoline_selfjump
|
||||||
|
- &grub_bsd64_trampoline_start));
|
||||||
|
|
||||||
|
/* Copy trampoline. */
|
||||||
|
grub_memcpy (trampoline, &grub_bsd64_trampoline_start,
|
||||||
|
&grub_bsd64_trampoline_end - &grub_bsd64_trampoline_start);
|
||||||
|
|
||||||
|
/* Launch trampoline. */
|
||||||
|
launch_trampoline (entry, entry_hi, pagetable, bi.bi_modulep,
|
||||||
|
kern_end);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev,
|
||||||
|
0, 0, 0, &bi, bi.bi_modulep, kern_end);
|
||||||
|
|
||||||
/* Not reached. */
|
/* Not reached. */
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
@ -485,6 +704,29 @@ grub_bsd_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr)
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_bsd_elf64_hook (Elf64_Phdr * phdr, grub_addr_t * addr)
|
||||||
|
{
|
||||||
|
Elf64_Addr paddr;
|
||||||
|
|
||||||
|
paddr = phdr->p_paddr & 0xffffff;
|
||||||
|
|
||||||
|
if ((paddr < grub_os_area_addr)
|
||||||
|
|| (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Address 0x%x is out of range",
|
||||||
|
paddr);
|
||||||
|
|
||||||
|
if ((!kern_start) || (paddr < kern_start))
|
||||||
|
kern_start = paddr;
|
||||||
|
|
||||||
|
if (paddr + phdr->p_memsz > kern_end)
|
||||||
|
kern_end = paddr + phdr->p_memsz;
|
||||||
|
|
||||||
|
*addr = paddr;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_bsd_load_elf (grub_elf_t elf)
|
grub_bsd_load_elf (grub_elf_t elf)
|
||||||
{
|
{
|
||||||
|
@ -495,6 +737,13 @@ grub_bsd_load_elf (grub_elf_t elf)
|
||||||
entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF;
|
entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF;
|
||||||
return grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
|
return grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
|
||||||
}
|
}
|
||||||
|
else if (grub_elf_is_elf64 (elf))
|
||||||
|
{
|
||||||
|
is_64bit = 1;
|
||||||
|
entry = elf->ehdr.ehdr64.e_entry & 0xffffffff;
|
||||||
|
entry_hi = (elf->ehdr.ehdr64.e_entry >> 32) & 0xffffffff;
|
||||||
|
return grub_elf64_load (elf, grub_bsd_elf64_hook, 0, 0);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return grub_error (GRUB_ERR_BAD_OS, "invalid elf");
|
return grub_error (GRUB_ERR_BAD_OS, "invalid elf");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue