[Top][All Lists]
[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, §or, &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