All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] memdisk plus lnxboot extension
@ 2007-12-29  9:05 Bean
  2007-12-30 13:48 ` Robert Millan
  0 siblings, 1 reply; 30+ messages in thread
From: Bean @ 2007-12-29  9:05 UTC (permalink / raw)
  To: The development of GRUB 2

Hi,

This patch is based on robert's memdisk patch. I also modify lnxboot
so that it can load the memdisk using initrd. Changes:

1, copy memdisk to grub_alloc'ed memory in grub_machine_init, so that
it won't be corrupted.
2, code cleanup for lnxboot.S, now it doesn't contain code that uses
32-bit address.
3, lnxboot.S will set the memdisk address to the initrd image
4, add option -x for grub-mkimage, it's used to build linux format
kernel directly.

./grub-mkimage -x -o grub2.bin modules

Now you can load memdisk using initrd:

kernel grub2.bin
initrd memdisk

or embed it in grub2.bin/core.img using -m option

./grub-mkimage -x -o grub2.bin -m memdisk modules

If both memdisk is used, external memdisk will take preference.

diff --git a/boot/i386/pc/lnxboot.S b/boot/i386/pc/lnxboot.S
index f1a4ded..6503e26 100644
--- a/boot/i386/pc/lnxboot.S
+++ b/boot/i386/pc/lnxboot.S
@@ -36,22 +36,7 @@
         .globl  start, _start

 data_start:
-	pushw	%cs
-	popw	%ds
-	xorl	%eax, %eax
-	xorl	%ebx, %ebx
-	call	data_next
-
-data_next:
-	popw	%bx
-	movw	%cs, %ax
-	shll	$4, %eax
-	leal	0x200 + data_start - data_next(%ebx,%eax), %eax
-	movzbl	setup_sects - data_next(%bx), %ecx
-	shll	$9, %ecx
-	addl	%ecx, %eax
-	movl	%eax, code32_start - data_next(%bx)
-
+	xorl	%ebp, %ebp
 	jmp	linux_next

 	. = data_start + 0x1F1
@@ -76,7 +61,7 @@ boot_flag:
 start:
 _start:

-	jmp linux_code
+	jmp linux_init

 	.ascii	"HdrS"			// Header signature
 	.word	0x0203			// Header version number
@@ -134,9 +119,10 @@ reg_edx:
 data_leng:
 	.long	0

-linux_code:
+linux_init:

 	movw	%cs:(reg_edx - start), %dx
+	movl	%cs:(code32_start - start), %ebp

 linux_next:

@@ -164,9 +150,6 @@ real_code:
 	movw	%si, %ss
 	movw	$(CODE_ADDR), %sp

-	pushl	%esi
-	pushl	%edi
-
 	// Move itself to 0:CODE_ADDR

 	cld
@@ -183,17 +166,26 @@ real_code:

 real_code_2:

+	xchgl	%ebp, %esi
+	orl	%esi, %esi
+	jnz	1f
+	movw	%ds, %si
+	shll	$4, %esi
+	addl	%ebp, %esi
+1:
+
 	pushw	%es
 	popw	%ds

-	movl	(ramdisk_image - start), %esi
-	or	%esi, %esi
+	movl	(data_leng - start), %ecx
+	or	%ecx, %ecx
 	jnz	1f
-	movl	(code32_start - start), %esi
+	movl	(ramdisk_image - start), %esi
+	movl	(ramdisk_size - start), %ecx
+	addl	$0x200, %esi
+	subl	$0x200, %ecx
 1:

-	movl	$0x200, %ecx
-	addl	%ecx, %esi
 	movl	$DATA_ADDR, %edi

 	call	move_memory
@@ -204,13 +196,17 @@ real_code_2:
 	movsbl	(reg_edx + 2 - start), %eax
 	movl	%eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART)

-	movl	%ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx
-	addl	$(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx
+	movl	(data_leng - start), %eax
+	or	%eax, %eax
+	jz	1f
+	movl	(ramdisk_size - start), %eax
+	or	%eax, %eax
+	jz	1f

-	call	move_memory
-
-	popl	%edi
-	popl	%esi
+	movl	%eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE)
+	movl	(ramdisk_image - start), %eax
+	movl	%eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_ADDR)
+1:

 	ljmp	$(DATA_ADDR >> 4), $0

@@ -261,8 +257,8 @@ move_memory:

 2:

-	leal	(%esi, %eax), %esi
-	leal	(%edi, %eax), %edi
+	addl	%eax, %esi
+	addl	%eax, %edi
 	subl	%eax, %ecx
 	jnz	1b

diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 2638ee5..b5f6a04 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -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
+	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 --git a/include/grub/disk.h b/include/grub/disk.h
index 4301942..9891a9c 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -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 --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h
index ec207a5..126df2b 100644
--- a/include/grub/i386/pc/kernel.h
+++ b/include/grub/i386/pc/kernel.h
@@ -34,8 +34,14 @@
 /* The offset of GRUB_INSTALL_BSD_PART.  */
 #define GRUB_KERNEL_MACHINE_INSTALL_BSD_PART	0x18

+/* The offset of GRUB_MEMDISK_IMAGE_ADDR   */
+#define GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_ADDR	0x1c
+
+/* The offset of GRUB_MEMDISK_IMAGE_SIZE.  */
+#define GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE	0x20
+
 /* The offset of GRUB_PREFIX.  */
-#define GRUB_KERNEL_MACHINE_PREFIX		0x1c
+#define GRUB_KERNEL_MACHINE_PREFIX		0x24

 /* End of the data section. */
 #define GRUB_KERNEL_MACHINE_DATA_END		0x50
@@ -47,12 +53,24 @@

 #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 address of memory disk image, if present.  */
+extern grub_int32_t grub_memdisk_image_addr;
+
+/* 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[];
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
index 77d209a..7413e19 100644
--- a/include/grub/kernel.h
+++ b/include/grub/kernel.h
@@ -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);
diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c
index 72ff9a2..2bdbc49 100644
--- a/kern/i386/pc/init.c
+++ b/kern/i386/pc/init.c
@@ -229,9 +229,26 @@ grub_machine_init (void)
       }
     else
       grub_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size);
-
+
   if (! grub_os_area_addr)
     grub_fatal ("no upper memory");
+
+  if (grub_memdisk_image_size)
+    {
+      char *p;
+
+      if (! grub_memdisk_image_addr)
+        grub_memdisk_image_addr = 0x100000 + (grub_kernel_image_size
- GRUB_KERNEL_MACHINE_RAW_SIZE) + grub_total_module_size;
+
+      p = grub_malloc (grub_memdisk_image_size);
+      if (! p)
+        grub_memdisk_image_size = 0;  // Not enough memory, dump the memdisk
+      else
+        {
+          grub_memcpy (p, (char*) grub_memdisk_image_addr,
grub_memdisk_image_size);
+	  grub_memdisk_image_addr = (grub_uint32_t) p;
+	}
+    }
 }

 void
@@ -253,3 +270,17 @@ 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_memdisk_image_addr;
+}
+
+/* Return the size of the memdisk image.  */
+grub_off_t
+grub_arch_memdisk_size (void)
+{
+  return grub_memdisk_image_size;
+}
diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S
index 4267f5b..33b301c 100644
--- a/kern/i386/pc/startup.S
+++ b/kern/i386/pc/startup.S
@@ -95,6 +95,10 @@ VARIABLE(grub_install_dos_part)
 	.long	0xFFFFFFFF
 VARIABLE(grub_install_bsd_part)
 	.long	0xFFFFFFFF
+VARIABLE(grub_memdisk_image_addr)
+	.long	0
+VARIABLE(grub_memdisk_image_size)
+	.long	0
 VARIABLE(grub_prefix)
 	/* to be filled by grub-mkimage */

diff --git a/util/i386/pc/grub-mkimage.c b/util/i386/pc/grub-mkimage.c
index e19649d..dd48509 100644
--- a/util/i386/pc/grub-mkimage.c
+++ b/util/i386/pc/grub-mkimage.c
@@ -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, int is_linux)
 {
   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);
@@ -137,17 +150,25 @@ generate_image (const char *dir, char *prefix,
FILE *out, char *mods[])
   if (num > 0xffff)
     grub_util_error ("the core image is too big");

-  boot_path = grub_util_get_path (dir, "diskboot.img");
+  boot_path = grub_util_get_path (dir, (is_linux)?
"lnxboot.img":"diskboot.img");
   boot_size = grub_util_get_image_size (boot_path);
-  if (boot_size != GRUB_DISK_SECTOR_SIZE)
+  if ((! is_linux) && (boot_size != GRUB_DISK_SECTOR_SIZE))
     grub_util_error ("diskboot.img is not one sector size");

   boot_img = grub_util_read_image (boot_path);
-
-  /* i386 is a little endian architecture.  */
-  *((grub_uint16_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
+
+  if (is_linux)
+    {
+      *((grub_uint32_t *) (boot_img + 0x264))
+      = grub_cpu_to_le32 (core_size);
+    }
+  else
+    {
+      /* i386 is a little endian architecture.  */
+      *((grub_uint16_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
 		       - GRUB_BOOT_MACHINE_LIST_SIZE + 8))
-    = grub_cpu_to_le16 (num);
+      = grub_cpu_to_le16 (num);
+    }

   grub_util_write_image (boot_img, boot_size, out);
   free (boot_img);
@@ -163,6 +184,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,7 +209,9 @@ static struct option options[] =
   {
     {"directory", required_argument, 0, 'd'},
     {"prefix", required_argument, 0, 'p'},
+    {"memdisk", required_argument, 0, 'm'},
     {"output", required_argument, 0, 'o'},
+    {"linux", no_argument, 0, 'x'},
     {"help", no_argument, 0, 'h'},
     {"version", no_argument, 0, 'V'},
     {"verbose", no_argument, 0, 'v'},
@@ -206,7 +231,9 @@ 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\
+  -x, --linux             add linux header\n\
   -h, --help              display this message and exit\n\
   -V, --version           print version information and exit\n\
   -v, --verbose           print verbose messages\n\
@@ -223,13 +250,15 @@ main (int argc, char *argv[])
   char *output = NULL;
   char *dir = NULL;
   char *prefix = NULL;
+  char *memdisk = NULL;
   FILE *fp = stdout;
+  int is_linux = 0;

   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:hVvx", options, 0);

       if (c == -1)
 	break;
@@ -250,6 +279,17 @@ main (int argc, char *argv[])
 	    dir = xstrdup (optarg);
 	    break;

+	  case 'm':
+	    if (memdisk)
+	      free (memdisk);
+
+	    memdisk = xstrdup (optarg);
+	    break;
+
+	  case 'x':
+	    is_linux = 1;
+	    break;
+
 	  case 'h':
 	    usage (0);
 	    break;
@@ -282,7 +322,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, is_linux);

   fclose (fp);

diff --git a/disk/memdisk.c b/disk/memdisk.c
new file mode 100755
index 0000000..48e0514
--- /dev/null
+++ b/disk/memdisk.c
@@ -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);
+}


-- 
Bean



^ permalink raw reply related	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2008-01-24 21:23 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-29  9:05 [PATCH] memdisk plus lnxboot extension Bean
2007-12-30 13:48 ` Robert Millan
2008-01-20 23:24   ` Robert Millan
2008-01-22  4:25     ` Bean
2008-01-22 13:57       ` Robert Millan
2008-01-22 16:22         ` Bean
2008-01-22 16:51           ` Robert Millan
2008-01-22 17:17             ` Bean
2008-01-22 19:53               ` Robert Millan
2008-01-23  8:54         ` Marco Gerards
2008-01-23 16:18           ` Bean
2008-01-23 19:01             ` Bean
2008-01-23 19:14               ` Robert Millan
2008-01-23 19:24                 ` Bean
2008-01-23 20:15                   ` Robert Millan
2008-01-23 21:04                     ` Bean
2008-01-23 21:15                       ` Robert Millan
2008-01-24  3:40                         ` Bean
2008-01-24 11:32                           ` Robert Millan
2008-01-24 11:49                             ` Bean
2008-01-24 14:25                               ` Robert Millan
2008-01-24 14:57                                 ` Bean
2008-01-24 15:16                                   ` Robert Millan
2008-01-24 16:55                                 ` Robert Millan
2008-01-24 17:04                                   ` Bean
2008-01-24 17:21                                     ` Robert Millan
2008-01-24 18:06                                       ` Marco Gerards
2008-01-24 21:23                               ` Yoshinori K. Okuji
2008-01-23 19:10             ` Robert Millan
2008-01-23  8:48       ` Marco Gerards

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.