Merge branch 'mainline' into relocator

This commit is contained in:
phcoder 2009-09-20 19:38:16 +02:00
commit 8f2e29a2a3
99 changed files with 3333 additions and 732 deletions

View file

@ -33,12 +33,14 @@
#include <grub/gzio.h>
#include <grub/aout.h>
#include <grub/command.h>
#include <grub/extcmd.h>
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/biosnum.h>
#endif
#include <grub/disk.h>
#include <grub/device.h>
#include <grub/partition.h>
#endif
#define ALIGN_DWORD(a) ALIGN_UP (a, 4)
#define ALIGN_QWORD(a) ALIGN_UP (a, 8)
@ -54,33 +56,80 @@ static grub_uint32_t bootflags;
static char *mod_buf;
static grub_uint32_t mod_buf_len, mod_buf_max, kern_end_mdofs;
static int is_elf_kernel, is_64bit;
static char *netbsd_root = NULL;
static const struct grub_arg_option freebsd_opts[] =
{
{"dual", 'D', 0, "Display output on all consoles.", 0, 0},
{"serial", 'h', 0, "Use serial console.", 0, 0},
{"askname", 'a', 0, "Ask for file name to reboot from.", 0, 0},
{"cdrom", 'C', 0, "Use cdrom as root.", 0, 0},
{"config", 'c', 0, "Invoke user configuration routing.", 0, 0},
{"kdb", 'd', 0, "Enter in KDB on boot.", 0, 0},
{"gdb", 'g', 0, "Use GDB remote debugger instead of DDB.", 0, 0},
{"mute", 'm', 0, "Disable all boot output.", 0, 0},
{"nointr", 'n', 0, "", 0, 0},
{"pause", 'p', 0, "Wait for keypress after every line of output.", 0, 0},
{"quiet", 'q', 0, "", 0, 0},
{"dfltroot", 'r', 0, "Use compiled-in rootdev.", 0, 0},
{"single", 's', 0, "Boot into single mode.", 0, 0},
{"verbose", 'v', 0, "Boot with verbose messages.", 0, 0},
{0, 0, 0, 0, 0, 0}
};
static const char freebsd_opts[] = "DhaCcdgmnpqrsv";
static const grub_uint32_t freebsd_flags[] =
{
FREEBSD_RB_DUAL, FREEBSD_RB_SERIAL, FREEBSD_RB_ASKNAME,
FREEBSD_RB_CDROM, FREEBSD_RB_CONFIG, FREEBSD_RB_KDB,
FREEBSD_RB_GDB, FREEBSD_RB_MUTE, FREEBSD_RB_NOINTR,
FREEBSD_RB_PAUSE, FREEBSD_RB_QUIET, FREEBSD_RB_DFLTROOT,
FREEBSD_RB_SINGLE, FREEBSD_RB_VERBOSE
FREEBSD_RB_SINGLE, FREEBSD_RB_VERBOSE, 0
};
static const char openbsd_opts[] = "abcsd";
static const struct grub_arg_option openbsd_opts[] =
{
{"askname", 'a', 0, "Ask for file name to reboot from.", 0, 0},
{"halt", 'b', 0, "Don't reboot, just halt.", 0, 0},
{"config", 'c', 0, "Change configured devices.", 0, 0},
{"single", 's', 0, "Boot into single mode.", 0, 0},
{"kdb", 'd', 0, "Enter in KDB on boot.", 0, 0},
{0, 0, 0, 0, 0, 0}
};
static const grub_uint32_t openbsd_flags[] =
{
OPENBSD_RB_ASKNAME, OPENBSD_RB_HALT, OPENBSD_RB_CONFIG,
OPENBSD_RB_SINGLE, OPENBSD_RB_KDB
OPENBSD_RB_SINGLE, OPENBSD_RB_KDB, 0
};
static const char netbsd_opts[] = "abcdmqsvxz";
static const struct grub_arg_option netbsd_opts[] =
{
{"no-smp", '1', 0, "Disable SMP.", 0, 0},
{"no-acpi", '2', 0, "Disable ACPI.", 0, 0},
{"askname", 'a', 0, "Ask for file name to reboot from.", 0, 0},
{"halt", 'b', 0, "Don't reboot, just halt.", 0, 0},
{"config", 'c', 0, "Change configured devices.", 0, 0},
{"kdb", 'd', 0, "Enter in KDB on boot.", 0, 0},
{"miniroot", 'm', 0, "", 0, 0},
{"quiet", 'q', 0, "Don't display boot diagnostic messages.", 0, 0},
{"single", 's', 0, "Boot into single mode.", 0, 0},
{"verbose", 'v', 0, "Boot with verbose messages.", 0, 0},
{"debug", 'x', 0, "Boot with debug messages.", 0, 0},
{"silent", 'z', 0, "Supress normal output (warnings remain).", 0, 0},
{"root", 'r', 0, "Set root device.", "DEVICE", ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
static const grub_uint32_t netbsd_flags[] =
{
NETBSD_RB_ASKNAME, NETBSD_RB_HALT, NETBSD_RB_USERCONFIG,
NETBSD_RB_KDB, NETBSD_RB_MINIROOT, NETBSD_AB_QUIET,
NETBSD_RB_SINGLE, NETBSD_AB_VERBOSE, NETBSD_AB_DEBUG,
NETBSD_AB_SILENT
NETBSD_AB_NOSMP, NETBSD_AB_NOACPI, NETBSD_RB_ASKNAME,
NETBSD_RB_HALT, NETBSD_RB_USERCONFIG, NETBSD_RB_KDB,
NETBSD_RB_MINIROOT, NETBSD_AB_QUIET, NETBSD_RB_SINGLE,
NETBSD_AB_VERBOSE, NETBSD_AB_DEBUG, NETBSD_AB_SILENT, 0
};
#define NETBSD_ROOT_ARG (ARRAY_SIZE (netbsd_flags) - 1)
static void
grub_bsd_get_device (grub_uint32_t * biosdev,
grub_uint32_t * unit,
@ -89,7 +138,11 @@ grub_bsd_get_device (grub_uint32_t * biosdev,
char *p;
grub_device_t dev;
#ifdef GRUB_MACHINE_PCBIOS
*biosdev = grub_get_root_biosnumber () & 0xff;
#else
*biosdev = 0xff;
#endif
*unit = (*biosdev & 0x7f);
*slice = 0xff;
*part = 0xff;
@ -525,6 +578,14 @@ grub_openbsd_boot (void)
pm->type = OPENBSD_MMAP_AVAILABLE;
break;
case GRUB_MACHINE_MEMORY_ACPI:
pm->type = OPENBSD_MMAP_ACPI;
break;
case GRUB_MACHINE_MEMORY_NVS:
pm->type = OPENBSD_MMAP_NVS;
break;
default:
pm->type = OPENBSD_MMAP_RESERVED;
break;
@ -540,6 +601,12 @@ grub_openbsd_boot (void)
pm = (struct grub_openbsd_bios_mmap *) (pa + 1);
grub_mmap_iterate (hook);
/* Memory map terminator. */
pm->addr = 0;
pm->len = 0;
pm->type = 0;
pm++;
pa->ba_size = (char *) pm - (char *) pa;
pa->ba_next = (struct grub_openbsd_bootargs *) pm;
pa = pa->ba_next;
@ -551,8 +618,8 @@ grub_openbsd_boot (void)
(part << OPENBSD_B_PARTSHIFT));
grub_unix_real_boot (entry, bootflags, bootdev, OPENBSD_BOOTARG_APIVER,
0, grub_mmap_get_upper () >> 10,
grub_mmap_get_lower () >> 10,
0, (grub_uint32_t) (grub_mmap_get_upper () >> 10),
(grub_uint32_t) (grub_mmap_get_lower () >> 10),
(char *) pa - buf, buf);
/* Not reached. */
@ -562,26 +629,93 @@ grub_openbsd_boot (void)
static grub_err_t
grub_netbsd_boot (void)
{
struct grub_netbsd_btinfo_rootdevice *rootdev;
struct grub_netbsd_bootinfo *bootinfo;
grub_uint32_t biosdev, unit, slice, part;
int count = 0;
struct grub_netbsd_btinfo_mmap_header *mmap;
struct grub_netbsd_btinfo_mmap_entry *pm;
void *curarg;
grub_bsd_get_device (&biosdev, &unit, &slice, &part);
auto int NESTED_FUNC_ATTR count_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR count_hook (grub_uint64_t addr __attribute__ ((unused)),
grub_uint64_t size __attribute__ ((unused)),
grub_uint32_t type __attribute__ ((unused)))
{
count++;
return 0;
}
rootdev = (struct grub_netbsd_btinfo_rootdevice *) GRUB_BSD_TEMP_BUFFER;
auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
{
pm->addr = addr;
pm->len = size;
rootdev->common.len = sizeof (struct grub_netbsd_btinfo_rootdevice);
rootdev->common.type = NETBSD_BTINFO_ROOTDEVICE;
grub_sprintf (rootdev->devname, "%cd%d%c", (biosdev & 0x80) ? 'w' : 'f',
unit, 'a' + part);
switch (type)
{
case GRUB_MACHINE_MEMORY_AVAILABLE:
pm->type = NETBSD_MMAP_AVAILABLE;
break;
bootinfo = (struct grub_netbsd_bootinfo *) (rootdev + 1);
bootinfo->bi_count = 1;
bootinfo->bi_data[0] = rootdev;
case GRUB_MACHINE_MEMORY_ACPI:
pm->type = NETBSD_MMAP_ACPI;
break;
case GRUB_MACHINE_MEMORY_NVS:
pm->type = NETBSD_MMAP_NVS;
break;
default:
pm->type = NETBSD_MMAP_RESERVED;
break;
}
pm++;
return 0;
}
grub_mmap_iterate (count_hook);
if (kern_end + sizeof (struct grub_netbsd_btinfo_rootdevice)
+ sizeof (struct grub_netbsd_bootinfo)
+ sizeof (struct grub_netbsd_btinfo_mmap_header)
+ count * sizeof (struct grub_netbsd_btinfo_mmap_entry)
> grub_os_area_addr + grub_os_area_size)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "No memory for boot info.");
curarg = mmap = (struct grub_netbsd_btinfo_mmap_header *) kern_end;
pm = (struct grub_netbsd_btinfo_mmap_entry *) (mmap + 1);
grub_mmap_iterate (fill_hook);
mmap->common.type = NETBSD_BTINFO_MEMMAP;
mmap->common.len = (char *) pm - (char *) mmap;
mmap->count = count;
curarg = pm;
if (netbsd_root)
{
struct grub_netbsd_btinfo_rootdevice *rootdev;
rootdev = (struct grub_netbsd_btinfo_rootdevice *) curarg;
rootdev->common.len = sizeof (struct grub_netbsd_btinfo_rootdevice);
rootdev->common.type = NETBSD_BTINFO_ROOTDEVICE;
grub_strncpy (rootdev->devname, netbsd_root, sizeof (rootdev->devname));
bootinfo = (struct grub_netbsd_bootinfo *) (rootdev + 1);
bootinfo->bi_count = 2;
bootinfo->bi_data[0] = mmap;
bootinfo->bi_data[1] = rootdev;
}
else
{
bootinfo = (struct grub_netbsd_bootinfo *) curarg;
bootinfo->bi_count = 1;
bootinfo->bi_data[0] = mmap;
}
grub_unix_real_boot (entry, bootflags, 0, bootinfo,
0, grub_mmap_get_upper () >> 10,
grub_mmap_get_lower () >> 10);
0, (grub_uint32_t) (grub_mmap_get_upper () >> 10),
(grub_uint32_t) (grub_mmap_get_lower () >> 10));
/* Not reached. */
return GRUB_ERR_NONE;
@ -600,6 +734,9 @@ grub_bsd_unload (void)
kernel_type = KERNEL_TYPE_NONE;
grub_dl_unref (my_mod);
grub_free (netbsd_root);
netbsd_root = NULL;
return GRUB_ERR_NONE;
}
@ -733,8 +870,18 @@ grub_bsd_load_elf (grub_elf_t elf)
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;
/* FreeBSD has 64-bit entry point. */
if (kernel_type == KERNEL_TYPE_FREEBSD)
{
entry = elf->ehdr.ehdr64.e_entry & 0xffffffff;
entry_hi = (elf->ehdr.ehdr64.e_entry >> 32) & 0xffffffff;
}
else
{
entry = elf->ehdr.ehdr64.e_entry & 0x0fffffff;
entry_hi = 0;
}
return grub_elf64_load (elf, grub_bsd_elf64_hook, 0, 0);
}
else
@ -785,41 +932,24 @@ fail:
}
static grub_uint32_t
grub_bsd_parse_flags (char *str, const char *opts,
grub_bsd_parse_flags (const struct grub_arg_list *state,
const grub_uint32_t * flags)
{
grub_uint32_t result = 0;
unsigned i;
while (*str)
{
const char *po;
const grub_uint32_t *pf;
po = opts;
pf = flags;
while (*po)
{
if (*str == *po)
{
result |= *pf;
break;
}
po++;
pf++;
}
str++;
}
for (i = 0; flags[i]; i++)
if (state[i].set)
result |= flags[i];
return result;
}
static grub_err_t
grub_cmd_freebsd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
grub_cmd_freebsd (grub_extcmd_t cmd, int argc, char *argv[])
{
kernel_type = KERNEL_TYPE_FREEBSD;
bootflags = ((argc <= 1) ? 0 :
grub_bsd_parse_flags (argv[1], freebsd_opts, freebsd_flags));
bootflags = grub_bsd_parse_flags (cmd->state, freebsd_flags);
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
{
@ -879,12 +1009,10 @@ grub_cmd_freebsd (grub_command_t cmd __attribute__ ((unused)),
}
static grub_err_t
grub_cmd_openbsd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
grub_cmd_openbsd (grub_extcmd_t cmd, int argc, char *argv[])
{
kernel_type = KERNEL_TYPE_OPENBSD;
bootflags = ((argc <= 1) ? 0 :
grub_bsd_parse_flags (argv[1], openbsd_opts, openbsd_flags));
bootflags = grub_bsd_parse_flags (cmd->state, openbsd_flags);
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 1);
@ -893,15 +1021,17 @@ grub_cmd_openbsd (grub_command_t cmd __attribute__ ((unused)),
}
static grub_err_t
grub_cmd_netbsd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[])
{
kernel_type = KERNEL_TYPE_NETBSD;
bootflags = ((argc <= 1) ? 0 :
grub_bsd_parse_flags (argv[1], netbsd_opts, netbsd_flags));
bootflags = grub_bsd_parse_flags (cmd->state, netbsd_flags);
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 1);
{
grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 1);
if (cmd->state[NETBSD_ROOT_ARG].set)
netbsd_root = grub_strdup (cmd->state[NETBSD_ROOT_ARG].arg);
}
return grub_errno;
}
@ -1112,21 +1242,24 @@ grub_cmd_freebsd_module_elf (grub_command_t cmd __attribute__ ((unused)),
}
static grub_command_t cmd_freebsd, cmd_openbsd, cmd_netbsd;
static grub_extcmd_t cmd_freebsd, cmd_openbsd, cmd_netbsd;
static grub_command_t cmd_freebsd_loadenv, cmd_freebsd_module;
static grub_command_t cmd_freebsd_module_elf;
GRUB_MOD_INIT (bsd)
{
cmd_freebsd =
grub_register_command ("freebsd", grub_cmd_freebsd,
0, "load kernel of FreeBSD");
cmd_openbsd =
grub_register_command ("openbsd", grub_cmd_openbsd,
0, "load kernel of OpenBSD");
cmd_netbsd =
grub_register_command ("netbsd", grub_cmd_netbsd,
0, "load kernel of NetBSD");
cmd_freebsd = grub_register_extcmd ("freebsd", grub_cmd_freebsd,
GRUB_COMMAND_FLAG_BOTH,
"freebsd FILE", "Load kernel of FreeBSD.",
freebsd_opts);
cmd_openbsd = grub_register_extcmd ("openbsd", grub_cmd_openbsd,
GRUB_COMMAND_FLAG_BOTH,
"openbsd FILE", "Load kernel of OpenBSD.",
openbsd_opts);
cmd_netbsd = grub_register_extcmd ("netbsd", grub_cmd_netbsd,
GRUB_COMMAND_FLAG_BOTH,
"netbsd FILE", "Load kernel of NetBSD.",
netbsd_opts);
cmd_freebsd_loadenv =
grub_register_command ("freebsd_loadenv", grub_cmd_freebsd_loadenv,
0, "load FreeBSD env");
@ -1142,9 +1275,9 @@ GRUB_MOD_INIT (bsd)
GRUB_MOD_FINI (bsd)
{
grub_unregister_command (cmd_freebsd);
grub_unregister_command (cmd_openbsd);
grub_unregister_command (cmd_netbsd);
grub_unregister_extcmd (cmd_freebsd);
grub_unregister_extcmd (cmd_openbsd);
grub_unregister_extcmd (cmd_netbsd);
grub_unregister_command (cmd_freebsd_loadenv);
grub_unregister_command (cmd_freebsd_module);

View file

@ -197,15 +197,15 @@ SUFFIX (grub_freebsd_load_elfmodule) (grub_file_t file, int argc, char *argv[],
if (curload < module + sizeof (e))
curload = module + sizeof (e);
load (file, UINT_TO_PTR (module + e.e_shoff), e.e_shoff,
load (file, UINT_TO_PTR (curload), e.e_shoff,
e.e_shnum * e.e_shentsize);
if (curload < module + e.e_shoff + e.e_shnum * e.e_shentsize)
curload = module + e.e_shoff + e.e_shnum * e.e_shentsize;
e.e_shoff = curload - module;
curload += e.e_shnum * e.e_shentsize;
load (file, UINT_TO_PTR (module + e.e_phoff), e.e_phoff,
load (file, UINT_TO_PTR (curload), e.e_phoff,
e.e_phnum * e.e_phentsize);
if (curload < module + e.e_phoff + e.e_phnum * e.e_phentsize)
curload = module + e.e_phoff + e.e_phnum * e.e_phentsize;
e.e_phoff = curload - module;
curload += e.e_phnum * e.e_phentsize;
*kern_end = curload;

View file

@ -33,6 +33,7 @@
#include <grub/video.h>
#include <grub/video_fb.h>
#include <grub/command.h>
#include <grub/i386/pc/vbe.h>
#define GRUB_LINUX_CL_OFFSET 0x1000
#define GRUB_LINUX_CL_END_OFFSET 0x2000
@ -416,6 +417,33 @@ grub_linux_setup_video (struct linux_kernel_params *params)
params->reserved_mask_size = mode_info.reserved_mask_size;
params->reserved_field_pos = mode_info.reserved_field_pos;
#ifdef GRUB_MACHINE_PCBIOS
/* VESA packed modes may come with zeroed mask sizes, which need
to be set here according to DAC Palette width. If we don't,
this results in Linux displaying a black screen. */
if (mode_info.bpp <= 8)
{
struct grub_vbe_info_block controller_info;
int status;
int width = 8;
status = grub_vbe_bios_get_controller_info (&controller_info);
if (status == GRUB_VBE_STATUS_OK &&
(controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH))
status = grub_vbe_bios_set_dac_palette_width (&width);
if (status != GRUB_VBE_STATUS_OK)
/* 6 is default after mode reset. */
width = 6;
params->red_mask_size = params->green_mask_size
= params->blue_mask_size = width;
params->reserved_mask_size = 0;
}
#endif
return 0;
}

View file

@ -247,7 +247,7 @@ grub_cpu_xnu_fill_devicetree (void)
curval->datasize = (SYSTEM_TABLE_SIZEOF (firmware_revision));
curval->data = grub_malloc (curval->datasize);
if (! curval->data)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't create device tree");
return grub_errno;
grub_memcpy (curval->data, (SYSTEM_TABLE_VAR(firmware_revision)),
curval->datasize);
@ -258,7 +258,7 @@ grub_cpu_xnu_fill_devicetree (void)
2 * (utf16_strlen (SYSTEM_TABLE_PTR (firmware_vendor)) + 1);
curval->data = grub_malloc (curval->datasize);
if (! curval->data)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't create device tree");
return grub_errno;
grub_memcpy (curval->data, SYSTEM_TABLE_PTR (firmware_vendor),
curval->datasize);
@ -268,7 +268,7 @@ grub_cpu_xnu_fill_devicetree (void)
curval->datasize = sizeof ("EFI32");
curval->data = grub_malloc (curval->datasize);
if (! curval->data)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't create device tree");
return grub_errno;
if (SIZEOF_OF_UINTN == 4)
grub_memcpy (curval->data, "EFI32", curval->datasize);
else
@ -287,7 +287,7 @@ grub_cpu_xnu_fill_devicetree (void)
curval->datasize = sizeof (grub_uint64_t);
curval->data = grub_malloc (curval->datasize);
if (!curval->data)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't create device tree");
return grub_errno;
/* First see if user supplies the value. */
char *fsbvar = grub_env_get ("fsb");
@ -362,8 +362,7 @@ grub_cpu_xnu_fill_devicetree (void)
curval->datasize = sizeof (guid);
curval->data = grub_malloc (curval->datasize);
if (! curval->data)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't create device tree");
return grub_errno;
grub_memcpy (curval->data, &guid, curval->datasize);
/* The value "table". */
@ -373,8 +372,7 @@ grub_cpu_xnu_fill_devicetree (void)
curval->datasize = SIZEOF_OF_UINTN;
curval->data = grub_malloc (curval->datasize);
if (! curval->data)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't create device tree");
return grub_errno;
if (SIZEOF_OF_UINTN == 4)
*((grub_uint32_t *)curval->data) = PTR_TO_UINT32 (ptr);
else
@ -392,8 +390,7 @@ grub_cpu_xnu_fill_devicetree (void)
curval->datasize = grub_strlen (table_aliases[j].name) + 1;
curval->data = grub_malloc (curval->datasize);
if (!curval->data)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't create device tree");
return grub_errno;
grub_memcpy (curval->data, table_aliases[j].name, curval->datasize);
}
}
@ -409,8 +406,7 @@ grub_cpu_xnu_fill_devicetree (void)
curval->datasize = SIZEOF_OF_UINTN;
curval->data = grub_malloc (curval->datasize);
if (! curval->data)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't create device tree");
return grub_errno;
if (SIZEOF_OF_UINTN == 4)
*((grub_uint32_t *) curval->data)
= PTR_TO_UINT32 (SYSTEM_TABLE_PTR (runtime_services));