merge abstractmbi into newreloc

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-01-11 11:29:52 +01:00
commit 5c8e58b0cb
9 changed files with 459 additions and 270 deletions

View file

@ -1,3 +1,21 @@
2010-01-10 Robert Millan <rmh.grub@aybabtu.com>
* loader/i386/ieee1275/linux.c (grub_linux_boot): Rework video position
initialization with similar approach as with other Linux loaders.
2010-01-10 Robert Millan <rmh.grub@aybabtu.com>
Fix i386-ieee1275 build.
* loader/i386/ieee1275/linux.c (grub_linux_boot): Use grub_term_width()
and grub_term_height() for video_{width,height} initialization.
2010-01-10 Robert Millan <rmh.grub@aybabtu.com>
Fix grub-emu build.
* conf/any-emu.rmk (grub_emu_SOURCES): Remove `kern/reader.c'.
2010-01-07 Vladimir Serbinenko <phcoder@gmail.com>
2010-01-09 Robert Millan <rmh.grub@aybabtu.com>

25
ChangeLog.abstractmbi Normal file
View file

@ -0,0 +1,25 @@
2010-01-10 Vladimir Serbinenko <phcoder@gmail.com>
* conf/i386-coreboot.rmk (multiboot_mod_SOURCES):
Add loader/i386/multiboot_mbi.c.
(multiboot2_mod_SOURCES): Likewise.
* conf/i386-pc.rmk (multiboot_mod_SOURCES): Likewise.
(multiboot2_mod_SOURCES): Likewise.
* include/grub/multiboot.h (grub_multiboot_get_mbi_size): New proto.
(grub_multiboot_make_mbi): Likewise.
(grub_multiboot_free_mbi): Likewise.
(grub_multiboot_init_mbi): Likewise.
(grub_multiboot_add_module): Likewise.
(grub_multiboot_set_bootdev): Likewise.
* loader/i386/multiboot.c (mbi): Removed.
(mbi_dest): Likewise.
(alloc_mbi): New variable.
(grub_multiboot_payload_size): Removed. All users updated.
(grub_multiboot_pure_size): New variable.
(grub_multiboot_boot): Use grub_multiboot_make_mbi.
(grub_multiboot_unload): Use grub_multiboot_free_mbi.
(grub_get_multiboot_mmap_len): Moved to loader/i386/multiboot_mbi.c.
(grub_fill_multiboot_mmap): Likewise.
(grub_multiboot_get_bootdev): Likewise.
(grub_multiboot): Use multiboot_mbi functions.
* loader/i386/multiboot_mbi.c: New file.

View file

@ -23,7 +23,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \
kern/err.c kern/list.c kern/handler.c \
kern/command.c kern/corecmd.c commands/extcmd.c kern/file.c \
kern/fs.c commands/boot.c kern/main.c kern/misc.c kern/parser.c \
kern/partition.c kern/reader.c kern/term.c \
kern/partition.c kern/term.c \
kern/rescue_reader.c kern/rescue_parser.c \
lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c \
normal/handler.c normal/auth.c lib/crypto.c normal/autofs.c \

View file

@ -142,6 +142,7 @@ serial_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += multiboot.mod
multiboot_mod_SOURCES = loader/i386/multiboot.c \
loader/i386/multiboot_mbi.c \
loader/multiboot_loader.c
multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
@ -149,7 +150,8 @@ multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS)
pkglib_MODULES += multiboot2.mod
multiboot2_mod_SOURCES = loader/i386/multiboot.c \
loader/multiboot_loader.c
loader/multiboot_loader.c \
loader/i386/multiboot_mbi.c
multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2
multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS)
multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS)

View file

@ -204,6 +204,7 @@ serial_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For multiboot.mod.
pkglib_MODULES += multiboot.mod
multiboot_mod_SOURCES = loader/i386/multiboot.c \
loader/i386/multiboot_mbi.c \
loader/multiboot_loader.c
multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
@ -211,6 +212,7 @@ multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS)
pkglib_MODULES += multiboot2.mod
multiboot2_mod_SOURCES = loader/i386/multiboot.c \
loader/i386/multiboot_mbi.c \
loader/multiboot_loader.c
multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2
multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS)

View file

@ -29,7 +29,18 @@
#include <multiboot.h>
#endif
#include <grub/types.h>
#include <grub/err.h>
void grub_multiboot (int argc, char *argv[]);
void grub_module (int argc, char *argv[]);
grub_err_t grub_multiboot_make_mbi (grub_uint32_t *target);
void grub_multiboot_free_mbi (void);
grub_err_t grub_multiboot_init_mbi (int argc, char *argv[]);
grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
int argc, char *argv[]);
void grub_multiboot_set_bootdev (void);
#endif /* ! GRUB_MULTIBOOT_HEADER */

View file

@ -1,7 +1,7 @@
/* linux.c - boot Linux zImage or bzImage */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
* 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
@ -110,8 +110,29 @@ grub_linux_boot (void)
params->cl_magic = GRUB_LINUX_CL_MAGIC;
params->cl_offset = GRUB_OFW_LINUX_CL_OFFSET;
params->video_width = (grub_getwh () >> 8);
params->video_height = (grub_getwh () & 0xff);
{
grub_term_output_t term;
int found = 0;
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (term->name, "ofconsole") == 0)
{
grub_uint16_t pos = grub_term_getxy (term);
params->video_cursor_x = pos >> 8;
params->video_cursor_y = pos & 0xff;
params->video_width = grub_term_width (term);
params->video_height = grub_term_height (term);
found = 1;
break;
}
if (!found)
{
params->video_cursor_x = 0;
params->video_cursor_y = 0;
params->video_width = 80;
params->video_height = 25;
}
}
params->font_size = 16;
params->ofw_signature = GRUB_LINUX_OFW_SIGNATURE;

View file

@ -45,29 +45,20 @@
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/env.h>
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/biosnum.h>
#include <grub/disk.h>
#include <grub/device.h>
#include <grub/partition.h>
#endif
#include <grub/i386/relocator.h>
extern grub_dl_t my_mod;
static struct multiboot_info *mbi, *mbi_dest;
struct grub_relocator *grub_multiboot_relocator = NULL;
static grub_size_t code_size;
grub_uint32_t grub_multiboot_payload_eip;
static grub_err_t
grub_multiboot_boot (void)
{
grub_err_t err;
struct grub_relocator32_state state =
{
.eax = MULTIBOOT_BOOTLOADER_MAGIC,
.ebx = PTR_TO_UINT32 (mbi_dest),
.ecx = 0,
.edx = 0,
.eip = grub_multiboot_payload_eip,
@ -76,6 +67,10 @@ grub_multiboot_boot (void)
.esp = 0x7ff00
};
err = grub_multiboot_make_mbi (&state.ebx);
if (err)
return err;
grub_relocator32_boot (grub_multiboot_relocator, state);
/* Not reached. */
@ -85,69 +80,16 @@ grub_multiboot_boot (void)
static grub_err_t
grub_multiboot_unload (void)
{
if (mbi)
{
unsigned int i;
for (i = 0; i < mbi->mods_count; i++)
{
grub_free ((void *)
((struct multiboot_mod_list *) mbi->mods_addr)[i].mod_start);
grub_free ((void *)
((struct multiboot_mod_list *) mbi->mods_addr)[i].cmdline);
}
grub_free ((void *) mbi->mods_addr);
}
grub_multiboot_free_mbi ();
grub_relocator_unload (grub_multiboot_relocator);
grub_multiboot_relocator = NULL;
mbi = NULL;
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
/* 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;
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 * sizeof (struct multiboot_mmap_entry);
}
/* Fill previously allocated Multiboot mmap. */
static void
grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry)
{
struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) first_entry;
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;
mmap_entry->type = type;
mmap_entry->size = sizeof (struct multiboot_mmap_entry) - sizeof (mmap_entry->size);
mmap_entry++;
return 0;
}
grub_mmap_iterate (hook);
}
#define MULTIBOOT_LOAD_ELF64
#include "multiboot_elfxx.c"
#undef MULTIBOOT_LOAD_ELF64
@ -168,61 +110,13 @@ grub_multiboot_load_elf (grub_file_t file, void *buffer)
return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
}
static int
grub_multiboot_get_bootdev (grub_uint32_t *bootdev)
{
#ifdef GRUB_MACHINE_PCBIOS
char *p;
grub_uint32_t biosdev, slice = ~0, part = ~0;
grub_device_t dev;
biosdev = grub_get_root_biosnumber ();
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)
grub_device_close (dev);
*bootdev = ((biosdev & 0xff) << 24) | ((slice & 0xff) << 16)
| ((part & 0xff) << 8) | 0xff;
return (biosdev != ~0UL);
#else
*bootdev = 0xffffffff;
return 0;
#endif
}
void
grub_multiboot (int argc, char *argv[])
{
grub_file_t file = 0;
char buffer[MULTIBOOT_SEARCH], *cmdline = 0, *p;
char buffer[MULTIBOOT_SEARCH];
struct multiboot_header *header;
grub_ssize_t len, cmdline_length, boot_loader_name_length;
grub_uint32_t mmap_length;
int i;
int cmdline_argc;
char **cmdline_argv;
int mbichunk_size;
void *mbichunk;
grub_addr_t mbichunk_dest;
grub_ssize_t len;
grub_err_t err;
grub_loader_unset ();
@ -274,31 +168,8 @@ grub_multiboot (int argc, char *argv[])
grub_relocator_unload (grub_multiboot_relocator);
grub_multiboot_relocator = NULL;
mmap_length = grub_get_multiboot_mmap_len ();
/* Figure out cmdline length. */
/* Skip filename. */
cmdline_argc = argc - 1;
cmdline_argv = argv + 1;
for (i = 0, cmdline_length = 0; i < cmdline_argc; i++)
cmdline_length += grub_strlen (cmdline_argv[i]) + 1;
if (cmdline_length == 0)
cmdline_length = 1;
boot_loader_name_length = sizeof(PACKAGE_STRING);
#define cmdline_addr(x) ((void *) (((grub_uint8_t *) x)))
#define boot_loader_name_addr(x) \
((void *) (((grub_uint8_t *) x) + cmdline_length))
#define mbi_addr(x) ((void *) (((grub_uint8_t *) x) + cmdline_length + boot_loader_name_length))
#define mmap_addr(x) ((void *) (((grub_uint8_t *) x) + cmdline_length + boot_loader_name_length + sizeof (struct multiboot_info)))
mbichunk_size = cmdline_length
/* boot_loader_name_length might need to grow for mbi,etc to be aligned (see below) */
+ boot_loader_name_length + 3
+ sizeof (struct multiboot_info) + mmap_length;
grub_multiboot_init_mbi (argc - 1, argv + 1);
grub_multiboot_relocator = grub_relocator_new ();
@ -343,59 +214,7 @@ grub_multiboot (int argc, char *argv[])
else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
goto fail;
/* This provides alignment for the MBI, the memory map and the backward relocator. */
boot_loader_name_length += (0x04 - ((unsigned long) mbi_addr (0) & 0x03));
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &mbichunk,
&mbichunk_dest,
0, (0xffffffff - mbichunk_size) + 1,
mbichunk_size, 4);
if (err)
{
grub_dprintf ("multiboot_loader", "Error allocating mbi chunk\n");
goto fail;
}
mbi = mbi_addr (mbichunk);
mbi_dest = mbi_addr (mbichunk_dest);
grub_memset (mbi, 0, sizeof (struct multiboot_info));
mbi->mmap_length = mmap_length;
grub_fill_multiboot_mmap (mmap_addr (mbichunk));
mbi->mmap_addr = (grub_uint32_t) mmap_addr (mbichunk_dest);
mbi->flags |= MULTIBOOT_INFO_MEM_MAP;
/* Convert from bytes to kilobytes. */
mbi->mem_lower = grub_mmap_get_lower () / 1024;
mbi->mem_upper = grub_mmap_get_upper () / 1024;
mbi->flags |= MULTIBOOT_INFO_MEMORY;
cmdline = p = cmdline_addr (mbichunk);
if (! cmdline)
goto fail;
for (i = 0; i < cmdline_argc; i++)
{
p = grub_stpcpy (p, cmdline_argv[i]);
*(p++) = ' ';
}
/* Remove the space after the last word. */
if (p != cmdline)
p--;
*p = 0;
mbi->flags |= MULTIBOOT_INFO_CMDLINE;
mbi->cmdline = (grub_uint32_t) cmdline_addr (mbichunk_dest);
grub_strcpy (boot_loader_name_addr (mbichunk), PACKAGE_STRING);
mbi->flags |= MULTIBOOT_INFO_BOOT_LOADER_NAME;
mbi->boot_loader_name = (grub_uint32_t) boot_loader_name_addr (mbichunk_dest);
if (grub_multiboot_get_bootdev (&mbi->boot_device))
mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
grub_multiboot_set_bootdev ();
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
@ -405,22 +224,19 @@ grub_multiboot (int argc, char *argv[])
if (grub_errno != GRUB_ERR_NONE)
{
grub_free (cmdline);
grub_free (mbi);
grub_relocator_unload (grub_multiboot_relocator);
grub_dl_unref (my_mod);
}
}
void
grub_module (int argc, char *argv[])
{
grub_file_t file = 0;
grub_ssize_t size, len = 0;
char *module = 0, *cmdline = 0, *p;
int i;
int cmdline_argc;
char **cmdline_argv;
grub_ssize_t size;
void *module = NULL;
grub_addr_t target;
grub_err_t err;
if (argc == 0)
{
@ -428,7 +244,7 @@ grub_module (int argc, char *argv[])
goto fail;
}
if (!mbi)
if (!grub_multiboot_relocator)
{
grub_error (GRUB_ERR_BAD_ARGUMENT,
"you need to load the multiboot kernel first");
@ -440,8 +256,15 @@ grub_module (int argc, char *argv[])
goto fail;
size = grub_file_size (file);
module = grub_memalign (MULTIBOOT_MOD_ALIGN, size);
if (! module)
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &module,
&target,
0, (0xffffffff - size) + 1,
size, MULTIBOOT_MOD_ALIGN);
if (err)
goto fail;
err = grub_multiboot_add_module (target, size, argc - 1, argv + 1);
if (err)
goto fail;
if (grub_file_read (file, module, size) != size)
@ -450,67 +273,8 @@ grub_module (int argc, char *argv[])
goto fail;
}
/* Skip module name. */
cmdline_argc = argc - 1;
cmdline_argv = argv + 1;
for (i = 0; i < cmdline_argc; i++)
len += grub_strlen (cmdline_argv[i]) + 1;
if (len == 0)
len = 1;
cmdline = p = grub_malloc (len);
if (! cmdline)
goto fail;
for (i = 0; i < cmdline_argc; i++)
{
p = grub_stpcpy (p, cmdline_argv[i]);
*(p++) = ' ';
}
/* Remove the space after the last word. */
if (p != cmdline)
p--;
*p = '\0';
if (mbi->flags & MULTIBOOT_INFO_MODS)
{
struct multiboot_mod_list *modlist = (struct multiboot_mod_list *) mbi->mods_addr;
modlist = grub_realloc (modlist, (mbi->mods_count + 1)
* sizeof (struct multiboot_mod_list));
if (! modlist)
goto fail;
mbi->mods_addr = (grub_uint32_t) modlist;
modlist += mbi->mods_count;
modlist->mod_start = (grub_uint32_t) module;
modlist->mod_end = (grub_uint32_t) module + size;
modlist->cmdline = (grub_uint32_t) cmdline;
modlist->pad = 0;
mbi->mods_count++;
}
else
{
struct multiboot_mod_list *modlist = grub_zalloc (sizeof (struct multiboot_mod_list));
if (! modlist)
goto fail;
modlist->mod_start = (grub_uint32_t) module;
modlist->mod_end = (grub_uint32_t) module + size;
modlist->cmdline = (grub_uint32_t) cmdline;
mbi->mods_count = 1;
mbi->mods_addr = (grub_uint32_t) modlist;
mbi->flags |= MULTIBOOT_INFO_MODS;
}
fail:
if (file)
grub_file_close (file);
}
if (grub_errno != GRUB_ERR_NONE)
{
grub_free (module);
grub_free (cmdline);
}
}

346
loader/i386/multiboot_mbi.c Normal file
View file

@ -0,0 +1,346 @@
/*
* 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/disk.h>
#include <grub/device.h>
#include <grub/partition.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/relocator.h>
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 grub_uint32_t bootdev;
static int bootdev_set;
/* 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;
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 * sizeof (struct multiboot_mmap_entry);
}
static grub_size_t
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 ();
}
/* Fill previously allocated Multiboot mmap. */
static void
grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry)
{
struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) first_entry;
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;
default:
mmap_entry->type = MULTIBOOT_MEMORY_RESERVED;
break;
}
mmap_entry->size = sizeof (struct multiboot_mmap_entry) - sizeof (mmap_entry->size);
mmap_entry++;
return 0;
}
grub_mmap_iterate (hook);
}
grub_err_t
grub_multiboot_make_mbi (grub_uint32_t *target)
{
struct multiboot_info *mbi;
struct multiboot_mod_list *modlist;
unsigned i;
struct module *cur;
grub_size_t mmap_size;
grub_uint8_t *ptrorig;
grub_addr_t ptrdest;
grub_err_t err;
grub_size_t bufsize;
bufsize = grub_multiboot_get_mbi_size ();
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator,
(void **) &ptrorig, &ptrdest,
0, 0xffffffff - bufsize,
bufsize, 4);
if (err)
return err;
*target = ptrdest;
mbi = (struct multiboot_info *) ptrorig;
ptrorig += sizeof (*mbi);
ptrdest += sizeof (*mbi);
grub_memset (mbi, 0, sizeof (*mbi));
grub_memcpy (ptrorig, cmdline, cmdline_size);
mbi->flags |= MULTIBOOT_INFO_CMDLINE;
mbi->cmdline = ptrdest;
ptrorig += ALIGN_UP (cmdline_size, 4);
ptrdest += ALIGN_UP (cmdline_size, 4);
grub_memcpy (ptrorig, PACKAGE_STRING, sizeof(PACKAGE_STRING));
mbi->flags |= MULTIBOOT_INFO_BOOT_LOADER_NAME;
mbi->boot_loader_name = ptrdest;
ptrorig += ALIGN_UP (sizeof(PACKAGE_STRING), 4);
ptrdest += ALIGN_UP (sizeof(PACKAGE_STRING), 4);
if (modcnt)
{
mbi->flags |= MULTIBOOT_INFO_MODS;
mbi->mods_addr = ptrdest;
mbi->mods_count = modcnt;
modlist = (struct multiboot_mod_list *) ptrorig;
ptrorig += modcnt * sizeof (struct multiboot_mod_list);
ptrdest += modcnt * sizeof (struct multiboot_mod_list);
for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
{
modlist[i].mod_start = cur->start;
modlist[i].mod_end = modlist[i].mod_start + cur->size;
modlist[i].cmdline = ptrdest;
grub_memcpy (ptrorig, cur->cmdline, cur->cmdline_size);
ptrorig += ALIGN_UP (cur->cmdline_size, 4);
ptrdest += ALIGN_UP (cur->cmdline_size, 4);
}
}
else
{
mbi->mods_addr = 0;
mbi->mods_count = 0;
}
mmap_size = grub_get_multiboot_mmap_len ();
grub_fill_multiboot_mmap ((struct multiboot_mmap_entry *) ptrorig);
mbi->mmap_length = mmap_size;
mbi->mmap_addr = ptrdest;
mbi->flags |= MULTIBOOT_INFO_MEM_MAP;
ptrorig += mmap_size;
ptrdest += mmap_size;
/* Convert from bytes to kilobytes. */
mbi->mem_lower = grub_mmap_get_lower () / 1024;
mbi->mem_upper = grub_mmap_get_upper () / 1024;
mbi->flags |= MULTIBOOT_INFO_MEMORY;
if (bootdev_set)
{
mbi->boot_device = bootdev;
mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
}
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, 4);
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)
{
char *p;
grub_uint32_t biosdev, slice = ~0, part = ~0;
grub_device_t dev;
#ifdef GRUB_MACHINE_PCBIOS
biosdev = grub_get_root_biosnumber ();
#else
biosdev = 0xffffffff;
#endif
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)
grub_device_close (dev);
bootdev = ((biosdev & 0xff) << 24) | ((slice & 0xff) << 16)
| ((part & 0xff) << 8) | 0xff;
bootdev_set = 1;
}