]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2008-01-21 Robert Millan <rmh@aybabtu.com>
authorrobertmh <robertmh@localhost>
Sun, 20 Jan 2008 23:20:36 +0000 (23:20 +0000)
committerrobertmh <robertmh@localhost>
Sun, 20 Jan 2008 23:20:36 +0000 (23:20 +0000)
        * conf/i386-pc.rmk (kernel_img_HEADERS): Add `machine/kernel.h'.
        (pkglib_MODULES): Add `memdisk.mod'.
        (memdisk_mod_SOURCES): New variable.
        (memdisk_mod_CFLAGS): Likewise.
        (memdisk_mod_LDFLAGS): Likewise.

        * disk/memdisk.c: New file.

        * include/grub/disk.h (grub_disk_dev_id): Add
        `GRUB_DISK_DEVICE_MEMDISK_ID'.

        * include/grub/i386/pc/kernel.h
        (GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE): New macro.
        (GRUB_KERNEL_MACHINE_PREFIX): Increment by 4.
        (grub_kernel_image_size): New variable declaration.
        (grub_total_module_size): Likewise.
        (grub_memdisk_image_size): Likewise.

        * include/grub/i386/pc/memory.h
        (GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR): New macro.

        * include/grub/kernel.h: Include `<grub/symbol.h>'.
        (grub_arch_memdisk_addr): New variable declaration.
        (grub_arch_memdisk_size): Likewise.

        * kern/i386/pc/init.c (grub_arch_memdisk_addr): New function.
        (grub_arch_memdisk_size): Likewise.

        * kern/i386/pc/startup.S (grub_memdisk_image_size): New variable.
        (codestart): Replace hardcoded `0x100000' with
        `GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR' macro.

        * util/i386/pc/grub-mkimage.c: Include `<grub/misc.h>'.
        (generate_image): Add `memdisk_path' parameter.  When `memdisk_path' is
        not NULL, append the contents of the file it refers to, at the end of
        the compressed kernel image.  Initialize `grub_memdisk_image_size'
        variable (at `GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE' offset).
        (options): Add "memdisk"|'m' option.
        (main): Parse --memdisk|-m option, and pass user-provided path as
        parameter to generate_image().

ChangeLog
conf/i386-pc.mk
conf/i386-pc.rmk
disk/memdisk.c [new file with mode: 0644]
include/grub/disk.h
include/grub/i386/pc/kernel.h
include/grub/i386/pc/memory.h
include/grub/kernel.h
kern/i386/pc/init.c
kern/i386/pc/startup.S
util/i386/pc/grub-mkimage.c

index 03a4dc6d3efcb8645670a5469c0520dd0c8196d3..16ccae743b817b30f02c3d34ac9ef31863cc85a8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+2008-01-21  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (kernel_img_HEADERS): Add `machine/kernel.h'.
+       (pkglib_MODULES): Add `memdisk.mod'.
+       (memdisk_mod_SOURCES): New variable.
+       (memdisk_mod_CFLAGS): Likewise.
+       (memdisk_mod_LDFLAGS): Likewise.
+
+       * disk/memdisk.c: New file.
+
+       * include/grub/disk.h (grub_disk_dev_id): Add
+       `GRUB_DISK_DEVICE_MEMDISK_ID'.
+
+       * include/grub/i386/pc/kernel.h
+       (GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE): New macro.
+       (GRUB_KERNEL_MACHINE_PREFIX): Increment by 4.
+       (grub_kernel_image_size): New variable declaration.
+       (grub_total_module_size): Likewise.
+       (grub_memdisk_image_size): Likewise.
+
+       * include/grub/i386/pc/memory.h
+       (GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR): New macro.
+
+       * include/grub/kernel.h: Include `<grub/symbol.h>'.
+       (grub_arch_memdisk_addr): New variable declaration.
+       (grub_arch_memdisk_size): Likewise.
+
+       * kern/i386/pc/init.c (grub_arch_memdisk_addr): New function.
+       (grub_arch_memdisk_size): Likewise.
+
+       * kern/i386/pc/startup.S (grub_memdisk_image_size): New variable.
+       (codestart): Replace hardcoded `0x100000' with
+       `GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR' macro.
+
+       * util/i386/pc/grub-mkimage.c: Include `<grub/misc.h>'.
+       (generate_image): Add `memdisk_path' parameter.  When `memdisk_path' is
+       not NULL, append the contents of the file it refers to, at the end of
+       the compressed kernel image.  Initialize `grub_memdisk_image_size'
+       variable (at `GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE' offset).
+       (options): Add "memdisk"|'m' option.
+       (main): Parse --memdisk|-m option, and pass user-provided path as
+       parameter to generate_image().
+
 2008-01-20  Robert Millan  <rmh@aybabtu.com>
 
        * kern/sparc64/ieee1275/openfw.c (grub_devalias_iterate): Copy debug
index fd73a0ac55af70211187ca74be031a60faad6a66..9ecbbc0390533a21ab4cfa502692a983850de30b 100644 (file)
@@ -180,7 +180,7 @@ kernel_img_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
        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)
@@ -915,7 +915,7 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
        _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
+       ata.mod vga.mod memdisk.mod
 
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -2424,4 +2424,56 @@ fs-vga_mod-term_i386_pc_vga.lst: term/i386/pc/vga.c genfslist.sh
 vga_mod_CFLAGS = $(COMMON_CFLAGS)
 vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+CLEANFILES += memdisk.mod mod-memdisk.o mod-memdisk.c pre-memdisk.o memdisk_mod-disk_memdisk.o und-memdisk.lst
+ifneq ($(memdisk_mod_EXPORTS),no)
+CLEANFILES += def-memdisk.lst
+DEFSYMFILES += def-memdisk.lst
+endif
+MOSTLYCLEANFILES += memdisk_mod-disk_memdisk.d
+UNDSYMFILES += und-memdisk.lst
+
+memdisk.mod: pre-memdisk.o mod-memdisk.o
+       -rm -f $@
+       $(TARGET_CC) $(memdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
+
+pre-memdisk.o: $(memdisk_mod_DEPENDENCIES) memdisk_mod-disk_memdisk.o
+       -rm -f $@
+       $(TARGET_CC) $(memdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ memdisk_mod-disk_memdisk.o
+
+mod-memdisk.o: mod-memdisk.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -c -o $@ $<
+
+mod-memdisk.c: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'memdisk' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(memdisk_mod_EXPORTS),no)
+def-memdisk.lst: pre-memdisk.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 memdisk/' > $@
+endif
+
+und-memdisk.lst: pre-memdisk.o
+       echo 'memdisk' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+memdisk_mod-disk_memdisk.o: disk/memdisk.c
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -MD -c -o $@ $<
+-include memdisk_mod-disk_memdisk.d
+
+CLEANFILES += cmd-memdisk_mod-disk_memdisk.lst fs-memdisk_mod-disk_memdisk.lst
+COMMANDFILES += cmd-memdisk_mod-disk_memdisk.lst
+FSFILES += fs-memdisk_mod-disk_memdisk.lst
+
+cmd-memdisk_mod-disk_memdisk.lst: disk/memdisk.c gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+fs-memdisk_mod-disk_memdisk.lst: disk/memdisk.c genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
index a46bc74571c497ea5fadcbb0f457587b2c56c3e4..6df833a0eddd737d0f92ba23065145de105b3845 100644 (file)
@@ -39,7 +39,7 @@ kernel_img_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
        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 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
        _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
+       ata.mod vga.mod memdisk.mod
 
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -264,4 +264,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 --git a/disk/memdisk.c b/disk/memdisk.c
new file mode 100644 (file)
index 0000000..23b3322
--- /dev/null
@@ -0,0 +1,94 @@
+/* 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/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_arch_memdisk_size () / GRUB_DISK_SECTOR_SIZE;
+  disk->id = (int) 'mdsk';
+  disk->has_partitions = 0;
+
+  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 __attribute((unused)), 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 __attribute((unused)), 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)
+{
+  if (! grub_arch_memdisk_size ())
+    return;
+  memdisk_addr = grub_arch_memdisk_addr ();
+  grub_disk_dev_register (&grub_memdisk_dev);
+}
+
+GRUB_MOD_FINI(memdisk)
+{
+  if (! grub_arch_memdisk_size ())
+    return;
+  grub_disk_dev_unregister (&grub_memdisk_dev);
+}
index 430194270c4d523145667a153ead66a4009a4710..9891a9cfc6f363fd4823b13b78aeeaec639895eb 100644 (file)
@@ -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;
index ec207a579adfb1640ec4499c06ec05628a0abf81..34f7ea17d62c242c0c24ea0e24d5f3eae1dd2f14 100644 (file)
 /* 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
 
 #include <grub/types.h>
 
+/* The size of kernel image.  */
+extern grub_int32_t grub_kernel_image_size;
+
+/* The total size of module images following the kernel.  */
+extern grub_int32_t grub_total_module_size;
+
 /* The DOS partition number of the installed partition.  */
 extern grub_int32_t grub_install_dos_part;
 
 /* The BSD partition number of the installed partition.  */
 extern grub_int32_t grub_install_bsd_part;
 
+/* The size of memory disk image, if present.  */
+extern grub_int32_t grub_memdisk_image_size;
+
 /* The prefix which points to the directory where GRUB modules and its
    configuration file are located.  */
 extern char grub_prefix[];
index b8f9850169656a8581ef300cebf715b4eaa8da39..c0ad73d4d793fd849aa0b4a2a74abffae7cc78da 100644 (file)
@@ -48,6 +48,9 @@
 #define GRUB_MEMORY_MACHINE_RESERVED_END       \
        (GRUB_MEMORY_MACHINE_PROT_STACK + 0x10)
 
+/* The area where GRUB is decompressed at early startup.  */
+#define GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR 0x100000
+
 /* The address of a partition table passed to another boot loader.  */
 #define GRUB_MEMORY_MACHINE_PART_TABLE_ADDR    0x7be
 
index 77d209a9ea9c782a1747c38065b35ed541a65927..7413e19bc5b7e0fae0f5b55459e9876b2e495301 100644 (file)
@@ -20,6 +20,7 @@
 #define GRUB_KERNEL_HEADER     1
 
 #include <grub/types.h>
+#include <grub/symbol.h>
 
 /* The module header.  */
 struct grub_module_header
@@ -44,6 +45,8 @@ struct grub_module_info
 };
 
 extern grub_addr_t grub_arch_modules_addr (void);
+extern grub_addr_t EXPORT_FUNC(grub_arch_memdisk_addr) (void);
+extern grub_off_t EXPORT_FUNC(grub_arch_memdisk_size) (void);
 
 /* The start point of the C code.  */
 void grub_main (void);
index b1c7984fdea18faba91ff2145c25573bcee4fea7..0cf81d769a221bac0cc58c2ec6cefe4284d74227 100644 (file)
@@ -248,3 +248,19 @@ grub_arch_modules_addr (void)
 {
   return grub_end_addr;
 }
+
+/* Return the start of the memdisk image.  */
+grub_addr_t
+grub_arch_memdisk_addr (void)
+{
+  return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
+    + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE)
+    + grub_total_module_size;
+}
+
+/* Return the size of the memdisk image.  */
+grub_off_t
+grub_arch_memdisk_size (void)
+{
+  return grub_memdisk_image_size;
+}
index c1da148aad09476343adc2e1031fa7db8c98c8fe..e4101a655f67b421e863f74db21755db5c602614 100644 (file)
@@ -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 */
 
@@ -196,7 +198,7 @@ codestart:
        call    EXT_C(grub_gate_a20)
        
        /* decompress the compressed part and put the result at 1MB */
-       movl    $0x100000, %esi
+       movl    $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %esi
        movl    $(START_SYMBOL + GRUB_KERNEL_MACHINE_RAW_SIZE), %edi
 
        pushl   %esi
index e19649d2430d17bbff35aaaa1b4c0bbd750bbb33..c002c0e69f2cdeb4aa18fe8f4a5d310caa3bbbf4 100644 (file)
@@ -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_t kernel_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 *prefix, FILE *out, char *mods[])
 
   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 *prefix, FILE *out, char *mods[])
       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 *prefix, FILE *out, char *mods[])
     = 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);