grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] mdadm 1.2 partitions array ready


From: Gaëtan Schmidt
Subject: [PATCH] mdadm 1.2 partitions array ready
Date: Tue, 20 Jul 2010 17:56:47 +0200

        modified:   disk/i386/pc/biosdisk.c
        modified:   disk/mdraid_linux.c
        modified:   disk/raid.c
        modified:   include/grub/disk.h
        modified:   include/grub/raid.h
        modified:   kern/device.c
        modified:   kern/disk.c
        modified:   kern/fs.c
        modified:   kern/parser.c
        modified:   normal/main.c
        modified:   partmap/apple.c
        modified:   partmap/gpt.c
        modified:   util/deviceiter.c
        modified:   util/getroot.c
        modified:   util/grub-install.in
        modified:   util/grub-mkconfig.in
        modified:   util/grub-probe.c
        modified:   util/hostdisk.c
        modified:   util/i386/pc/grub-setup.c

Signed-off-by: Gaëtan Schmidt <address@hidden>
---
 disk/i386/pc/biosdisk.c   |    2 +-
 disk/mdraid_linux.c       |  177 +++++++++++++---
 disk/raid.c               |   52 ++++-
 include/grub/disk.h       |    3 +
 include/grub/raid.h       |    2 +
 kern/device.c             |    4 +
 kern/disk.c               |   17 ++-
 kern/fs.c                 |    6 +
 kern/parser.c             |    8 +-
 normal/main.c             |    6 +
 partmap/apple.c           |    4 +-
 partmap/gpt.c             |    9 +-
 util/deviceiter.c         |   19 ++
 util/getroot.c            |   23 +--
 util/grub-install.in      |    2 +-
 util/grub-mkconfig.in     |   18 ++-
 util/grub-probe.c         |   13 +-
 util/hostdisk.c           |   15 ++-
 util/i386/pc/grub-setup.c |  502 ++++++++++++++++++++++----------------------
 19 files changed, 563 insertions(+), 319 deletions(-)

diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c
index 94d0e37..4dfc49f 100644
--- a/disk/i386/pc/biosdisk.c
+++ b/disk/i386/pc/biosdisk.c
@@ -108,7 +108,7 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
     return grub_errno;
 
   disk->has_partitions = ((drive & 0x80) && (drive != cd_drive));
-  disk->id = drive;
+  disk->id = drive % 0x80; /* XXX */
 
   data = (struct grub_biosdisk_data *) grub_zalloc (sizeof (*data));
   if (! data)
diff --git a/disk/mdraid_linux.c b/disk/mdraid_linux.c
index 306c66a..e53085e 100644
--- a/disk/mdraid_linux.c
+++ b/disk/mdraid_linux.c
@@ -159,59 +159,178 @@ struct grub_raid_super_09
   struct grub_raid_disk_09 this_disk;
 } __attribute__ ((packed));
 
+struct grub_raid_super_1
+{
+           /* constant array information - 128 bytes */
+    grub_uint32_t   magic;      /* MD_SB_MAGIC: 0xa92b4efc - little endian */
+    grub_uint32_t   major_version;  /* 1 */
+    grub_uint32_t   feature_map;    /* 0 for now */
+    grub_uint32_t   pad0;       /* always set to 0 when writing */
+
+    grub_uint8_t    set_uuid[16];   /* user-space generated. */
+    char    set_name[32];   /* set and interpreted by user-space */
+
+    grub_uint64_t   ctime;      /* lo 40 bits are seconds, top 24 are 
microseconds or 0*/
+    grub_uint32_t   level;      /* -4 (multipath), -1 (linear), 0,1,4,5 */
+    grub_uint32_t   layout;     /* only for raid5 currently */
+    grub_uint64_t   size;       /* used size of component devices, in 512byte 
sectors */
+
+    grub_uint32_t   chunksize;  /* in 512byte sectors */
+    grub_uint32_t   raid_disks;
+    grub_uint32_t   bitmap_offset;  /* sectors after start of superblock that 
bitmap starts
+                 * NOTE: signed, so bitmap can be before superblock
+                 * only meaningful of feature_map[0] is set.
+                 */
+
+    /* These are only valid with feature bit '4' */
+    grub_uint32_t   new_level;  /* new level we are reshaping to        */
+    grub_uint64_t   reshape_position;   /* next address in array-space for 
reshape */
+    grub_uint32_t   delta_disks;    /* change in number of raid_disks       */
+    grub_uint32_t   new_layout; /* new layout                   */
+    grub_uint32_t   new_chunk;  /* new chunk size (bytes)           */
+    grub_uint8_t    pad1[128-124];  /* set to 0 when written */
+
+    /* constant this-device information - 64 bytes */
+    grub_uint64_t   data_offset;    /* sector start of data, often 0 */
+    grub_uint64_t   data_size;  /* sectors in this device that can be used for 
data */
+    grub_uint64_t   super_offset;   /* sector start of this superblock */
+    grub_uint64_t   recovery_offset;/* sectors before this offset (from 
data_offset) have been recovered */
+    grub_uint32_t   dev_number; /* permanent identifier of this  device - not 
role in raid */
+    grub_uint32_t   cnt_corrected_read; /* number of read errors that were 
corrected by re-writing */
+    grub_uint8_t    device_uuid[16]; /* user-space setable, ignored by kernel 
*/
+    grub_uint8_t    devflags;        /* per-device flags.  Only one 
defined...*/
+#define WriteMostly1    1        /* mask for writemostly flag in above */
+    grub_uint8_t    pad2[64-57];    /* set to 0 when writing */
+
+    /* array state information - 64 bytes */
+    grub_uint64_t   utime;      /* 40 bits second, 24 btes microseconds */
+    grub_uint64_t   events;     /* incremented when superblock updated */
+    grub_uint64_t   resync_offset;  /* data before this offset (from 
data_offset) known to be in sync */
+    grub_uint32_t   sb_csum;    /* checksum upto devs[max_dev] */
+    grub_uint32_t   max_dev;    /* size of devs[] array to consider */
+    grub_uint8_t    pad3[64-32];    /* set to 0 when writing */
+
+    /* device state information. Indexed by dev_number.
+     * 2 bytes per device
+     * Note there are no per-device state flags. State information is rolled
+     * into the 'roles' value.  If a device is spare or faulty, then it doesn't
+     * have a meaningful role.
+     */
+    grub_uint16_t   dev_roles[0];   /* role in array, or 0xffff for a spare, 
or 0xfffe for faulty */
+
+} __attribute__ ((packed));
+
+typedef union __attribute__ ((__transparent_union__)) {
+  struct grub_raid_super_09 v0;
+  struct grub_raid_super_1 v1;
+} grub_raid_super_t;
+
 static grub_err_t
 grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array)
 {
   grub_disk_addr_t sector;
   grub_uint64_t size;
-  struct grub_raid_super_09 sb;
+  grub_raid_super_t sb;
   grub_uint32_t *uuid;
+  int i;
 
   /* The sector where the RAID superblock is stored, if available. */
   size = grub_disk_get_size (disk);
   sector = NEW_SIZE_SECTORS (size);
 
-  if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb))
+  if (grub_disk_read (disk, sector, 0, sizeof(struct grub_raid_super_09), 
&(sb.v0)))
     return grub_errno;
 
-  /* Look whether there is a RAID superblock. */
-  if (sb.md_magic != SB_MAGIC)
-    return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
-
-  /* FIXME: Also support version 1.0. */
-  if (sb.major_version != 0 || sb.minor_version != 90)
-    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
-                      "unsupported RAID version: %d.%d",
-                      sb.major_version, sb.minor_version);
-
+  if ((sb.v0).md_magic == SB_MAGIC) {
   /* FIXME: Check the checksum. */
 
   /* Multipath.  */
-  if ((int) sb.level == -4)
-    sb.level = 1;
+  if ((int) (sb.v0).level == -4)
+    (sb.v0).level = 1;
 
-  if (sb.level != 0 && sb.level != 1 && sb.level != 4 &&
-      sb.level != 5 && sb.level != 6 && sb.level != 10)
+  if ((sb.v0).level != 0 && (sb.v0).level != 1 && (sb.v0).level != 4 &&
+      (sb.v0).level != 5 && (sb.v0).level != 6 && (sb.v0).level != 10)
     return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
-                      "unsupported RAID level: %d", sb.level);
-
-  array->number = sb.md_minor;
-  array->level = sb.level;
-  array->layout = sb.layout;
-  array->total_devs = sb.raid_disks;
-  array->disk_size = (sb.size) ? sb.size * 2 : sector;
-  array->chunk_size = sb.chunk_size >> 9;
-  array->index = sb.this_disk.number;
+                      "Unsupported RAID level: %d", (sb.v0).level);
+
+    array->version = (sb.v0).major_version;
+    array->data_offset = 0;
+    array->number = (sb.v0).md_minor;
+    array->level = (sb.v0).level;
+    array->layout = (sb.v0).layout;
+    array->total_devs = (sb.v0).raid_disks;
+    array->disk_size = ((sb.v0).size) ? (sb.v0).size * 2 : sector;
+    array->chunk_size = (sb.v0).chunk_size >> 9;
+    array->index = (sb.v0).this_disk.number;
+    array->uuid_len = 16;
+    array->uuid = grub_malloc (16);
+    if (!array->uuid)
+      return grub_errno;
+
+    uuid = (grub_uint32_t *) array->uuid;
+    uuid[0] = (sb.v0).set_uuid0;
+    uuid[1] = (sb.v0).set_uuid1;
+    uuid[2] = (sb.v0).set_uuid2;
+    uuid[3] = (sb.v0).set_uuid3;
+
+  }
+  else {
+
+  /* Look whether there is a RAID superblock. */
+       grub_dprintf ("mdraid", "No signature found for %s at sector 0x%llx\n", 
disk->name, (unsigned long long) sector);
+
+       sector = SB_SECTORS;
+
+       if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1), 
&(sb.v1)))
+                 return grub_errno;
+
+       if (grub_le_to_cpu32((sb.v1).magic) != SB_MAGIC)
+       return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
+
+       grub_dprintf ("mdraid", "Signature found for %s at sector 0x%llx\n", 
disk->name, (unsigned long long) sector);
+
+       if ((int) grub_le_to_cpu32((sb.v1).level) == -4)
+               (sb.v1).level = 1;
+
+       switch(grub_le_to_cpu32((sb.v1).level)) {
+               case 0:
+               case 1:
+               case 4:
+               case 5:
+               case 6:
+               case 10:
+                       break;
+               default:
+               return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported 
RAID level: %d", grub_le_to_cpu32((sb.v1).level));
+       }
+
+       array->version = grub_le_to_cpu32((sb.v1).major_version);
+       array->data_offset = grub_le_to_cpu64((sb.v1).data_offset);
+       /* array->number = grub_le_to_cpu32((sb.v1).dev_number); */
+       array->number = 0;
+       array->level = grub_le_to_cpu32((sb.v1).level);
+       array->layout = grub_le_to_cpu32((sb.v1).layout);
+       array->total_devs = grub_le_to_cpu32((sb.v1).raid_disks);
+       array->disk_size = grub_le_to_cpu64((sb.v1).size);
+       array->chunk_size = grub_le_to_cpu32((sb.v1).chunksize)*512;
+       /* array->index = grub_le_to_cpu32((sb.v1).dev_number);  dev_number 
could be anything >=0 */
+       array->index = disk->id; /* gives many prbs when id isn't modulo 0x80, 
devices are counted from 0 */
   array->uuid_len = 16;
   array->uuid = grub_malloc (16);
   if (!array->uuid)
     return grub_errno;
 
   uuid = (grub_uint32_t *) array->uuid;
-  uuid[0] = sb.set_uuid0;
-  uuid[1] = sb.set_uuid1;
-  uuid[2] = sb.set_uuid2;
-  uuid[3] = sb.set_uuid3;
+
+       for (i = 0; i < 4; i++)
+               uuid[i] = (sb.v1).set_uuid[i];
+
+       grub_dprintf ("mdraid", "(sb.v1).data_offset=%lld\n", (long long int) 
grub_le_to_cpu64((sb.v1).data_offset));
+       grub_dprintf ("mdraid", "array->number=%d ((sb.v1).dev_number=%ld)\n",
+                       array->number, grub_le_to_cpu64((sb.v1).dev_number));
+  }
+
+  grub_dprintf("mdraid", "Found RAID %d, vers. %d\n", (int) array->level, 
array->version);
 
   return 0;
 }
diff --git a/disk/raid.c b/disk/raid.c
index 2d544af..dce4a44 100644
--- a/disk/raid.c
+++ b/disk/raid.c
@@ -23,6 +23,9 @@
 #include <grub/err.h>
 #include <grub/misc.h>
 #include <grub/raid.h>
+#if 0 && ! defined (GRUB_UTIL)
+#include <grub/env.h>
+#endif
 
 /* Linked list of RAID arrays. */
 static struct grub_raid_array *array_list;
@@ -80,6 +83,8 @@ grub_raid_iterate (int (*hook) (const char *name))
 
   for (array = array_list; array != NULL; array = array->next)
     {
+      grub_dprintf ("raid", "iterate(%s)\n", array->name);
+
       if (grub_is_array_readable (array))
        if (hook (array->name))
          return 1;
@@ -130,8 +135,8 @@ grub_raid_open (const char *name, grub_disk_t disk)
   disk->id = array->number;
   disk->data = array;
 
-  grub_dprintf ("raid", "%s: total_devs=%d, disk_size=%lld\n", name,
-               array->total_devs, (unsigned long long) array->disk_size);
+  grub_dprintf ("raid", "%s: total_devs=%d, disk_size=%lld, number=%lu\n", 
name,
+                array->total_devs, (unsigned long long) array->disk_size, 
disk->id);
 
   switch (array->level)
     {
@@ -195,6 +200,13 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
   struct grub_raid_array *array = disk->data;
   grub_err_t err = 0;
 
+  grub_dprintf ("raid", "idx %d, devs %d, vers %d, layout %d, address@hidden, 
chunk %lu\n",
+                 array->index, array->total_devs, array->version, 
array->layout,
+                 (unsigned long long) array->data_offset, (unsigned long) 
array->chunk_size);
+  grub_dprintf("raid", "\tread('%s', 0x%lx, 0x%lx)\n",disk->name, (unsigned 
long) sector, (unsigned long) size);
+
+  sector += array->data_offset;
+
   switch (array->level)
     {
     case 0:
@@ -226,9 +238,11 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
             far_ofs *= array->chunk_size;
           }
 
+        grub_dprintf("raid", "\tdivmod64(%lld,%d,?)\n",
+                       (unsigned long long) read_sector * 
near,array->total_devs);
         read_sector = grub_divmod64 (read_sector * near, array->total_devs,
                                      &disknr);
-
+        grub_dprintf("raid", "read sector %ld, devs %d, disknr %d\n",(unsigned 
long) read_sector,array->total_devs,disknr);
         ofs *= array->chunk_size;
         read_sector *= ofs;
 
@@ -250,6 +264,7 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
                   {
                     if (array->device[k])
                       {
+                        grub_dprintf("raid", "read physical device '%s' 
%d\n",array->device[k]->name, k);
                         if (grub_errno == GRUB_ERR_READ_ERROR)
                           grub_errno = GRUB_ERR_NONE;
 
@@ -479,6 +494,14 @@ insert_array (grub_disk_t disk, struct grub_raid_array 
*new_array,
 {
   struct grub_raid_array *array = 0, *p;
 
+#if 0 && ! defined (GRUB_UTIL)
+  grub_env_set("debug","raid");
+#endif
+  grub_dprintf ("raid", "See whether the device is part of an array\n");
+  if (disk->dev->id == GRUB_DISK_DEVICE_RAID_ID ) {
+         grub_dprintf ("raid", "Already a raid array!\n");
+         return 0;
+  }
   /* See whether the device is part of an array we have already seen a
      device from. */
   for (p = array_list; p != NULL; p = p->next)
@@ -497,13 +520,13 @@ insert_array (grub_disk_t disk, struct grub_raid_array 
*new_array,
           /* We found more members of the array than the array
              actually has according to its superblock.  This shouldn't
              happen normally.  */
-          grub_dprintf ("raid", "array->nr_devs > array->total_devs (%d)?!?",
+          grub_dprintf ("raid", "array->nr_devs > array->total_devs (%d)?!?\n",
                        array->total_devs);
 
         if (array->device[new_array->index] != NULL)
           /* We found multiple devices with the same number. Again,
              this shouldn't happen.*/
-          grub_dprintf ("raid", "Found two disks with the number %d?!?",
+          grub_dprintf ("raid", "Found two disks with the number %d?!?\n",
                        new_array->number);
 
         if (new_array->disk_size < array->disk_size)
@@ -565,7 +588,12 @@ insert_array (grub_disk_t disk, struct grub_raid_array 
*new_array,
           return grub_errno;
         }
 
-      grub_dprintf ("raid", "Found array %s (%s)\n", array->name,
+      if (array->version == 1)
+          array->name = grub_xasprintf ("md_d%d", array->number);
+      else
+          array->name = grub_xasprintf ("md%d", array->number);
+
+      grub_dprintf ("raid", "Found array %s (scanner is %s)\n", array->name,
                     scanner_name);
 
       /* Add our new array to the list.  */
@@ -574,10 +602,17 @@ insert_array (grub_disk_t disk, struct grub_raid_array 
*new_array,
 
       /* RAID 1 doesn't use a chunksize but code assumes one so set
         one. */
-      if (array->level == 1)
+      if (array->level == 1) {
        array->chunk_size = 64;
+        grub_dprintf ("raid", "warning: chunk size is forced to %lu\n", 
(unsigned long) array->chunk_size);
+      }
     }
 
+  grub_dprintf ("raid", "Add device '%s', id %lu to the array %s at index 
%d\n",
+                 disk->name, disk->id, array->name, new_array->index);
+#if 0 && ! defined (GRUB_UTIL)
+  grub_dprintf ("device '%s' at position %d is id %lu\n", disk->name, 
new_array->index, disk->id);
+#endif
   /* Add the device to the array. */
   array->device[new_array->index] = disk;
   array->nr_devs++;
@@ -633,6 +668,9 @@ grub_raid_register (grub_raid_t raid)
          (! insert_array (disk, &array, grub_raid_list->name)))
        return 0;
 
+      if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+        grub_dprintf ("raid", "'%s' is not a raid device\n", name);
+
       /* This error usually means it's not raid, no need to display
         it.  */
       if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
diff --git a/include/grub/disk.h b/include/grub/disk.h
index e60b1f3..92c73a1 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -105,6 +105,9 @@ struct grub_disk
   /* The id used by the disk cache manager.  */
   unsigned long id;
 
+  /* The start of data.  */
+  grub_uint64_t data_offset;
+
   /* The partition information. This is machine-specific.  */
   struct grub_partition *partition;
 
diff --git a/include/grub/raid.h b/include/grub/raid.h
index 8fa4c38..848040c 100644
--- a/include/grub/raid.h
+++ b/include/grub/raid.h
@@ -34,6 +34,8 @@
 
 struct grub_raid_array
 {
+  unsigned int version;
+  grub_disk_addr_t data_offset;
   int number;              /* The device number, taken from md_minor so we
                              are consistent with the device name in
                              Linux. */
diff --git a/kern/device.c b/kern/device.c
index cd019fd..5b96528 100644
--- a/kern/device.c
+++ b/kern/device.c
@@ -100,6 +100,8 @@ grub_device_iterate (int (*hook) (const char *name))
       if (! dev)
        return 0;
 
+      grub_dprintf("device","iterate_disk(%s)\n", disk_name);
+
       if (dev->disk && dev->disk->has_partitions)
        {
          struct part_ent *p;
@@ -146,6 +148,8 @@ grub_device_iterate (int (*hook) (const char *name))
          return 1;
        }
 
+      grub_dprintf ("device","iterate_partition(%s,%s)\n", disk->name, 
partition_name);
+
       p->name = grub_xasprintf ("%s,%s", disk->name, partition_name);
       if (!p->name)
        {
diff --git a/kern/disk.c b/kern/disk.c
index 5c30e17..d77f9e0 100644
--- a/kern/disk.c
+++ b/kern/disk.c
@@ -24,6 +24,7 @@
 #include <grub/misc.h>
 #include <grub/time.h>
 #include <grub/file.h>
+#include <grub/raid.h>
 
 #define        GRUB_CACHE_TIMEOUT      2
 
@@ -386,6 +387,9 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
   char *tmp_buf;
   unsigned real_offset;
 
+  grub_dprintf ("disk", "\tReading '%s' @ sector 0x%llx:0x%x, len %llu, buf 
%p)\n", disk->name,
+                 (unsigned long long) sector, (unsigned int) offset, (unsigned 
long long) size, buf);
+
   /* First of all, check if the region is within the disk.  */
   if (grub_disk_adjust_range (disk, &sector, &offset, size) != GRUB_ERR_NONE)
     {
@@ -398,6 +402,8 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
 
   real_offset = offset;
 
+  grub_dprintf ("disk", "\tAdjust range to 0x%llx:0x%x\n", (unsigned long 
long) sector, (unsigned) real_offset);
+
   /* Allocate a temporary buffer.  */
   tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
   if (! tmp_buf)
@@ -430,6 +436,10 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
       else
        {
          /* Otherwise read data from the disk actually.  */
+         grub_dprintf ("disk", "\tread data from '%s' (%s) id=%lu at 0x%llx of 
size %d into cache %p\n",
+                         disk->name, disk->dev->name, disk->id,
+                         (unsigned long long )start_sector, 
GRUB_DISK_CACHE_SIZE, tmp_buf);
+
          if (start_sector + GRUB_DISK_CACHE_SIZE > disk->total_sectors
              || (disk->dev->read) (disk, start_sector,
                                    GRUB_DISK_CACHE_SIZE, tmp_buf)
@@ -450,6 +460,8 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
 
              tmp_buf = p;
 
+             grub_dprintf ("disk", "\tread retry: sector 0x%llx len %d, cache 
%p\n",
+                             (unsigned long long ) sector, num, tmp_buf);
              if ((disk->dev->read) (disk, sector, num, tmp_buf))
                {
                  grub_error_push ();
@@ -465,13 +477,14 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
                while (size)
                  {
                    grub_size_t to_read = (size > GRUB_DISK_SECTOR_SIZE) ? 
GRUB_DISK_SECTOR_SIZE : size;
+                   grub_dprintf ("disk", "\tcall read hook\n");
                    (disk->read_hook) (sector, real_offset,
                                       to_read);
                    if (grub_errno != GRUB_ERR_NONE)
                      goto finish;
 
                    sector++;
-                   size -= to_read - real_offset;
+                   size -= to_read - real_offset; /* size -= 
GRUB_DISK_SECTOR_SIZE - real_offset; */
                    real_offset = 0;
                  }
 
@@ -511,10 +524,12 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
       buf = (char *) buf + len;
       size -= len;
       real_offset = 0;
+      grub_dprintf ("disk", "\tremains %lu bytes to read...\n", (unsigned 
long) size);
     }
 
  finish:
 
+  grub_dprintf ("disk", "End reading `%s'...\n", disk->name);
   grub_free (tmp_buf);
 
   return grub_errno;
diff --git a/kern/fs.c b/kern/fs.c
index 0c45637..7f2972a 100644
--- a/kern/fs.c
+++ b/kern/fs.c
@@ -26,6 +26,7 @@
 #include <grub/types.h>
 #include <grub/mm.h>
 #include <grub/term.h>
+#include <grub/partition.h>
 
 static grub_fs_t grub_fs_list;
 
@@ -76,6 +77,11 @@ grub_fs_probe (grub_device_t device)
 
   if (device->disk)
     {
+      grub_dprintf ("fs", "Probe device %s (data offset %lu)...\n", 
device->disk->name, device->disk->data_offset);
+      grub_dprintf ("fs", "\tdevice has%s partition(s)\n", 
device->disk->has_partitions ? "": "n't");
+      if (device->disk->partition)
+        grub_dprintf ("fs", "\tpartition offset %lu\n", ((grub_partition_t) 
device->disk->partition)->offset);
+
       /* Make it sure not to have an infinite recursive calls.  */
       static int count = 0;
 
diff --git a/kern/parser.c b/kern/parser.c
index dd4608b..26e9c57 100644
--- a/kern/parser.c
+++ b/kern/parser.c
@@ -249,8 +249,12 @@ grub_parser_execute (char *source)
        }
 
       p = grub_strchr (source, '\n');
-      if (p)
-       *p = 0;
+      if (p) {
+       char *c = p - 1;
+       /* sweep away trailing spaces */
+       for (; c >= source && grub_isspace(*c); c--);
+       *++c = 0;
+      }
 
       *line = grub_strdup (source);
       if (p)
diff --git a/normal/main.c b/normal/main.c
index 5a54674..7e3d086 100644
--- a/normal/main.c
+++ b/normal/main.c
@@ -110,8 +110,14 @@ grub_file_getline (grub_file_t file)
        }
     }
 
+  /* GROSS: Get Rid Of Space Series */
+  while (pos > 0 && grub_isspace(cmdline[pos - 1])) {
+    pos--;
+  }
+
   cmdline[pos] = '\0';
 
+
   /* If the buffer is empty, don't return anything at all.  */
   if (pos == 0)
     {
diff --git a/partmap/apple.c b/partmap/apple.c
index a1a645a..7fc55f9 100644
--- a/partmap/apple.c
+++ b/partmap/apple.c
@@ -121,7 +121,7 @@ apple_partition_map_iterate (grub_disk_t disk,
   if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC)
     {
       grub_dprintf ("partition",
-                   "bad magic (found 0x%x; wanted 0x%x\n",
+                   "bad magic (found 0x%x; wanted 0x%x)\n",
                    grub_be_to_cpu16 (aheader.magic),
                    GRUB_APPLE_HEADER_MAGIC);
       goto fail;
@@ -139,7 +139,7 @@ apple_partition_map_iterate (grub_disk_t disk,
       if (grub_be_to_cpu16 (apart.magic) != GRUB_APPLE_PART_MAGIC)
        {
          grub_dprintf ("partition",
-                       "partition %d: bad magic (found 0x%x; wanted 0x%x\n",
+                       "partition %d: bad magic (found 0x%x; wanted 0x%x)\n",
                        partno, grub_be_to_cpu16 (apart.magic),
                        GRUB_APPLE_PART_MAGIC);
          break;
diff --git a/partmap/gpt.c b/partmap/gpt.c
index cb1229b..9caabcc 100644
--- a/partmap/gpt.c
+++ b/partmap/gpt.c
@@ -24,6 +24,7 @@
 #include <grub/dl.h>
 #include <grub/msdos_partition.h>
 #include <grub/gpt_partition.h>
+#include <grub/raid.h>
 
 static grub_uint8_t grub_gpt_magic[8] =
   {
@@ -58,6 +59,8 @@ gpt_partition_map_iterate (grub_disk_t disk,
   if (grub_disk_read (&raw, 0, 0, sizeof (mbr), &mbr))
     return grub_errno;
 
+  grub_dprintf ("gpt", "Read the protective MBR of %s\n", disk->name);
+
   /* Check if it is valid.  */
   if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
     return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
@@ -73,7 +76,7 @@ gpt_partition_map_iterate (grub_disk_t disk,
   if (grub_memcmp (gpt.magic, grub_gpt_magic, sizeof (grub_gpt_magic)))
     return grub_error (GRUB_ERR_BAD_PART_TABLE, "no valid GPT header");
 
-  grub_dprintf ("gpt", "Read a valid GPT header\n");
+  grub_dprintf ("gpt", "Found a valid GPT header at sector 0x%x\n", 1);
 
   entries = grub_le_to_cpu64 (gpt.partitions);
   for (i = 0; i < grub_le_to_cpu32 (gpt.maxpart); i++)
@@ -101,6 +104,7 @@ gpt_partition_map_iterate (grub_disk_t disk,
          if (hook (disk, &part))
            return 1;
        }
+      else grub_dprintf ("gpt", "GPT entry %d: empty\n", i);
 
       last_offset += grub_le_to_cpu32 (gpt.partentry_size);
       if (last_offset == GRUB_DISK_SECTOR_SIZE)
@@ -110,6 +114,8 @@ gpt_partition_map_iterate (grub_disk_t disk,
        }
     }
 
+    grub_dprintf ("gpt", "GPT last partition %d reached\n", gpt.maxpart - 1);
+
   return 0;
 }
 
@@ -126,6 +132,7 @@ gpt_partition_map_probe (grub_disk_t disk, const char *str)
   int find_func (grub_disk_t d __attribute__ ((unused)),
                 const grub_partition_t partition)
     {
+    grub_dprintf ("gpt", "find_func() partition %d == %d\n", partnum, 
partition->index);
       if (partnum == partition->index)
        {
          p = (grub_partition_t) grub_malloc (sizeof (*p));
diff --git a/util/deviceiter.c b/util/deviceiter.c
index b0a9e13..37d2d16 100644
--- a/util/deviceiter.c
+++ b/util/deviceiter.c
@@ -283,6 +283,12 @@ get_virtio_disk_name (char *name, int unit)
 }
 
 static void
+get_mdraid_disk_name (char *name, int unit)
+{
+  sprintf (name, "/dev/md_d%d", unit);
+}
+
+static void
 get_dac960_disk_name (char *name, int controller, int drive)
 {
   sprintf (name, "/dev/rd/c%dd%d", controller, drive);
@@ -485,7 +491,20 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) 
(const char *, int),
            return;
        }
     }
+#if 0
+  /* MDRAID disks.  */
+  for (i = 0; i < 8; i++)
+    {
+      char name[20];
 
+      get_mdraid_disk_name (name, i);
+      if (check_device (name))
+       {
+         if (hook (name, 0))
+           return;
+        }
+    }
+#endif
   /* ATARAID disks.  */
   for (i = 0; i < 8; i++)
     {
diff --git a/util/getroot.c b/util/getroot.c
index 8239363..090a8ae 100644
--- a/util/getroot.c
+++ b/util/getroot.c
@@ -535,34 +535,19 @@ grub_util_get_grub_dev (const char *os_dev)
 
     case GRUB_DEV_ABSTRACTION_RAID:
 
-      if (os_dev[7] == '_' && os_dev[8] == 'd')
+      if ((os_dev[7] == '_' || os_dev[7] == '/') && os_dev[8] == 'd')
        {
-         /* This a partitionable RAID device of the form /dev/md_dNNpMM. */
+         /* This a partitionable RAID device of the form /dev/md[/_]dNNpMM. */
 
          char *p, *q;
 
-         p = strdup (os_dev + sizeof ("/dev/md_d") - 1);
+         p = strdup (&os_dev[9]);
 
          q = strchr (p, 'p');
          if (q)
            *q = ',';
 
-         grub_dev = xasprintf ("md%s", p);
-         free (p);
-       }
-      else if (os_dev[7] == '/' && os_dev[8] == 'd')
-       {
-         /* This a partitionable RAID device of the form /dev/md/dNNpMM. */
-
-         char *p, *q;
-
-         p = strdup (os_dev + sizeof ("/dev/md/d") - 1);
-
-         q = strchr (p, 'p');
-         if (q)
-           *q = ',';
-
-         grub_dev = xasprintf ("md%s", p);
+         grub_dev = xasprintf ("md_d%s", p);
          free (p);
        }
       else if (os_dev[7] >= '0' && os_dev[7] <= '9')
diff --git a/util/grub-install.in b/util/grub-install.in
index bb323d7..6d08929 100644
--- a/util/grub-install.in
+++ b/util/grub-install.in
@@ -306,7 +306,7 @@ config_opt=
 
 if [ "x${devabstraction_module}" = "x" ] ; then
     if [ x"${install_device}" != x ]; then
-      if echo "${install_device}" | grep -qx "(.*)" ; then
+      if echo "${install_device}" | grep -q "(.*)" ; then
         install_drive="${install_device}"
       else
         install_drive="`$grub_probe --target=drive --device ${install_device}`"
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index daa110b..ffd925b 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -44,6 +44,7 @@ Generate a grub config file
   -o, --output=FILE       output generated config to FILE [default=stdout]
   -h, --help              print this message and exit
   -v, --version           print the version information and exit
+  -t, --target=PATH       mountpoint of target device
 
 Report bugs to <address@hidden>.
 EOF
@@ -62,6 +63,9 @@ for option in "$@"; do
        shift
        grub_cfg=$1
        ;;
+    --target=*)
+       ROOT=`echo "$option" | sed 's/--target=//'`
+       ;;
     --output=*)
        grub_cfg=`echo "$option" | sed 's/--output=//'`
        ;;
@@ -118,17 +122,25 @@ if test -e ${grub_prefix}/device.map ; then : ; else
   ${grub_mkdevicemap}
 fi
 
+if test -f ${sysconfdir}/default/grub ; then
+  . ${sysconfdir}/default/grub
+fi
+
+if [ -z "${GRUB_DEVICE}" ]; then
 # Device containing our userland.  Typically used for root= parameter.
-GRUB_DEVICE="`${grub_probe} --target=device /`"
+  GRUB_DEVICE="`${grub_probe} --target=device ${ROOT}/`"
+fi
 GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> 
/dev/null`" || true
 
+if [ -z "${GRUB_DEVICE_BOOT}" ]; then
 # Device containing our /boot partition.  Usually the same as GRUB_DEVICE.
-GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
+  GRUB_DEVICE_BOOT="`${grub_probe} --target=device ${ROOT}/boot`"
+fi
 GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} 
--target=fs_uuid 2> /dev/null`" || true
 
 # Filesystem for the device containing our userland.  Used for stuff like
 # choosing Hurd filesystem module.
-GRUB_FS="`${grub_probe} --target=fs / 2> /dev/null || echo unknown`"
+GRUB_FS="`${grub_probe} --target=fs ${ROOT}/ 2> /dev/null || echo unknown`"
 
 if test -f ${sysconfdir}/default/grub ; then
   . ${sysconfdir}/default/grub
diff --git a/util/grub-probe.c b/util/grub-probe.c
index ba2fe4c..4b5a876 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -99,9 +99,11 @@ probe_raid_level (grub_disk_t disk)
   if (!disk)
     return -1;
 
+  grub_util_info("disk->name=%s disk->dev->id=%d\n", disk->name, 
disk->dev->id);
   if (disk->dev->id != GRUB_DISK_DEVICE_RAID_ID)
     return -1;
 
+  grub_util_info("disk->name=%s disk->data->level=%d\n", disk->name, ((struct 
grub_raid_array *) disk->data)->level);
   return ((struct grub_raid_array *) disk->data)->level;
 }
 
@@ -161,6 +163,7 @@ probe (const char *path, char *device_name)
       int raid_level;
 
       raid_level = probe_raid_level (dev->disk);
+      grub_util_info ("raid_level=%d", raid_level);
       if (raid_level >= 0)
        {
          is_raid = 1;
@@ -168,10 +171,12 @@ probe (const char *path, char *device_name)
          is_raid6 |= (raid_level == 6);
        }
 
-      if ((is_lvm) && (dev->disk->dev->memberlist))
+      if (!is_raid && dev->disk->dev->memberlist)
        list = dev->disk->dev->memberlist (dev->disk);
+
       while (list)
        {
+          grub_util_info ("list->disk->name=%s", list->disk->name);
          raid_level = probe_raid_level (list->disk);
          if (raid_level >= 0)
            {
@@ -210,6 +215,9 @@ probe (const char *path, char *device_name)
       /* Check if dev->disk itself is contained in a partmap.  */
       probe_partmap (dev->disk);
 
+      if (dev->disk->dev->id == GRUB_DISK_DEVICE_RAID_ID && 
dev->disk->data_offset > 0)
+        goto end;
+
       /* In case of LVM/RAID, check the member devices as well.  */
       if (dev->disk->dev->memberlist)
        list = dev->disk->dev->memberlist (dev->disk);
@@ -402,6 +410,9 @@ main (int argc, char *argv[])
          }
     }
 
+  /* in case we are in debug mode */
+  grub_env_set ("debug", "");
+
   if (verbosity > 1)
     grub_env_set ("debug", "all");
 
diff --git a/util/hostdisk.c b/util/hostdisk.c
index 98d3d53..46c7d29 100644
--- a/util/hostdisk.c
+++ b/util/hostdisk.c
@@ -121,7 +121,7 @@ have_devfs (void)
 }
 #endif /* __linux__ */
 
-static int
+int
 find_grub_drive (const char *name)
 {
   unsigned int i;
@@ -335,6 +335,8 @@ open_device (const grub_disk_t disk, grub_disk_addr_t 
sector, int flags)
     int is_partition = 0;
     char dev[PATH_MAX];
 
+    grub_dprintf ("hostdisk", "opening device '%s', map[%ld]\n", 
map[disk->id].device, disk->id);
+
     strcpy (dev, map[disk->id].device);
     if (disk->partition && sector >= disk->partition->start
        && strncmp (map[disk->id].device, "/dev/", 5) == 0)
@@ -797,6 +799,17 @@ convert_system_partition_to_system_disk (const char 
*os_dev)
          return path;
        }
 
+      /* If this is a md Raid Array.  */
+      if (!strncmp ("md/d", p, 4) || !strncmp ("md_d", p, 4))
+       {
+         /* /dev/md[_/]d[0-9]+(p[0-9]+)? */
+         p = strchr (p, 'p');
+         if (p)
+           *p = '\0';
+grub_dprintf("hostdisk", "path=%s\n", path);
+         return path;
+       }
+
       /* If this is a Compaq Intelligent Drive Array.  */
       if (strncmp ("ida/c", p, sizeof ("ida/c") - 1) == 0)
        {
diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c
index 4e2517e..5c59cca 100644
--- a/util/i386/pc/grub-setup.c
+++ b/util/i386/pc/grub-setup.c
@@ -34,10 +34,11 @@
 #include <grub/term.h>
 #include <grub/i18n.h>
 #include <grub/util/raid.h>
+#include <grub/raid.h>
 #include <grub/util/lvm.h>
 #include <grub/util/getroot.h>
 
-static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = 
GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
+#include <grub/mm.h>
 
 #include <grub_setup_init.h>
 
@@ -50,8 +51,12 @@ static const grub_gpt_part_type_t 
grub_gpt_partition_type_bios_boot = GRUB_GPT_P
 #include <dirent.h>
 #include <assert.h>
 #include "progname.h"
+#include <grub/util/getroot.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <fcntl.h>
+
 
-#define _GNU_SOURCE    1
 #include <getopt.h>
 
 #define DEFAULT_BOOT_FILE      "boot.img"
@@ -78,17 +83,49 @@ grub_refresh (void)
   fflush (stdout);
 }
 
+/* awrite() comes from the MDADM project (http://neil.brown.name/blog/mdadm). 
*/
+static char abuf[4096+4096];
+static int awrite(int fd, void *buf, int len) {
+  /* aligned write.
+    * On devices with a 4K sector size, we need to write
+    * the full sector.  We pre-read if the sector is larger
+    * than the write.
+    * The address must be sector-aligned.
+    */
+  int bsize;
+  char *b;
+  int n;
+  if(ioctl(fd, BLKSSZGET, &bsize) != 0 ||
+      bsize <= len)
+          return write(fd, buf, len);
+  if(bsize > 4096)
+          return -1;
+  b =(char*)(((long)(abuf+4096))&~4095UL);
+
+  n = read(fd, b, bsize);
+  if(n <= 0)
+          return n;
+  lseek(fd, -n, 1);
+  memcpy(b, buf, len);
+  n = write(fd, b, bsize);
+  if(n <= 0)
+          return n;
+  lseek(fd, len - n, 1);
+  return len;
+}
+
 static void
 setup (const char *dir,
        const char *boot_file, const char *core_file,
-       const char *root, const char *dest, int must_embed, int force, int 
fs_probe)
+       const char *root, const char *dest, int must_embed __attribute__ 
((unused)), int force __attribute__ ((unused)), int fs_probe)
 {
-  char *boot_path, *core_path, *core_path_dev, *core_path_dev_full;
+  char *boot_path, *core_path;
   char *boot_img, *core_img;
   size_t boot_size, core_size;
   grub_uint16_t core_sectors;
   grub_device_t root_dev, dest_dev;
-  const char *dest_partmap;
+  grub_disk_t disk;
+  const char *partmap;
   grub_uint8_t *boot_drive;
   grub_disk_addr_t *kernel_sector;
   grub_uint16_t *boot_drive_check;
@@ -96,52 +133,18 @@ setup (const char *dir,
   grub_int32_t *install_dos_part, *install_bsd_part;
   grub_int32_t dos_part, bsd_part;
   char *tmp_img;
-  int i;
-  grub_disk_addr_t first_sector;
-  grub_uint16_t current_segment
-    = GRUB_BOOT_MACHINE_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
-  grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE;
-  grub_file_t file;
-  FILE *fp;
-  struct { grub_uint64_t start; grub_uint64_t end; } embed_region;
-  embed_region.start = embed_region.end = ~0UL;
-
-  auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, 
unsigned offset,
-                              unsigned length);
-  auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, 
unsigned offset,
-                            unsigned length);
-
-  auto int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk,
-                                                     const grub_partition_t p);
-  int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk 
__attribute__ ((unused)),
-                                                const grub_partition_t p)
-    {
-      struct grub_msdos_partition *pcdata = p->data;
-
-      /* There's always an embed region, and it starts right after the MBR.  */
-      embed_region.start = 1;
+  grub_disk_addr_t first_sector = 0;
+  struct { grub_uint64_t start; grub_uint64_t end; int index;} embed_region = 
{ ~0UL, ~0UL, 0 };
 
-      /* For its end offset, include as many dummy partitions as we can.  */
-      if (! grub_msdos_partition_is_empty (pcdata->dos_type)
-         && ! grub_msdos_partition_is_bsd (pcdata->dos_type)
-         && embed_region.end > p->start)
-       embed_region.end = p->start;
-
-      return 0;
-    }
-
-  auto int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk,
-                                                   const grub_partition_t p);
-  int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk __attribute__ 
((unused)),
-                                              const grub_partition_t p)
-    {
+  auto int NESTED_FUNC_ATTR
+  part_gpt(grub_disk_t d __attribute__((unused)), const grub_partition_t p) {
       struct grub_gpt_partentry *gptdata = p->data;
+    grub_gpt_part_type_t grub_bios = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
 
-      /* If there's an embed region, it is in a dedicated partition.  */
-      if (! memcmp (&gptdata->type, &grub_gpt_partition_type_bios_boot, 16))
-       {
+    if(!memcmp(&gptdata->type, &grub_bios, 16)) {
          embed_region.start = p->start;
          embed_region.end = p->start + p->len;
+      embed_region.index = p->index + 1;
 
          return 1;
        }
@@ -149,48 +152,25 @@ setup (const char *dir,
       return 0;
     }
 
-  void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned 
offset,
-                         unsigned length)
-    {
-      grub_util_info ("the first sector is <%llu,%u,%u>",
-                     sector, offset, length);
-
-      if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
-       grub_util_error (_("the first sector of the core file is not 
sector-aligned"));
-
-      first_sector = sector;
-    }
-
-  void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned 
offset,
-                       unsigned length)
-    {
-      struct grub_boot_blocklist *prev = block + 1;
+  auto int NESTED_FUNC_ATTR
+  part_msdos(grub_disk_t d __attribute__((unused)),const grub_partition_t p){
+    struct grub_msdos_partition *pcdata = p->data;
 
-      grub_util_info ("saving <%llu,%u,%u> with the segment 0x%x",
-                     sector, offset, length, (unsigned) current_segment);
+    /* There's always an embed region, and it starts right after the MBR */
+    embed_region.start = 1;
 
-      if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE)
-       grub_util_error (_("non-sector-aligned data is found in the core 
file"));
+    /* For its end offset, include as many dummy partitions as we can */
+    if(grub_msdos_partition_is_empty(pcdata->dos_type))
+      return 0;
 
-      if (block != first_block
-         && (grub_le_to_cpu64 (prev->start)
-             + grub_le_to_cpu16 (prev->len)) == sector)
-       prev->len = grub_cpu_to_le16 (grub_le_to_cpu16 (prev->len) + 1);
-      else
-       {
-         block->start = grub_cpu_to_le64 (sector);
-         block->len = grub_cpu_to_le16 (1);
-         block->segment = grub_cpu_to_le16 (current_segment);
+    if(embed_region.end > p->start) {
+      embed_region.end = p->start;
 
-         block--;
-         if (block->len)
-           grub_util_error (_("the sectors of the core file are too 
fragmented"));
+      return 1;
        }
 
-      last_length = length;
-      current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
+    return 0;
     }
-
   /* Read the boot image by the OS service.  */
   boot_path = grub_util_get_path (dir, boot_file);
   boot_size = grub_util_get_image_size (boot_path);
@@ -241,9 +221,11 @@ setup (const char *dir,
   if (grub_env_set ("root", root) != GRUB_ERR_NONE)
     grub_util_error ("%s", grub_errmsg);
 
+  disk = dest_dev->disk;
+
   /* Read the original sector from the disk.  */
   tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE);
-  if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img))
+  if (grub_disk_read (disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img))
     grub_util_error ("%s", grub_errmsg);
 
   if (dest_dev->disk->partition && fs_probe)
@@ -268,7 +250,7 @@ setup (const char *dir,
          GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START);
 
   /* Copy the possible partition table.  */
-  if (dest_dev->disk->has_partitions)
+  if (disk->has_partitions)
     memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC,
            tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC,
            GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC);
@@ -278,7 +260,7 @@ setup (const char *dir,
   /* If DEST_DRIVE is a hard disk, enable the workaround, which is
      for buggy BIOSes which don't pass boot drive correctly. Instead,
      they pass 0x00 or 0x01 even when booted from 0x80.  */
-  if (dest_dev->disk->id & 0x80)
+  if (disk->id & 0x80)
     /* Replace the jmp (2 bytes) with double nop's.  */
     *boot_drive_check = 0x9090;
 
@@ -311,23 +293,23 @@ setup (const char *dir,
     }
   else
     {
+      grub_util_info ("drive is part of prefix");
       dos_part = grub_le_to_cpu32 (*install_dos_part);
       bsd_part = grub_le_to_cpu32 (*install_bsd_part);
     }
 
-  grub_util_info ("dos partition is %d, bsd partition is %d",
-                 dos_part, bsd_part);
+  grub_util_info ("DOS partition is %d, BSD partition is %d", dos_part, 
bsd_part);
 
-  if (! dest_dev->disk->has_partitions)
+  if (! disk->has_partitions)
     {
       grub_util_warn (_("Attempting to install GRUB to a partitionless disk.  
This is a BAD idea."));
-      goto unable_to_embed;
+      goto finish;
     }
 
-  if (dest_dev->disk->partition)
+  if (disk->partition)
     {
       grub_util_warn (_("Attempting to install GRUB to a partition instead of 
the MBR.  This is a BAD idea."));
-      goto unable_to_embed;
+      goto finish;
     }
 
   /* Unlike root_dev, with dest_dev we're interested in the partition map even
@@ -337,51 +319,68 @@ setup (const char *dir,
   int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ 
((unused)),
                                         const grub_partition_t p)
     {
-      dest_partmap = p->partmap->name;
+      partmap = p->partmap->name;
       return 1;
     }
-  dest_partmap = 0;
-  grub_partition_iterate (dest_dev->disk, identify_partmap);
 
-  if (! dest_partmap)
-    {
-      grub_util_warn (_("Attempting to install GRUB to a partitionless disk.  
This is a BAD idea."));
-      goto unable_to_embed;
+
+  partmap = 0;
+  grub_partition_iterate (disk, identify_partmap);
+
+  if (! partmap) {
+      grub_util_warn ("Attempting to install GRUB to a partitionless disk %s", 
disk->name);
+      goto finish;
     }
 
-  if (strcmp (dest_partmap, "part_msdos") == 0)
-    grub_partition_iterate (dest_dev->disk, find_usable_region_msdos);
-  else if (strcmp (dest_partmap, "part_gpt") == 0)
-    grub_partition_iterate (dest_dev->disk, find_usable_region_gpt);
-  else
-    grub_util_error (_("No DOS-style partitions found"));
+  grub_util_info ("%s: identified partmap %s\n", disk->name, partmap);
+
+  grub_util_info ("Scanning device %s for usable region (data 
offset=%lu)...\n", disk->name, disk->data_offset);
+
+  int(*find)(grub_disk_t d, const grub_partition_t p);
+
+  find =(strcmp(partmap, "part_msdos")? part_gpt : part_msdos);
+  grub_partition_iterate(disk, find);
 
   if (embed_region.end == embed_region.start)
     {
-      if (! strcmp (dest_partmap, "part_msdos"))
+      if (! strcmp (partmap, "part_msdos"))
        grub_util_warn (_("This msdos-style partition label has no post-MBR 
gap; embedding won't be possible!"));
       else
        grub_util_warn (_("This GPT partition label has no BIOS Boot Partition; 
embedding won't be possible!"));
-      goto unable_to_embed;
+      goto finish;
     }
 
   if ((unsigned long) core_sectors > embed_region.end - embed_region.start)
     {
       if (core_sectors > 62)
        grub_util_warn (_("Your core.img is unusually large.  It won't fit in 
the embedding area."));
-      else /* embed_region.end - embed_region.start < 62 */
+      else if (embed_region.end - embed_region.start < 62)
        grub_util_warn (_("Your embedding area is unusually small.  core.img 
won't fit in it."));
-      goto unable_to_embed;
+      else
+        grub_util_warn ("Embedding area is too small for core.img.");
+      goto finish;
     }
 
+    if (!embed_region.index)
+      grub_util_info ("Embedding area of %s is right after MBR", disk->name);
+    else
+      grub_util_info ("Embedding area of %s is GPT BIOS partition %d", 
disk->name, embed_region.index);
+
+    if (disk->dev->id == GRUB_DISK_DEVICE_RAID_ID) {
+      struct grub_raid_array *array = disk->data;
+
+      first_sector = array->data_offset;
+      grub_util_info ("disk %s is a raid device\n", disk->name);
+    }
+
+    grub_util_info ("first data sector for %s is %ld\n", disk->name, 
first_sector);
 
-  grub_util_info ("the core image will be embedded at sector 0x%llx", 
embed_region.start);
 
   *install_dos_part = grub_cpu_to_le32 (dos_part);
   *install_bsd_part = grub_cpu_to_le32 (bsd_part);
 
   /* The first blocklist contains the whole sectors.  */
-  first_block->start = grub_cpu_to_le64 (embed_region.start + 1);
+  first_block->start = grub_cpu_to_le64 (embed_region.start + first_sector + 
1);
 
   /* These are filled elsewhere.  Verify them just in case.  */
   assert (first_block->len == grub_host_to_target16 (core_sectors - 1));
@@ -394,165 +393,179 @@ setup (const char *dir,
   block->len = 0;
   block->segment = 0;
 
-  /* Write the core image onto the disk.  */
-  if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, 
core_img))
-    grub_util_error ("%s", grub_errmsg);
 
-  /* FIXME: can this be skipped?  */
-  *boot_drive = 0xFF;
-
-  *kernel_sector = grub_cpu_to_le64 (embed_region.start);
-
-  /* Write the boot image onto the disk.  */
-  if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE,
-                      boot_img))
-    grub_util_error ("%s", grub_errmsg);
+  int fd;
+  char *os_dev = NULL;
+  int drive;
 
-  goto finish;
+  extern int find_grub_drive (const char *);
+  extern struct {
+    char *drive;
+    char *device;
+  } map[256];
 
-unable_to_embed:
+  char *partname = NULL;
+  char *p;
 
-  if (must_embed)
-    grub_util_error (_("embedding is not possible, but this is required when "
-                      "the root device is on a RAID array or LVM volume"));
+  drive = find_grub_drive(disk->name);
 
-  grub_util_warn (_("Embedding is not possible.  GRUB can only be installed in 
this "
-                   "setup by using blocklists.  However, blocklists are 
UNRELIABLE and "
-                   "its use is discouraged."));
-  if (! force)
-    grub_util_error (_("if you really want blocklists, use --force"));
+  if (drive < 0) {
 
-  /* Make sure that GRUB reads the identical image as the OS.  */
-  tmp_img = xmalloc (core_size);
-  core_path_dev_full = grub_util_get_path (dir, core_file);
-  core_path_dev = make_system_path_relative_to_its_root (core_path_dev_full);
-  free (core_path_dev_full);
+    if (embed_region.index)
+      partname = xasprintf ("%s,%d", disk->name, embed_region.index);
+    else
+      partname = xasprintf ("%s", disk->name);
 
-  /* It is a Good Thing to sync two times.  */
-  sync ();
-  sync ();
+    os_dev = xasprintf ("/dev/%s", partname);
+    p = strchr (os_dev, ',');
+    if (p) *p = 'p';
 
-#define MAX_TRIES      5
+    grub_util_info ("%s (%s) is a md%c RAID array, also no mapping is needed 
for it.",
+                   os_dev, partname, (p)? *p:' ');
+  }
+  else {
+    os_dev = grub_malloc (PATH_MAX);
 
-  for (i = 0; i < MAX_TRIES; i++)
-    {
-      grub_util_info ((i == 0) ? _("attempting to read the core image `%s' 
from GRUB")
-                     : _("attempting to read the core image `%s' from GRUB 
again"),
-                     core_path_dev);
+    strcpy(os_dev, map[drive].device);
 
-      grub_disk_cache_invalidate_all ();
+    if (embed_region.index) {
+      size_t len = strlen (map[drive].device);
+      const char *format;
 
-      file = grub_file_open (core_path_dev);
-      if (file)
-       {
-         if (grub_file_size (file) != core_size)
-           grub_util_info ("succeeded in opening the core image but the size 
is different (%d != %d)",
-                           (int) grub_file_size (file), (int) core_size);
-         else if (grub_file_read (file, tmp_img, core_size)
-                  != (grub_ssize_t) core_size)
-           grub_util_info ("succeeded in opening the core image but cannot 
read %d bytes",
-                           (int) core_size);
-         else if (memcmp (core_img, tmp_img, core_size) != 0)
-           {
-#if 0
-             FILE *dump;
-             FILE *dump2;
-
-             dump = fopen ("dump.img", "wb");
-             if (dump)
-               {
-                 fwrite (tmp_img, 1, core_size, dump);
-                 fclose (dump);
+      if (strcmp (os_dev + len - 5, "/disc") == 0) {
+        p = os_dev + len - 4;
+        format = "part%d";
+      }
+      else if (os_dev[len - 1] >= '0' && os_dev[len - 1] <= '9') {
+        p = os_dev + len;
+        format = "p%d";
+      }
+      else {
+        p = os_dev + len;
+        format = "%d";
                }
 
-             dump2 = fopen ("dump2.img", "wb");
-             if (dump2)
-               {
-                 fwrite (core_img, 1, core_size, dump2);
-                 fclose (dump2);
+      sprintf (p, format, embed_region.index);
+    }
                }
 
-#endif
-             grub_util_info ("succeeded in opening the core image but the data 
is different");
+  if (partname)
+    free(partname);
+
+  fprintf(stderr, "Opening %s\n", os_dev);
+
+  fd = open(os_dev, O_RDWR);
+  if(fd < 0) {
+    fprintf(stderr, "open(): invalid device %s\n",os_dev);
+    exit(4);
            }
-         else
-           {
-             grub_file_close (file);
-             break;
+
+  free (os_dev);
+
+  if (!embed_region.index) {
+    off_t offset = embed_region.start * GRUB_DISK_SECTOR_SIZE;
+    if (lseek(fd, offset , SEEK_SET) != offset) {
+      fprintf(stderr, "lseek(): unable to seek\n");
+      exit(4);
            }
 
-         grub_file_close (file);
+    grub_util_info ("Write the core image (%d bytes) after the MBR", 
core_size);
        }
       else
-       grub_util_info ("couldn't open the core image");
+    grub_util_info ("Write the core image (%d bytes) into partition %d", 
core_size, embed_region.index);
 
-      if (grub_errno)
-       grub_util_info ("error message = %s", grub_errmsg);
+  /* Write the core image onto the disk.  */
+  if (awrite (fd, core_img, core_size) != (int) core_size)
+    grub_util_error ("%s", grub_errmsg);
 
-      grub_errno = GRUB_ERR_NONE;
-      sync ();
-      sleep (1);
-    }
+  close(fd);
 
-  if (i == MAX_TRIES)
-    grub_util_error (_("cannot read `%s' correctly"), core_path_dev);
+  /* Write the boot image onto the disk.  */
+  /* FIXME: can this be skipped?  */
+  *boot_drive = 0xFF;
 
-  /* Clean out the blocklists.  */
-  block = first_block;
-  while (block->len)
-    {
-      block->start = 0;
-      block->len = 0;
-      block->segment = 0;
+  *kernel_sector = grub_cpu_to_le64 (embed_region.start + first_sector);
+
+  grub_util_info ("Copy the boot image (%d bytes) into the legacy MBR", 
boot_size);
+
+  grub_disk_memberlist_t list = NULL;
+
+  if (disk->dev->id == GRUB_DISK_DEVICE_RAID_ID) {
+    grub_disk_memberlist_t tmp;
 
-      block--;
+    grub_util_info ("disk %s is a raid\n", disk->name);
 
-      if ((char *) block <= core_img)
-       grub_util_error (_("no terminator in the core image"));
+    if (disk->dev->memberlist)
+      list = disk->dev->memberlist (disk);
+
+    while (list)
+    {
+      grub_util_info ("list->disk->name=%s", list->disk->name);
+      drive = find_grub_drive (list->disk->name);
+      if (drive < 0) {
+        grub_util_warn ("no mapping exists for %s", list->disk->name);
+        continue;
+      }
+      else {
+        grub_util_info ("found array %s", list->disk->name);
+
+        os_dev = strdup(map[drive].device);
+
+        fprintf(stderr, "Opening %s\n", os_dev);
+
+        fd = open(os_dev, O_RDWR);
+        if(fd < 0) {
+          grub_util_warn("invalid device %s\n",os_dev);
+          exit(4);
     }
 
-  /* Now read the core image to determine where the sectors are.  */
-  file = grub_file_open (core_path_dev);
-  if (! file)
+        grub_util_info ("Copy the boot image into the legacy MBR of %s\n", 
os_dev);
+
+        free (os_dev);
+
+        /* Write the boot image onto the disk.  */
+        if (awrite (fd, boot_img, boot_size) != (int) boot_size)
     grub_util_error ("%s", grub_errmsg);
 
-  file->read_hook = save_first_sector;
-  if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE)
-      != GRUB_DISK_SECTOR_SIZE)
-    grub_util_error (_("failed to read the first sector of the core image"));
+      }
 
-  block = first_block;
-  file->read_hook = save_blocklists;
-  if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE)
-      != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE)
-    grub_util_error (_("failed to read the rest sectors of the core image"));
+      tmp = list->next;
+      free (list);
+      list = tmp;
+    }
 
-  grub_file_close (file);
+    goto finish;
+  }
 
-  free (core_path_dev);
-  free (tmp_img);
+  drive = find_grub_drive(disk->name);
 
-  *kernel_sector = grub_cpu_to_le64 (first_sector);
+  if (drive < 0) {
+    grub_util_warn ("no mapping exists for %s", disk->name);
+    goto finish;
+  }
 
-  /* FIXME: can this be skipped?  */
-  *boot_drive = 0xFF;
+  grub_util_info ("found device %s", disk->name);
 
-  *install_dos_part = grub_cpu_to_le32 (dos_part);
-  *install_bsd_part = grub_cpu_to_le32 (bsd_part);
+  os_dev = strdup(map[drive].device);
+
+  fprintf(stderr, "Opening %s\n", os_dev);
+
+  fd = open(os_dev, O_RDWR);
+  if(fd < 0) {
+    grub_util_warn("invalid device %s\n",os_dev);
+    exit(4);
+  }
 
-  /* Write the first two sectors of the core image onto the disk.  */
-  grub_util_info ("opening the core image `%s'", core_path);
-  fp = fopen (core_path, "r+b");
-  if (! fp)
-    grub_util_error (_("cannot open `%s'"), core_path);
+  grub_util_info ("Copy the boot image into the legacy MBR of %s\n", os_dev);
 
-  grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp);
-  fclose (fp);
+  free (os_dev);
 
   /* Write the boot image onto the disk.  */
-  if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, boot_img))
+  if (awrite (fd, boot_img, boot_size) != (int) boot_size)
     grub_util_error ("%s", grub_errmsg);
 
+  close(fd);
+
  finish:
 
   /* Sync is a Good Thing.  */
@@ -710,6 +723,9 @@ main (int argc, char *argv[])
          }
     }
 
+  /* if we have forced the debug mode in the code */
+  grub_env_set ("debug", "");
+
   if (verbosity > 1)
     grub_env_set ("debug", "all");
 
@@ -727,7 +743,7 @@ main (int argc, char *argv[])
     }
 
   /* Initialize the emulated biosdisk driver.  */
-  grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP);
+  grub_util_biosdisk_init (dev_map ? dev_map : DEFAULT_DEVICE_MAP);
 
   /* Initialize all modules. */
   grub_init_all ();
@@ -760,7 +776,7 @@ main (int argc, char *argv[])
     }
   else
     {
-      root_dev = grub_util_get_grub_dev (grub_guess_root_device (dir ? : 
DEFAULT_DIRECTORY));
+      root_dev = grub_util_get_grub_dev (grub_guess_root_device (dir ? dir : 
DEFAULT_DIRECTORY));
       if (! root_dev)
        {
          grub_util_info ("guessing the root device failed, because of `%s'",
@@ -773,35 +789,18 @@ main (int argc, char *argv[])
   if (grub_util_lvm_isvolume (root_dev))
     must_embed = 1;
 
-  if (root_dev[0] == 'm' && root_dev[1] == 'd'
-      && root_dev[2] >= '0' && root_dev[2] <= '9')
-    {
+  if (root_dev[0] == 'm' && root_dev[1] == 'd') {
+    int i = (root_dev[2] == '_')? 2 : 3;
+    if ( root_dev[i] >= '0' && root_dev[i] <= '9')
       /* FIXME: we can avoid this on RAID1.  */
       must_embed = 1;
     }
 
-  if (dest_dev[0] == 'm' && dest_dev[1] == 'd'
-      && dest_dev[2] >= '0' && dest_dev[2] <= '9')
-    {
-      char **devicelist;
-      int i;
-
-      devicelist = grub_util_raid_getmembers (dest_dev);
-
-      for (i = 0; devicelist[i]; i++)
-       {
-         setup (dir ? : DEFAULT_DIRECTORY,
-                boot_file ? : DEFAULT_BOOT_FILE,
-                core_file ? : DEFAULT_CORE_FILE,
-                root_dev, grub_util_get_grub_dev (devicelist[i]), 1, force, 
fs_probe);
-       }
-    }
-  else
 #endif
   /* Do the real work.  */
-    setup (dir ? : DEFAULT_DIRECTORY,
-          boot_file ? : DEFAULT_BOOT_FILE,
-          core_file ? : DEFAULT_CORE_FILE,
+    setup (dir ? dir : DEFAULT_DIRECTORY,
+          boot_file ? boot_file : DEFAULT_BOOT_FILE,
+          core_file ? core_file : DEFAULT_CORE_FILE,
           root_dev, dest_dev, must_embed, force, fs_probe);
 
   /* Free resources.  */
@@ -817,3 +816,4 @@ main (int argc, char *argv[])
 
   return 0;
 }
+
-- 
1.7.1.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]