merge mainline

This commit is contained in:
Colin Watson 2010-06-12 12:17:28 +01:00
commit 934302d00b
545 changed files with 51148 additions and 23539 deletions

View file

@ -140,7 +140,6 @@ grub_bsd_get_device (grub_uint32_t * biosdev,
grub_uint32_t * unit,
grub_uint32_t * slice, grub_uint32_t * part)
{
char *p;
grub_device_t dev;
#ifdef GRUB_MACHINE_PCBIOS
@ -154,21 +153,13 @@ grub_bsd_get_device (grub_uint32_t * biosdev,
dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition)
{
p = dev->disk->partition->partmap->get_name (dev->disk->partition);
if (p)
if (dev->disk->partition->parent)
{
if ((p[0] >= '0') && (p[0] <= '9'))
{
*slice = grub_strtoul (p, &p, 0);
if ((p) && (p[0] == ','))
p++;
}
if ((p[0] >= 'a') && (p[0] <= 'z'))
*part = p[0] - 'a';
*part = dev->disk->partition->number;
*slice = dev->disk->partition->parent->number + 1;
}
else
*slice = dev->disk->partition->number + 1;
}
if (dev)
grub_device_close (dev);
@ -461,14 +452,14 @@ grub_freebsd_boot (void)
}
grub_memset (&bi, 0, sizeof (bi));
bi.bi_version = FREEBSD_BOOTINFO_VERSION;
bi.bi_size = sizeof (bi);
bi.version = FREEBSD_BOOTINFO_VERSION;
bi.length = sizeof (bi);
grub_bsd_get_device (&biosdev, &unit, &slice, &part);
bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) +
(unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT));
bi.bi_bios_dev = biosdev;
bi.boot_device = biosdev;
p = (char *) kern_end;
@ -478,7 +469,7 @@ grub_freebsd_boot (void)
{
*(p++) = 0;
bi.bi_envp = kern_end;
bi.environment = kern_end;
kern_end = ALIGN_PAGE ((grub_uint32_t) p);
}
@ -491,23 +482,23 @@ grub_freebsd_boot (void)
return grub_errno;
grub_memcpy ((char *) kern_end, mod_buf, mod_buf_len);
bi.bi_modulep = kern_end;
bi.tags = kern_end;
kern_end = ALIGN_PAGE (kern_end + mod_buf_len);
if (is_64bit)
kern_end += 4096 * 4;
md_ofs = bi.bi_modulep + kern_end_mdofs;
md_ofs = bi.tags + 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;
*((grub_uint32_t *) md_ofs) = bi.environment;
md_ofs -= ofs;
*((grub_uint32_t *) md_ofs) = bootflags;
}
bi.bi_kernend = kern_end;
bi.kern_end = kern_end;
grub_video_set_mode ("text", 0, 0);
@ -554,12 +545,12 @@ grub_freebsd_boot (void)
&grub_bsd64_trampoline_end - &grub_bsd64_trampoline_start);
/* Launch trampoline. */
launch_trampoline (entry, entry_hi, pagetable, bi.bi_modulep,
launch_trampoline (entry, entry_hi, pagetable, bi.tags,
kern_end);
}
else
grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev,
0, 0, 0, &bi, bi.bi_modulep, kern_end);
0, 0, 0, &bi, bi.tags, kern_end);
/* Not reached. */
return GRUB_ERR_NONE;
@ -1145,14 +1136,20 @@ grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)),
if (*curr)
{
char name[grub_strlen (curr) + sizeof("kFreeBSD.")];
char *name;
if (*p == '"')
p++;
grub_sprintf (name, "kFreeBSD.%s", curr);
if (grub_env_set (name, p))
name = grub_xasprintf ("kFreeBSD.%s", curr);
if (!name)
goto fail;
if (grub_env_set (name, p))
{
grub_free (name);
goto fail;
}
grub_free (name);
}
}

View file

@ -80,7 +80,7 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (grub_file_t file, int argc,
{
Elf_Ehdr e;
Elf_Shdr *s;
char *shdr;
char *shdr = 0;
grub_addr_t curload, module;
grub_err_t err;
@ -148,7 +148,7 @@ SUFFIX (grub_freebsd_load_elfmodule) (grub_file_t file, int argc, char *argv[],
{
Elf_Ehdr e;
Elf_Shdr *s;
char *shdr;
char *shdr = 0;
grub_addr_t curload, module;
grub_err_t err;
@ -223,7 +223,7 @@ SUFFIX (grub_freebsd_load_elf_meta) (grub_file_t file, grub_addr_t *kern_end)
grub_err_t err;
Elf_Ehdr e;
Elf_Shdr *s;
char *shdr;
char *shdr = 0;
unsigned symoff, stroff, symsize, strsize;
grub_addr_t curload;
grub_freebsd_addr_t symstart, symend, symentsize, dynamic;

View file

@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc.
* Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -305,7 +305,8 @@ grub_linux_setup_video (struct linux_kernel_params *params)
params->lfb_line_len = mode_info.pitch;
params->lfb_base = (grub_size_t) framebuffer;
params->lfb_size = (params->lfb_line_len * params->lfb_height + 65535) >> 16;
params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height,
65536);
params->red_mask_size = mode_info.red_mask_size;
params->red_field_pos = mode_info.red_field_pos;
@ -316,7 +317,7 @@ 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;
params->have_vga = GRUB_VIDEO_TYPE_EFI;
params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
#ifdef GRUB_MACHINE_PCBIOS
/* VESA packed modes may come with zeroed mask sizes, which need
@ -433,11 +434,9 @@ grub_linux_boot (void)
May change in future if we have modes without framebuffer. */
if (modevar && *modevar != 0)
{
tmp = grub_malloc (grub_strlen (modevar)
+ sizeof (";auto"));
tmp = grub_xasprintf ("%s;auto", modevar);
if (! tmp)
return grub_errno;
grub_sprintf (tmp, "%s;auto", modevar);
err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
grub_free (tmp);
}
@ -609,8 +608,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
/* XXX Linux assumes that only elilo can boot Linux on EFI!!! */
params->type_of_loader = (LINUX_LOADER_ID_ELILO << 4);
params->type_of_loader = (LINUX_LOADER_ID_GRUB << 4);
params->cl_magic = GRUB_LINUX_CL_MAGIC;
params->cl_offset = 0x1000;
@ -783,7 +781,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
else if (grub_memcmp (argv[i], "video=efifb", 11) == 0)
{
if (params->have_vga)
params->have_vga = GRUB_VIDEO_TYPE_EFI;
params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
}
/* Specify the boot file. */

View file

@ -394,12 +394,15 @@ grub_linux_setup_video (struct linux_kernel_params *params)
{
struct grub_video_mode_info mode_info;
void *framebuffer;
int ret;
grub_err_t err;
ret = grub_video_get_info_and_fini (&mode_info, &framebuffer);
err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
if (ret)
return 1;
if (err)
{
grub_errno = GRUB_ERR_NONE;
return 1;
}
params->lfb_width = mode_info.width;
params->lfb_height = mode_info.height;
@ -407,7 +410,7 @@ grub_linux_setup_video (struct linux_kernel_params *params)
params->lfb_line_len = mode_info.pitch;
params->lfb_base = (grub_size_t) framebuffer;
params->lfb_size = (params->lfb_line_len * params->lfb_height + 65535) >> 16;
params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height, 65536);
params->red_mask_size = mode_info.red_mask_size;
params->red_field_pos = mode_info.red_field_pos;
@ -519,11 +522,9 @@ grub_linux_boot (void)
May change in future if we have modes without framebuffer. */
if (modevar && *modevar != 0)
{
tmp = grub_malloc (grub_strlen (modevar)
+ sizeof (";text"));
tmp = grub_xasprintf ("%s;text", modevar);
if (! tmp)
return grub_errno;
grub_sprintf (tmp, "%s;text", modevar);
err = grub_video_set_mode (tmp, 0, 0);
grub_free (tmp);
}
@ -538,16 +539,22 @@ grub_linux_boot (void)
}
if (! grub_linux_setup_video (params))
params->have_vga = GRUB_VIDEO_TYPE_VLFB;
{
/* Use generic framebuffer unless VESA is known to be supported. */
if (params->have_vga != GRUB_VIDEO_LINUX_TYPE_VESA)
params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
else
params->lfb_size >>= 16;
}
else
{
params->have_vga = GRUB_VIDEO_TYPE_TEXT;
params->have_vga = GRUB_VIDEO_LINUX_TYPE_TEXT;
params->video_width = 80;
params->video_height = 25;
}
/* Initialize these last, because terminal position could be affected by printfs above. */
if (params->have_vga == GRUB_VIDEO_TYPE_TEXT)
if (params->have_vga == GRUB_VIDEO_LINUX_TYPE_TEXT)
{
grub_term_output_t term;
int found = 0;
@ -796,19 +803,22 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
break;
}
buf = grub_malloc (sizeof ("WWWWxHHHHxDD;WWWWxHHHH"));
if (! buf)
goto fail;
/* We can't detect VESA, but user is implicitly telling us that it
is built-in because `vga=' parameter was used. */
params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA;
linux_mode
= &linux_vesafb_modes[vid_mode - GRUB_LINUX_VID_MODE_VESA_START];
grub_sprintf (buf, "%ux%ux%u,%ux%u",
linux_vesafb_res[linux_mode->res_index].width,
linux_vesafb_res[linux_mode->res_index].height,
linux_mode->depth,
linux_vesafb_res[linux_mode->res_index].width,
linux_vesafb_res[linux_mode->res_index].height);
buf = grub_xasprintf ("%ux%ux%u,%ux%u",
linux_vesafb_res[linux_mode->res_index].width,
linux_vesafb_res[linux_mode->res_index].height,
linux_mode->depth,
linux_vesafb_res[linux_mode->res_index].width,
linux_vesafb_res[linux_mode->res_index].height);
if (! buf)
goto fail;
grub_printf ("%s is deprecated. "
"Use set gfxpayload=%s before "
"linux command instead.\n",

View file

@ -1,331 +0,0 @@
/* multiboot.c - boot a multiboot OS image. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* FIXME: The following features from the Multiboot specification still
* need to be implemented:
* - VBE support
* - symbol table
* - drives table
* - ROM configuration table
* - APM table
*/
/* The bits in the required part of flags field we don't support. */
#define UNSUPPORTED_FLAGS 0x0000fff8
#include <grub/loader.h>
#include <grub/machine/loader.h>
#include <grub/multiboot.h>
#include <grub/cpu/multiboot.h>
#include <grub/elf.h>
#include <grub/aout.h>
#include <grub/file.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/env.h>
#include <grub/i386/relocator.h>
#include <grub/video.h>
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/efi.h>
#endif
extern grub_dl_t my_mod;
static grub_size_t code_size, alloc_mbi;
char *grub_multiboot_payload_orig;
grub_addr_t grub_multiboot_payload_dest;
grub_size_t grub_multiboot_pure_size;
grub_uint32_t grub_multiboot_payload_eip;
static grub_err_t
grub_multiboot_boot (void)
{
grub_size_t mbi_size;
grub_err_t err;
struct grub_relocator32_state state =
{
.eax = MULTIBOOT_BOOTLOADER_MAGIC,
.ecx = 0,
.edx = 0,
.eip = grub_multiboot_payload_eip,
/* Set esp to some random location in low memory to avoid breaking
non-compliant kernels. */
.esp = 0x7ff00
};
mbi_size = grub_multiboot_get_mbi_size ();
if (alloc_mbi < mbi_size)
{
grub_multiboot_payload_orig
= grub_relocator32_realloc (grub_multiboot_payload_orig,
grub_multiboot_pure_size + mbi_size);
if (!grub_multiboot_payload_orig)
return grub_errno;
alloc_mbi = mbi_size;
}
state.ebx = grub_multiboot_payload_dest + grub_multiboot_pure_size;
err = grub_multiboot_make_mbi (grub_multiboot_payload_orig,
grub_multiboot_payload_dest,
grub_multiboot_pure_size, mbi_size);
if (err)
return err;
#ifdef GRUB_MACHINE_EFI
if (! grub_efi_finish_boot_services ())
grub_fatal ("cannot exit boot services");
#endif
grub_relocator32_boot (grub_multiboot_payload_orig,
grub_multiboot_payload_dest,
state);
/* Not reached. */
return GRUB_ERR_NONE;
}
static grub_err_t
grub_multiboot_unload (void)
{
grub_multiboot_free_mbi ();
grub_relocator32_free (grub_multiboot_payload_orig);
alloc_mbi = 0;
grub_multiboot_payload_orig = NULL;
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
#define MULTIBOOT_LOAD_ELF64
#include "multiboot_elfxx.c"
#undef MULTIBOOT_LOAD_ELF64
#define MULTIBOOT_LOAD_ELF32
#include "multiboot_elfxx.c"
#undef MULTIBOOT_LOAD_ELF32
/* Load ELF32 or ELF64. */
static grub_err_t
grub_multiboot_load_elf (grub_file_t file, void *buffer)
{
if (grub_multiboot_is_elf32 (buffer))
return grub_multiboot_load_elf32 (file, buffer);
else if (grub_multiboot_is_elf64 (buffer))
return grub_multiboot_load_elf64 (file, buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
}
void
grub_multiboot (int argc, char *argv[])
{
grub_file_t file = 0;
char buffer[MULTIBOOT_SEARCH];
struct multiboot_header *header;
grub_ssize_t len;
grub_loader_unset ();
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
goto fail;
}
file = grub_gzfile_open (argv[0], 1);
if (! file)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
goto fail;
}
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
{
grub_error (GRUB_ERR_BAD_OS, "file too small");
goto fail;
}
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + 4))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
break;
}
if (header == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
goto fail;
}
if (header->flags & UNSUPPORTED_FLAGS)
{
grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported flag: 0x%x", header->flags);
goto fail;
}
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_payload_orig = NULL;
/* Skip filename. */
grub_multiboot_init_mbi (argc - 1, argv + 1);
if (header->flags & MULTIBOOT_AOUT_KLUDGE)
{
int offset = ((char *) header - buffer -
(header->header_addr - header->load_addr));
int load_size = ((header->load_end_addr == 0) ? file->size - offset :
header->load_end_addr - header->load_addr);
if (header->bss_end_addr)
code_size = (header->bss_end_addr - header->load_addr);
else
code_size = load_size;
grub_multiboot_payload_dest = header->load_addr;
grub_multiboot_pure_size += code_size;
/* Allocate a bit more to avoid relocations in most cases. */
alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi);
if (! grub_multiboot_payload_orig)
goto fail;
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
goto fail;
grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
if (grub_errno)
goto fail;
if (header->bss_end_addr)
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
header->bss_end_addr - header->load_addr - load_size);
grub_multiboot_payload_eip = header->entry_addr;
}
else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
goto fail;
if (header->flags & MULTIBOOT_VIDEO_MODE)
{
switch (header->mode_type)
{
case 1:
grub_env_set ("gfxpayload", "text");
break;
case 0:
{
char buf[sizeof ("XXXXXXXXXXxXXXXXXXXXXxXXXXXXXXXX,XXXXXXXXXXxXXXXXXXXXX,auto")];
if (header->depth && header->width && header->height)
grub_sprintf (buf, "%dx%dx%d,%dx%d,auto", header->width,
header->height, header->depth, header->width,
header->height);
else if (header->width && header->height)
grub_sprintf (buf, "%dx%d,auto", header->width, header->height);
else
grub_sprintf (buf, "auto");
grub_env_set ("gfxpayload", buf);
break;
}
}
}
grub_multiboot_set_accepts_video (!!(header->flags & MULTIBOOT_VIDEO_MODE));
grub_multiboot_set_bootdev ();
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
fail:
if (file)
grub_file_close (file);
if (grub_errno != GRUB_ERR_NONE)
{
grub_relocator32_free (grub_multiboot_payload_orig);
grub_dl_unref (my_mod);
}
}
void
grub_module (int argc, char *argv[])
{
grub_file_t file = 0;
grub_ssize_t size;
char *module = 0;
grub_err_t err;
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
goto fail;
}
if (!grub_multiboot_payload_orig)
{
grub_error (GRUB_ERR_BAD_ARGUMENT,
"you need to load the multiboot kernel first");
goto fail;
}
file = grub_gzfile_open (argv[0], 1);
if (! file)
goto fail;
size = grub_file_size (file);
module = grub_memalign (MULTIBOOT_MOD_ALIGN, size);
if (! module)
goto fail;
err = grub_multiboot_add_module ((grub_addr_t) module, size,
argc - 1, argv + 1);
if (err)
goto fail;
if (grub_file_read (file, module, size) != size)
{
grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
goto fail;
}
fail:
if (file)
grub_file_close (file);
}

View file

@ -23,6 +23,7 @@
#endif
#include <grub/multiboot.h>
#include <grub/cpu/multiboot.h>
#include <grub/cpu/relocator.h>
#include <grub/disk.h>
#include <grub/device.h>
#include <grub/partition.h>
@ -30,15 +31,10 @@
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/video.h>
#include <grub/file.h>
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
#include <grub/i386/pc/vbe.h>
#define DEFAULT_VIDEO_MODE "text"
#define HAS_VGA_TEXT 1
#else
#define DEFAULT_VIDEO_MODE "auto"
#define HAS_VGA_TEXT 0
#endif
/* The bits in the required part of flags field we don't support. */
#define UNSUPPORTED_FLAGS 0x0000fff8
struct module
{
@ -56,33 +52,136 @@ static unsigned modcnt;
static char *cmdline = NULL;
static grub_uint32_t bootdev;
static int bootdev_set;
static int accepts_video;
void
grub_multiboot_set_accepts_video (int val)
grub_err_t
grub_multiboot_load (grub_file_t file)
{
accepts_video = val;
}
char *buffer;
grub_ssize_t len;
struct multiboot_header *header;
grub_err_t err;
/* Return the length of the Multiboot mmap that will be needed to allocate
our platform's map. */
static grub_uint32_t
grub_get_multiboot_mmap_len (void)
{
grub_size_t count = 0;
buffer = grub_malloc (MULTIBOOT_SEARCH);
if (!buffer)
return grub_errno;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)),
grub_uint64_t size __attribute__ ((unused)),
grub_uint32_t type __attribute__ ((unused)))
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
{
count++;
return 0;
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_OS, "file too small");
}
grub_mmap_iterate (hook);
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
break;
}
return count * sizeof (struct multiboot_mmap_entry);
if (header == 0)
{
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
}
if (header->flags & UNSUPPORTED_FLAGS)
{
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported flag: 0x%x", header->flags);
}
if (header->flags & MULTIBOOT_AOUT_KLUDGE)
{
int offset = ((char *) header - buffer -
(header->header_addr - header->load_addr));
int load_size = ((header->load_end_addr == 0) ? file->size - offset :
header->load_end_addr - header->load_addr);
grub_size_t code_size;
if (header->bss_end_addr)
code_size = (header->bss_end_addr - header->load_addr);
else
code_size = load_size;
grub_multiboot_payload_dest = header->load_addr;
grub_multiboot_pure_size += code_size;
/* Allocate a bit more to avoid relocations in most cases. */
grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
if (! grub_multiboot_payload_orig)
{
grub_free (buffer);
return grub_errno;
}
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
{
grub_free (buffer);
return grub_errno;
}
grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
if (grub_errno)
{
grub_free (buffer);
return grub_errno;
}
if (header->bss_end_addr)
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
header->bss_end_addr - header->load_addr - load_size);
grub_multiboot_payload_eip = header->entry_addr;
}
else
{
err = grub_multiboot_load_elf (file, buffer);
if (err)
{
grub_free (buffer);
return err;
}
}
if (header->flags & MULTIBOOT_VIDEO_MODE)
{
switch (header->mode_type)
{
case 1:
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
| GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
0, 0, 0, 0);
break;
case 0:
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
| GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
header->width, header->height,
header->depth, 0);
break;
default:
err = grub_error (GRUB_ERR_BAD_OS,
"unsupported graphical mode type %d",
header->mode_type);
break;
}
}
else
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
0, 0, 0, 0);
return err;
}
grub_size_t
@ -90,7 +189,8 @@ grub_multiboot_get_mbi_size (void)
{
return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
+ modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ()
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4)
+ grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
+ 256 * sizeof (struct multiboot_color);
}
@ -110,6 +210,18 @@ grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry)
case GRUB_MACHINE_MEMORY_AVAILABLE:
mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE;
break;
#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE
case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE:
mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
break;
#endif
#ifdef GRUB_MACHINE_MEMORY_NVS
case GRUB_MACHINE_MEMORY_NVS:
mmap_entry->type = MULTIBOOT_MEMORY_NVS;
break;
#endif
default:
mmap_entry->type = MULTIBOOT_MEMORY_RESERVED;
@ -124,35 +236,6 @@ grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry)
grub_mmap_iterate (hook);
}
static grub_err_t
set_video_mode (void)
{
grub_err_t err;
const char *modevar;
if (accepts_video || !HAS_VGA_TEXT)
{
modevar = grub_env_get ("gfxpayload");
if (! modevar || *modevar == 0)
err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
else
{
char *tmp;
tmp = grub_malloc (grub_strlen (modevar)
+ sizeof (DEFAULT_VIDEO_MODE) + 1);
if (! tmp)
return grub_errno;
grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
err = grub_video_set_mode (tmp, 0, 0);
grub_free (tmp);
}
}
else
err = grub_video_set_mode ("text", 0, 0);
return err;
}
static grub_err_t
retrieve_video_parameters (struct multiboot_info *mbi,
grub_uint8_t *ptrorig, grub_uint32_t ptrdest)
@ -163,7 +246,7 @@ retrieve_video_parameters (struct multiboot_info *mbi,
grub_video_driver_id_t driv_id;
struct grub_video_palette_data palette[256];
err = set_video_mode ();
err = grub_multiboot_set_video_mode ();
if (err)
{
grub_print_error ();
@ -283,7 +366,8 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
mbi->mods_count = 0;
}
mmap_size = grub_get_multiboot_mmap_len ();
mmap_size = grub_get_multiboot_mmap_count ()
* sizeof (struct multiboot_mmap_entry);
grub_fill_multiboot_mmap ((struct multiboot_mmap_entry *) ptrorig);
mbi->mmap_length = mmap_size;
mbi->mmap_addr = ptrdest;
@ -425,7 +509,6 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
void
grub_multiboot_set_bootdev (void)
{
char *p;
grub_uint32_t biosdev, slice = ~0, part = ~0;
grub_device_t dev;
@ -435,24 +518,19 @@ grub_multiboot_set_bootdev (void)
biosdev = 0xffffffff;
#endif
if (biosdev == 0xffffffff)
return;
dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition)
{
p = dev->disk->partition->partmap->get_name (dev->disk->partition);
if (p)
{
if ((p[0] >= '0') && (p[0] <= '9'))
{
slice = grub_strtoul (p, &p, 0) - 1;
if ((p) && (p[0] == ','))
p++;
}
if ((p[0] >= 'a') && (p[0] <= 'z'))
part = p[0] - 'a';
if (dev->disk->partition->parent)
{
part = dev->disk->partition->number;
slice = dev->disk->partition->parent->number;
}
else
slice = dev->disk->partition->number;
}
if (dev)
grub_device_close (dev);

View file

@ -31,6 +31,7 @@
#include <grub/machine/memory.h>
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/msdos_partition.h>
#include <grub/machine/biosnum.h>
#include <grub/i18n.h>
#include <grub/video.h>
@ -98,10 +99,22 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition)
{
grub_disk_read (dev->disk, dev->disk->partition->offset, 446, 64,
(void *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR);
part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR
+ (dev->disk->partition->index << 4));
grub_disk_t disk = dev->disk;
if (disk)
{
grub_partition_t p = disk->partition;
if (p && grub_strcmp (p->partmap->name, "msdos") == 0)
{
disk->partition = p->parent;
grub_disk_read (disk, p->offset, 446, 64,
(void *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR);
part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR
+ (p->index << 4));
disk->partition = p;
}
}
}
if (dev)

View file

@ -33,6 +33,7 @@
#include <grub/command.h>
#include <grub/gzio.h>
#include <grub/i18n.h>
#include <grub/bitmap_scale.h>
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
@ -754,11 +755,13 @@ grub_cpu_xnu_fill_devicetree (void)
#endif
/* The name of key for new table. */
grub_sprintf (guidbuf, "%08x-%04x-%04x-%02x%02x-",
guid.data1, guid.data2, guid.data3, guid.data4[0],
guid.data4[1]);
grub_snprintf (guidbuf, sizeof (guidbuf), "%08x-%04x-%04x-%02x%02x-",
guid.data1, guid.data2, guid.data3, guid.data4[0],
guid.data4[1]);
for (j = 2; j < 8; j++)
grub_sprintf (guidbuf + grub_strlen (guidbuf), "%02x", guid.data4[j]);
grub_snprintf (guidbuf + grub_strlen (guidbuf),
sizeof (guidbuf) - grub_strlen (guidbuf),
"%02x", guid.data4[j]);
/* For some reason GUID has to be in uppercase. */
for (j = 0; guidbuf[j] ; j++)
if (guidbuf[j] >= 'a' && guidbuf[j] <= 'f')
@ -847,9 +850,11 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
{
struct grub_video_mode_info mode_info;
int ret;
char *tmp, *modevar;
char *tmp;
const char *modevar;
void *framebuffer;
grub_err_t err;
struct grub_video_bitmap *bitmap = NULL;
modevar = grub_env_get ("gfxpayload");
/* Consider only graphical 32-bit deep modes. */
@ -860,12 +865,9 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
32 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS);
else
{
tmp = grub_malloc (grub_strlen (modevar)
+ sizeof (DEFAULT_VIDEO_MODE) + 1);
tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
if (! tmp)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't allocate temporary storag");
grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
return grub_errno;
err = grub_video_set_mode (tmp,
GRUB_VIDEO_MODE_TYPE_PURE_TEXT
| GRUB_VIDEO_MODE_TYPE_DEPTH_MASK,
@ -876,31 +878,46 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
if (err)
return err;
ret = grub_video_get_info (&mode_info);
if (ret)
return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters");
if (grub_xnu_bitmap)
{
if (grub_xnu_bitmap_mode == GRUB_XNU_BITMAP_STRETCH)
err = grub_video_bitmap_create_scaled (&bitmap,
mode_info.width,
mode_info.height,
grub_xnu_bitmap,
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
else
bitmap = grub_xnu_bitmap;
}
if (bitmap)
{
int x, y;
x = mode_info.width - grub_xnu_bitmap->mode_info.width;
x = mode_info.width - bitmap->mode_info.width;
x /= 2;
y = mode_info.height - grub_xnu_bitmap->mode_info.height;
y = mode_info.height - bitmap->mode_info.height;
y /= 2;
err = grub_video_blit_bitmap (grub_xnu_bitmap,
err = grub_video_blit_bitmap (bitmap,
GRUB_VIDEO_BLIT_REPLACE,
x > 0 ? x : 0,
y > 0 ? y : 0,
x < 0 ? -x : 0,
y < 0 ? -y : 0,
min (grub_xnu_bitmap->mode_info.width,
min (bitmap->mode_info.width,
mode_info.width),
min (grub_xnu_bitmap->mode_info.height,
min (bitmap->mode_info.height,
mode_info.height));
if (err)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
grub_xnu_bitmap = 0;
}
err = GRUB_ERR_NONE;
}
if (err)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
bitmap = 0;
}
ret = grub_video_get_info_and_fini (&mode_info, &framebuffer);
@ -913,8 +930,8 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
params->lfb_line_len = mode_info.pitch;
params->lfb_base = PTR_TO_UINT32 (framebuffer);
params->lfb_mode = grub_xnu_bitmap
? GRUB_XNU_VIDEO_SPLASH : GRUB_XNU_VIDEO_TEXT_IN_VIDEO;
params->lfb_mode = bitmap ? GRUB_XNU_VIDEO_SPLASH
: GRUB_XNU_VIDEO_TEXT_IN_VIDEO;
return GRUB_ERR_NONE;
}

398
loader/mips/linux.c Normal file
View file

@ -0,0 +1,398 @@
/* linux.c - boot Linux */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2007,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/elf.h>
#include <grub/elfload.h>
#include <grub/loader.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/machine/loader.h>
#include <grub/command.h>
#include <grub/mips/relocator.h>
#include <grub/machine/memory.h>
#include <grub/i18n.h>
/* For frequencies. */
#include <grub/pci.h>
#include <grub/machine/time.h>
#define ELF32_LOADMASK (0x00000000UL)
#define ELF64_LOADMASK (0x0000000000000000ULL)
static grub_dl_t my_mod;
static int loaded;
static grub_size_t linux_size;
static grub_uint8_t *playground;
static grub_addr_t target_addr, entry_addr;
static int linux_argc;
static grub_off_t argv_off, envp_off;
static grub_off_t rd_addr_arg_off, rd_size_arg_off;
static int initrd_loaded = 0;
static grub_err_t
grub_linux_boot (void)
{
struct grub_relocator32_state state;
/* Boot the kernel. */
state.gpr[1] = entry_addr;
state.gpr[4] = linux_argc;
state.gpr[5] = target_addr + argv_off;
state.gpr[6] = target_addr + envp_off;
state.jumpreg = 1;
grub_relocator32_boot (playground, target_addr, state);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_linux_release_mem (void)
{
grub_relocator32_free (playground);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_linux_unload (void)
{
grub_err_t err;
err = grub_linux_release_mem ();
grub_dl_unref (my_mod);
loaded = 0;
return err;
}
static grub_err_t
grub_linux_load32 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size)
{
Elf32_Addr base;
int extraoff;
/* Linux's entry point incorrectly contains a virtual address. */
entry_addr = elf->ehdr.ehdr32.e_entry & ~ELF32_LOADMASK;
linux_size = grub_elf32_size (elf, &base);
if (linux_size == 0)
return grub_errno;
target_addr = base;
/* Pad it; the kernel scribbles over memory beyond its load address. */
linux_size += 0x100000;
linux_size = ALIGN_UP (base + linux_size, 4) - base;
extraoff = linux_size;
linux_size += extra_size;
playground = grub_relocator32_alloc (linux_size);
if (!playground)
return grub_errno;
*extra_mem = playground + extraoff;
/* Now load the segments into the area we claimed. */
auto grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load);
grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load)
{
if (phdr->p_type != PT_LOAD)
{
*do_load = 0;
return 0;
}
*do_load = 1;
/* Linux's program headers incorrectly contain virtual addresses.
* Translate those to physical, and offset to the area we claimed. */
*addr = (grub_addr_t) (phdr->p_paddr - base + playground);
return 0;
}
return grub_elf32_load (elf, offset_phdr, 0, 0);
}
static grub_err_t
grub_linux_load64 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size)
{
Elf64_Addr base;
int extraoff;
/* Linux's entry point incorrectly contains a virtual address. */
entry_addr = elf->ehdr.ehdr64.e_entry & ~ELF64_LOADMASK;
linux_size = grub_elf64_size (elf, &base);
if (linux_size == 0)
return grub_errno;
target_addr = base;
/* Pad it; the kernel scribbles over memory beyond its load address. */
linux_size += 0x100000;
linux_size = ALIGN_UP (base + linux_size, 4) - base;
extraoff = linux_size;
linux_size += extra_size;
playground = grub_relocator32_alloc (linux_size);
if (!playground)
return grub_errno;
*extra_mem = playground + extraoff;
/* Now load the segments into the area we claimed. */
auto grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load);
grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load)
{
if (phdr->p_type != PT_LOAD)
{
*do_load = 0;
return 0;
}
*do_load = 1;
/* Linux's program headers incorrectly contain virtual addresses.
* Translate those to physical, and offset to the area we claimed. */
*addr = (grub_addr_t) (phdr->p_paddr - base + playground);
return 0;
}
return grub_elf64_load (elf, offset_phdr, 0, 0);
}
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_elf_t elf = 0;
int i;
int size;
void *extra = NULL;
grub_uint32_t *linux_argv, *linux_envp;
char *linux_args, *linux_envs;
grub_err_t err;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
elf = grub_elf_open (argv[0]);
if (! elf)
return grub_errno;
if (elf->ehdr.ehdr32.e_type != ET_EXEC)
{
grub_elf_close (elf);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"this ELF file is not of the right type\n");
}
/* Release the previously used memory. */
grub_loader_unset ();
loaded = 0;
/* For arguments. */
linux_argc = argc;
/* Main arguments. */
size = (linux_argc) * sizeof (grub_uint32_t);
/* Initrd address and size. */
size += 2 * sizeof (grub_uint32_t);
/* NULL terminator. */
size += sizeof (grub_uint32_t);
/* First argument is always "a0". */
size += ALIGN_UP (sizeof ("a0"), 4);
/* Normal arguments. */
for (i = 1; i < argc; i++)
size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4);
/* rd arguments. */
size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
/* For the environment. */
size += sizeof (grub_uint32_t);
size += 4 * sizeof (grub_uint32_t);
size += ALIGN_UP (sizeof ("memsize=XXXXXXXXXXXXXXXXXXXX"), 4)
+ ALIGN_UP (sizeof ("highmemsize=XXXXXXXXXXXXXXXXXXXX"), 4)
+ ALIGN_UP (sizeof ("busclock=XXXXXXXXXX"), 4)
+ ALIGN_UP (sizeof ("cpuclock=XXXXXXXXXX"), 4);
if (grub_elf_is_elf32 (elf))
err = grub_linux_load32 (elf, &extra, size);
else
if (grub_elf_is_elf64 (elf))
err = grub_linux_load64 (elf, &extra, size);
else
err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "unknown ELF class");
grub_elf_close (elf);
if (err)
return err;
linux_argv = extra;
argv_off = (grub_uint8_t *) linux_argv - (grub_uint8_t *) playground;
extra = linux_argv + (linux_argc + 1 + 2);
linux_args = extra;
grub_memcpy (linux_args, "a0", sizeof ("a0"));
*linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground
+ target_addr;
linux_argv++;
linux_args += ALIGN_UP (sizeof ("a0"), 4);
for (i = 1; i < argc; i++)
{
grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1);
*linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground
+ target_addr;
linux_argv++;
linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4);
}
/* Reserve space for rd arguments. */
rd_addr_arg_off = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground;
linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
*linux_argv = 0;
linux_argv++;
rd_size_arg_off = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground;
linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
*linux_argv = 0;
linux_argv++;
*linux_argv = 0;
extra = linux_args;
linux_envp = extra;
envp_off = (grub_uint8_t *) linux_envp - (grub_uint8_t *) playground;
linux_envs = (char *) (linux_envp + 5);
grub_snprintf (linux_envs, sizeof ("memsize=XXXXXXXXXXXXXXXXXXXX"),
"memsize=%lld",
(unsigned long long) grub_mmap_get_lower () >> 20);
linux_envp[0] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground
+ target_addr;
linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4);
grub_snprintf (linux_envs, sizeof ("highmemsize=XXXXXXXXXXXXXXXXXXXX"),
"highmemsize=%lld",
(unsigned long long) grub_mmap_get_upper () >> 20);
linux_envp[1] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground
+ target_addr;
linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4);
grub_snprintf (linux_envs, sizeof ("busclock=XXXXXXXXXX"),
"busclock=%d", grub_arch_busclock);
linux_envp[2] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground
+ target_addr;
linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4);
grub_snprintf (linux_envs, sizeof ("cpuclock=XXXXXXXXXX"),
"cpuclock=%d", grub_arch_cpuclock);
linux_envp[3] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground
+ target_addr;
linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4);
linux_envp[4] = 0;
grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
initrd_loaded = 0;
loaded = 1;
grub_dl_ref (my_mod);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
grub_ssize_t size;
grub_size_t overhead;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no initrd specified");
if (!loaded)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load Linux first.");
if (initrd_loaded)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd can be loaded.");
file = grub_file_open (argv[0]);
if (! file)
return grub_errno;
size = grub_file_size (file);
overhead = ALIGN_UP (target_addr + linux_size + 0x10000, 0x10000)
- (target_addr + linux_size);
playground = grub_relocator32_realloc (playground,
linux_size + overhead + size);
if (!playground)
{
grub_file_close (file);
return grub_errno;
}
if (grub_file_read (file, playground + linux_size + overhead, size) != size)
{
grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
grub_file_close (file);
return grub_errno;
}
grub_snprintf ((char *) playground + rd_addr_arg_off,
sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%llx",
(unsigned long long) target_addr + linux_size + overhead);
((grub_uint32_t *) (playground + argv_off))[linux_argc]
= target_addr + rd_addr_arg_off;
linux_argc++;
grub_snprintf ((char *) playground + rd_size_arg_off,
sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%llx",
(unsigned long long) size);
((grub_uint32_t *) (playground + argv_off))[linux_argc]
= target_addr + rd_size_arg_off;
linux_argc++;
initrd_loaded = 1;
grub_file_close (file);
return GRUB_ERR_NONE;
}
static grub_command_t cmd_linux, cmd_initrd;
GRUB_MOD_INIT(linux)
{
cmd_linux = grub_register_command ("linux", grub_cmd_linux,
0, N_("Load Linux."));
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
0, N_("Load initrd."));
my_mod = mod;
}
GRUB_MOD_FINI(linux)
{
grub_unregister_command (cmd_linux);
grub_unregister_command (cmd_initrd);
}

356
loader/multiboot.c Normal file
View file

@ -0,0 +1,356 @@
/* multiboot.c - boot a multiboot OS image. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* FIXME: The following features from the Multiboot specification still
* need to be implemented:
* - VBE support
* - symbol table
* - drives table
* - ROM configuration table
* - APM table
*/
#include <grub/loader.h>
#include <grub/command.h>
#include <grub/machine/loader.h>
#include <grub/multiboot.h>
#include <grub/cpu/multiboot.h>
#include <grub/elf.h>
#include <grub/aout.h>
#include <grub/file.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/env.h>
#include <grub/cpu/relocator.h>
#include <grub/video.h>
#include <grub/memory.h>
#include <grub/i18n.h>
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/efi.h>
#endif
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
#define DEFAULT_VIDEO_MODE "text"
#else
#define DEFAULT_VIDEO_MODE "auto"
#endif
grub_size_t grub_multiboot_alloc_mbi;
char *grub_multiboot_payload_orig;
grub_addr_t grub_multiboot_payload_dest;
grub_size_t grub_multiboot_pure_size;
grub_uint32_t grub_multiboot_payload_eip;
static int accepts_video;
static int accepts_ega_text;
static int console_required;
static grub_dl_t my_mod;
/* Return the length of the Multiboot mmap that will be needed to allocate
our platform's map. */
grub_uint32_t
grub_get_multiboot_mmap_count (void)
{
grub_size_t count = 0;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)),
grub_uint64_t size __attribute__ ((unused)),
grub_uint32_t type __attribute__ ((unused)))
{
count++;
return 0;
}
grub_mmap_iterate (hook);
return count;
}
grub_err_t
grub_multiboot_set_video_mode (void)
{
grub_err_t err;
const char *modevar;
if (accepts_video || !GRUB_MACHINE_HAS_VGA_TEXT)
{
modevar = grub_env_get ("gfxpayload");
if (! modevar || *modevar == 0)
err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
else
{
char *tmp;
tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
if (! tmp)
return grub_errno;
err = grub_video_set_mode (tmp, 0, 0);
grub_free (tmp);
}
}
else
err = grub_video_set_mode ("text", 0, 0);
return err;
}
static grub_err_t
grub_multiboot_boot (void)
{
grub_size_t mbi_size;
grub_err_t err;
struct grub_relocator32_state state = MULTIBOOT_INITIAL_STATE;
state.MULTIBOOT_ENTRY_REGISTER = grub_multiboot_payload_eip;
mbi_size = grub_multiboot_get_mbi_size ();
if (grub_multiboot_alloc_mbi < mbi_size)
{
grub_multiboot_payload_orig
= grub_relocator32_realloc (grub_multiboot_payload_orig,
grub_multiboot_pure_size + mbi_size);
if (!grub_multiboot_payload_orig)
return grub_errno;
grub_multiboot_alloc_mbi = mbi_size;
}
state.MULTIBOOT_MBI_REGISTER = grub_multiboot_payload_dest
+ grub_multiboot_pure_size;
err = grub_multiboot_make_mbi (grub_multiboot_payload_orig,
grub_multiboot_payload_dest,
grub_multiboot_pure_size, mbi_size);
if (err)
return err;
#ifdef GRUB_MACHINE_EFI
if (! grub_efi_finish_boot_services ())
grub_fatal ("cannot exit boot services");
#endif
grub_relocator32_boot (grub_multiboot_payload_orig,
grub_multiboot_payload_dest,
state);
/* Not reached. */
return GRUB_ERR_NONE;
}
static grub_err_t
grub_multiboot_unload (void)
{
grub_multiboot_free_mbi ();
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_alloc_mbi = 0;
grub_multiboot_payload_orig = NULL;
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
#define MULTIBOOT_LOAD_ELF64
#include "multiboot_elfxx.c"
#undef MULTIBOOT_LOAD_ELF64
#define MULTIBOOT_LOAD_ELF32
#include "multiboot_elfxx.c"
#undef MULTIBOOT_LOAD_ELF32
/* Load ELF32 or ELF64. */
grub_err_t
grub_multiboot_load_elf (grub_file_t file, void *buffer)
{
if (grub_multiboot_is_elf32 (buffer))
return grub_multiboot_load_elf32 (file, buffer);
else if (grub_multiboot_is_elf64 (buffer))
return grub_multiboot_load_elf64 (file, buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
}
grub_err_t
grub_multiboot_set_console (int console_type, int accepted_consoles,
int width, int height, int depth,
int console_req)
{
console_required = console_req;
if (!(accepted_consoles
& (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
| (GRUB_MACHINE_HAS_VGA_TEXT ? GRUB_MULTIBOOT_CONSOLE_EGA_TEXT : 0))))
{
if (console_required)
return grub_error (GRUB_ERR_BAD_OS,
"OS requires a console but none is available");
grub_printf ("WARNING: no console will be available to OS");
accepts_video = 0;
accepts_ega_text = 0;
return GRUB_ERR_NONE;
}
if (console_type == GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER)
{
char *buf;
if (depth && width && height)
buf = grub_xasprintf ("%dx%dx%d,%dx%d,auto", width,
height, depth, width, height);
else if (width && height)
buf = grub_xasprintf ("%dx%d,auto", width, height);
else
buf = grub_strdup ("auto");
if (!buf)
return grub_errno;
grub_env_set ("gfxpayload", buf);
grub_free (buf);
}
else
grub_env_set ("gfxpayload", "text");
accepts_video = !!(accepted_consoles & GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER);
accepts_ega_text = !!(accepted_consoles & GRUB_MULTIBOOT_CONSOLE_EGA_TEXT);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
grub_err_t err;
grub_loader_unset ();
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
file = grub_gzfile_open (argv[0], 1);
if (! file)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
grub_dl_ref (my_mod);
/* Skip filename. */
grub_multiboot_init_mbi (argc - 1, argv + 1);
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_payload_orig = NULL;
err = grub_multiboot_load (file);
if (err)
goto fail;
grub_multiboot_set_bootdev ();
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
fail:
if (file)
grub_file_close (file);
if (grub_errno != GRUB_ERR_NONE)
{
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_free_mbi ();
grub_dl_unref (my_mod);
}
return grub_errno;
}
static grub_err_t
grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
grub_ssize_t size;
char *module = 0;
grub_err_t err;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
if (!grub_multiboot_payload_orig)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"you need to load the multiboot kernel first");
file = grub_gzfile_open (argv[0], 1);
if (! file)
return grub_errno;
size = grub_file_size (file);
module = grub_memalign (MULTIBOOT_MOD_ALIGN, size);
if (! module)
{
grub_file_close (file);
return grub_errno;
}
err = grub_multiboot_add_module ((grub_addr_t) module, size,
argc - 1, argv + 1);
if (err)
{
grub_file_close (file);
return err;
}
if (grub_file_read (file, module, size) != size)
{
grub_file_close (file);
return grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
}
grub_file_close (file);
return GRUB_ERR_NONE;;
}
static grub_command_t cmd_multiboot, cmd_module;
GRUB_MOD_INIT(multiboot)
{
cmd_multiboot =
#ifdef GRUB_USE_MULTIBOOT2
grub_register_command ("multiboot2", grub_cmd_multiboot,
0, N_("Load a multiboot 2 kernel."));
cmd_module =
grub_register_command ("module2", grub_cmd_module,
0, N_("Load a multiboot 2 module."));
#else
grub_register_command ("multiboot", grub_cmd_multiboot,
0, N_("Load a multiboot kernel."));
cmd_module =
grub_register_command ("module", grub_cmd_module,
0, N_("Load a multiboot module."));
#endif
my_mod = mod;
}
GRUB_MOD_FINI(multiboot)
{
grub_unregister_command (cmd_multiboot);
grub_unregister_command (cmd_module);
}

View file

@ -18,13 +18,13 @@
#if defined(MULTIBOOT_LOAD_ELF32)
# define XX 32
# define E_MACHINE EM_386
# define E_MACHINE MULTIBOOT_ELF32_MACHINE
# define ELFCLASSXX ELFCLASS32
# define Elf_Ehdr Elf32_Ehdr
# define Elf_Phdr Elf32_Phdr
#elif defined(MULTIBOOT_LOAD_ELF64)
# define XX 64
# define E_MACHINE EM_X86_64
# define E_MACHINE MULTIBOOT_ELF64_MACHINE
# define ELFCLASSXX ELFCLASS64
# define Elf_Ehdr Elf64_Ehdr
# define Elf_Phdr Elf64_Phdr
@ -53,6 +53,7 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
char *phdr_base;
int lowest_segment = -1, highest_segment = -1;
int i;
grub_size_t code_size;
if (ehdr->e_ident[EI_CLASS] != ELFCLASSXX)
return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
@ -73,7 +74,11 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH)
return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
#ifdef MULTIBOOT_LOAD_ELF64
#if defined (MULTIBOOT_LOAD_ELF64) && defined (__mips)
/* We still in 32-bit mode. */
if (ehdr->e_entry < 0xffffffff80000000ULL)
return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64");
#else
/* We still in 32-bit mode. */
if (ehdr->e_entry > 0xffffffff)
return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64");
@ -102,9 +107,9 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
grub_multiboot_pure_size += code_size;
alloc_mbi = grub_multiboot_get_mbi_size ();
grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi + 65536);
= grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
if (!grub_multiboot_payload_orig)
return grub_errno;

View file

@ -1,150 +0,0 @@
/* multiboot_loader.c - boot multiboot kernel image */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/multiboot.h>
#include <grub/elf.h>
#include <grub/file.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/command.h>
#include <grub/i18n.h>
grub_dl_t my_mod;
static int
find_multi_boot1_header (grub_file_t file)
{
struct multiboot_header *header;
char buffer[MULTIBOOT_SEARCH];
int found_status = 0;
grub_ssize_t len;
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
return found_status;
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + 4))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
{
found_status = 1;
break;
}
}
return found_status;
}
static grub_err_t
grub_cmd_multiboot_loader (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
int header_multi_ver_found = 0;
grub_dl_ref (my_mod);
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
goto fail;
}
file = grub_gzfile_open (argv[0], 1);
if (! file)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
goto fail;
}
/* find which header is in the file */
if (find_multi_boot1_header (file))
header_multi_ver_found = 1;
else
{
grub_error (GRUB_ERR_BAD_OS, "multiboot header not found");
goto fail;
}
/* close file before calling functions */
if (file)
grub_file_close (file);
/* Launch multi boot with header */
grub_dprintf ("multiboot_loader",
"Launching multiboot 1 grub_multiboot() function\n");
grub_multiboot (argc, argv);
return grub_errno;
fail:
if (file)
grub_file_close (file);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_cmd_module_loader (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_dprintf("multiboot_loader",
"Launching multiboot 1 grub_module() function\n");
grub_module (argc, argv);
return grub_errno;
}
static grub_command_t cmd_multiboot, cmd_module;
GRUB_MOD_INIT(multiboot)
{
cmd_multiboot =
#ifdef GRUB_USE_MULTIBOOT2
grub_register_command ("multiboot2", grub_cmd_multiboot_loader,
0, N_("Load a multiboot 2 kernel."));
#else
grub_register_command ("multiboot", grub_cmd_multiboot_loader,
0, N_("Load a multiboot kernel."));
#endif
cmd_module =
grub_register_command ("module", grub_cmd_module_loader,
0, N_("Load a multiboot module."));
my_mod = mod;
}
GRUB_MOD_FINI(multiboot)
{
grub_unregister_command (cmd_multiboot);
grub_unregister_command (cmd_module);
}

701
loader/multiboot_mbi2.c Normal file
View file

@ -0,0 +1,701 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/machine/memory.h>
#include <grub/memory.h>
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/biosnum.h>
#endif
#include <grub/multiboot.h>
#include <grub/cpu/multiboot.h>
#include <grub/cpu/relocator.h>
#include <grub/disk.h>
#include <grub/device.h>
#include <grub/partition.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/video.h>
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU)
#include <grub/i386/pc/vbe.h>
#define HAS_VGA_TEXT 1
#else
#define HAS_VGA_TEXT 0
#endif
struct module
{
struct module *next;
grub_addr_t start;
grub_size_t size;
char *cmdline;
int cmdline_size;
};
struct module *modules, *modules_last;
static grub_size_t cmdline_size;
static grub_size_t total_modcmd;
static unsigned modcnt;
static char *cmdline = NULL;
static int bootdev_set;
static grub_uint32_t biosdev, slice, part;
grub_err_t
grub_multiboot_load (grub_file_t file)
{
char *buffer;
grub_ssize_t len;
struct multiboot_header *header;
grub_err_t err;
struct multiboot_header_tag *tag;
struct multiboot_header_tag_address *addr_tag = NULL;
int entry_specified = 0;
grub_addr_t entry = 0;
grub_uint32_t console_required = 0;
struct multiboot_header_tag_framebuffer *fbtag = NULL;
int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
buffer = grub_malloc (MULTIBOOT_SEARCH);
if (!buffer)
return grub_errno;
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
{
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_OS, "file too small");
}
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->architecture
+ header->header_length + header->checksum)
&& header->architecture == MULTIBOOT_ARCHITECTURE_CURRENT)
break;
}
if (header == 0)
{
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
}
for (tag = (struct multiboot_header_tag *) (header + 1);
tag->type != MULTIBOOT_TAG_TYPE_END;
tag = (struct multiboot_header_tag *) ((char *) tag + tag->size))
switch (tag->type)
{
case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
{
unsigned i;
struct multiboot_header_tag_information_request *request_tag
= (struct multiboot_header_tag_information_request *) tag;
if (request_tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
break;
for (i = 0; i < (request_tag->size - sizeof (request_tag))
/ sizeof (request_tag->requests[0]); i++)
switch (request_tag->requests[i])
{
case MULTIBOOT_TAG_TYPE_END:
case MULTIBOOT_TAG_TYPE_CMDLINE:
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
case MULTIBOOT_TAG_TYPE_MODULE:
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
case MULTIBOOT_TAG_TYPE_BOOTDEV:
case MULTIBOOT_TAG_TYPE_MMAP:
case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
break;
case MULTIBOOT_TAG_TYPE_VBE:
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
case MULTIBOOT_TAG_TYPE_APM:
default:
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported information tag: 0x%x",
request_tag->requests[i]);
}
break;
}
case MULTIBOOT_HEADER_TAG_ADDRESS:
addr_tag = (struct multiboot_header_tag_address *) tag;
break;
case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
entry_specified = 1;
entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
break;
case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
& MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
accepted_consoles &= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
if (((struct multiboot_header_tag_console_flags *) tag)->console_flags
& MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED)
console_required = 1;
break;
case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
fbtag = (struct multiboot_header_tag_framebuffer *) tag;
accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
break;
/* GRUB always page-aligns modules. */
case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
break;
default:
if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
{
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported tag: 0x%x", tag->type);
}
break;
}
if (addr_tag && !entry_specified)
{
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"load address tag without entry address tag");
}
if (addr_tag)
{
int offset = ((char *) header - buffer -
(addr_tag->header_addr - addr_tag->load_addr));
int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset :
addr_tag->load_end_addr - addr_tag->load_addr);
grub_size_t code_size;
if (addr_tag->bss_end_addr)
code_size = (addr_tag->bss_end_addr - addr_tag->load_addr);
else
code_size = load_size;
grub_multiboot_payload_dest = addr_tag->load_addr;
grub_multiboot_pure_size += code_size;
/* Allocate a bit more to avoid relocations in most cases. */
grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
if (! grub_multiboot_payload_orig)
{
grub_free (buffer);
return grub_errno;
}
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
{
grub_free (buffer);
return grub_errno;
}
grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
if (grub_errno)
{
grub_free (buffer);
return grub_errno;
}
if (addr_tag->bss_end_addr)
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
addr_tag->bss_end_addr - addr_tag->load_addr - load_size);
}
else
{
err = grub_multiboot_load_elf (file, buffer);
if (err)
{
grub_free (buffer);
return err;
}
}
if (entry_specified)
grub_multiboot_payload_eip = entry;
if (fbtag)
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
accepted_consoles,
fbtag->width, fbtag->height,
fbtag->depth, console_required);
else
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
accepted_consoles,
0, 0, 0, console_required);
return err;
}
grub_size_t
grub_multiboot_get_mbi_size (void)
{
return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag)
+ (sizeof (struct multiboot_tag_string)
+ ALIGN_UP (cmdline_size, MULTIBOOT_TAG_ALIGN))
+ (sizeof (struct multiboot_tag_string)
+ ALIGN_UP (sizeof (PACKAGE_STRING), MULTIBOOT_TAG_ALIGN))
+ (modcnt * sizeof (struct multiboot_tag_module) + total_modcmd)
+ sizeof (struct multiboot_tag_basic_meminfo)
+ ALIGN_UP (sizeof (struct multiboot_tag_bootdev), MULTIBOOT_TAG_ALIGN)
+ (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count ()
* sizeof (struct multiboot_mmap_entry))
+ sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1;
}
/* Fill previously allocated Multiboot mmap. */
static void
grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag)
{
struct multiboot_mmap_entry *mmap_entry = tag->entries;
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)
{
mmap_entry->addr = addr;
mmap_entry->len = size;
switch (type)
{
case GRUB_MACHINE_MEMORY_AVAILABLE:
mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE;
break;
#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE
case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE:
mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
break;
#endif
#ifdef GRUB_MACHINE_MEMORY_NVS
case GRUB_MACHINE_MEMORY_NVS:
mmap_entry->type = MULTIBOOT_MEMORY_NVS;
break;
#endif
default:
mmap_entry->type = MULTIBOOT_MEMORY_RESERVED;
break;
}
mmap_entry++;
return 0;
}
tag->type = MULTIBOOT_TAG_TYPE_MMAP;
tag->size = sizeof (struct multiboot_tag_mmap)
+ sizeof (struct multiboot_mmap_entry) * grub_get_multiboot_mmap_count ();
tag->entry_size = sizeof (struct multiboot_mmap_entry);
tag->entry_version = 0;
grub_mmap_iterate (hook);
}
static grub_err_t
retrieve_video_parameters (grub_uint8_t **ptrorig)
{
grub_err_t err;
struct grub_video_mode_info mode_info;
void *framebuffer;
grub_video_driver_id_t driv_id;
struct grub_video_palette_data palette[256];
struct multiboot_tag_framebuffer *tag
= (struct multiboot_tag_framebuffer *) *ptrorig;
err = grub_multiboot_set_video_mode ();
if (err)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
driv_id = grub_video_get_driver_id ();
#if HAS_VGA_TEXT
if (driv_id == GRUB_VIDEO_DRIVER_NONE)
{
struct grub_vbe_mode_info_block vbe_mode_info;
grub_uint32_t vbe_mode;
#if defined (GRUB_MACHINE_PCBIOS)
{
grub_vbe_status_t status;
void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
status = grub_vbe_bios_get_mode (scratch);
vbe_mode = *(grub_uint32_t *) scratch;
if (status != GRUB_VBE_STATUS_OK)
return GRUB_ERR_NONE;
}
#else
vbe_mode = 3;
#endif
/* get_mode_info isn't available for mode 3. */
if (vbe_mode == 3)
{
grub_memset (&vbe_mode_info, 0,
sizeof (struct grub_vbe_mode_info_block));
vbe_mode_info.memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
vbe_mode_info.x_resolution = 80;
vbe_mode_info.y_resolution = 25;
}
#if defined (GRUB_MACHINE_PCBIOS)
else
{
grub_vbe_status_t status;
void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
if (status != GRUB_VBE_STATUS_OK)
return GRUB_ERR_NONE;
grub_memcpy (&vbe_mode_info, scratch,
sizeof (struct grub_vbe_mode_info_block));
}
#endif
if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
{
tag = (struct multiboot_tag_framebuffer *) *ptrorig;
tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
tag->common.size = 0;
tag->common.framebuffer_addr = 0xb8000;
tag->common.framebuffer_pitch = 2 * vbe_mode_info.x_resolution;
tag->common.framebuffer_width = vbe_mode_info.x_resolution;
tag->common.framebuffer_height = vbe_mode_info.y_resolution;
tag->common.framebuffer_bpp = 16;
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
tag->common.size = sizeof (tag->common);
tag->common.reserved = 0;
*ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
}
return GRUB_ERR_NONE;
}
#else
if (driv_id == GRUB_VIDEO_DRIVER_NONE)
return GRUB_ERR_NONE;
#endif
err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
if (err)
return err;
tag = (struct multiboot_tag_framebuffer *) *ptrorig;
tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
tag->common.size = 0;
tag->common.framebuffer_addr = (grub_addr_t) framebuffer;
tag->common.framebuffer_pitch = mode_info.pitch;
tag->common.framebuffer_width = mode_info.width;
tag->common.framebuffer_height = mode_info.height;
tag->common.framebuffer_bpp = mode_info.bpp;
tag->common.reserved = 0;
if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
{
unsigned i;
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
tag->framebuffer_palette_num_colors = mode_info.number_of_colors;
if (tag->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
tag->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
tag->common.size = sizeof (struct multiboot_tag_framebuffer_common)
+ sizeof (multiboot_uint16_t) + tag->framebuffer_palette_num_colors
* sizeof (struct multiboot_color);
for (i = 0; i < tag->framebuffer_palette_num_colors; i++)
{
tag->framebuffer_palette[i].red = palette[i].r;
tag->framebuffer_palette[i].green = palette[i].g;
tag->framebuffer_palette[i].blue = palette[i].b;
}
}
else
{
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
tag->framebuffer_red_field_position = mode_info.green_field_pos;
tag->framebuffer_red_mask_size = mode_info.green_mask_size;
tag->framebuffer_green_field_position = mode_info.green_field_pos;
tag->framebuffer_green_mask_size = mode_info.green_mask_size;
tag->framebuffer_blue_field_position = mode_info.blue_field_pos;
tag->framebuffer_blue_mask_size = mode_info.blue_mask_size;
tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6;
}
*ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
return GRUB_ERR_NONE;
}
grub_err_t
grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
grub_size_t bufsize)
{
grub_uint8_t *ptrorig;
grub_uint8_t *mbistart = (grub_uint8_t *) orig + buf_off
+ (ALIGN_UP (dest + buf_off, MULTIBOOT_TAG_ALIGN) - (dest + buf_off));
grub_err_t err;
if (bufsize < grub_multiboot_get_mbi_size ())
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small");
ptrorig = mbistart + 2 * sizeof (grub_uint32_t);
{
struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
tag->size = sizeof (struct multiboot_tag_string) + cmdline_size;
grub_memcpy (tag->string, cmdline, cmdline_size);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME;
tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING);
grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING));
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
unsigned i;
struct module *cur;
for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
{
struct multiboot_tag_module *tag
= (struct multiboot_tag_module *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_MODULE;
tag->size = sizeof (struct multiboot_tag_module) + cur->cmdline_size;
tag->mod_start = cur->start;
tag->mod_end = tag->mod_start + cur->size;
grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
}
{
struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
grub_fill_multiboot_mmap (tag);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
struct multiboot_tag_basic_meminfo *tag
= (struct multiboot_tag_basic_meminfo *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
tag->size = sizeof (struct multiboot_tag_basic_meminfo);
/* Convert from bytes to kilobytes. */
tag->mem_lower = grub_mmap_get_lower () / 1024;
tag->mem_upper = grub_mmap_get_upper () / 1024;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
if (bootdev_set)
{
struct multiboot_tag_bootdev *tag
= (struct multiboot_tag_bootdev *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_BOOTDEV;
tag->size = sizeof (struct multiboot_tag_bootdev);
tag->biosdev = biosdev;
tag->slice = slice;
tag->part = part;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
err = retrieve_video_parameters (&ptrorig);
if (err)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
}
{
struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_END;
tag->size = sizeof (struct multiboot_tag);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
((grub_uint32_t *) mbistart)[0] = ptrorig - mbistart;
((grub_uint32_t *) mbistart)[1] = 0;
return GRUB_ERR_NONE;
}
void
grub_multiboot_free_mbi (void)
{
struct module *cur, *next;
cmdline_size = 0;
total_modcmd = 0;
modcnt = 0;
grub_free (cmdline);
cmdline = NULL;
bootdev_set = 0;
for (cur = modules; cur; cur = next)
{
next = cur->next;
grub_free (cur->cmdline);
grub_free (cur);
}
modules = NULL;
modules_last = NULL;
}
grub_err_t
grub_multiboot_init_mbi (int argc, char *argv[])
{
grub_ssize_t len = 0;
char *p;
int i;
grub_multiboot_free_mbi ();
for (i = 0; i < argc; i++)
len += grub_strlen (argv[i]) + 1;
if (len == 0)
len = 1;
cmdline = p = grub_malloc (len);
if (! cmdline)
return grub_errno;
cmdline_size = len;
for (i = 0; i < argc; i++)
{
p = grub_stpcpy (p, argv[i]);
*(p++) = ' ';
}
/* Remove the space after the last word. */
if (p != cmdline)
p--;
*p = '\0';
return GRUB_ERR_NONE;
}
grub_err_t
grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
int argc, char *argv[])
{
struct module *newmod;
char *p;
grub_ssize_t len = 0;
int i;
newmod = grub_malloc (sizeof (*newmod));
if (!newmod)
return grub_errno;
newmod->start = start;
newmod->size = size;
for (i = 0; i < argc; i++)
len += grub_strlen (argv[i]) + 1;
if (len == 0)
len = 1;
newmod->cmdline = p = grub_malloc (len);
if (! newmod->cmdline)
{
grub_free (newmod);
return grub_errno;
}
newmod->cmdline_size = len;
total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN);
for (i = 0; i < argc; i++)
{
p = grub_stpcpy (p, argv[i]);
*(p++) = ' ';
}
/* Remove the space after the last word. */
if (p != newmod->cmdline)
p--;
*p = '\0';
if (modules_last)
modules_last->next = newmod;
else
{
modules = newmod;
modules_last->next = NULL;
}
modules_last = newmod;
modcnt++;
return GRUB_ERR_NONE;
}
void
grub_multiboot_set_bootdev (void)
{
grub_device_t dev;
slice = ~0;
part = ~0;
#ifdef GRUB_MACHINE_PCBIOS
biosdev = grub_get_root_biosnumber ();
#else
biosdev = 0xffffffff;
#endif
if (biosdev == 0xffffffff)
return;
dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition)
{
if (dev->disk->partition->parent)
{
part = dev->disk->partition->number;
slice = dev->disk->partition->parent->number;
}
else
slice = dev->disk->partition->number;
}
if (dev)
grub_device_close (dev);
bootdev_set = 1;
}

View file

@ -111,7 +111,7 @@ grub_linux_load32 (grub_elf_t elf)
if (entry == 0)
entry = 0x01400000;
linux_size = grub_elf32_size (elf);
linux_size = grub_elf32_size (elf, 0);
if (linux_size == 0)
return grub_errno;
/* Pad it; the kernel scribbles over memory beyond its load address. */
@ -161,7 +161,7 @@ grub_linux_load64 (grub_elf_t elf)
if (entry == 0)
entry = 0x01400000;
linux_size = grub_elf64_size (elf);
linux_size = grub_elf64_size (elf, 0);
if (linux_size == 0)
return grub_errno;
/* Pad it; the kernel scribbles over memory beyond its load address. */

View file

@ -58,9 +58,6 @@ static grub_size_t linux_size;
static char *linux_args;
typedef void (*kernel_entry_t) (unsigned long, unsigned long,
unsigned long, unsigned long, int (void *));
struct linux_bootstr_info {
int len, valid;
char buf[];
@ -92,7 +89,6 @@ static grub_err_t
grub_linux_boot (void)
{
struct linux_bootstr_info *bp;
kernel_entry_t linuxmain;
struct linux_hdrs *hp;
grub_addr_t addr;
@ -141,8 +137,17 @@ grub_linux_boot (void)
grub_dprintf ("loader", "Jumping to Linux...\n");
/* Boot the kernel. */
linuxmain = (kernel_entry_t) linux_addr;
linuxmain (0, 0, 0, 0, grub_ieee1275_entry_fn);
asm volatile ("sethi %hi(grub_ieee1275_entry_fn), %o1\n"
"ldx [%o1 + %lo(grub_ieee1275_entry_fn)], %o4\n"
"sethi %hi(grub_ieee1275_original_stack), %o1\n"
"ldx [%o1 + %lo(grub_ieee1275_original_stack)], %o6\n"
"sethi %hi(linux_addr), %o1\n"
"ldx [%o1 + %lo(linux_addr)], %o5\n"
"mov %g0, %o0\n"
"mov %g0, %o2\n"
"mov %g0, %o3\n"
"jmp %o5\n"
"mov %g0, %o1\n");
return GRUB_ERR_NONE;
}
@ -173,12 +178,6 @@ grub_linux_unload (void)
#define FOUR_MB (4 * 1024 * 1024)
static grub_addr_t
align_addr(grub_addr_t val, grub_addr_t align)
{
return (val + (align - 1)) & ~(align - 1);
}
static grub_addr_t
alloc_phys (grub_addr_t size)
{
@ -192,39 +191,39 @@ alloc_phys (grub_addr_t size)
if (type != 1)
return 0;
addr = align_addr (addr, FOUR_MB);
if (addr >= end)
addr = ALIGN_UP (addr, FOUR_MB);
if (addr + size >= end)
return 0;
if (addr >= grub_phys_start && addr < grub_phys_end)
{
addr = align_addr (grub_phys_end, FOUR_MB);
if (addr >= end)
addr = ALIGN_UP (grub_phys_end, FOUR_MB);
if (addr + size >= end)
return 0;
}
if ((addr + size) >= grub_phys_start
&& (addr + size) < grub_phys_end)
{
addr = align_addr (grub_phys_end, FOUR_MB);
if (addr >= end)
addr = ALIGN_UP (grub_phys_end, FOUR_MB);
if (addr + size >= end)
return 0;
}
if (loaded)
{
grub_addr_t linux_end = align_addr (linux_paddr + linux_size, FOUR_MB);
grub_addr_t linux_end = ALIGN_UP (linux_paddr + linux_size, FOUR_MB);
if (addr >= linux_paddr && addr < linux_end)
{
addr = linux_end;
if (addr >= end)
if (addr + size >= end)
return 0;
}
if ((addr + size) >= linux_paddr
&& (addr + size) < linux_end)
{
addr = linux_end;
if (addr >= end)
if (addr + size >= end)
return 0;
}
}
@ -247,7 +246,7 @@ grub_linux_load64 (grub_elf_t elf)
linux_entry = elf->ehdr.ehdr64.e_entry;
linux_addr = 0x40004000;
off = 0x4000;
linux_size = grub_elf64_size (elf);
linux_size = grub_elf64_size (elf, 0);
if (linux_size == 0)
return grub_errno;
@ -258,8 +257,8 @@ grub_linux_load64 (grub_elf_t elf)
if (paddr == (grub_addr_t) -1)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't allocate physical memory");
ret = grub_ieee1275_map_physical (paddr, linux_addr - off,
linux_size + off, IEEE1275_MAP_DEFAULT);
ret = grub_ieee1275_map (paddr, linux_addr - off,
linux_size + off, IEEE1275_MAP_DEFAULT);
if (ret)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't map physical memory");
@ -409,7 +408,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
"couldn't allocate physical memory");
goto fail;
}
ret = grub_ieee1275_map_physical (paddr, addr, size, IEEE1275_MAP_DEFAULT);
ret = grub_ieee1275_map (paddr, addr, size, IEEE1275_MAP_DEFAULT);
if (ret)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY,

View file

@ -31,6 +31,7 @@
#include <grub/gzio.h>
#include <grub/command.h>
#include <grub/misc.h>
#include <grub/extcmd.h>
#include <grub/env.h>
#include <grub/i18n.h>
@ -569,10 +570,9 @@ grub_xnu_register_memory (char *prefix, int *suffix,
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register memory");
if (suffix)
{
driverkey->name = grub_malloc (grub_strlen (prefix) + 10);
driverkey->name = grub_xasprintf ("%s%d", prefix, (*suffix)++);
if (!driverkey->name)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register memory");
grub_sprintf (driverkey->name, "%s%d", prefix, (*suffix)++);
}
else
driverkey->name = grub_strdup (prefix);
@ -1355,23 +1355,42 @@ grub_xnu_fill_devicetree (void)
}
struct grub_video_bitmap *grub_xnu_bitmap = 0;
grub_xnu_bitmap_mode_t grub_xnu_bitmap_mode;
/* Option array indices. */
#define XNU_SPLASH_CMD_ARGINDEX_MODE 0
static const struct grub_arg_option xnu_splash_cmd_options[] =
{
{"mode", 'm', 0, "Background image mode.", "stretch|normal",
ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
static grub_err_t
grub_cmd_xnu_splash (grub_command_t cmd __attribute__ ((unused)),
grub_cmd_xnu_splash (grub_extcmd_t cmd,
int argc, char *args[])
{
grub_err_t err;
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
if (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].set &&
grub_strcmp (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].arg,
"stretch") == 0)
grub_xnu_bitmap_mode = GRUB_XNU_BITMAP_STRETCH;
else
grub_xnu_bitmap_mode = GRUB_XNU_BITMAP_CENTER;
err = grub_video_bitmap_load (&grub_xnu_bitmap, args[0]);
if (err)
grub_xnu_bitmap = 0;
return err;
}
#ifndef GRUB_UTIL
#ifndef GRUB_MACHINE_EMU
static grub_err_t
grub_cmd_xnu_resume (grub_command_t cmd __attribute__ ((unused)),
int argc, char *args[])
@ -1400,7 +1419,8 @@ grub_xnu_unlock ()
}
static grub_command_t cmd_kernel64, cmd_kernel, cmd_mkext, cmd_kext;
static grub_command_t cmd_kextdir, cmd_ramdisk, cmd_resume, cmd_splash;
static grub_command_t cmd_kextdir, cmd_ramdisk, cmd_resume;
static grub_extcmd_t cmd_splash;
GRUB_MOD_INIT(xnu)
{
@ -1416,12 +1436,15 @@ GRUB_MOD_INIT(xnu)
N_("DIRECTORY [OSBundleRequired]"),
N_("Load XNU extension directory."));
cmd_ramdisk = grub_register_command ("xnu_ramdisk", grub_cmd_xnu_ramdisk, 0,
N_("Load XNU ramdisk. "
"It will be seen as md0."));
cmd_splash = grub_register_command ("xnu_splash", grub_cmd_xnu_splash, 0,
N_("Load a splash image for XNU."));
"Load XNU ramdisk. "
"It will be seen as md0.");
cmd_splash = grub_register_extcmd ("xnu_splash",
grub_cmd_xnu_splash,
GRUB_COMMAND_FLAG_BOTH, 0,
N_("Load a splash image for XNU."),
xnu_splash_cmd_options);
#ifndef GRUB_UTIL
#ifndef GRUB_MACHINE_EMU
cmd_resume = grub_register_command ("xnu_resume", grub_cmd_xnu_resume,
0, N_("Load XNU hibernate image."));
#endif
@ -1433,7 +1456,7 @@ GRUB_MOD_INIT(xnu)
GRUB_MOD_FINI(xnu)
{
#ifndef GRUB_UTIL
#ifndef GRUB_MACHINE_EMU
grub_unregister_command (cmd_resume);
#endif
grub_unregister_command (cmd_mkext);
@ -1441,8 +1464,8 @@ GRUB_MOD_FINI(xnu)
grub_unregister_command (cmd_kextdir);
grub_unregister_command (cmd_ramdisk);
grub_unregister_command (cmd_kernel);
grub_unregister_extcmd (cmd_splash);
grub_unregister_command (cmd_kernel64);
grub_unregister_command (cmd_splash);
grub_cpu_xnu_fini ();
}