On Fri, Dec 21, 2007 at 07:04:05PM +0100, Robert Millan wrote:
> > >
> > > I'd prefer to support embedding filesystems in core.img instead.  This
> > > solves the problem for every situation instead of just PC boot media
> > > (e.g. LinuxBIOS ELF payload image).
> > 
> > Agreed, I would like to see such feature.  Also for stuff like
> > diskless boot.
> > 
> > What I had in mind was the following.  We could perhaps make it
> > possible to add all files using grub-mkimage, not only modules.  When
> > you add modules, those will be loaded automatically.  All other files
> > will be ignored.
> > 
> > Another filesystem module has to be written.  It scans over these
> > files and will make them available.  This can be simple and elegant.
> > I do not like the idea of adding a diskimage or so.  Are you
> > interested in working on this?
> 
> Well, I already have an almost-working implementation.  I guess I'll have to
> defend it then! :-P
> 
> Really, it's clean and elegant.  Very simple and flexible.  Once I get the
> address detection right, that is..

Please have a look at the attached patch.  This allows adding an arbitrary
number of files.  No extra filesystem module is needed, since any of the
supported filesystems can be used with this feature:

  genisoimage -o filesystem_image -r stuff
  grub-mkimage -o core.img -m filesystem_image

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call, if you are unable to speak?
(as seen on /.)
diff -x '*.mk' -Nurp grub2/conf/i386-pc.rmk grub2.memdisk/conf/i386-pc.rmk
--- grub2/conf/i386-pc.rmk	2007-12-21 12:41:23.000000000 +0100
+++ grub2.memdisk/conf/i386-pc.rmk	2007-12-21 21:47:57.000000000 +0100
@@ -39,7 +39,7 @@ kernel_img_HEADERS = arg.h boot.h cache.
 	env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
 	partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
 	machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \
-	machine/memory.h machine/loader.h machine/vga.h machine/vbe.h
+	machine/memory.h machine/loader.h machine/vga.h machine/vbe.h machine/kernel.h
 kernel_img_CFLAGS = $(COMMON_CFLAGS)
 kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
 kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-Ttext,8200 $(COMMON_CFLAGS)
@@ -136,7 +136,7 @@ pkgdata_MODULES = biosdisk.mod _chain.mo
 	_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod	\
 	vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
 	videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod ata.mod \
-	vga.mod
+	vga.mod memdisk.mod
 
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -263,4 +263,9 @@ vga_mod_SOURCES = term/i386/pc/vga.c
 vga_mod_CFLAGS = $(COMMON_CFLAGS)
 vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff -x '*.mk' -Nurp grub2/disk/memdisk.c grub2.memdisk/disk/memdisk.c
--- grub2/disk/memdisk.c	1970-01-01 01:00:00.000000000 +0100
+++ grub2.memdisk/disk/memdisk.c	2007-12-21 21:43:25.000000000 +0100
@@ -0,0 +1,92 @@
+/* memdisk.c - Access embedded memory disk.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007  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/disk.h>
+#include <grub/dl.h>
+#include <grub/machine/kernel.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+
+static grub_addr_t memdisk_addr;
+
+static int
+grub_memdisk_iterate (int (*hook) (const char *name))
+{
+  return hook ("memdisk");
+}
+
+static grub_err_t
+grub_memdisk_open (const char *name, grub_disk_t disk)
+{
+  if (grub_strcmp (name, "memdisk"))
+      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a memdisk");
+
+  disk->total_sectors = grub_memdisk_image_size / GRUB_DISK_SECTOR_SIZE;
+  disk->id = (int) 'mdsk';
+
+  disk->has_partitions = 0;
+  disk->data = NULL;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_memdisk_close (grub_disk_t disk __attribute((unused)))
+{
+}
+
+static grub_err_t
+grub_memdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
+		    grub_size_t size, char *buf)
+{
+  grub_memcpy (buf, memdisk_addr + (sector << GRUB_DISK_SECTOR_BITS), size << GRUB_DISK_SECTOR_BITS);
+  return 0;
+}
+
+static grub_err_t
+grub_memdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
+		     grub_size_t size, const char *buf)
+{
+  grub_memcpy (memdisk_addr + (sector << GRUB_DISK_SECTOR_BITS), buf, size << GRUB_DISK_SECTOR_BITS);
+  return 0;
+}
+
+static struct grub_disk_dev grub_memdisk_dev =
+  {
+    .name = "memdisk",
+    .id = GRUB_DISK_DEVICE_MEMDISK_ID,
+    .iterate = grub_memdisk_iterate,
+    .open = grub_memdisk_open,
+    .close = grub_memdisk_close,
+    .read = grub_memdisk_read,
+    .write = grub_memdisk_write,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(memdisk)
+{
+  memdisk_addr = 0x100000 + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE) + grub_total_module_size;
+  grub_disk_dev_register (&grub_memdisk_dev);
+}
+
+GRUB_MOD_FINI(memdisk)
+{
+  grub_disk_dev_unregister (&grub_memdisk_dev);
+}
diff -x '*.mk' -Nurp grub2/include/grub/disk.h grub2.memdisk/include/grub/disk.h
--- grub2/include/grub/disk.h	2007-11-05 17:15:26.000000000 +0100
+++ grub2.memdisk/include/grub/disk.h	2007-12-21 17:47:06.000000000 +0100
@@ -35,7 +35,8 @@ enum grub_disk_dev_id
     GRUB_DISK_DEVICE_RAID_ID,
     GRUB_DISK_DEVICE_LVM_ID,
     GRUB_DISK_DEVICE_HOST_ID,
-    GRUB_DISK_DEVICE_ATA_ID
+    GRUB_DISK_DEVICE_ATA_ID,
+    GRUB_DISK_DEVICE_MEMDISK_ID,
   };
 
 struct grub_disk;
diff -x '*.mk' -Nurp grub2/include/grub/i386/pc/kernel.h grub2.memdisk/include/grub/i386/pc/kernel.h
--- grub2/include/grub/i386/pc/kernel.h	2007-07-22 01:32:23.000000000 +0200
+++ grub2.memdisk/include/grub/i386/pc/kernel.h	2007-12-21 18:22:26.000000000 +0100
@@ -34,8 +34,11 @@
 /* The offset of GRUB_INSTALL_BSD_PART.  */
 #define GRUB_KERNEL_MACHINE_INSTALL_BSD_PART	0x18
 
+/* The offset of GRUB_MEMDISK_IMAGE_SIZE.  */
+#define GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE	0x1c
+
 /* The offset of GRUB_PREFIX.  */
-#define GRUB_KERNEL_MACHINE_PREFIX		0x1c
+#define GRUB_KERNEL_MACHINE_PREFIX		0x20
 
 /* End of the data section. */
 #define GRUB_KERNEL_MACHINE_DATA_END		0x50
@@ -47,6 +50,10 @@
 
 #include <grub/types.h>
 
+extern grub_int32_t EXPORT_VAR(grub_kernel_image_size);
+extern grub_int32_t EXPORT_VAR(grub_total_module_size);
+extern grub_int32_t EXPORT_VAR(grub_memdisk_image_size);
+
 /* The DOS partition number of the installed partition.  */
 extern grub_int32_t grub_install_dos_part;
 
diff -x '*.mk' -Nurp grub2/kern/i386/pc/startup.S grub2.memdisk/kern/i386/pc/startup.S
--- grub2/kern/i386/pc/startup.S	2007-10-22 22:14:45.000000000 +0200
+++ grub2.memdisk/kern/i386/pc/startup.S	2007-12-21 17:53:01.000000000 +0100
@@ -95,6 +95,8 @@ VARIABLE(grub_install_dos_part)
 	.long	0xFFFFFFFF
 VARIABLE(grub_install_bsd_part)
 	.long	0xFFFFFFFF
+VARIABLE(grub_memdisk_image_size)
+	.long	0
 VARIABLE(grub_prefix)
 	/* to be filled by grub-mkimage */
 
diff -x '*.mk' -Nurp grub2/util/i386/pc/grub-mkimage.c grub2.memdisk/util/i386/pc/grub-mkimage.c
--- grub2/util/i386/pc/grub-mkimage.c	2007-07-22 01:32:32.000000000 +0200
+++ grub2.memdisk/util/i386/pc/grub-mkimage.c	2007-12-21 21:46:35.000000000 +0100
@@ -25,6 +25,7 @@
 #include <grub/disk.h>
 #include <grub/util/misc.h>
 #include <grub/util/resolve.h>
+#include <grub/misc.h>
 
 #include <stdio.h>
 #include <unistd.h>
@@ -75,11 +76,11 @@ compress_kernel (char *kernel_img, size_
 }
 
 static void
-generate_image (const char *dir, char *prefix, FILE *out, char *mods[])
+generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *memdisk_path)
 {
   grub_addr_t module_addr = 0;
   char *kernel_img, *boot_img, *core_img;
-  size_t kernel_size, boot_size, total_module_size, core_size;
+  size_t kernel_size, boot_size, total_module_size, core_size, memdisk_size = 0;
   char *kernel_path, *boot_path;
   unsigned num;
   size_t offset;
@@ -98,7 +99,13 @@ generate_image (const char *dir, char *p
 
   grub_util_info ("the total module size is 0x%x", total_module_size);
 
-  kernel_img = xmalloc (kernel_size + total_module_size);
+  if (memdisk_path)
+    {
+      memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
+      grub_util_info ("the size of memory disk is 0x%x", memdisk_size);
+    }
+
+  kernel_img = xmalloc (kernel_size + total_module_size + memdisk_size);
   grub_util_load_image (kernel_path, kernel_img);
 
   if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END)
@@ -122,13 +129,19 @@ generate_image (const char *dir, char *p
       header = (struct grub_module_header *) (kernel_img + offset);
       header->offset = grub_cpu_to_le32 (sizeof (*header));
       header->size = grub_cpu_to_le32 (mod_size + sizeof (*header));
-      
-      grub_util_load_image (p->name, kernel_img + offset + sizeof (*header));
+      offset += sizeof (*header);
+
+      grub_util_load_image (p->name, kernel_img + offset);
+      offset += mod_size;
+    }
 
-      offset += sizeof (*header) + mod_size;
+  if (memdisk_path)
+    {
+      grub_util_load_image (memdisk_path, kernel_img + offset);
+      offset += memdisk_size;
     }
 
-  compress_kernel (kernel_img, kernel_size + total_module_size,
+  compress_kernel (kernel_img, kernel_size + total_module_size + memdisk_size,
 		   &core_img, &core_size);
 
   grub_util_info ("the core size is 0x%x", core_size);
@@ -163,6 +176,8 @@ generate_image (const char *dir, char *p
     = grub_cpu_to_le32 (total_module_size);
   *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE))
     = grub_cpu_to_le32 (kernel_size);
+  *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE))
+    = grub_cpu_to_le32 (memdisk_size);
   *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE))
     = grub_cpu_to_le32 (core_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
   
@@ -186,6 +201,7 @@ static struct option options[] =
   {
     {"directory", required_argument, 0, 'd'},
     {"prefix", required_argument, 0, 'p'},
+    {"memdisk", required_argument, 0, 'm'},
     {"output", required_argument, 0, 'o'},
     {"help", no_argument, 0, 'h'},
     {"version", no_argument, 0, 'V'},
@@ -206,6 +222,7 @@ Make a bootable image of GRUB.\n\
 \n\
   -d, --directory=DIR     use images and modules under DIR [default=%s]\n\
   -p, --prefix=DIR        set grub_prefix directory [default=%s]\n\
+  -m, --memdisk=FILE      embed FILE as a memdisk image\n\
   -o, --output=FILE       output a generated image to FILE [default=stdout]\n\
   -h, --help              display this message and exit\n\
   -V, --version           print version information and exit\n\
@@ -223,13 +240,14 @@ main (int argc, char *argv[])
   char *output = NULL;
   char *dir = NULL;
   char *prefix = NULL;
+  char *memdisk = NULL;
   FILE *fp = stdout;
 
   progname = "grub-mkimage";
   
   while (1)
     {
-      int c = getopt_long (argc, argv, "d:p:o:hVv", options, 0);
+      int c = getopt_long (argc, argv, "d:p:m:o:hVv", options, 0);
 
       if (c == -1)
 	break;
@@ -250,6 +268,13 @@ main (int argc, char *argv[])
 	    dir = xstrdup (optarg);
 	    break;
 
+	  case 'm':
+	    if (memdisk)
+	      free (memdisk);
+
+	    memdisk = xstrdup (optarg);
+	    break;
+
 	  case 'h':
 	    usage (0);
 	    break;
@@ -282,7 +307,7 @@ main (int argc, char *argv[])
 	grub_util_error ("cannot open %s", output);
     }
 
-  generate_image (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY, fp, argv + optind);
+  generate_image (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY, fp, argv + optind, memdisk);
 
   fclose (fp);
 
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to