grub-devel
[Top][All Lists]
Advanced

[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;
+}

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]