2008-07-31 Robert Millan * disk/memdisk.c (memdisk_size): Don't initialize. (GRUB_MOD_INIT(memdisk)): Find memdisk using grub_module_iterate(). * include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE): Remove macro. (GRUB_KERNEL_MACHINE_PREFIX, GRUB_KERNEL_MACHINE_DATA_END): Shift. (grub_memdisk_image_size, grub_arch_memdisk_addr) (grub_arch_memdisk_size): Remove. * include/grub/kernel.h (struct grub_module_header): Remove `offset' field (was only used to transfer a constant). Add `type' field to support multiple module types. (grub_module_iterate): New function. * kern/device.c (grub_device_open): Do not hide error messages when grub_disk_open() fails. Use grub_print_error() instead. * kern/i386/pc/init.c (grub_arch_modules_addr) (grub_arch_memdisk_size): Remove functions. (grub_arch_modules_addr): Return the module address in high memory (now that it isn't copied anymore). * kern/i386/pc/startup.S (grub_memdisk_image_size): Remove variable. (codestart): Don't add grub_memdisk_image_size to %ecx in LZMA decompression routine (grub_total_module_size already includes that now). Don't copy modules back to low memory. * kern/main.c: Include `'. (grub_load_modules): Split out (and use) ... (grub_module_iterate): ... this function, which iterates through module objects and runs a hook. Comment out grub_mm_init_region() call, as it would cause non-ELF modules to be overwritten. * util/i386/pc/grub-mkimage.c (generate_image): Instead of appending the memdisk image in its own region, make it part of the module list. * util/elf/grub-mkimage.c (options): Add "memdisk"|'m' option. (main): Parse --memdisk|-m option, and pass user-provided path as parameter to generate_image(). (add_segments): Pass `memdisk_path' down to load_modules(). (load_modules): Embed memdisk image in module section when requested. * conf/powerpc-ieee1275.rmk (pkglib_MODULES): Add `memdisk.mod'. (memdisk_mod_SOURCES, memdisk_mod_CFLAGS) (memdisk_mod_LDFLAGS): New variables. * conf/i386-coreboot.rmk: Likewise. * conf/i386-ieee1275.rmk: Likewise. Index: conf/i386-coreboot.rmk =================================================================== --- conf/i386-coreboot.rmk (revision 1754) +++ conf/i386-coreboot.rmk (working copy) @@ -94,7 +94,7 @@ # Modules. pkglib_MODULES = _linux.mod linux.mod normal.mod \ _multiboot.mod multiboot.mod aout.mod \ - play.mod cpuid.mod serial.mod ata.mod + play.mod cpuid.mod serial.mod ata.mod memdisk.mod # For _linux.mod. _linux_mod_SOURCES = loader/i386/pc/linux.c @@ -154,4 +154,9 @@ ata_mod_CFLAGS = $(COMMON_CFLAGS) ata_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 Index: conf/powerpc-ieee1275.rmk =================================================================== --- conf/powerpc-ieee1275.rmk (revision 1754) +++ conf/powerpc-ieee1275.rmk (working copy) @@ -110,7 +110,8 @@ reboot.mod \ suspend.mod \ _multiboot.mod \ - multiboot.mod + multiboot.mod \ + memdisk.mod # For _linux.mod. _linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c @@ -159,6 +160,10 @@ multiboot_mod_CFLAGS = $(COMMON_CFLAGS) multiboot_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 Index: conf/i386-ieee1275.rmk =================================================================== --- conf/i386-ieee1275.rmk (revision 1754) +++ conf/i386-ieee1275.rmk (working copy) @@ -102,7 +102,7 @@ # Modules. pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod cpuid.mod \ multiboot.mod _multiboot.mod aout.mod serial.mod linux.mod \ - _linux.mod nand.mod + _linux.mod nand.mod memdisk.mod # For normal.mod. normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \ @@ -171,4 +171,9 @@ nand_mod_CFLAGS = $(COMMON_CFLAGS) nand_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 Index: disk/memdisk.c =================================================================== --- disk/memdisk.c (revision 1754) +++ disk/memdisk.c (working copy) @@ -82,21 +82,30 @@ GRUB_MOD_INIT(memdisk) { - char *memdisk_orig_addr; + auto int hook (struct grub_module_header *); + int hook (struct grub_module_header *header) + { + if (header->type == OBJ_TYPE_MEMDISK) + { + char *memdisk_orig_addr; + memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header); - memdisk_size = grub_arch_memdisk_size (); - if (! memdisk_size) - return; + grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr); - memdisk_orig_addr = (char *) grub_arch_memdisk_addr (); - grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr); + memdisk_size = header->size - sizeof (struct grub_module_header); + memdisk_addr = grub_malloc (memdisk_size); - memdisk_addr = grub_malloc (memdisk_size); + grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n"); + grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size); - grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n"); - grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size); + grub_disk_dev_register (&grub_memdisk_dev); + return 1; + } - grub_disk_dev_register (&grub_memdisk_dev); + return 0; + } + + grub_module_iterate (hook); } GRUB_MOD_FINI(memdisk) Index: kern/device.c =================================================================== --- kern/device.c (revision 1754) +++ kern/device.c (working copy) @@ -50,7 +50,8 @@ disk = grub_disk_open (name); if (! disk) { - grub_error (GRUB_ERR_BAD_DEVICE, "unknown device %s", name); + grub_print_error (); + grub_errno = GRUB_ERR_NONE; goto fail; } Index: kern/i386/pc/startup.S =================================================================== --- kern/i386/pc/startup.S (revision 1754) +++ kern/i386/pc/startup.S (working copy) @@ -96,8 +96,6 @@ .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 */ @@ -211,7 +209,6 @@ call lzo1x_decompress addl $12, %esp - /* copy back the decompressed part */ movl %eax, %ecx cld #elif defined(ENABLE_LZMA) @@ -221,19 +218,22 @@ pushl %esi movl EXT_C(grub_kernel_image_size), %ecx addl EXT_C(grub_total_module_size), %ecx - addl EXT_C(grub_memdisk_image_size), %ecx subl $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx pushl %ecx leal (%edi, %ecx), %ebx call _LzmaDecodeA + /* _LzmaDecodeA clears DF, so no need to run cld */ popl %ecx popl %edi popl %esi #endif + /* copy back the decompressed part (except the modules) */ + subl EXT_C(grub_total_module_size), %ecx rep movsb +#if 0 /* copy modules before cleaning out the bss */ movl EXT_C(grub_total_module_size), %ecx movl EXT_C(grub_kernel_image_size), %esi @@ -246,6 +246,7 @@ std rep movsb +#endif /* clean out the bss */ movl $BSS_START_SYMBOL, %edi Index: kern/i386/pc/init.c =================================================================== --- kern/i386/pc/init.c (revision 1754) +++ kern/i386/pc/init.c (working copy) @@ -250,21 +250,6 @@ grub_addr_t 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; + + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE); } - -/* Return the size of the memdisk image. */ -grub_off_t -grub_arch_memdisk_size (void) -{ - return grub_memdisk_image_size; -} Index: kern/main.c =================================================================== --- kern/main.c (revision 1754) +++ kern/main.c (working copy) @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -28,9 +27,8 @@ #include #include -/* Load all modules in core. */ -static void -grub_load_modules (void) +void +grub_module_iterate (int (*hook) (struct grub_module_header *header)) { struct grub_module_info *modinfo; struct grub_module_header *header; @@ -47,13 +45,30 @@ header < (struct grub_module_header *) (modbase + modinfo->size); header = (struct grub_module_header *) ((char *) header + header->size)) { - if (! grub_dl_load_core ((char *) header + header->offset, - (header->size - header->offset))) + if (hook (header)) + break; + } +} + +/* Load all modules in core. */ +static void +grub_load_modules (void) +{ + auto int hook (struct grub_module_header *); + int hook (struct grub_module_header *header) + { + /* Not an ELF module, skip. */ + if (header->type != OBJ_TYPE_ELF) + return 0; + + if (! grub_dl_load_core ((char *) header + sizeof (struct grub_module_header), + (header->size - sizeof (struct grub_module_header)))) grub_fatal ("%s", grub_errmsg); + + return 0; } - /* Add the region where modules reside into dynamic memory. */ - grub_mm_init_region ((void *) modinfo, modinfo->size); + grub_module_iterate (hook); } /* Write hook for the environment variables of root. Remove surrounding Index: include/grub/kernel.h =================================================================== --- include/grub/kernel.h (revision 1754) +++ include/grub/kernel.h (working copy) @@ -25,9 +25,15 @@ /* The module header. */ struct grub_module_header { - /* The offset of object code. */ - grub_target_off_t offset; - /* The size of object code plus this header. */ + /* The type of object. */ + grub_int8_t type; + enum + { + OBJ_TYPE_ELF, + OBJ_TYPE_MEMDISK, + } grub_module_header_types; + + /* The size of object (including this header). */ grub_target_size_t size; }; @@ -49,6 +55,8 @@ extern grub_addr_t grub_arch_modules_addr (void); +extern void EXPORT_FUNC(grub_module_iterate) (int (*hook) (struct grub_module_header *)); + /* The start point of the C code. */ void grub_main (void); Index: include/grub/i386/pc/kernel.h =================================================================== --- include/grub/i386/pc/kernel.h (revision 1754) +++ include/grub/i386/pc/kernel.h (working copy) @@ -34,14 +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 0x20 +#define GRUB_KERNEL_MACHINE_PREFIX 0x1c /* End of the data section. */ -#define GRUB_KERNEL_MACHINE_DATA_END 0x60 +#define GRUB_KERNEL_MACHINE_DATA_END 0x5c /* The size of the first region which won't be compressed. */ #if defined(ENABLE_LZO) @@ -67,9 +64,6 @@ /* 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[]; @@ -83,9 +77,6 @@ /* The end address of the kernel. */ extern grub_addr_t grub_end_addr; -extern grub_addr_t EXPORT_FUNC(grub_arch_memdisk_addr) (void); -extern grub_off_t EXPORT_FUNC(grub_arch_memdisk_size) (void); - #endif /* ! ASM_FILE */ #endif /* ! KERNEL_MACHINE_HEADER */ Index: util/i386/pc/grub-mkimage.c =================================================================== --- util/i386/pc/grub-mkimage.c (revision 1754) +++ util/i386/pc/grub-mkimage.c (working copy) @@ -146,19 +146,21 @@ kernel_size = grub_util_get_image_size (kernel_path); total_module_size = sizeof (struct grub_module_info); - for (p = path_list; p; p = p->next) - total_module_size += (grub_util_get_image_size (p->name) - + sizeof (struct grub_module_header)); - grub_util_info ("the total module size is 0x%x", 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); + total_module_size += memdisk_size + sizeof (struct grub_module_header); } - kernel_img = xmalloc (kernel_size + total_module_size + memdisk_size); + for (p = path_list; p; p = p->next) + total_module_size += (grub_util_get_image_size (p->name) + + sizeof (struct grub_module_header)); + + grub_util_info ("the total module size is 0x%x", total_module_size); + + kernel_img = xmalloc (kernel_size + total_module_size); grub_util_load_image (kernel_path, kernel_img); if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END) @@ -180,7 +182,7 @@ mod_size = grub_util_get_image_size (p->name); header = (struct grub_module_header *) (kernel_img + offset); - header->offset = grub_cpu_to_le32 (sizeof (*header)); + header->type = grub_cpu_to_le32 (OBJ_TYPE_ELF); header->size = grub_cpu_to_le32 (mod_size + sizeof (*header)); offset += sizeof (*header); @@ -190,11 +192,18 @@ if (memdisk_path) { + struct grub_module_header *header; + + header = (struct grub_module_header *) (kernel_img + offset); + header->type = grub_cpu_to_le32 (OBJ_TYPE_MEMDISK); + header->size = grub_cpu_to_le32 (memdisk_size + sizeof (*header)); + offset += sizeof (*header); + grub_util_load_image (memdisk_path, kernel_img + offset); offset += memdisk_size; } - compress_kernel (kernel_img, kernel_size + total_module_size + memdisk_size, + compress_kernel (kernel_img, kernel_size + total_module_size, &core_img, &core_size); grub_util_info ("the core size is 0x%x", core_size); @@ -229,8 +238,6 @@ = 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); Index: util/elf/grub-mkimage.c =================================================================== --- util/elf/grub-mkimage.c (revision 1754) +++ util/elf/grub-mkimage.c (working copy) @@ -97,19 +97,26 @@ void load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir, - char *mods[], FILE *out) + char *mods[], FILE *out, char *memdisk_path) { char *module_img; struct grub_util_path_list *path_list; struct grub_util_path_list *p; struct grub_module_info *modinfo; - size_t offset; - size_t total_module_size; + size_t offset, total_module_size, memdisk_size; path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods); offset = sizeof (struct grub_module_info); total_module_size = sizeof (struct grub_module_info); + + 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); + total_module_size += memdisk_size + sizeof (struct grub_module_header); + } + for (p = path_list; p; p = p->next) { total_module_size += (grub_util_get_image_size (p->name) @@ -135,7 +142,7 @@ mod_size = grub_util_get_image_size (p->name); header = (struct grub_module_header *) (module_img + offset); - header->offset = grub_host_to_target32 (sizeof (*header)); + header->type = grub_host_to_target32 (OBJ_TYPE_ELF); header->size = grub_host_to_target32 (mod_size + sizeof (*header)); grub_util_load_image (p->name, module_img + offset + sizeof (*header)); @@ -143,6 +150,20 @@ offset += sizeof (*header) + mod_size; } + if (memdisk_path) + { + struct grub_module_header *header; + + header = (struct grub_module_header *) (module_img + offset); + header->type = grub_cpu_to_le32 (OBJ_TYPE_MEMDISK); + header->size = grub_cpu_to_le32 (memdisk_size + sizeof (*header)); + offset += sizeof (*header); + + grub_util_load_image (memdisk_path, module_img + offset); + offset += memdisk_size; + } + + /* Write the module data to the new segment. */ grub_util_write_image_at (module_img, total_module_size, grub_host_to_target32 (phdr->p_offset), out); @@ -158,7 +179,7 @@ } void -add_segments (char *dir, char *prefix, FILE *out, int chrp, char *mods[]) +add_segments (char *dir, char *prefix, FILE *out, int chrp, char *mods[], char *memdisk_path) { Elf32_Ehdr ehdr; Elf32_Phdr *phdrs = NULL; @@ -247,7 +268,7 @@ phdr->p_offset = grub_host_to_target32 (ALIGN_UP (grub_util_get_fp_size (out), GRUB_TARGET_SIZEOF_LONG)); - load_modules (modbase, phdr, dir, mods, out); + load_modules (modbase, phdr, dir, mods, out, memdisk_path); } if (chrp) @@ -289,6 +310,7 @@ { {"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'}, {"note", no_argument, 0, 'n'}, @@ -310,6 +332,7 @@ \n\ -d, --directory=DIR use images and modules under DIR [default=%s]\n\ -p, --prefix=DIR set grub_prefix directory\n\ +-m, --memdisk=FILE embed FILE as a memdisk image\n\ -o, --output=FILE output a generated image to FILE\n\ -h, --help display this message and exit\n\ -n, --note add NOTE segment for CHRP Open Firmware\n\ @@ -329,13 +352,14 @@ char *output = NULL; char *dir = NULL; char *prefix = NULL; + char *memdisk = NULL; int chrp = 0; progname = "grub-mkimage"; while (1) { - int c = getopt_long (argc, argv, "d:p:o:hVvn", options, 0); + int c = getopt_long (argc, argv, "d:p:m:o:hVvn", options, 0); if (c == -1) break; @@ -351,6 +375,16 @@ free (prefix); prefix = xstrdup (optarg); break; + case 'm': + if (memdisk) + free (memdisk); + memdisk = xstrdup (optarg); + + if (prefix) + free (prefix); + prefix = xstrdup ("(memdisk)/boot/grub"); + + break; case 'h': usage (0); break; @@ -381,7 +415,7 @@ if (! fp) grub_util_error ("cannot open %s", output); - add_segments (dir ? : GRUB_LIBDIR, prefix, fp, chrp, argv + optind); + add_segments (dir ? : GRUB_LIBDIR, prefix, fp, chrp, argv + optind, memdisk); fclose (fp);