=== modified file 'ChangeLog' --- old/ChangeLog 2010-09-15 23:05:16 +0000 +++ new/ChangeLog 2010-09-15 23:43:38 +0000 @@ -1,5 +1,20 @@ 2010-09-16 Szymon Janc + New module xzmemdisk.mod. + Support for XZ compressed memory disk in grub-mkimage. + + * grub-core/disk/xzmemdisk.c: New file. + * grub-core/Makefile.core.def (xzmemdisk): New module. + * include/grub/disk.h (grub_disk_dev_id): Add + GRUB_DISK_DEVICE_XZMEMDISK_ID. + * include/grub/kernel.h (OBJ_TYPE_XZMEMDISK): New enum value. + * util/grub-mkimage.c: (generate_image): New parameter (int xz) to mark + memory disk as XZ compressed. Callers updated. + * util/grub-mkimage.c: New options (-M, --xzmemdisk) to include XZ + compressed memdisk into image. + +2010-09-16 Szymon Janc + Move some xz generic code from grub-core/io/xzio.c to grub-core/lib/xzembed/xz_misc.{h|c}. It will be used in xzmemdisk. === modified file 'grub-core/Makefile.core.def' --- old/grub-core/Makefile.core.def 2010-09-15 23:05:16 +0000 +++ new/grub-core/Makefile.core.def 2010-09-15 23:43:38 +0000 @@ -759,6 +759,16 @@ }; module = { + name = xzmemdisk; + common = disk/xzmemdisk.c; + common = lib/xzembed/xz_dec_bcj.c; + common = lib/xzembed/xz_dec_lzma2.c; + common = lib/xzembed/xz_dec_stream.c; + common = lib/xzembed/xz_misc.c; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed'; +}; + +module = { name = ata; common = disk/ata.c; enable = pci; === added file 'grub-core/disk/xzmemdisk.c' --- old/grub-core/disk/xzmemdisk.c 1970-01-01 00:00:00 +0000 +++ new/grub-core/disk/xzmemdisk.c 2010-09-15 23:43:38 +0000 @@ -0,0 +1,187 @@ +/* xzmemdisk.c - Access embedded xz compressed memory disk. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 + +#include "xz.h" +#include "xz_stream.h" +#include "xz_misc.h" + +static grub_uint8_t *xzmemdisk_addr = 0; +static grub_off_t xzmemdisk_size = 0; + +static int +grub_xzmemdisk_iterate (int (*hook) (const char *name)) +{ + return hook ("xzmemdisk"); +} + +static grub_err_t +grub_xzmemdisk_open (const char *name, grub_disk_t disk) +{ + if (grub_strcmp (name, "xzmemdisk")) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a xzmemdisk"); + + disk->total_sectors = xzmemdisk_size / GRUB_DISK_SECTOR_SIZE; + disk->id = (unsigned long) "xzmd"; + + return GRUB_ERR_NONE; +} + +static void +grub_xzmemdisk_close (grub_disk_t disk __attribute ((unused))) +{ +} + +static grub_err_t +grub_xzmemdisk_read (grub_disk_t disk __attribute ((unused)), + grub_disk_addr_t sector, grub_size_t size, char *buf) +{ + grub_memcpy (buf, xzmemdisk_addr + (sector << GRUB_DISK_SECTOR_BITS), + size << GRUB_DISK_SECTOR_BITS); + return 0; +} + +static grub_err_t +grub_xzmemdisk_write (grub_disk_t disk __attribute ((unused)), + grub_disk_addr_t sector, grub_size_t size, + const char *buf) +{ + grub_memcpy (xzmemdisk_addr + (sector << GRUB_DISK_SECTOR_BITS), buf, + size << GRUB_DISK_SECTOR_BITS); + return 0; +} + +static struct grub_disk_dev grub_xzmemdisk_dev = { + .name = "xzmemdisk", + .id = GRUB_DISK_DEVICE_XZMEMDISK_ID, + .iterate = grub_xzmemdisk_iterate, + .open = grub_xzmemdisk_open, + .close = grub_xzmemdisk_close, + .read = grub_xzmemdisk_read, + .write = grub_xzmemdisk_write, + .next = 0 +}; + +GRUB_MOD_INIT (xzmemdisk) +{ + auto int hook (struct grub_module_header *); + int hook (struct grub_module_header *header) + { + if (header->type == OBJ_TYPE_XZMEMDISK) + { + grub_uint8_t *xzmemdisk_orig_addr; + xzmemdisk_orig_addr = + (grub_uint8_t *) header + sizeof (struct grub_module_header); + grub_dprintf ("xzmemdisk", "Found xzmemdisk image at %p\n", + xzmemdisk_orig_addr); + xzmemdisk_size = header->size - sizeof (struct grub_module_header); + + /* Remove 512 bytes alignment padding (trailing nulls), + * xz file size is always multiple of 4 bytes. */ + grub_uint32_t pad; + pad = *(grub_uint32_t *) (xzmemdisk_orig_addr + xzmemdisk_size - 4); + while (pad == 0) + { + xzmemdisk_size -= 4; + pad = + *(grub_uint32_t *) (xzmemdisk_orig_addr + xzmemdisk_size - 4); + } + + /* Get backward size. */ + grub_uint32_t backsize; + backsize = + xz_test_footer (xzmemdisk_orig_addr + xzmemdisk_size - + XZ_STREAM_FOOTER_SIZE, XZ_STREAM_FOOTER_SIZE); + + if (backsize == 0) + return 0; + + grub_uint64_t uncompressed_size; + if (!xz_test_index (xzmemdisk_orig_addr + xzmemdisk_size - + XZ_STREAM_FOOTER_SIZE - backsize, backsize, &uncompressed_size)) + return 0; + + struct xz_buf buf; + buf.in = xzmemdisk_orig_addr; + buf.in_pos = 0; + buf.in_size = xzmemdisk_size; + + /* round up size to GRUB_DISK_SECTOR_SIZE */ + xzmemdisk_size = uncompressed_size; + while (xzmemdisk_size % GRUB_DISK_SECTOR_SIZE) + xzmemdisk_size++; + + xzmemdisk_addr = grub_malloc (xzmemdisk_size); + if (!xzmemdisk_addr) + { + grub_dprintf ("xzmemdisk", + "Cannot allocate memory for decompression"); + return 0; + } + + buf.out = xzmemdisk_addr; + buf.out_pos = 0; + buf.out_size = xzmemdisk_size; + + grub_dprintf ("xzmemdisk", + "Decompressing xzmemdisk image to dynamic memory\n"); + enum xz_ret xzret; + struct xz_dec *dec; + dec = xz_dec_init (0); + if (!dec) + { + grub_dprintf ("xzmemdisk", "Cannot initialize decompressor"); + grub_free (xzmemdisk_addr); + return 0; + } + + xzret = xz_dec_run (dec, &buf); + xz_dec_end (dec); + + if (xzret != XZ_STREAM_END) + { + grub_dprintf ("xzmemdisk", + "Decompression failed with error code %u\n", xzret); + grub_free (xzmemdisk_addr); + return 0; + } + + grub_disk_dev_register (&grub_xzmemdisk_dev); + return 1; + } + + return 0; + } + + grub_module_iterate (hook); +} + +GRUB_MOD_FINI (xzmemdisk) +{ + if (!xzmemdisk_size) + return; + grub_free (xzmemdisk_addr); + grub_disk_dev_unregister (&grub_xzmemdisk_dev); +} === modified file 'include/grub/disk.h' --- old/include/grub/disk.h 2010-09-13 21:59:22 +0000 +++ new/include/grub/disk.h 2010-09-15 23:43:38 +0000 @@ -37,6 +37,7 @@ GRUB_DISK_DEVICE_HOST_ID, GRUB_DISK_DEVICE_ATA_ID, GRUB_DISK_DEVICE_MEMDISK_ID, + GRUB_DISK_DEVICE_XZMEMDISK_ID, GRUB_DISK_DEVICE_NAND_ID, GRUB_DISK_DEVICE_UUID_ID, GRUB_DISK_DEVICE_PXE_ID, === modified file 'include/grub/kernel.h' --- old/include/grub/kernel.h 2010-08-30 18:23:04 +0000 +++ new/include/grub/kernel.h 2010-09-15 23:43:38 +0000 @@ -26,6 +26,7 @@ { OBJ_TYPE_ELF, OBJ_TYPE_MEMDISK, + OBJ_TYPE_XZMEMDISK, OBJ_TYPE_CONFIG }; === modified file 'util/grub-mkimage.c' --- old/util/grub-mkimage.c 2010-09-03 12:54:04 +0000 +++ new/util/grub-mkimage.c 2010-09-15 23:43:38 +0000 @@ -527,7 +527,7 @@ static void generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *memdisk_path, char *config_path, - struct image_target_desc *image_target, int note) + struct image_target_desc *image_target, int note, int xz) { char *kernel_img, *core_img; size_t kernel_size, total_module_size, core_size, exec_size; @@ -630,7 +630,7 @@ header = (struct grub_module_header *) (kernel_img + offset); memset (header, 0, sizeof (struct grub_module_header)); - header->type = grub_host_to_target32 (OBJ_TYPE_MEMDISK); + header->type = grub_host_to_target32 (xz ? OBJ_TYPE_XZMEMDISK : OBJ_TYPE_MEMDISK); header->size = grub_host_to_target32 (memdisk_size + sizeof (*header)); offset += sizeof (*header); @@ -1213,6 +1213,7 @@ {"directory", required_argument, 0, 'd'}, {"prefix", required_argument, 0, 'p'}, {"memdisk", required_argument, 0, 'm'}, + {"xzmemdisk", required_argument, 0, 'M'}, {"font", required_argument, 0, 'f'}, {"config", required_argument, 0, 'c'}, {"output", required_argument, 0, 'o'}, @@ -1255,6 +1256,7 @@ -d, --directory=DIR use images and modules under DIR [default=%s/@address@hidden -p, --prefix=DIR set grub_prefix directory [default=%s]\n\ -m, --memdisk=FILE embed FILE as a memdisk image\n\ + -M, --xzmemdisk=FILE embed FILE as a xz compressed memdisk image\n\ -c, --config=FILE embed FILE as boot config\n\ -n, --note add NOTE segment for CHRP Open Firmware\n\ -o, --output=FILE output a generated image to FILE [default=stdout]\n\ @@ -1281,6 +1283,7 @@ char *dir = NULL; char *prefix = NULL; char *memdisk = NULL; + int xz = 0; char *font = NULL; char *config = NULL; FILE *fp = stdout; @@ -1293,7 +1296,7 @@ while (1) { - int c = getopt_long (argc, argv, "d:p:m:c:o:O:f:hVvn", options, 0); + int c = getopt_long (argc, argv, "d:p:m:M:c:o:O:f:hVvn", options, 0); if (c == -1) break; @@ -1331,6 +1334,8 @@ note = 1; break; + case 'M': + xz = 1; case 'm': if (memdisk) free (memdisk); @@ -1340,7 +1345,7 @@ if (prefix) free (prefix); - prefix = xstrdup ("(memdisk)/boot/grub"); + prefix = xstrdup (xz ? "(xzmemdisk)/boot/grub" : "(memdisk)/boot/grub"); break; case 'c': @@ -1408,7 +1413,7 @@ generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp, argv + optind, memdisk, config, - image_target, note); + image_target, note, xz); fclose (fp);