[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Manipulate mbi in abstract way
From: |
Vladimir 'φ-coder/phcoder' Serbinenko |
Subject: |
[PATCH] Manipulate mbi in abstract way |
Date: |
Sun, 10 Jan 2010 19:01:47 +0100 |
User-agent: |
Mozilla-Thunderbird 2.0.0.22 (X11/20091109) |
It cleans up some mess in grub_multiboot and allows easier code sharing
with upcomming tagged mbi
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
=== added file 'ChangeLog.abstractmbi'
--- ChangeLog.abstractmbi 1970-01-01 00:00:00 +0000
+++ ChangeLog.abstractmbi 2010-01-10 16:11:01 +0000
@@ -0,0 +1,25 @@
+2010-01-10 Vladimir Serbinenko <address@hidden>
+
+ * 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.
=== modified file 'conf/i386-coreboot.rmk'
--- conf/i386-coreboot.rmk 2010-01-09 22:22:48 +0000
+++ conf/i386-coreboot.rmk 2010-01-10 15:39:05 +0000
@@ -142,14 +142,16 @@
pkglib_MODULES += multiboot.mod
multiboot_mod_SOURCES = loader/i386/multiboot.c \
- loader/multiboot_loader.c
+ loader/i386/multiboot_mbi.c \
+ loader/multiboot_loader.c
multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
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)
=== modified file 'conf/i386-pc.rmk'
--- conf/i386-pc.rmk 2010-01-09 22:22:48 +0000
+++ conf/i386-pc.rmk 2010-01-10 15:39:05 +0000
@@ -203,6 +203,7 @@
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)
@@ -210,7 +211,8 @@
pkglib_MODULES += multiboot2.mod
multiboot2_mod_SOURCES = loader/i386/multiboot.c \
- loader/multiboot_loader.c
+ loader/i386/multiboot_mbi.c \
+ loader/multiboot_loader.c
multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2
multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS)
multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS)
=== modified file 'include/grub/multiboot.h'
--- include/grub/multiboot.h 2010-01-07 21:05:25 +0000
+++ include/grub/multiboot.h 2010-01-10 15:50:59 +0000
@@ -29,7 +29,20 @@
#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_size_t grub_multiboot_get_mbi_size (void);
+grub_err_t grub_multiboot_make_mbi (void *orig, grub_uint32_t dest,
+ grub_off_t buf_off, grub_size_t bufsize);
+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 */
=== modified file 'loader/i386/multiboot.c'
--- loader/i386/multiboot.c 2010-01-07 19:55:16 +0000
+++ loader/i386/multiboot.c 2010-01-10 16:09:27 +0000
@@ -45,31 +45,24 @@
#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;
-
-static grub_size_t code_size;
+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_payload_size;
+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,
- .ebx = PTR_TO_UINT32 (mbi_dest),
.ecx = 0,
.edx = 0,
.eip = grub_multiboot_payload_eip,
@@ -78,6 +71,24 @@
.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;
+
grub_relocator32_boot (grub_multiboot_payload_orig,
grub_multiboot_payload_dest,
state);
@@ -89,69 +100,18 @@
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_relocator32_free (grub_multiboot_payload_orig);
- mbi = NULL;
+ alloc_mbi = 0;
+
grub_multiboot_payload_orig = 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
@@ -172,58 +132,13 @@
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;
+ grub_ssize_t len;
grub_loader_unset ();
@@ -274,31 +189,8 @@
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_payload_orig = 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 *) ((x) + code_size))
-#define boot_loader_name_addr(x) \
- ((void *) ((x) + code_size + cmdline_length))
-#define mbi_addr(x) ((void *) ((x) + code_size + cmdline_length +
boot_loader_name_length))
-#define mmap_addr(x) ((void *) ((x) + code_size + cmdline_length +
boot_loader_name_length + sizeof (struct multiboot_info)))
-
- grub_multiboot_payload_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);
if (header->flags & MULTIBOOT_AOUT_KLUDGE)
{
@@ -313,10 +205,12 @@
code_size = load_size;
grub_multiboot_payload_dest = header->load_addr;
- grub_multiboot_payload_size += code_size;
+ 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_payload_size);
+ = grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi);
if (! grub_multiboot_payload_orig)
goto fail;
@@ -338,53 +232,35 @@
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
(grub_multiboot_payload_dest) & 0x03));
-
- mbi = mbi_addr (grub_multiboot_payload_orig);
- mbi_dest = mbi_addr (grub_multiboot_payload_dest);
- grub_memset (mbi, 0, sizeof (struct multiboot_info));
- mbi->mmap_length = mmap_length;
-
- grub_fill_multiboot_mmap (mmap_addr (grub_multiboot_payload_orig));
-
- /* FIXME: grub_uint32_t will break for addresses above 4 GiB, but is mandated
- by the spec. Is there something we can do about it? */
- mbi->mmap_addr = (grub_uint32_t) mmap_addr (grub_multiboot_payload_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 (grub_multiboot_payload_orig);
- if (! cmdline)
- goto fail;
-
- for (i = 0; i < cmdline_argc; i++)
+ if (header->flags & MULTIBOOT_VIDEO_MODE)
{
- p = grub_stpcpy (p, cmdline_argv[i]);
- *(p++) = ' ';
+ 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;
+ }
+ }
}
- /* 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 (grub_multiboot_payload_dest);
-
-
- grub_strcpy (boot_loader_name_addr (grub_multiboot_payload_orig),
PACKAGE_STRING);
- mbi->flags |= MULTIBOOT_INFO_BOOT_LOADER_NAME;
- mbi->boot_loader_name = (grub_uint32_t) boot_loader_name_addr
(grub_multiboot_payload_dest);
-
- if (grub_multiboot_get_bootdev (&mbi->boot_device))
- mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
-
- grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 1);
+ grub_multiboot_set_bootdev ();
+
+ grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
fail:
if (file)
@@ -392,22 +268,18 @@
if (grub_errno != GRUB_ERR_NONE)
{
- grub_free (cmdline);
- grub_free (mbi);
+ 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, len = 0;
- char *module = 0, *cmdline = 0, *p;
- int i;
- int cmdline_argc;
- char **cmdline_argv;
+ grub_ssize_t size;
+ char *module = 0;
+ grub_err_t err;
if (argc == 0)
{
@@ -415,7 +287,7 @@
goto fail;
}
- if (!mbi)
+ if (!grub_multiboot_payload_orig)
{
grub_error (GRUB_ERR_BAD_ARGUMENT,
"you need to load the multiboot kernel first");
@@ -431,73 +303,19 @@
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;
}
- /* 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);
- }
}
+
=== modified file 'loader/i386/multiboot_elfxx.c'
--- loader/i386/multiboot_elfxx.c 2009-12-13 18:29:15 +0000
+++ loader/i386/multiboot_elfxx.c 2010-01-10 15:39:05 +0000
@@ -100,10 +100,11 @@
code_size = (phdr(highest_segment)->p_paddr +
phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr;
- grub_multiboot_payload_size += code_size;
+ grub_multiboot_pure_size += code_size;
+ alloc_mbi = grub_multiboot_get_mbi_size ();
grub_multiboot_payload_orig
- = grub_relocator32_alloc (grub_multiboot_payload_size);
+ = grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi);
if (!grub_multiboot_payload_orig)
return grub_errno;
=== added file 'loader/i386/multiboot_mbi.c'
--- loader/i386/multiboot_mbi.c 1970-01-01 00:00:00 +0000
+++ loader/i386/multiboot_mbi.c 2010-01-10 17:00:27 +0000
@@ -0,0 +1,336 @@
+/*
+ * 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>
+
+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);
+}
+
+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 (void *orig, grub_uint32_t dest, grub_off_t buf_off,
+ grub_size_t bufsize)
+{
+ grub_uint8_t *ptrorig = (grub_uint8_t *) orig + buf_off;
+ grub_uint32_t ptrdest = dest + buf_off;
+ struct multiboot_info *mbi;
+ struct multiboot_mod_list *modlist;
+ unsigned i;
+ struct module *cur;
+ grub_size_t mmap_size;
+
+ if (bufsize < grub_multiboot_get_mbi_size ())
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small");
+
+ 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;
+}
signature.asc
Description: OpenPGP digital signature
- [PATCH] Manipulate mbi in abstract way,
Vladimir 'φ-coder/phcoder' Serbinenko <=