#include <grub/err.h>
#include <grub/misc.h>
#include <grub/raid.h>
+#ifdef GRUB_UTIL
+#include <grub/util/misc.h>
+#endif
+
+GRUB_MOD_LICENSE ("GPLv3+");
/* Linked list of RAID arrays. */
static struct grub_raid_array *array_list;
}
#endif
+static inline int
+ascii2hex (char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return 0;
+}
+
static grub_err_t
grub_raid_open (const char *name, grub_disk_t disk)
{
struct grub_raid_array *array;
unsigned n;
- for (array = array_list; array != NULL; array = array->next)
+ if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0)
{
- if (!grub_strcmp (array->name, name))
- if (grub_is_array_readable (array))
- break;
+ const char *uuidstr = name + sizeof ("mduuid/") - 1;
+ grub_size_t uuid_len = grub_strlen (uuidstr) / 2;
+ grub_uint8_t uuidbin[uuid_len];
+ unsigned i;
+ for (i = 0; i < uuid_len; i++)
+ uuidbin[i] = ascii2hex (uuidstr[2 * i + 1])
+ | (ascii2hex (uuidstr[2 * i]) << 4);
+
+ for (array = array_list; array != NULL; array = array->next)
+ {
+ if (uuid_len == (unsigned) array->uuid_len
+ && grub_memcmp (uuidbin, array->uuid, uuid_len) == 0)
+ if (grub_is_array_readable (array))
+ break;
+ }
}
+ else
+ for (array = array_list; array != NULL; array = array->next)
+ {
+ if (!grub_strcmp (array->name, name))
+ if (grub_is_array_readable (array))
+ break;
+ }
if (!array)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
case 10:
{
grub_disk_addr_t read_sector, far_ofs;
- grub_uint32_t disknr, b, near, far, ofs;
+ grub_uint64_t disknr, b, near, far, ofs;
read_sector = grub_divmod64 (sector, array->chunk_size, &b);
far = ofs = near = 1;
case 6:
{
grub_disk_addr_t read_sector;
- grub_uint32_t b, p, n, disknr, e;
+ grub_uint64_t b, p, n, disknr, e;
/* n = 1 for level 4 and 5, 2 for level 6. */
n = array->level / 3;
/* 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)?!?",
- array->total_devs);
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ "superfluous RAID member (%d found)",
+ array->total_devs);
if (array->members[new_array->index].device != NULL)
/* We found multiple devices with the same number. Again,
this shouldn't happen. */
- grub_dprintf ("raid", "Found two disks with the number %d?!?",
- new_array->number);
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ "found two disks with the index %d for RAID %s",
+ new_array->index, array->name);
if (new_array->disk_size < array->disk_size)
array->disk_size = new_array->disk_size;
{
for (p = array_list; p != NULL; p = p->next)
{
- if (! p->name && p->number == array->number)
+ if (p->number == array->number)
break;
}
}
grub_dprintf ("raid", "Found array %s (%s)\n", array->name,
scanner_name);
+#ifdef GRUB_UTIL
+ grub_util_info ("Found array %s (%s)", array->name,
+ scanner_name);
+#endif
+
+ {
+ int max_used_number = 0, len, need_new_name = 0;
+ int add_us = 0;
+ len = grub_strlen (array->name);
+ if (len && grub_isdigit (array->name[len-1]))
+ add_us = 1;
+ for (p = array_list; p != NULL; p = p->next)
+ {
+ int cur_num;
+ char *num, *end;
+ if (grub_strncmp (p->name, array->name, len) != 0)
+ continue;
+ if (p->name[len] == 0)
+ {
+ need_new_name = 1;
+ continue;
+ }
+ if (add_us && p->name[len] != '_')
+ continue;
+ if (add_us)
+ num = p->name + len + 1;
+ else
+ num = p->name + len;
+ if (!grub_isdigit (num[0]))
+ continue;
+ cur_num = grub_strtoull (num, &end, 10);
+ if (end[0])
+ continue;
+ if (cur_num > max_used_number)
+ max_used_number = cur_num;
+ }
+ if (need_new_name)
+ {
+ char *tmp;
+ tmp = grub_xasprintf ("%s%s%d", array->name, add_us ? "_" : "",
+ max_used_number + 1);
+ if (!tmp)
+ return grub_errno;
+ grub_free (array->name);
+ array->name = tmp;
+ }
+ }
/* Add our new array to the list. */
array->next = array_list;
struct grub_raid_array array;
grub_disk_addr_t start_sector;
- grub_dprintf ("raid", "Scanning for RAID devices on disk %s\n", name);
+ grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n",
+ grub_raid_list->name, name);
+#ifdef GRUB_UTIL
+ grub_util_info ("Scanning for %s RAID devices on disk %s",
+ grub_raid_list->name, name);
+#endif
disk = grub_disk_open (name);
if (!disk)