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 . + */ + +#include +#include +#include +#include +#include +#include + +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 +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 #include #include +#include #include #include @@ -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);