All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Vladimir 'φ-coder/phcoder' Serbinenko" <phcoder@gmail.com>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: [PATCH] Manipulate mbi in abstract way
Date: Sun, 10 Jan 2010 19:01:47 +0100	[thread overview]
Message-ID: <4B4A160B.6010908@gmail.com> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 158 bytes --]

It cleans up some mess in grub_multiboot and allows easier code sharing
with upcomming tagged mbi

-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: abstractmbi.diff --]
[-- Type: text/x-diff; name="abstractmbi.diff", Size: 26406 bytes --]

=== 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  <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.

=== 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 #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 293 bytes --]

             reply	other threads:[~2010-01-10 18:02 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-01-10 18:01 Vladimir 'φ-coder/phcoder' Serbinenko [this message]
2010-01-14 11:42 ` [PATCH] Manipulate mbi in abstract way Vladimir 'φ-coder/phcoder' Serbinenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B4A160B.6010908@gmail.com \
    --to=phcoder@gmail.com \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.