Hello,

Attached patches add support for XZ compressed memory disk.
01_xzmisc.diff moves some code from xzio to xzembed to reuse it in xzmemdisk
02_xzmemdisk.diff adds new module xzmemdisk.mod and new option for grub-mkimage 

xzmemdisk.mod depends on gcry_crc.mod and crypto.mod (~22KiB)

To compress memdisk please use following command:
xz --lzma2=dict=2MiB --check=crc32 memdisk.tar
You can adjust dictionary size if needed (dictionary larger than memdisk.tar 
does not improve compression ratio).

I've noticed that on i386 memdisk.tar gets better compresion ratio without BCJ 
filter.

Example (all GRUB modules in tar) size profit:  1296 KiB vs 392 KiB.

Comments and testing(!) are welcome :)

-- 
Szymon K. Janc
szy...@janc.net.pl // GG: 1383435
=== modified file 'ChangeLog'
--- old/ChangeLog	2010-09-14 22:39:49 +0000
+++ new/ChangeLog	2010-09-15 23:05:16 +0000
@@ -1,3 +1,16 @@
+2010-09-16  Szymon Janc <szy...@janc.net.pl>
+
+	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.
+
+	* grub-core/lib/xzembed/xz_dec_stream.h: New defines 
+	XZ_STREAM_FOOTER_SIZE, XZ_CRC_SIZE, VLI_MAX_DIGITS.
+	* grub-core/lib/xzembed/xz_misc.h: New file.
+	* grub-core/lib/xzembed/xz_misc.c: New file.
+	* grub-core/io/xzio.c (test_footer): Rewritten to use helper functions
+	from grub-core/lib/xzembed/xz_misc.h.
+	* grub-core/Makefile.core.def (xzio): Include lib/xzembed/xz_misc.c.
+
 2010-09-15  Szymon Janc <szy...@janc.net.pl>
 
 	* grub-core/lib/xzembed/xz_dec_stream.c (dec_main): Fix index and block

=== modified file 'grub-core/Makefile.core.def'
--- old/grub-core/Makefile.core.def	2010-09-14 20:32:33 +0000
+++ new/grub-core/Makefile.core.def	2010-09-15 23:05:16 +0000
@@ -1424,6 +1424,7 @@
   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';
 };
 

=== modified file 'grub-core/io/xzio.c'
--- old/grub-core/io/xzio.c	2010-09-05 15:12:13 +0000
+++ new/grub-core/io/xzio.c	2010-09-15 23:05:16 +0000
@@ -26,10 +26,9 @@
 
 #include "xz.h"
 #include "xz_stream.h"
+#include "xz_misc.h"
 
 #define XZBUFSIZ 0x2000
-#define VLI_MAX_DIGITS 9
-#define XZ_STREAM_FOOTER_SIZE 12
 
 struct grub_xzio
 {
@@ -44,46 +43,6 @@
 typedef struct grub_xzio *grub_xzio_t;
 static struct grub_fs grub_xzio_fs;
 
-static grub_size_t
-decode_vli (const grub_uint8_t buf[], grub_size_t size_max,
-	    grub_uint64_t * num)
-{
-  if (size_max == 0)
-    return 0;
-
-  if (size_max > VLI_MAX_DIGITS)
-    size_max = VLI_MAX_DIGITS;
-
-  *num = buf[0] & 0x7F;
-  grub_size_t i = 0;
-
-  while (buf[i++] & 0x80)
-    {
-      if (i >= size_max || buf[i] == 0x00)
-	return 0;
-
-      *num |= (uint64_t) (buf[i] & 0x7F) << (i * 7);
-    }
-
-  return i;
-}
-
-static grub_ssize_t
-read_vli (grub_file_t file, grub_uint64_t * num)
-{
-  grub_uint8_t buf[VLI_MAX_DIGITS];
-  grub_ssize_t read;
-  grub_size_t dec;
-
-  read = grub_file_read (file, buf, VLI_MAX_DIGITS);
-  if (read < 0)
-    return -1;
-
-  dec = decode_vli (buf, read, num);
-  grub_file_seek (file, file->offset - (read - dec));
-  return dec;
-}
-
 /* Function xz_dec_run() should consume header and ask for more (XZ_OK)
  * else file is corrupted (or options not supported) or not xz.  */
 static int
@@ -121,55 +80,43 @@
 static int
 test_footer (grub_file_t file)
 {
+
   grub_xzio_t xzio = file->data;
-  grub_uint8_t footer[FOOTER_MAGIC_SIZE];
+  grub_uint8_t footer[XZ_STREAM_FOOTER_SIZE];
   grub_uint32_t backsize;
-  grub_uint8_t imarker;
-  grub_uint64_t uncompressed_size_total = 0;
   grub_uint64_t uncompressed_size;
-  grub_uint64_t records;
-
-  grub_file_seek (xzio->file, xzio->file->size - FOOTER_MAGIC_SIZE);
-  if (grub_file_read (xzio->file, footer, FOOTER_MAGIC_SIZE) !=
-      FOOTER_MAGIC_SIZE
-      || grub_memcmp (footer, FOOTER_MAGIC, FOOTER_MAGIC_SIZE) != 0)
-    goto ERROR;
-
-  grub_file_seek (xzio->file, xzio->file->size - 8);
-  if (grub_file_read (xzio->file, &backsize, sizeof (backsize))
-      != sizeof (backsize))
-    goto ERROR;
-
-  /* Calculate real backward size.  */
-  backsize = (grub_le_to_cpu32 (backsize) + 1) * 4;
+  grub_uint8_t *index = 0;
+
+  grub_file_seek (xzio->file, xzio->file->size - XZ_STREAM_FOOTER_SIZE);
+  if (grub_file_read (xzio->file, footer, XZ_STREAM_FOOTER_SIZE) != XZ_STREAM_FOOTER_SIZE)
+    {
+	  goto ERROR;
+    }
+
+  /* Test footer and calculate real backward size.  */
+  backsize = xz_test_footer(footer, XZ_STREAM_FOOTER_SIZE);
+  if(backsize == 0)
+    {
+	  goto ERROR;
+    }
 
   /* Set file to the beginning of stream index.  */
-  grub_file_seek (xzio->file,
-		  xzio->file->size - XZ_STREAM_FOOTER_SIZE - backsize);
-
-  /* Test index marker.  */
-  if (grub_file_read (xzio->file, &imarker, sizeof (imarker)) !=
-      sizeof (imarker) && imarker != 0x00)
-    goto ERROR;
-
-  if (read_vli (xzio->file, &records) <= 0)
-    goto ERROR;
-
-  for (; records != 0; records--)
+  grub_file_seek (xzio->file, xzio->file->size - XZ_STREAM_FOOTER_SIZE - backsize);
+
+  /* Test index.  */
+  index = grub_malloc(backsize);
+  if(!index	|| grub_file_read(xzio->file, index, backsize) != (grub_ssize_t)backsize
+		|| !xz_test_index(index, backsize, &uncompressed_size))
     {
-      if (read_vli (xzio->file, &uncompressed_size) <= 0)	/* Ignore unpadded.  */
-	goto ERROR;
-      if (read_vli (xzio->file, &uncompressed_size) <= 0)	/* Uncompressed.  */
-	goto ERROR;
-
-      uncompressed_size_total += uncompressed_size;
+	goto ERROR;
     }
 
-  file->size = uncompressed_size_total;
+  file->size = uncompressed_size;
   grub_file_seek (xzio->file, STREAM_HEADER_SIZE);
   return 1;
 
 ERROR:
+  grub_free(index);
   grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "bad footer magic");
   return 0;
 }

=== added file 'grub-core/lib/xzembed/xz_misc.c'
--- old/grub-core/lib/xzembed/xz_misc.c	1970-01-01 00:00:00 +0000
+++ new/grub-core/lib/xzembed/xz_misc.c	2010-09-15 23:05:16 +0000
@@ -0,0 +1,88 @@
+/* xz_misc.c - Common helper functions for xz file format decoder.  */
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "xz_misc.h"
+
+static grub_size_t
+xz_decode_vli (const grub_uint8_t buf[], grub_size_t size_max,
+	       grub_uint64_t * num)
+{
+  if (size_max == 0)
+    return 0;
+
+  if (size_max > VLI_MAX_DIGITS)
+    size_max = VLI_MAX_DIGITS;
+
+  *num = buf[0] & 0x7F;
+  grub_size_t i = 0;
+
+  while (buf[i++] & 0x80)
+    {
+      if (i >= size_max || buf[i] == 0x00)
+	return 0;
+
+      *num |= (uint64_t) (buf[i] & 0x7F) << (i * 7);
+    }
+
+  return i;
+}
+
+int
+xz_test_index (const grub_uint8_t * index, grub_size_t size,
+	       grub_uint64_t * usize)
+{
+  if (size == 0 || index[0] != 0x00)
+    return 0;
+
+  index++;
+  size--;
+
+  grub_uint64_t records;
+  *usize = 0;
+  grub_uint64_t uncompressed_size;
+  grub_size_t ret;
+
+  ret = xz_decode_vli (index, size, &records);
+  index += ret;
+  size -= ret;
+
+  for (; records != 0; records--)
+    {
+      ret = xz_decode_vli (index, size, &uncompressed_size);	/* Ignore unpadded.  */
+      index += ret;
+      size -= ret;
+
+      ret = xz_decode_vli (index, size, &uncompressed_size);	/* Uncompressed.  */
+      index += ret;
+      size -= ret;
+
+      *usize += uncompressed_size;
+    }
+
+  /* Check padding.  */
+  while (size % 4)
+    {
+      if (size == 0 || *index != 0)
+	return 0;
+      index++;
+      size--;
+    }
+
+  return (size == XZ_CRC_SIZE);
+}

=== added file 'grub-core/lib/xzembed/xz_misc.h'
--- old/grub-core/lib/xzembed/xz_misc.h	1970-01-01 00:00:00 +0000
+++ new/grub-core/lib/xzembed/xz_misc.h	2010-09-15 23:05:16 +0000
@@ -0,0 +1,42 @@
+/* xz_misc.h - Common helper functions for xz file format decoder.  */
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef XZ_MISC_H
+#define XZ_MISC_H
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include "xz_stream.h"
+
+/* On success returns calculated backward size or 0 if error occurred.  */
+inline static grub_uint32_t
+xz_test_footer(const grub_uint8_t *buf, grub_size_t size)
+{
+	return (size == XZ_STREAM_FOOTER_SIZE
+			&& grub_memcmp(buf + XZ_STREAM_FOOTER_SIZE - FOOTER_MAGIC_SIZE,
+					FOOTER_MAGIC, FOOTER_MAGIC_SIZE) == 0)
+			? (grub_le_to_cpu32 (*(grub_uint32_t*)(buf + XZ_CRC_SIZE)) + 1) * 4 : 0;
+}
+
+/* Test index and get uncompressed data size (on success).  */
+int
+xz_test_index(const grub_uint8_t index[], grub_size_t size,
+		grub_uint64_t *usize);
+
+#endif

=== modified file 'grub-core/lib/xzembed/xz_stream.h'
--- old/grub-core/lib/xzembed/xz_stream.h	2010-09-05 15:12:13 +0000
+++ new/grub-core/lib/xzembed/xz_stream.h	2010-09-15 23:05:16 +0000
@@ -24,6 +24,8 @@
 #ifndef XZ_STREAM_H
 #define XZ_STREAM_H
 
+#include <stdint.h>
+
 /*
  * See the .xz file format specification at
  * http://tukaani.org/xz/xz-file-format.txt
@@ -38,6 +40,9 @@
 #define FOOTER_MAGIC "YZ"
 #define FOOTER_MAGIC_SIZE 2
 
+#define XZ_STREAM_FOOTER_SIZE 12
+#define XZ_CRC_SIZE 4
+
 /*
  * Variable-length integer can hold a 63-bit unsigned integer, or a special
  * value to indicate that the value is unknown.
@@ -49,5 +54,6 @@
 
 /* Maximum encoded size of a VLI */
 #define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7)
+#define VLI_MAX_DIGITS 9
 
 #endif

=== 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 <szy...@janc.net.pl>
 
+	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 <szy...@janc.net.pl>
+
 	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 <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>
+
+#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/@platf...@]\n\
   -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);
 

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to