Remove nested functions from device iterators.

* include/grub/arc/arc.h (grub_arc_iterate_devs_hook_t): New type.
(grub_arc_iterate_devs): Add hook_data argument.
* include/grub/ata.h (grub_ata_dev_iterate_hook_t): New type.
(struct grub_ata_dev.iterate): Add hook_data argument.
* include/grub/device.h (grub_device_iterate_hook_t): New type.
(grub_device_iterate): Add hook_data argument.
* include/grub/disk.h (grub_disk_dev_iterate_hook_t): New type.
(struct grub_disk_dev.iterate): Add hook_data argument.
(grub_disk_dev_iterate): Likewise.
* include/grub/gpt_partition.h (grub_gpt_partition_map_iterate):
Likewise.
* include/grub/msdos_partition.h (grub_partition_msdos_iterate):
Likewise.
* include/grub/partition.h (grub_partition_iterate_hook_t): New
type.
(struct grub_partition_map.iterate): Add hook_data argument.
(grub_partition_iterate): Likewise.
* include/grub/scsi.h (grub_scsi_dev_iterate_hook_t): New type.
(struct grub_scsi_dev.iterate): Add hook_data argument.

Update all callers.
This commit is contained in:
Colin Watson 2013-01-20 15:52:15 +00:00
parent 6c0314d638
commit 25239370fd
50 changed files with 1455 additions and 1165 deletions

View File

@ -1,3 +1,29 @@
2013-01-20 Colin Watson <cjwatson@ubuntu.com>
Remove nested functions from device iterators.
* include/grub/arc/arc.h (grub_arc_iterate_devs_hook_t): New type.
(grub_arc_iterate_devs): Add hook_data argument.
* include/grub/ata.h (grub_ata_dev_iterate_hook_t): New type.
(struct grub_ata_dev.iterate): Add hook_data argument.
* include/grub/device.h (grub_device_iterate_hook_t): New type.
(grub_device_iterate): Add hook_data argument.
* include/grub/disk.h (grub_disk_dev_iterate_hook_t): New type.
(struct grub_disk_dev.iterate): Add hook_data argument.
(grub_disk_dev_iterate): Likewise.
* include/grub/gpt_partition.h (grub_gpt_partition_map_iterate):
Likewise.
* include/grub/msdos_partition.h (grub_partition_msdos_iterate):
Likewise.
* include/grub/partition.h (grub_partition_iterate_hook_t): New
type.
(struct grub_partition_map.iterate): Add hook_data argument.
(grub_partition_iterate): Likewise.
* include/grub/scsi.h (grub_scsi_dev_iterate_hook_t): New type.
(struct grub_scsi_dev.iterate): Add hook_data argument.
Update all callers.
2013-01-20 Colin Watson <cjwatson@ubuntu.com> 2013-01-20 Colin Watson <cjwatson@ubuntu.com>
Fix typos for "developer" and "development". Fix typos for "developer" and "development".

View File

@ -24,18 +24,22 @@
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
/* Helper for grub_cmd_lsdev. */
static int
grub_cmd_lsdev_iter (const char *name,
const struct grub_arc_component *comp __attribute__ ((unused)),
void *data __attribute__ ((unused)))
{
grub_printf ("%s\n", name);
return 0;
}
static grub_err_t static grub_err_t
grub_cmd_lsdev (grub_command_t cmd __attribute__ ((unused)), grub_cmd_lsdev (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)), int argc __attribute__ ((unused)),
char **args __attribute__ ((unused))) char **args __attribute__ ((unused)))
{ {
auto int hook (const char *name, const struct grub_arc_component *comp); grub_arc_iterate_devs (grub_cmd_lsdev_iter, 0, 0);
int hook (const char *name, const struct grub_arc_component *comp __attribute__ ((unused)))
{
grub_printf ("%s\n", name);
return 0;
}
grub_arc_iterate_devs (hook, 0);
return 0; return 0;
} }

View File

@ -45,21 +45,24 @@ static const struct grub_arg_option options[] =
static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'}; static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'};
/* Helper for grub_ls_list_devices. */
static int
grub_ls_print_devices (const char *name, void *data)
{
int *longlist = data;
if (longlist)
grub_normal_print_device_info (name);
else
grub_printf ("(%s) ", name);
return 0;
}
static grub_err_t static grub_err_t
grub_ls_list_devices (int longlist) grub_ls_list_devices (int longlist)
{ {
auto int grub_ls_print_devices (const char *name); grub_device_iterate (grub_ls_print_devices, &longlist);
int grub_ls_print_devices (const char *name)
{
if (longlist)
grub_normal_print_device_info (name);
else
grub_printf ("(%s) ", name);
return 0;
}
grub_device_iterate (grub_ls_print_devices);
grub_xputs ("\n"); grub_xputs ("\n");
#if 0 #if 0

View File

@ -42,23 +42,29 @@ struct cache_entry
static struct cache_entry *cache; static struct cache_entry *cache;
void /* Context for FUNC_NAME. */
FUNC_NAME (const char *key, const char *var, int no_floppy, struct search_ctx
char **hints, unsigned nhints)
{ {
int count = 0; const char *key;
int is_cache = 0; const char *var;
grub_fs_autoload_hook_t saved_autoload; int no_floppy;
char **hints;
unsigned nhints;
int count;
int is_cache;
};
auto int iterate_device (const char *name); /* Helper for FUNC_NAME. */
int iterate_device (const char *name) static int
{ iterate_device (const char *name, void *data)
int found = 0; {
struct search_ctx *ctx = data;
int found = 0;
/* Skip floppy drives when requested. */ /* Skip floppy drives when requested. */
if (no_floppy && if (ctx->no_floppy &&
name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
return 0; return 0;
#ifdef DO_SEARCH_FS_UUID #ifdef DO_SEARCH_FS_UUID
#define compare_fn grub_strcasecmp #define compare_fn grub_strcasecmp
@ -67,34 +73,34 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
#endif #endif
#ifdef DO_SEARCH_FILE #ifdef DO_SEARCH_FILE
{ {
char *buf; char *buf;
grub_file_t file; grub_file_t file;
buf = grub_xasprintf ("(%s)%s", name, key); buf = grub_xasprintf ("(%s)%s", name, ctx->key);
if (! buf) if (! buf)
return 1; return 1;
grub_file_filter_disable_compression (); grub_file_filter_disable_compression ();
file = grub_file_open (buf); file = grub_file_open (buf);
if (file) if (file)
{ {
found = 1; found = 1;
grub_file_close (file); grub_file_close (file);
} }
grub_free (buf); grub_free (buf);
} }
#else #else
{ {
/* SEARCH_FS_UUID or SEARCH_LABEL */ /* SEARCH_FS_UUID or SEARCH_LABEL */
grub_device_t dev; grub_device_t dev;
grub_fs_t fs; grub_fs_t fs;
char *quid; char *quid;
dev = grub_device_open (name); dev = grub_device_open (name);
if (dev) if (dev)
{ {
fs = grub_fs_probe (dev); fs = grub_fs_probe (dev);
#ifdef DO_SEARCH_FS_UUID #ifdef DO_SEARCH_FS_UUID
#define read_fn uuid #define read_fn uuid
@ -102,173 +108,191 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
#define read_fn label #define read_fn label
#endif #endif
if (fs && fs->read_fn) if (fs && fs->read_fn)
{ {
fs->read_fn (dev, &quid); fs->read_fn (dev, &quid);
if (grub_errno == GRUB_ERR_NONE && quid) if (grub_errno == GRUB_ERR_NONE && quid)
{ {
if (compare_fn (quid, key) == 0) if (compare_fn (quid, ctx->key) == 0)
found = 1; found = 1;
grub_free (quid); grub_free (quid);
} }
} }
grub_device_close (dev); grub_device_close (dev);
} }
} }
#endif #endif
if (!is_cache && found && count == 0) if (!ctx->is_cache && found && ctx->count == 0)
{ {
struct cache_entry *cache_ent; struct cache_entry *cache_ent;
cache_ent = grub_malloc (sizeof (*cache_ent)); cache_ent = grub_malloc (sizeof (*cache_ent));
if (cache_ent) if (cache_ent)
{ {
cache_ent->key = grub_strdup (key); cache_ent->key = grub_strdup (ctx->key);
cache_ent->value = grub_strdup (name); cache_ent->value = grub_strdup (name);
if (cache_ent->value && cache_ent->key) if (cache_ent->value && cache_ent->key)
{ {
cache_ent->next = cache; cache_ent->next = cache;
cache = cache_ent; cache = cache_ent;
} }
else else
{ {
grub_free (cache_ent->value); grub_free (cache_ent->value);
grub_free (cache_ent->key); grub_free (cache_ent->key);
grub_free (cache_ent); grub_free (cache_ent);
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
} }
} }
else else
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
} }
if (found) if (found)
{ {
count++; ctx->count++;
if (var) if (ctx->var)
grub_env_set (var, name); grub_env_set (ctx->var, name);
else else
grub_printf (" %s", name); grub_printf (" %s", name);
} }
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
return (found && var); return (found && ctx->var);
} }
auto int part_hook (grub_disk_t disk, const grub_partition_t partition); /* Helper for FUNC_NAME. */
int part_hook (grub_disk_t disk, const grub_partition_t partition) static int
{ part_hook (grub_disk_t disk, const grub_partition_t partition, void *data)
char *partition_name, *devname; {
int ret; struct search_ctx *ctx = data;
char *partition_name, *devname;
int ret;
partition_name = grub_partition_get_name (partition); partition_name = grub_partition_get_name (partition);
if (! partition_name) if (! partition_name)
return 1; return 1;
devname = grub_xasprintf ("%s,%s", disk->name, partition_name); devname = grub_xasprintf ("%s,%s", disk->name, partition_name);
grub_free (partition_name); grub_free (partition_name);
if (!devname) if (!devname)
return 1; return 1;
ret = iterate_device (devname); ret = iterate_device (devname, ctx);
grub_free (devname); grub_free (devname);
return ret; return ret;
} }
auto void try (void); /* Helper for FUNC_NAME. */
void try (void) static void
{ try (struct search_ctx *ctx)
unsigned i; {
struct cache_entry **prev; unsigned i;
struct cache_entry *cache_ent; struct cache_entry **prev;
struct cache_entry *cache_ent;
for (prev = &cache, cache_ent = *prev; cache_ent; for (prev = &cache, cache_ent = *prev; cache_ent;
prev = &cache_ent->next, cache_ent = *prev) prev = &cache_ent->next, cache_ent = *prev)
if (compare_fn (cache_ent->key, key) == 0) if (compare_fn (cache_ent->key, ctx->key) == 0)
break; break;
if (cache_ent) if (cache_ent)
{ {
is_cache = 1; ctx->is_cache = 1;
if (iterate_device (cache_ent->value)) if (iterate_device (cache_ent->value, ctx))
{ {
is_cache = 0; ctx->is_cache = 0;
return;
}
ctx->is_cache = 0;
/* Cache entry was outdated. Remove it. */
if (!ctx->count)
{
grub_free (cache_ent->key);
grub_free (cache_ent->value);
grub_free (cache_ent);
*prev = cache_ent->next;
}
}
for (i = 0; i < ctx->nhints; i++)
{
char *end;
if (!ctx->hints[i][0])
continue;
end = ctx->hints[i] + grub_strlen (ctx->hints[i]) - 1;
if (*end == ',')
*end = 0;
if (iterate_device (ctx->hints[i], ctx))
{
if (!*end)
*end = ',';
return;
}
if (!*end)
{
grub_device_t dev;
int ret;
dev = grub_device_open (ctx->hints[i]);
if (!dev)
{
if (!*end)
*end = ',';
continue;
}
if (!dev->disk)
{
grub_device_close (dev);
if (!*end)
*end = ',';
continue;
}
ret = grub_partition_iterate (dev->disk, part_hook, ctx);
if (!*end)
*end = ',';
grub_device_close (dev);
if (ret)
return; return;
} }
is_cache = 0; }
/* Cache entry was outdated. Remove it. */ grub_device_iterate (iterate_device, ctx);
if (!count) }
{
grub_free (cache_ent->key);
grub_free (cache_ent->value);
grub_free (cache_ent);
*prev = cache_ent->next;
}
}
for (i = 0; i < nhints; i++) void
{ FUNC_NAME (const char *key, const char *var, int no_floppy,
char *end; char **hints, unsigned nhints)
if (!hints[i][0]) {
continue; struct search_ctx ctx = {
end = hints[i] + grub_strlen (hints[i]) - 1; .key = key,
if (*end == ',') .var = var,
*end = 0; .no_floppy = no_floppy,
if (iterate_device (hints[i])) .hints = hints,
{ .nhints = nhints,
if (!*end) .count = 0,
*end = ','; .is_cache = 0
return; };
} grub_fs_autoload_hook_t saved_autoload;
if (!*end)
{
grub_device_t dev;
int ret;
dev = grub_device_open (hints[i]);
if (!dev)
{
if (!*end)
*end = ',';
continue;
}
if (!dev->disk)
{
grub_device_close (dev);
if (!*end)
*end = ',';
continue;
}
ret = grub_partition_iterate (dev->disk, part_hook);
if (!*end)
*end = ',';
grub_device_close (dev);
if (ret)
return;
}
}
grub_device_iterate (iterate_device);
}
/* First try without autoloading if we're setting variable. */ /* First try without autoloading if we're setting variable. */
if (var) if (var)
{ {
saved_autoload = grub_fs_autoload_hook; saved_autoload = grub_fs_autoload_hook;
grub_fs_autoload_hook = 0; grub_fs_autoload_hook = 0;
try (); try (&ctx);
/* Restore autoload hook. */ /* Restore autoload hook. */
grub_fs_autoload_hook = saved_autoload; grub_fs_autoload_hook = saved_autoload;
/* Retry with autoload if nothing found. */ /* Retry with autoload if nothing found. */
if (grub_errno == GRUB_ERR_NONE && count == 0) if (grub_errno == GRUB_ERR_NONE && ctx.count == 0)
try (); try (&ctx);
} }
else else
try (); try (&ctx);
if (grub_errno == GRUB_ERR_NONE && count == 0) if (grub_errno == GRUB_ERR_NONE && ctx.count == 0)
grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key); grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
} }

View File

@ -210,59 +210,71 @@ split_path (const char *str, const char **noregexop, const char **regexop)
*noregexop = split; *noregexop = split;
} }
/* Context for match_devices. */
struct match_devices_ctx
{
const regex_t *regexp;
int noparts;
int ndev;
char **devs;
};
/* Helper for match_devices. */
static int
match_devices_iter (const char *name, void *data)
{
struct match_devices_ctx *ctx = data;
char **t;
char *buffer;
/* skip partitions if asked to. */
if (ctx->noparts && grub_strchr (name, ','))
return 0;
buffer = grub_xasprintf ("(%s)", name);
if (! buffer)
return 1;
grub_dprintf ("expand", "matching: %s\n", buffer);
if (regexec (ctx->regexp, buffer, 0, 0, 0))
{
grub_dprintf ("expand", "not matched\n");
grub_free (buffer);
return 0;
}
t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2));
if (! t)
return 1;
ctx->devs = t;
ctx->devs[ctx->ndev++] = buffer;
ctx->devs[ctx->ndev] = 0;
return 0;
}
static char ** static char **
match_devices (const regex_t *regexp, int noparts) match_devices (const regex_t *regexp, int noparts)
{ {
struct match_devices_ctx ctx = {
.regexp = regexp,
.noparts = noparts,
.ndev = 0,
.devs = 0
};
int i; int i;
int ndev;
char **devs;
auto int match (const char *name); if (grub_device_iterate (match_devices_iter, &ctx))
int match (const char *name)
{
char **t;
char *buffer;
/* skip partitions if asked to. */
if (noparts && grub_strchr(name, ','))
return 0;
buffer = grub_xasprintf ("(%s)", name);
if (! buffer)
return 1;
grub_dprintf ("expand", "matching: %s\n", buffer);
if (regexec (regexp, buffer, 0, 0, 0))
{
grub_dprintf ("expand", "not matched\n");
grub_free (buffer);
return 0;
}
t = grub_realloc (devs, sizeof (char*) * (ndev + 2));
if (! t)
return 1;
devs = t;
devs[ndev++] = buffer;
devs[ndev] = 0;
return 0;
}
ndev = 0;
devs = 0;
if (grub_device_iterate (match))
goto fail; goto fail;
return devs; return ctx.devs;
fail: fail:
for (i = 0; devs && devs[i]; i++) for (i = 0; ctx.devs && ctx.devs[i]; i++)
grub_free (devs[i]); grub_free (ctx.devs[i]);
grub_free (devs); grub_free (ctx.devs);
return 0; return 0;
} }

View File

@ -455,8 +455,8 @@ grub_ahci_restore_hw (void)
static int static int
grub_ahci_iterate (int (*hook) (int id, int bus), grub_ahci_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
struct grub_ahci_device *dev; struct grub_ahci_device *dev;
@ -464,7 +464,7 @@ grub_ahci_iterate (int (*hook) (int id, int bus),
return 0; return 0;
FOR_LIST_ELEMENTS(dev, grub_ahci_devices) FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num)) if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num, hook_data))
return 1; return 1;
return 0; return 0;

View File

@ -80,23 +80,37 @@ arcdisk_hash_add (char *devpath)
} }
/* Context for grub_arcdisk_iterate. */
struct grub_arcdisk_iterate_ctx
{
grub_disk_dev_iterate_hook_t hook;
void *hook_data;
};
/* Helper for grub_arcdisk_iterate. */
static int
grub_arcdisk_iterate_iter (const char *name,
const struct grub_arc_component *comp, void *data)
{
struct grub_arcdisk_iterate_ctx *ctx = data;
if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
|| comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
|| comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE))
return 0;
return ctx->hook (name, ctx->hook_data);
}
static int static int
grub_arcdisk_iterate (int (*hook_in) (const char *name), grub_arcdisk_iterate (int (*hook_in) (const char *name),
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
auto int hook (const char *name, const struct grub_arc_component *comp); struct grub_arcdisk_iterate_ctx ctx = { hook, hook_data };
int hook (const char *name, const struct grub_arc_component *comp)
{
if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
|| comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
|| comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE))
return 0;
return hook_in (name);
}
if (pull != GRUB_DISK_PULL_NONE) if (pull != GRUB_DISK_PULL_NONE)
return 0; return 0;
return grub_arc_iterate_devs (hook, 1); return grub_arc_iterate_devs (grub_arcdisk_iterate_iter, &ctx, 1);
} }
#define RAW_SUFFIX "partition(10)" #define RAW_SUFFIX "partition(10)"

View File

@ -392,40 +392,50 @@ grub_ata_real_open (int id, int bus)
return NULL; return NULL;
} }
/* Context for grub_ata_iterate. */
struct grub_ata_iterate_ctx
{
grub_disk_dev_iterate_hook_t hook;
void *hook_data;
};
/* Helper for grub_ata_iterate. */
static int static int
grub_ata_iterate (int (*hook_in) (const char *name), grub_ata_iterate_iter (int id, int bus, void *data)
{
struct grub_ata_iterate_ctx *ctx = data;
struct grub_ata *ata;
int ret;
char devname[40];
ata = grub_ata_real_open (id, bus);
if (!ata)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (ata->atapi)
{
grub_ata_real_close (ata);
return 0;
}
grub_snprintf (devname, sizeof (devname),
"%s%d", grub_scsi_names[id], bus);
ret = ctx->hook (devname, ctx->hook_data);
grub_ata_real_close (ata);
return ret;
}
static int
grub_ata_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
auto int hook (int id, int bus); struct grub_ata_iterate_ctx ctx = { hook, hook_data };
int hook (int id, int bus)
{
struct grub_ata *ata;
int ret;
char devname[40];
ata = grub_ata_real_open (id, bus);
if (!ata)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (ata->atapi)
{
grub_ata_real_close (ata);
return 0;
}
grub_snprintf (devname, sizeof (devname),
"%s%d", grub_scsi_names[id], bus);
ret = hook_in (devname);
grub_ata_real_close (ata);
return ret;
}
grub_ata_dev_t p; grub_ata_dev_t p;
for (p = grub_ata_dev_list; p; p = p->next) for (p = grub_ata_dev_list; p; p = p->next)
if (p->iterate && p->iterate (hook, pull)) if (p->iterate && p->iterate (grub_ata_iterate_iter, &ctx, pull))
return 1; return 1;
return 0; return 0;
} }
@ -561,37 +571,47 @@ grub_atapi_open (int id, int bus, struct grub_scsi *scsi)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
/* Context for grub_atapi_iterate. */
struct grub_atapi_iterate_ctx
{
grub_scsi_dev_iterate_hook_t hook;
void *hook_data;
};
/* Helper for grub_atapi_iterate. */
static int static int
grub_atapi_iterate (int NESTED_FUNC_ATTR (*hook_in) (int id, int bus, int luns), grub_atapi_iterate_iter (int id, int bus, void *data)
{
struct grub_atapi_iterate_ctx *ctx = data;
struct grub_ata *ata;
int ret;
ata = grub_ata_real_open (id, bus);
if (!ata)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (!ata->atapi)
{
grub_ata_real_close (ata);
return 0;
}
ret = ctx->hook (id, bus, 1, ctx->hook_data);
grub_ata_real_close (ata);
return ret;
}
static int
grub_atapi_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
auto int hook (int id, int bus); struct grub_atapi_iterate_ctx ctx = { hook, hook_data };
int hook (int id, int bus)
{
struct grub_ata *ata;
int ret;
ata = grub_ata_real_open (id, bus);
if (!ata)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (!ata->atapi)
{
grub_ata_real_close (ata);
return 0;
}
ret = hook_in (id, bus, 1);
grub_ata_real_close (ata);
return ret;
}
grub_ata_dev_t p; grub_ata_dev_t p;
for (p = grub_ata_dev_list; p; p = p->next) for (p = grub_ata_dev_list; p; p = p->next)
if (p->iterate && p->iterate (hook, pull)) if (p->iterate && p->iterate (grub_atapi_iterate_iter, &ctx, pull))
return 1; return 1;
return 0; return 0;
} }

View File

@ -448,8 +448,8 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t ke
} }
static int static int
grub_cryptodisk_iterate (int (*hook) (const char *name), grub_cryptodisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
grub_cryptodisk_t i; grub_cryptodisk_t i;
@ -460,7 +460,7 @@ grub_cryptodisk_iterate (int (*hook) (const char *name),
{ {
char buf[30]; char buf[30];
grub_snprintf (buf, sizeof (buf), "crypto%lu", i->id); grub_snprintf (buf, sizeof (buf), "crypto%lu", i->id);
if (hook (buf)) if (hook (buf, hook_data))
return 1; return 1;
} }
@ -866,7 +866,8 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
#endif #endif
static int static int
grub_cryptodisk_scan_device (const char *name) grub_cryptodisk_scan_device (const char *name,
void *data __attribute__ ((unused)))
{ {
grub_err_t err; grub_err_t err;
grub_disk_t source; grub_disk_t source;
@ -908,7 +909,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
check_boot = state[2].set; check_boot = state[2].set;
search_uuid = args[0]; search_uuid = args[0];
grub_device_iterate (&grub_cryptodisk_scan_device); grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
search_uuid = NULL; search_uuid = NULL;
if (!have_it) if (!have_it)
@ -919,7 +920,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{ {
search_uuid = NULL; search_uuid = NULL;
check_boot = state[2].set; check_boot = state[2].set;
grub_device_iterate (&grub_cryptodisk_scan_device); grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
search_uuid = NULL; search_uuid = NULL;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }

View File

@ -120,65 +120,68 @@ is_valid_diskfilter_name (const char *name)
|| grub_memcmp (name, "ldm/", sizeof ("ldm/") - 1) == 0); || grub_memcmp (name, "ldm/", sizeof ("ldm/") - 1) == 0);
} }
/* Helper for scan_disk. */
static int
scan_disk_partition_iter (grub_disk_t disk, grub_partition_t p, void *data)
{
const char *name = data;
struct grub_diskfilter_vg *arr;
grub_disk_addr_t start_sector;
struct grub_diskfilter_pv_id id;
grub_diskfilter_t diskfilter;
grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n",
name);
#ifdef GRUB_UTIL
grub_util_info ("Scanning for DISKFILTER devices on disk %s", name);
#endif
disk->partition = p;
for (arr = array_list; arr != NULL; arr = arr->next)
{
struct grub_diskfilter_pv *m;
for (m = arr->pvs; m; m = m->next)
if (m->disk && m->disk->id == disk->id
&& m->disk->dev->id == disk->dev->id
&& m->part_start == grub_partition_get_start (disk->partition)
&& m->part_size == grub_disk_get_size (disk))
return 0;
}
for (diskfilter = grub_diskfilter_list; diskfilter; diskfilter = diskfilter->next)
{
#ifdef GRUB_UTIL
grub_util_info ("Scanning for %s devices on disk %s",
diskfilter->name, name);
#endif
id.uuid = 0;
id.uuidlen = 0;
arr = diskfilter->detect (disk, &id, &start_sector);
if (arr &&
(! insert_array (disk, &id, arr, start_sector, diskfilter)))
{
if (id.uuidlen)
grub_free (id.uuid);
return 0;
}
if (arr && id.uuidlen)
grub_free (id.uuid);
/* This error usually means it's not diskfilter, no need to display
it. */
if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
return 0;
}
static int static int
scan_disk (const char *name, int accept_diskfilter) scan_disk (const char *name, int accept_diskfilter)
{ {
auto int hook (grub_disk_t disk, grub_partition_t p);
int hook (grub_disk_t disk, grub_partition_t p)
{
struct grub_diskfilter_vg *arr;
grub_disk_addr_t start_sector;
struct grub_diskfilter_pv_id id;
grub_diskfilter_t diskfilter;
grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n",
name);
#ifdef GRUB_UTIL
grub_util_info ("Scanning for DISKFILTER devices on disk %s", name);
#endif
disk->partition = p;
for (arr = array_list; arr != NULL; arr = arr->next)
{
struct grub_diskfilter_pv *m;
for (m = arr->pvs; m; m = m->next)
if (m->disk && m->disk->id == disk->id
&& m->disk->dev->id == disk->dev->id
&& m->part_start == grub_partition_get_start (disk->partition)
&& m->part_size == grub_disk_get_size (disk))
return 0;
}
for (diskfilter = grub_diskfilter_list; diskfilter; diskfilter = diskfilter->next)
{
#ifdef GRUB_UTIL
grub_util_info ("Scanning for %s devices on disk %s",
diskfilter->name, name);
#endif
id.uuid = 0;
id.uuidlen = 0;
arr = diskfilter->detect (disk, &id, &start_sector);
if (arr &&
(! insert_array (disk, &id, arr, start_sector, diskfilter)))
{
if (id.uuidlen)
grub_free (id.uuid);
return 0;
}
if (arr && id.uuidlen)
grub_free (id.uuid);
/* This error usually means it's not diskfilter, no need to display
it. */
if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
return 0;
}
grub_disk_t disk; grub_disk_t disk;
static int scan_depth = 0; static int scan_depth = 0;
@ -196,12 +199,12 @@ scan_disk (const char *name, int accept_diskfilter)
scan_depth--; scan_depth--;
return 0; return 0;
} }
if (hook (disk, 0)) if (scan_disk_partition_iter (disk, 0, (void *) name))
{ {
scan_depth--; scan_depth--;
return 1; return 1;
} }
if (grub_partition_iterate (disk, hook)) if (grub_partition_iterate (disk, scan_disk_partition_iter, (void *) name))
{ {
scan_depth--; scan_depth--;
return 1; return 1;
@ -212,7 +215,7 @@ scan_disk (const char *name, int accept_diskfilter)
} }
static int static int
scan_disk_hook (const char *name) scan_disk_hook (const char *name, void *data __attribute__ ((unused)))
{ {
return scan_disk (name, 0); return scan_disk (name, 0);
} }
@ -230,7 +233,7 @@ scan_devices (const char *arname)
if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
&& p->iterate) && p->iterate)
{ {
if ((p->iterate) (scan_disk_hook, pull)) if ((p->iterate) (scan_disk_hook, NULL, pull))
return; return;
if (arname && is_lv_readable (find_lv (arname), 1)) if (arname && is_lv_readable (find_lv (arname), 1))
return; return;
@ -249,8 +252,8 @@ scan_devices (const char *arname)
} }
static int static int
grub_diskfilter_iterate (int (*hook) (const char *name), grub_diskfilter_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
struct grub_diskfilter_vg *array; struct grub_diskfilter_vg *array;
int islcnt = 0; int islcnt = 0;
@ -271,7 +274,7 @@ grub_diskfilter_iterate (int (*hook) (const char *name),
for (lv = array->lvs; lv; lv = lv->next) for (lv = array->lvs; lv; lv = lv->next)
if (lv->visible && lv->fullname && lv->became_readable_at >= islcnt) if (lv->visible && lv->fullname && lv->became_readable_at >= islcnt)
{ {
if (hook (lv->fullname)) if (hook (lv->fullname, hook_data))
return 1; return 1;
} }
} }
@ -303,7 +306,7 @@ grub_diskfilter_memberlist (grub_disk_t disk)
if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
&& p->iterate) && p->iterate)
{ {
(p->iterate) (scan_disk_hook, pull); (p->iterate) (scan_disk_hook, NULL, pull);
while (pv && pv->disk) while (pv && pv->disk)
pv = pv->next; pv = pv->next;
} }

View File

@ -404,7 +404,7 @@ enumerate_disks (void)
} }
static int static int
grub_efidisk_iterate (int (*hook) (const char *name), grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
struct grub_efidisk_data *d; struct grub_efidisk_data *d;
@ -418,7 +418,7 @@ grub_efidisk_iterate (int (*hook) (const char *name),
{ {
grub_snprintf (buf, sizeof (buf), "hd%d", count); grub_snprintf (buf, sizeof (buf), "hd%d", count);
grub_dprintf ("efidisk", "iterating %s\n", buf); grub_dprintf ("efidisk", "iterating %s\n", buf);
if (hook (buf)) if (hook (buf, hook_data))
return 1; return 1;
} }
break; break;
@ -427,7 +427,7 @@ grub_efidisk_iterate (int (*hook) (const char *name),
{ {
grub_snprintf (buf, sizeof (buf), "fd%d", count); grub_snprintf (buf, sizeof (buf), "fd%d", count);
grub_dprintf ("efidisk", "iterating %s\n", buf); grub_dprintf ("efidisk", "iterating %s\n", buf);
if (hook (buf)) if (hook (buf, hook_data))
return 1; return 1;
} }
@ -435,7 +435,7 @@ grub_efidisk_iterate (int (*hook) (const char *name),
{ {
grub_snprintf (buf, sizeof (buf), "cd%d", count); grub_snprintf (buf, sizeof (buf), "cd%d", count);
grub_dprintf ("efidisk", "iterating %s\n", buf); grub_dprintf ("efidisk", "iterating %s\n", buf);
if (hook (buf)) if (hook (buf, hook_data))
return 1; return 1;
} }
break; break;
@ -736,6 +736,31 @@ get_diskname_from_path (const grub_efi_device_path_t *path,
return 0; return 0;
} }
/* Context for grub_efidisk_get_device_name. */
struct grub_efidisk_get_device_name_ctx
{
char *partition_name;
grub_efi_hard_drive_device_path_t hd;
};
/* Helper for grub_efidisk_get_device_name.
Find the identical partition. */
static int
grub_efidisk_get_device_name_iter (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t part, void *data)
{
struct grub_efidisk_get_device_name_ctx *ctx = data;
if (grub_partition_get_start (part) == ctx->hd.partition_start
&& grub_partition_get_len (part) == ctx->hd.partition_size)
{
ctx->partition_name = grub_partition_get_name (part);
return 1;
}
return 0;
}
char * char *
grub_efidisk_get_device_name (grub_efi_handle_t *handle) grub_efidisk_get_device_name (grub_efi_handle_t *handle)
{ {
@ -754,28 +779,11 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
{ {
char *partition_name = NULL; struct grub_efidisk_get_device_name_ctx ctx;
char *dev_name; char *dev_name;
grub_efi_device_path_t *dup_dp, *dup_ldp; grub_efi_device_path_t *dup_dp, *dup_ldp;
grub_efi_hard_drive_device_path_t hd;
grub_disk_t parent = 0; grub_disk_t parent = 0;
auto int find_partition (grub_disk_t disk, const grub_partition_t part);
/* Find the identical partition. */
int find_partition (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t part)
{
if (grub_partition_get_start (part) == hd.partition_start
&& grub_partition_get_len (part) == hd.partition_size)
{
partition_name = grub_partition_get_name (part);
return 1;
}
return 0;
}
/* It is necessary to duplicate the device path so that GRUB /* It is necessary to duplicate the device path so that GRUB
can overwrite it. */ can overwrite it. */
dup_dp = duplicate_device_path (dp); dup_dp = duplicate_device_path (dp);
@ -797,24 +805,27 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
return 0; return 0;
/* Find a partition which matches the hard drive device path. */ /* Find a partition which matches the hard drive device path. */
grub_memcpy (&hd, ldp, sizeof (hd)); ctx.partition_name = NULL;
if (hd.partition_start == 0 grub_memcpy (&ctx.hd, ldp, sizeof (ctx.hd));
&& hd.partition_size == grub_disk_get_size (parent)) if (ctx.hd.partition_start == 0
&& ctx.hd.partition_size == grub_disk_get_size (parent))
{ {
dev_name = grub_strdup (parent->name); dev_name = grub_strdup (parent->name);
} }
else else
{ {
grub_partition_iterate (parent, find_partition); grub_partition_iterate (parent, grub_efidisk_get_device_name_iter,
&ctx);
if (! partition_name) if (! ctx.partition_name)
{ {
grub_disk_close (parent); grub_disk_close (parent);
return 0; return 0;
} }
dev_name = grub_xasprintf ("%s,%s", parent->name, partition_name); dev_name = grub_xasprintf ("%s,%s", parent->name,
grub_free (partition_name); ctx.partition_name);
grub_free (ctx.partition_name);
} }
grub_disk_close (parent); grub_disk_close (parent);

View File

@ -27,13 +27,13 @@
int grub_disk_host_i_want_a_reference; int grub_disk_host_i_want_a_reference;
static int static int
grub_host_iterate (int (*hook) (const char *name), grub_host_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
if (pull != GRUB_DISK_PULL_NONE) if (pull != GRUB_DISK_PULL_NONE)
return 0; return 0;
if (hook ("host")) if (hook ("host", hook_data))
return 1; return 1;
return 0; return 0;
} }

View File

@ -272,20 +272,21 @@ grub_biosdisk_get_drive (const char *name)
} }
static int static int
grub_biosdisk_call_hook (int (*hook) (const char *name), int drive) grub_biosdisk_call_hook (grub_disk_dev_iterate_hook_t hook, void *hook_data,
int drive)
{ {
char name[10]; char name[10];
if (cd_drive && drive == cd_drive) if (cd_drive && drive == cd_drive)
return hook ("cd"); return hook ("cd", hook_data);
grub_snprintf (name, sizeof (name), grub_snprintf (name, sizeof (name),
(drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80)); (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
return hook (name); return hook (name, hook_data);
} }
static int static int
grub_biosdisk_iterate (int (*hook) (const char *name), grub_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull __attribute__ ((unused))) grub_disk_pull_t pull __attribute__ ((unused)))
{ {
int num_floppies; int num_floppies;
@ -304,7 +305,7 @@ grub_biosdisk_iterate (int (*hook) (const char *name),
break; break;
} }
if (grub_biosdisk_call_hook (hook, drive)) if (grub_biosdisk_call_hook (hook, hook_data, drive))
return 1; return 1;
} }
return 0; return 0;
@ -312,14 +313,14 @@ grub_biosdisk_iterate (int (*hook) (const char *name),
case GRUB_DISK_PULL_REMOVABLE: case GRUB_DISK_PULL_REMOVABLE:
if (cd_drive) if (cd_drive)
{ {
if (grub_biosdisk_call_hook (hook, cd_drive)) if (grub_biosdisk_call_hook (hook, hook_data, cd_drive))
return 1; return 1;
} }
/* For floppy disks, we can get the number safely. */ /* For floppy disks, we can get the number safely. */
num_floppies = grub_biosdisk_get_num_floppies (); num_floppies = grub_biosdisk_get_num_floppies ();
for (drive = 0; drive < num_floppies; drive++) for (drive = 0; drive < num_floppies; drive++)
if (grub_biosdisk_call_hook (hook, drive)) if (grub_biosdisk_call_hook (hook, hook_data, drive))
return 1; return 1;
return 0; return 0;
default: default:

View File

@ -33,7 +33,7 @@ struct grub_nand_data
}; };
static int static int
grub_nand_iterate (int (*hook) (const char *name), grub_nand_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
auto int dev_iterate (struct grub_ieee1275_devalias *alias); auto int dev_iterate (struct grub_ieee1275_devalias *alias);
@ -41,7 +41,7 @@ grub_nand_iterate (int (*hook) (const char *name),
{ {
if (grub_strcmp (alias->name, "nand") == 0) if (grub_strcmp (alias->name, "nand") == 0)
{ {
hook (alias->name); hook (alias->name, hook_data);
return 1; return 1;
} }

View File

@ -218,7 +218,7 @@ scan (void)
} }
static int static int
grub_ofdisk_iterate (int (*hook) (const char *name), grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
unsigned i; unsigned i;
@ -276,7 +276,7 @@ grub_ofdisk_iterate (int (*hook) (const char *name),
*optr++ = *iptr++; *optr++ = *iptr++;
} }
*optr = 0; *optr = 0;
if (hook (buffer)) if (hook (buffer, hook_data))
return 1; return 1;
} }
} }

View File

@ -105,35 +105,39 @@ read_int (grub_uint8_t *in, grub_size_t s)
static const grub_gpt_part_type_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM; static const grub_gpt_part_type_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM;
/* Helper for gpt_ldm_sector. */
static int
gpt_ldm_sector_iter (grub_disk_t disk, const grub_partition_t p, void *data)
{
grub_disk_addr_t *sector = data;
struct grub_gpt_partentry gptdata;
grub_partition_t p2;
p2 = disk->partition;
disk->partition = p->parent;
if (grub_disk_read (disk, p->offset, p->index,
sizeof (gptdata), &gptdata))
{
disk->partition = p2;
return 0;
}
disk->partition = p2;
if (! grub_memcmp (&gptdata.type, &ldm_type, 16))
{
*sector = p->start + p->len - 1;
return 1;
}
return 0;
}
static grub_disk_addr_t static grub_disk_addr_t
gpt_ldm_sector (grub_disk_t dsk) gpt_ldm_sector (grub_disk_t dsk)
{ {
grub_disk_addr_t sector = 0; grub_disk_addr_t sector = 0;
grub_err_t err; grub_err_t err;
auto int hook (grub_disk_t disk, const grub_partition_t p);
int hook (grub_disk_t disk, const grub_partition_t p)
{
struct grub_gpt_partentry gptdata;
grub_partition_t p2;
p2 = disk->partition; err = grub_gpt_partition_map_iterate (dsk, gpt_ldm_sector_iter, &sector);
disk->partition = p->parent;
if (grub_disk_read (disk, p->offset, p->index,
sizeof (gptdata), &gptdata))
{
disk->partition = p2;
return 0;
}
disk->partition = p2;
if (! grub_memcmp (&gptdata.type, &ldm_type, 16))
{
sector = p->start + p->len - 1;
return 1;
}
return 0;
}
err = grub_gpt_partition_map_iterate (dsk, hook);
if (err) if (err)
{ {
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;

View File

@ -135,15 +135,15 @@ fail:
static int static int
grub_loopback_iterate (int (*hook) (const char *name), grub_loopback_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
struct grub_loopback *d; struct grub_loopback *d;
if (pull != GRUB_DISK_PULL_NONE) if (pull != GRUB_DISK_PULL_NONE)
return 0; return 0;
for (d = loopback_list; d; d = d->next) for (d = loopback_list; d; d = d->next)
{ {
if (hook (d->devname)) if (hook (d->devname, hook_data))
return 1; return 1;
} }
return 0; return 0;

View File

@ -30,13 +30,13 @@ static char *memdisk_addr;
static grub_off_t memdisk_size = 0; static grub_off_t memdisk_size = 0;
static int static int
grub_memdisk_iterate (int (*hook) (const char *name), grub_memdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
if (pull != GRUB_DISK_PULL_NONE) if (pull != GRUB_DISK_PULL_NONE)
return 0; return 0;
return hook ("memdisk"); return hook ("memdisk", hook_data);
} }
static grub_err_t static grub_err_t

View File

@ -501,7 +501,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata)
} }
static int static int
grub_pata_iterate (int (*hook) (int id, int bus), grub_pata_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
struct grub_pata_device *dev; struct grub_pata_device *dev;
@ -510,7 +510,8 @@ grub_pata_iterate (int (*hook) (int id, int bus),
return 0; return 0;
for (dev = grub_pata_devices; dev; dev = dev->next) for (dev = grub_pata_devices; dev; dev = dev->next)
if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device)) if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device,
hook_data))
return 1; return 1;
return 0; return 0;

View File

@ -423,50 +423,59 @@ grub_scsi_write16 (grub_disk_t disk, grub_disk_addr_t sector,
static int /* Context for grub_scsi_iterate. */
grub_scsi_iterate (int (*hook) (const char *name), struct grub_scsi_iterate_ctx
grub_disk_pull_t pull)
{ {
grub_scsi_dev_t p; grub_disk_dev_iterate_hook_t hook;
void *hook_data;
};
auto int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns); /* Helper for grub_scsi_iterate. */
static int
scsi_iterate (int id, int bus, int luns, void *data)
{
struct grub_scsi_iterate_ctx *ctx = data;
int i;
int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns) /* In case of a single LUN, just return `usbX'. */
if (luns == 1)
{ {
int i; char *sname;
int ret;
/* In case of a single LUN, just return `usbX'. */ sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus);
if (luns == 1) if (!sname)
{ return 1;
char *sname; ret = ctx->hook (sname, ctx->hook_data);
int ret; grub_free (sname);
sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus); return ret;
if (!sname)
return 1;
ret = hook (sname);
grub_free (sname);
return ret;
}
/* In case of multiple LUNs, every LUN will get a prefix to
distinguish it. */
for (i = 0; i < luns; i++)
{
char *sname;
int ret;
sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i);
if (!sname)
return 1;
ret = hook (sname);
grub_free (sname);
if (ret)
return 1;
}
return 0;
} }
/* In case of multiple LUNs, every LUN will get a prefix to
distinguish it. */
for (i = 0; i < luns; i++)
{
char *sname;
int ret;
sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i);
if (!sname)
return 1;
ret = ctx->hook (sname, ctx->hook_data);
grub_free (sname);
if (ret)
return 1;
}
return 0;
}
static int
grub_scsi_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull)
{
struct grub_scsi_iterate_ctx ctx = { hook, hook_data };
grub_scsi_dev_t p;
for (p = grub_scsi_dev_list; p; p = p->next) for (p = grub_scsi_dev_list; p; p = p->next)
if (p->iterate && (p->iterate) (scsi_iterate, pull)) if (p->iterate && (p->iterate) (scsi_iterate, &ctx, pull))
return 1; return 1;
return 0; return 0;

View File

@ -265,7 +265,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
static int static int
grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns), grub_usbms_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
unsigned i; unsigned i;
@ -278,7 +278,8 @@ grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns),
for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++) for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)
if (grub_usbms_devices[i]) if (grub_usbms_devices[i])
{ {
if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns)) if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns,
hook_data))
return 1; return 1;
} }

View File

@ -538,56 +538,71 @@ lower_bound (struct grub_btrfs_data *data,
} }
} }
/* Context for find_device. */
struct find_device_ctx
{
struct grub_btrfs_data *data;
grub_uint64_t id;
grub_device_t dev_found;
};
/* Helper for find_device. */
static int
find_device_iter (const char *name, void *data)
{
struct find_device_ctx *ctx = data;
grub_device_t dev;
grub_err_t err;
struct grub_btrfs_superblock sb;
dev = grub_device_open (name);
if (!dev)
return 0;
if (!dev->disk)
{
grub_device_close (dev);
return 0;
}
err = read_sblock (dev->disk, &sb);
if (err == GRUB_ERR_BAD_FS)
{
grub_device_close (dev);
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (err)
{
grub_device_close (dev);
grub_print_error ();
return 0;
}
if (grub_memcmp (ctx->data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0
|| sb.this_device.device_id != ctx->id)
{
grub_device_close (dev);
return 0;
}
ctx->dev_found = dev;
return 1;
}
static grub_device_t static grub_device_t
find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan) find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan)
{ {
grub_device_t dev_found = NULL; struct find_device_ctx ctx = {
auto int hook (const char *name); .data = data,
int hook (const char *name) .id = id,
{ .dev_found = NULL
grub_device_t dev; };
grub_err_t err;
struct grub_btrfs_superblock sb;
dev = grub_device_open (name);
if (!dev)
return 0;
if (!dev->disk)
{
grub_device_close (dev);
return 0;
}
err = read_sblock (dev->disk, &sb);
if (err == GRUB_ERR_BAD_FS)
{
grub_device_close (dev);
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (err)
{
grub_device_close (dev);
grub_print_error ();
return 0;
}
if (grub_memcmp (data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0
|| sb.this_device.device_id != id)
{
grub_device_close (dev);
return 0;
}
dev_found = dev;
return 1;
}
unsigned i; unsigned i;
for (i = 0; i < data->n_devices_attached; i++) for (i = 0; i < data->n_devices_attached; i++)
if (id == data->devices_attached[i].id) if (id == data->devices_attached[i].id)
return data->devices_attached[i].dev; return data->devices_attached[i].dev;
if (do_rescan) if (do_rescan)
grub_device_iterate (hook); grub_device_iterate (find_device_iter, &ctx);
if (!dev_found) if (!ctx.dev_found)
{ {
grub_error (GRUB_ERR_BAD_FS, grub_error (GRUB_ERR_BAD_FS,
N_("couldn't find a necessary member device " N_("couldn't find a necessary member device "
@ -605,14 +620,14 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan)
* sizeof (data->devices_attached[0])); * sizeof (data->devices_attached[0]));
if (!data->devices_attached) if (!data->devices_attached)
{ {
grub_device_close (dev_found); grub_device_close (ctx.dev_found);
data->devices_attached = tmp; data->devices_attached = tmp;
return NULL; return NULL;
} }
} }
data->devices_attached[data->n_devices_attached - 1].id = id; data->devices_attached[data->n_devices_attached - 1].id = id;
data->devices_attached[data->n_devices_attached - 1].dev = dev_found; data->devices_attached[data->n_devices_attached - 1].dev = ctx.dev_found;
return dev_found; return ctx.dev_found;
} }
static grub_err_t static grub_err_t

View File

@ -988,43 +988,47 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data,
return grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label"); return grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label");
} }
/* Helper for scan_devices. */
static int
scan_devices_iter (const char *name, void *hook_data)
{
struct grub_zfs_data *data = hook_data;
grub_device_t dev;
grub_err_t err;
int inserted;
dev = grub_device_open (name);
if (!dev)
return 0;
if (!dev->disk)
{
grub_device_close (dev);
return 0;
}
err = scan_disk (dev, data, 0, &inserted);
if (err == GRUB_ERR_BAD_FS)
{
grub_device_close (dev);
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (err)
{
grub_device_close (dev);
grub_print_error ();
return 0;
}
if (!inserted)
grub_device_close (dev);
return 0;
}
static grub_err_t static grub_err_t
scan_devices (struct grub_zfs_data *data) scan_devices (struct grub_zfs_data *data)
{ {
auto int hook (const char *name); grub_device_iterate (scan_devices_iter, data);
int hook (const char *name)
{
grub_device_t dev;
grub_err_t err;
int inserted;
dev = grub_device_open (name);
if (!dev)
return 0;
if (!dev->disk)
{
grub_device_close (dev);
return 0;
}
err = scan_disk (dev, data, 0, &inserted);
if (err == GRUB_ERR_BAD_FS)
{
grub_device_close (dev);
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (err)
{
grub_device_close (dev);
grub_print_error ();
return 0;
}
if (!inserted)
grub_device_close (dev);
return 0;
}
grub_device_iterate (hook);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }

View File

@ -96,7 +96,7 @@ grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)),
} }
static int static int
grub_mini_print_devices (const char *name) grub_mini_print_devices (const char *name, void *data __attribute__ ((unused)))
{ {
grub_printf ("(%s) ", name); grub_printf ("(%s) ", name);
@ -119,7 +119,7 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)),
{ {
if (argc < 1) if (argc < 1)
{ {
grub_device_iterate (grub_mini_print_devices); grub_device_iterate (grub_mini_print_devices, NULL);
grub_xputs ("\n"); grub_xputs ("\n");
grub_refresh (); grub_refresh ();
} }

View File

@ -85,94 +85,107 @@ grub_device_close (grub_device_t device)
return grub_errno; return grub_errno;
} }
int struct part_ent
grub_device_iterate (int (*hook) (const char *name))
{ {
auto int iterate_disk (const char *disk_name); struct part_ent *next;
auto int iterate_partition (grub_disk_t disk, char *name;
const grub_partition_t partition); };
struct part_ent /* Context for grub_device_iterate. */
{ struct grub_device_iterate_ctx
struct part_ent *next; {
char *name; grub_device_iterate_hook_t hook;
} *ents; void *hook_data;
struct part_ent *ents;
};
int iterate_disk (const char *disk_name) /* Helper for grub_device_iterate. */
static int
iterate_partition (grub_disk_t disk, const grub_partition_t partition,
void *data)
{
struct grub_device_iterate_ctx *ctx = data;
struct part_ent *p;
char *part_name;
p = grub_malloc (sizeof (*p));
if (!p)
{ {
grub_device_t dev; return 1;
}
if (hook (disk_name)) part_name = grub_partition_get_name (partition);
return 1; if (!part_name)
{
grub_free (p);
return 1;
}
p->name = grub_xasprintf ("%s,%s", disk->name, part_name);
grub_free (part_name);
if (!p->name)
{
grub_free (p);
return 1;
}
dev = grub_device_open (disk_name); p->next = ctx->ents;
if (! dev) ctx->ents = p;
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (dev->disk) return 0;
{ }
struct part_ent *p;
int ret = 0;
ents = NULL; /* Helper for grub_device_iterate. */
(void) grub_partition_iterate (dev->disk, iterate_partition); static int
grub_device_close (dev); iterate_disk (const char *disk_name, void *data)
{
struct grub_device_iterate_ctx *ctx = data;
grub_device_t dev;
grub_errno = GRUB_ERR_NONE; if (ctx->hook (disk_name, ctx->hook_data))
return 1;
p = ents; dev = grub_device_open (disk_name);
while (p != NULL) if (! dev)
{ {
struct part_ent *next = p->next; grub_errno = GRUB_ERR_NONE;
if (!ret)
ret = hook (p->name);
grub_free (p->name);
grub_free (p);
p = next;
}
return ret;
}
grub_device_close (dev);
return 0; return 0;
} }
int iterate_partition (grub_disk_t disk, const grub_partition_t partition) if (dev->disk)
{ {
struct part_ent *p; struct part_ent *p;
char *part_name; int ret = 0;
p = grub_malloc (sizeof (*p)); ctx->ents = NULL;
if (!p) (void) grub_partition_iterate (dev->disk, iterate_partition, ctx);
{ grub_device_close (dev);
return 1;
}
part_name = grub_partition_get_name (partition); grub_errno = GRUB_ERR_NONE;
if (!part_name)
p = ctx->ents;
while (p != NULL)
{ {
struct part_ent *next = p->next;
if (!ret)
ret = ctx->hook (p->name, ctx->hook_data);
grub_free (p->name);
grub_free (p); grub_free (p);
return 1; p = next;
}
p->name = grub_xasprintf ("%s,%s", disk->name, part_name);
grub_free (part_name);
if (!p->name)
{
grub_free (p);
return 1;
} }
p->next = ents; return ret;
ents = p;
return 0;
} }
/* Only disk devices are supported at the moment. */ grub_device_close (dev);
return grub_disk_dev_iterate (iterate_disk); return 0;
}
int
grub_device_iterate (grub_device_iterate_hook_t hook, void *hook_data)
{
struct grub_device_iterate_ctx ctx = { hook, hook_data, NULL };
/* Only disk devices are supported at the moment. */
return grub_disk_dev_iterate (iterate_disk, &ctx);
} }

View File

@ -223,7 +223,7 @@ find_free_slot (void)
} }
static int static int
grub_util_biosdisk_iterate (int (*hook) (const char *name), grub_util_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull) grub_disk_pull_t pull)
{ {
unsigned i; unsigned i;
@ -232,7 +232,7 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name),
return 0; return 0;
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
if (map[i].drive && hook (map[i].drive)) if (map[i].drive && hook (map[i].drive, hook_data))
return 1; return 1;
return 0; return 0;

View File

@ -48,8 +48,7 @@ const char *type_names[] = {
static int static int
iterate_rec (const char *prefix, const struct grub_arc_component *parent, iterate_rec (const char *prefix, const struct grub_arc_component *parent,
int (*hook) (const char *name, grub_arc_iterate_devs_hook_t hook, void *hook_data,
const struct grub_arc_component *comp),
int alt_names) int alt_names)
{ {
const struct grub_arc_component *comp; const struct grub_arc_component *comp;
@ -67,12 +66,13 @@ iterate_rec (const char *prefix, const struct grub_arc_component *parent,
name = grub_xasprintf ("%s%s(%lu)", prefix, cname, comp->key); name = grub_xasprintf ("%s%s(%lu)", prefix, cname, comp->key);
if (!name) if (!name)
return 1; return 1;
if (hook (name, comp)) if (hook (name, comp, hook_data))
{ {
grub_free (name); grub_free (name);
return 1; return 1;
} }
if (iterate_rec ((parent ? name : prefix), comp, hook, alt_names)) if (iterate_rec ((parent ? name : prefix), comp, hook, hook_data,
alt_names))
{ {
grub_free (name); grub_free (name);
return 1; return 1;
@ -83,11 +83,11 @@ iterate_rec (const char *prefix, const struct grub_arc_component *parent,
} }
int int
grub_arc_iterate_devs (int (*hook) (const char *name, grub_arc_iterate_devs (grub_arc_iterate_devs_hook_t hook, void *hook_data,
const struct grub_arc_component *comp),
int alt_names) int alt_names)
{ {
return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, alt_names); return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, hook_data,
alt_names);
} }
grub_err_t grub_err_t

View File

@ -59,39 +59,50 @@ grub_partition_check_containment (const grub_disk_t disk,
return 1; return 1;
} }
/* Context for grub_partition_map_probe. */
struct grub_partition_map_probe_ctx
{
int partnum;
grub_partition_t p;
};
/* Helper for grub_partition_map_probe. */
static int
probe_iter (grub_disk_t dsk, const grub_partition_t partition, void *data)
{
struct grub_partition_map_probe_ctx *ctx = data;
if (ctx->partnum != partition->number)
return 0;
if (!(grub_partition_check_containment (dsk, partition)))
return 0;
ctx->p = (grub_partition_t) grub_malloc (sizeof (*ctx->p));
if (! ctx->p)
return 1;
grub_memcpy (ctx->p, partition, sizeof (*ctx->p));
return 1;
}
static grub_partition_t static grub_partition_t
grub_partition_map_probe (const grub_partition_map_t partmap, grub_partition_map_probe (const grub_partition_map_t partmap,
grub_disk_t disk, int partnum) grub_disk_t disk, int partnum)
{ {
grub_partition_t p = 0; struct grub_partition_map_probe_ctx ctx = {
.partnum = partnum,
.p = 0
};
auto int find_func (grub_disk_t d, const grub_partition_t partition); partmap->iterate (disk, probe_iter, &ctx);
int find_func (grub_disk_t dsk,
const grub_partition_t partition)
{
if (partnum != partition->number)
return 0;
if (!(grub_partition_check_containment (dsk, partition)))
return 0;
p = (grub_partition_t) grub_malloc (sizeof (*p));
if (! p)
return 1;
grub_memcpy (p, partition, sizeof (*p));
return 1;
}
partmap->iterate (disk, find_func);
if (grub_errno) if (grub_errno)
goto fail; goto fail;
return p; return ctx.p;
fail: fail:
grub_free (p); grub_free (ctx.p);
return 0; return 0;
} }
@ -162,62 +173,71 @@ grub_partition_probe (struct grub_disk *disk, const char *str)
return part; return part;
} }
/* Context for grub_partition_iterate. */
struct grub_partition_iterate_ctx
{
int ret;
grub_partition_iterate_hook_t hook;
void *hook_data;
};
/* Helper for grub_partition_iterate. */
static int
part_iterate (grub_disk_t dsk, const grub_partition_t partition, void *data)
{
struct grub_partition_iterate_ctx *ctx = data;
struct grub_partition p = *partition;
if (!(grub_partition_check_containment (dsk, partition)))
return 0;
p.parent = dsk->partition;
dsk->partition = 0;
if (ctx->hook (dsk, &p, ctx->hook_data))
{
ctx->ret = 1;
return 1;
}
if (p.start != 0)
{
const struct grub_partition_map *partmap;
dsk->partition = &p;
FOR_PARTITION_MAPS(partmap)
{
grub_err_t err;
err = partmap->iterate (dsk, part_iterate, ctx);
if (err)
grub_errno = GRUB_ERR_NONE;
if (ctx->ret)
break;
}
}
dsk->partition = p.parent;
return ctx->ret;
}
int int
grub_partition_iterate (struct grub_disk *disk, grub_partition_iterate (struct grub_disk *disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook, void *hook_data)
const grub_partition_t partition))
{ {
int ret = 0; struct grub_partition_iterate_ctx ctx = {
.ret = 0,
auto int part_iterate (grub_disk_t dsk, const grub_partition_t p); .hook = hook,
.hook_data = hook_data
int part_iterate (grub_disk_t dsk, };
const grub_partition_t partition) const struct grub_partition_map *partmap;
{
struct grub_partition p = *partition;
if (!(grub_partition_check_containment (dsk, partition)))
return 0;
p.parent = dsk->partition;
dsk->partition = 0;
if (hook (dsk, &p))
{
ret = 1;
return 1;
}
if (p.start != 0)
{
const struct grub_partition_map *partmap;
dsk->partition = &p;
FOR_PARTITION_MAPS(partmap)
{
grub_err_t err;
err = partmap->iterate (dsk, part_iterate);
if (err)
grub_errno = GRUB_ERR_NONE;
if (ret)
break;
}
}
dsk->partition = p.parent;
return ret;
}
FOR_PARTITION_MAPS(partmap)
{ {
const struct grub_partition_map *partmap; grub_err_t err;
FOR_PARTITION_MAPS(partmap) err = partmap->iterate (disk, part_iterate, &ctx);
{ if (err)
grub_err_t err; grub_errno = GRUB_ERR_NONE;
err = partmap->iterate (disk, part_iterate); if (ctx.ret)
if (err) break;
grub_errno = GRUB_ERR_NONE;
if (ret)
break;
}
} }
return ret; return ctx.ret;
} }
char * char *

View File

@ -102,248 +102,281 @@ grub_plan9_unload (void)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
static grub_err_t /* Context for grub_cmd_plan9. */
grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) struct grub_cmd_plan9_ctx
{ {
grub_file_t file = 0; grub_extcmd_context_t ctxt;
void *mem; grub_file_t file;
grub_size_t memsize, padsize; char *pmap;
struct grub_plan9_header hdr; grub_size_t pmapalloc;
char *config, *configptr; grub_size_t pmapptr;
grub_size_t configsize; int noslash;
char *pmap = NULL;
grub_size_t pmapalloc = 256;
grub_size_t pmapptr = 0;
int noslash = 1;
char prefixes[5][10] = {"dos", "plan9", "ntfs", "linux", "linuxswap"};
int prefixescnt[5]; int prefixescnt[5];
char *bootdisk = NULL, *bootpart = NULL, *bootpath = NULL; char *bootdisk, *bootpart;
};
auto int fill_partition (grub_disk_t disk, static const char prefixes[5][10] = {
const grub_partition_t partition); "dos", "plan9", "ntfs", "linux", "linuxswap"
int fill_partition (grub_disk_t disk, };
const grub_partition_t partition)
{
int file_disk = 0;
int pstart, pend;
if (!noslash)
{
if (grub_extend_alloc (pmapptr + 1, &pmapalloc, (void **) &pmap))
return 1;
pmap[pmapptr++] = '/';
}
noslash = 0;
file_disk = file->device->disk && disk->id == file->device->disk->id /* Helper for grub_cmd_plan9. */
&& disk->dev->id == file->device->disk->dev->id; static int
fill_partition (grub_disk_t disk, const grub_partition_t partition, void *data)
{
struct grub_cmd_plan9_ctx *fill_ctx = data;
int file_disk = 0;
int pstart, pend;
pstart = pmapptr; if (!fill_ctx->noslash)
if (grub_strcmp (partition->partmap->name, "plan") == 0) {
{ if (grub_extend_alloc (fill_ctx->pmapptr + 1, &fill_ctx->pmapalloc,
unsigned ptr = partition->index + sizeof ("part ") - 1; (void **) &fill_ctx->pmap))
grub_err_t err; return 1;
disk->partition = partition->parent; fill_ctx->pmap[fill_ctx->pmapptr++] = '/';
do }
{ fill_ctx->noslash = 0;
if (grub_extend_alloc (pmapptr + 1, &pmapalloc, (void **) &pmap))
return 1;
err = grub_disk_read (disk, 1, ptr, 1, pmap + pmapptr);
if (err)
{
disk->partition = 0;
return err;
}
ptr++;
pmapptr++;
}
while (grub_isalpha (pmap[pmapptr - 1])
|| grub_isdigit (pmap[pmapptr - 1]));
pmapptr--;
}
else
{
char name[50];
int c = 0;
if (grub_strcmp (partition->partmap->name, "msdos") == 0)
{
switch (partition->msdostype)
{
case GRUB_PC_PARTITION_TYPE_PLAN9:
c = 1;
break;
case GRUB_PC_PARTITION_TYPE_NTFS:
c = 2;
break;
case GRUB_PC_PARTITION_TYPE_MINIX:
case GRUB_PC_PARTITION_TYPE_LINUX_MINIX:
case GRUB_PC_PARTITION_TYPE_EXT2FS:
c = 3;
break;
case GRUB_PC_PARTITION_TYPE_LINUX_SWAP:
c = 4;
break;
}
}
if (prefixescnt[c] == 0) file_disk = fill_ctx->file->device->disk
grub_strcpy (name, prefixes[c]); && disk->id == fill_ctx->file->device->disk->id
else && disk->dev->id == fill_ctx->file->device->disk->dev->id;
grub_snprintf (name, sizeof (name), "%s.%d", prefixes[c],
prefixescnt[c]);
prefixescnt[c]++;
if (grub_extend_alloc (pmapptr + grub_strlen (name) + 1,
&pmapalloc, (void **) &pmap))
return 1;
grub_strcpy (pmap + pmapptr, name);
pmapptr += grub_strlen (name);
}
pend = pmapptr;
if (grub_extend_alloc (pmapptr + 2 + 25 + 5 + 25, &pmapalloc,
(void **) &pmap))
return 1;
pmap[pmapptr++] = ' ';
grub_snprintf (pmap + pmapptr, 25 + 5 + 25,
"%" PRIuGRUB_UINT64_T " %" PRIuGRUB_UINT64_T,
grub_partition_get_start (partition),
grub_partition_get_start (partition)
+ grub_partition_get_len (partition));
if (file_disk && grub_partition_get_start (partition)
== grub_partition_get_start (file->device->disk->partition)
&& grub_partition_get_len (partition)
== grub_partition_get_len (file->device->disk->partition))
{
grub_free (bootpart);
bootpart = grub_strndup (pmap + pstart, pend - pstart);
}
pmapptr += grub_strlen (pmap + pmapptr); pstart = fill_ctx->pmapptr;
return 0; if (grub_strcmp (partition->partmap->name, "plan") == 0)
} {
unsigned ptr = partition->index + sizeof ("part ") - 1;
auto int fill_disk (const char *name); grub_err_t err;
int fill_disk (const char *name) disk->partition = partition->parent;
{ do
grub_device_t dev;
char *plan9name = NULL;
unsigned i;
int file_disk = 0;
dev = grub_device_open (name);
if (!dev)
{
grub_print_error ();
return 0;
}
if (!dev->disk)
{
grub_device_close (dev);
return 0;
}
file_disk = file->device->disk && dev->disk->id == file->device->disk->id
&& dev->disk->dev->id == file->device->disk->dev->id;
for (i = 0; ctxt->state[0].args && ctxt->state[0].args[i]; i++)
if (grub_strncmp (name, ctxt->state[0].args[i], grub_strlen (name)) == 0
&& ctxt->state[0].args[i][grub_strlen (name)] == '=')
break;
if (ctxt->state[0].args && ctxt->state[0].args[i])
plan9name = grub_strdup (ctxt->state[0].args[i] + grub_strlen (name) + 1);
else
switch (dev->disk->dev->id)
{ {
case GRUB_DISK_DEVICE_BIOSDISK_ID: if (grub_extend_alloc (fill_ctx->pmapptr + 1, &fill_ctx->pmapalloc,
if (dev->disk->id & 0x80) (void **) &fill_ctx->pmap))
plan9name = grub_xasprintf ("sdB%u", return 1;
(unsigned) (dev->disk->id & 0x7f)); err = grub_disk_read (disk, 1, ptr, 1,
else fill_ctx->pmap + fill_ctx->pmapptr);
plan9name = grub_xasprintf ("fd%u", if (err)
(unsigned) (dev->disk->id & 0x7f));
break;
/* Shouldn't happen as Plan9 doesn't work on these platforms. */
case GRUB_DISK_DEVICE_OFDISK_ID:
case GRUB_DISK_DEVICE_EFIDISK_ID:
/* Plan9 doesn't see those. */
default:
/* Not sure how to handle those. */
case GRUB_DISK_DEVICE_NAND_ID:
if (!file_disk)
{ {
grub_device_close (dev); disk->partition = 0;
return 0; return err;
} }
ptr++;
/* if it's the disk the kernel is loaded from we need to name fill_ctx->pmapptr++;
it nevertheless. */ }
plan9name = grub_strdup ("sdZ0"); while (grub_isalpha (fill_ctx->pmap[fill_ctx->pmapptr - 1])
break; || grub_isdigit (fill_ctx->pmap[fill_ctx->pmapptr - 1]));
fill_ctx->pmapptr--;
}
else
{
char name[50];
int c = 0;
if (grub_strcmp (partition->partmap->name, "msdos") == 0)
{
switch (partition->msdostype)
{
case GRUB_PC_PARTITION_TYPE_PLAN9:
c = 1;
break;
case GRUB_PC_PARTITION_TYPE_NTFS:
c = 2;
break;
case GRUB_PC_PARTITION_TYPE_MINIX:
case GRUB_PC_PARTITION_TYPE_LINUX_MINIX:
case GRUB_PC_PARTITION_TYPE_EXT2FS:
c = 3;
break;
case GRUB_PC_PARTITION_TYPE_LINUX_SWAP:
c = 4;
break;
}
}
case GRUB_DISK_DEVICE_ATA_ID: if (fill_ctx->prefixescnt[c] == 0)
grub_strcpy (name, prefixes[c]);
else
grub_snprintf (name, sizeof (name), "%s.%d", prefixes[c],
fill_ctx->prefixescnt[c]);
fill_ctx->prefixescnt[c]++;
if (grub_extend_alloc (fill_ctx->pmapptr + grub_strlen (name) + 1,
&fill_ctx->pmapalloc, (void **) &fill_ctx->pmap))
return 1;
grub_strcpy (fill_ctx->pmap + fill_ctx->pmapptr, name);
fill_ctx->pmapptr += grub_strlen (name);
}
pend = fill_ctx->pmapptr;
if (grub_extend_alloc (fill_ctx->pmapptr + 2 + 25 + 5 + 25,
&fill_ctx->pmapalloc, (void **) &fill_ctx->pmap))
return 1;
fill_ctx->pmap[fill_ctx->pmapptr++] = ' ';
grub_snprintf (fill_ctx->pmap + fill_ctx->pmapptr, 25 + 5 + 25,
"%" PRIuGRUB_UINT64_T " %" PRIuGRUB_UINT64_T,
grub_partition_get_start (partition),
grub_partition_get_start (partition)
+ grub_partition_get_len (partition));
if (file_disk && grub_partition_get_start (partition)
== grub_partition_get_start (fill_ctx->file->device->disk->partition)
&& grub_partition_get_len (partition)
== grub_partition_get_len (fill_ctx->file->device->disk->partition))
{
grub_free (fill_ctx->bootpart);
fill_ctx->bootpart = grub_strndup (fill_ctx->pmap + pstart,
pend - pstart);
}
fill_ctx->pmapptr += grub_strlen (fill_ctx->pmap + fill_ctx->pmapptr);
return 0;
}
/* Helper for grub_cmd_plan9. */
static int
fill_disk (const char *name, void *data)
{
struct grub_cmd_plan9_ctx *fill_ctx = data;
grub_device_t dev;
char *plan9name = NULL;
unsigned i;
int file_disk = 0;
dev = grub_device_open (name);
if (!dev)
{
grub_print_error ();
return 0;
}
if (!dev->disk)
{
grub_device_close (dev);
return 0;
}
file_disk = fill_ctx->file->device->disk
&& dev->disk->id == fill_ctx->file->device->disk->id
&& dev->disk->dev->id == fill_ctx->file->device->disk->dev->id;
for (i = 0;
fill_ctx->ctxt->state[0].args && fill_ctx->ctxt->state[0].args[i]; i++)
if (grub_strncmp (name, fill_ctx->ctxt->state[0].args[i],
grub_strlen (name)) == 0
&& fill_ctx->ctxt->state[0].args[i][grub_strlen (name)] == '=')
break;
if (fill_ctx->ctxt->state[0].args && fill_ctx->ctxt->state[0].args[i])
plan9name = grub_strdup (fill_ctx->ctxt->state[0].args[i]
+ grub_strlen (name) + 1);
else
switch (dev->disk->dev->id)
{
case GRUB_DISK_DEVICE_BIOSDISK_ID:
if (dev->disk->id & 0x80)
plan9name = grub_xasprintf ("sdB%u",
(unsigned) (dev->disk->id & 0x7f));
else
plan9name = grub_xasprintf ("fd%u",
(unsigned) (dev->disk->id & 0x7f));
break;
/* Shouldn't happen as Plan9 doesn't work on these platforms. */
case GRUB_DISK_DEVICE_OFDISK_ID:
case GRUB_DISK_DEVICE_EFIDISK_ID:
/* Plan9 doesn't see those. */
default:
/* Not sure how to handle those. */
case GRUB_DISK_DEVICE_NAND_ID:
if (!file_disk)
{
grub_device_close (dev);
return 0;
}
/* if it's the disk the kernel is loaded from we need to name
it nevertheless. */
plan9name = grub_strdup ("sdZ0");
break;
case GRUB_DISK_DEVICE_ATA_ID:
{
int unit;
if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1)
unit = 0;
else
unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1, 0, 0);
plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2);
}
break;
case GRUB_DISK_DEVICE_SCSI_ID:
if (((dev->disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xff)
== GRUB_SCSI_SUBSYSTEM_PATA)
{ {
int unit; int unit;
if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1) if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1)
unit = 0; unit = 0;
else else
unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1, 0, 0); unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1,
0, 0);
plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2); plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2);
break;
} }
break;
case GRUB_DISK_DEVICE_SCSI_ID: /* FIXME: how does Plan9 number controllers?
if (((dev->disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xff) We probably need save the SCSI devices and sort them */
== GRUB_SCSI_SUBSYSTEM_PATA) plan9name
{ = grub_xasprintf ("sd0%u", (unsigned)
int unit; ((dev->disk->id >> GRUB_SCSI_ID_BUS_SHIFT)
if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1) & 0xf));
unit = 0; break;
else
unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1,
0, 0);
plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2);
break;
}
/* FIXME: how does Plan9 number controllers?
We probably need save the SCSI devices and sort them */
plan9name
= grub_xasprintf ("sd0%u", (unsigned)
((dev->disk->id >> GRUB_SCSI_ID_BUS_SHIFT)
& 0xf));
break;
}
if (!plan9name)
{
grub_print_error ();
return 0;
} }
if (grub_extend_alloc (pmapptr + grub_strlen (plan9name) if (!plan9name)
+ sizeof ("part="), &pmapalloc, {
(void **) &pmap)) grub_print_error ();
{ return 0;
grub_free (plan9name); }
return 1; if (grub_extend_alloc (fill_ctx->pmapptr + grub_strlen (plan9name)
} + sizeof ("part="), &fill_ctx->pmapalloc,
grub_strcpy (pmap + pmapptr, plan9name); (void **) &fill_ctx->pmap))
pmapptr += grub_strlen (plan9name); {
if (!file_disk)
grub_free (plan9name); grub_free (plan9name);
else
{
grub_free (bootdisk);
bootdisk = plan9name;
}
grub_strcpy (pmap + pmapptr, "part=");
pmapptr += sizeof ("part=") - 1;
noslash = 1;
grub_memset (prefixescnt, 0, sizeof (prefixescnt));
if (grub_partition_iterate (dev->disk, fill_partition))
return 1; return 1;
if (grub_extend_alloc (pmapptr + 1, &pmapalloc, (void **) &pmap)) }
return 1; grub_strcpy (fill_ctx->pmap + fill_ctx->pmapptr, plan9name);
pmap[pmapptr++] = '\n'; fill_ctx->pmapptr += grub_strlen (plan9name);
if (!file_disk)
grub_free (plan9name);
else
{
grub_free (fill_ctx->bootdisk);
fill_ctx->bootdisk = plan9name;
}
grub_strcpy (fill_ctx->pmap + fill_ctx->pmapptr, "part=");
fill_ctx->pmapptr += sizeof ("part=") - 1;
return 0; fill_ctx->noslash = 1;
} grub_memset (fill_ctx->prefixescnt, 0, sizeof (fill_ctx->prefixescnt));
if (grub_partition_iterate (dev->disk, fill_partition, fill_ctx))
return 1;
if (grub_extend_alloc (fill_ctx->pmapptr + 1, &fill_ctx->pmapalloc,
(void **) &fill_ctx->pmap))
return 1;
fill_ctx->pmap[fill_ctx->pmapptr++] = '\n';
return 0;
}
static grub_err_t
grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
{
struct grub_cmd_plan9_ctx fill_ctx = {
.ctxt = ctxt,
.file = 0,
.pmap = NULL,
.pmapalloc = 256,
.pmapptr = 0,
.noslash = 1,
.bootdisk = NULL,
.bootpart = NULL
};
void *mem;
grub_size_t memsize, padsize;
struct grub_plan9_header hdr;
char *config, *configptr;
grub_size_t configsize;
char *bootpath = NULL;
if (argc == 0) if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@ -354,21 +387,21 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
if (!rel) if (!rel)
goto fail; goto fail;
file = grub_file_open (argv[0]); fill_ctx.file = grub_file_open (argv[0]);
if (! file) if (! fill_ctx.file)
goto fail; goto fail;
pmap = grub_malloc (pmapalloc); fill_ctx.pmap = grub_malloc (fill_ctx.pmapalloc);
if (!pmap) if (!fill_ctx.pmap)
goto fail; goto fail;
if (grub_disk_dev_iterate (fill_disk)) if (grub_disk_dev_iterate (fill_disk, &fill_ctx))
goto fail; goto fail;
if (grub_extend_alloc (pmapptr + 1, &pmapalloc, if (grub_extend_alloc (fill_ctx.pmapptr + 1, &fill_ctx.pmapalloc,
(void **) &pmap)) (void **) &fill_ctx.pmap))
goto fail; goto fail;
pmap[pmapptr] = 0; fill_ctx.pmap[fill_ctx.pmapptr] = 0;
{ {
char *file_name = grub_strchr (argv[0], ')'); char *file_name = grub_strchr (argv[0], ')');
@ -379,17 +412,19 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
if (*file_name) if (*file_name)
file_name++; file_name++;
if (bootpart) if (fill_ctx.bootpart)
bootpath = grub_xasprintf ("%s!%s!%s", bootdisk, bootpart, file_name); bootpath = grub_xasprintf ("%s!%s!%s", fill_ctx.bootdisk,
fill_ctx.bootpart, file_name);
else else
bootpath = grub_xasprintf ("%s!%s", bootdisk, file_name); bootpath = grub_xasprintf ("%s!%s", fill_ctx.bootdisk, file_name);
grub_free (bootdisk); grub_free (fill_ctx.bootdisk);
grub_free (bootpart); grub_free (fill_ctx.bootpart);
} }
if (!bootpath) if (!bootpath)
goto fail; goto fail;
if (grub_file_read (file, &hdr, sizeof (hdr)) != (grub_ssize_t) sizeof (hdr)) if (grub_file_read (fill_ctx.file, &hdr,
sizeof (hdr)) != (grub_ssize_t) sizeof (hdr))
{ {
if (!grub_errno) if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@ -420,7 +455,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
configsize += grub_strlen (argv[i]) + 1; configsize += grub_strlen (argv[i]) + 1;
} }
configsize += (sizeof ("bootfile=") - 1) + grub_strlen (bootpath) + 1; configsize += (sizeof ("bootfile=") - 1) + grub_strlen (bootpath) + 1;
configsize += pmapptr; configsize += fill_ctx.pmapptr;
/* Terminating \0. */ /* Terminating \0. */
configsize++; configsize++;
@ -452,7 +487,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
*configptr++ = '\n'; *configptr++ = '\n';
} }
} }
configptr = grub_stpcpy (configptr, pmap); configptr = grub_stpcpy (configptr, fill_ctx.pmap);
{ {
grub_relocator_chunk_t ch; grub_relocator_chunk_t ch;
@ -471,7 +506,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
grub_memcpy (ptr, &hdr, sizeof (hdr)); grub_memcpy (ptr, &hdr, sizeof (hdr));
ptr += sizeof (hdr); ptr += sizeof (hdr);
if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.text_size)) if (grub_file_read (fill_ctx.file, ptr, grub_be_to_cpu32 (hdr.text_size))
!= (grub_ssize_t) grub_be_to_cpu32 (hdr.text_size)) != (grub_ssize_t) grub_be_to_cpu32 (hdr.text_size))
{ {
if (!grub_errno) if (!grub_errno)
@ -487,7 +522,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
grub_memset (ptr, 0, padsize); grub_memset (ptr, 0, padsize);
ptr += padsize; ptr += padsize;
if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.data_size)) if (grub_file_read (fill_ctx.file, ptr, grub_be_to_cpu32 (hdr.data_size))
!= (grub_ssize_t) grub_be_to_cpu32 (hdr.data_size)) != (grub_ssize_t) grub_be_to_cpu32 (hdr.data_size))
{ {
if (!grub_errno) if (!grub_errno)
@ -508,10 +543,10 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
fail: fail:
grub_free (pmap); grub_free (fill_ctx.pmap);
if (file) if (fill_ctx.file)
grub_file_close (file); grub_file_close (fill_ctx.file);
grub_plan9_unload (); grub_plan9_unload ();

View File

@ -99,7 +99,8 @@ add_completion (const char *completion, const char *extra,
} }
static int static int
iterate_partition (grub_disk_t disk, const grub_partition_t p) iterate_partition (grub_disk_t disk, const grub_partition_t p,
void *data __attribute__ ((unused)))
{ {
const char *disk_name = disk->name; const char *disk_name = disk->name;
char *name; char *name;
@ -154,7 +155,7 @@ iterate_dir (const char *filename, const struct grub_dirhook_info *info)
} }
static int static int
iterate_dev (const char *devname) iterate_dev (const char *devname, void *data __attribute__ ((unused)))
{ {
grub_device_t dev; grub_device_t dev;
@ -180,7 +181,7 @@ iterate_dev (const char *devname)
} }
if (dev->disk) if (dev->disk)
if (grub_partition_iterate (dev->disk, iterate_partition)) if (grub_partition_iterate (dev->disk, iterate_partition, NULL))
{ {
grub_device_close (dev); grub_device_close (dev);
return 1; return 1;
@ -213,7 +214,7 @@ complete_device (void)
if (! p) if (! p)
{ {
/* Complete the disk part. */ /* Complete the disk part. */
if (grub_disk_dev_iterate (iterate_dev)) if (grub_disk_dev_iterate (iterate_dev, NULL))
return 1; return 1;
} }
else else
@ -228,7 +229,7 @@ complete_device (void)
{ {
if (dev->disk) if (dev->disk)
{ {
if (grub_partition_iterate (dev->disk, iterate_partition)) if (grub_partition_iterate (dev->disk, iterate_partition, NULL))
{ {
grub_device_close (dev); grub_device_close (dev);
return 1; return 1;

View File

@ -101,8 +101,8 @@ fail:
static grub_err_t static grub_err_t
acorn_partition_map_iterate (grub_disk_t disk, acorn_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)) void *hook_data)
{ {
struct grub_partition part; struct grub_partition part;
struct linux_part map[LINUX_MAP_ENTRIES]; struct linux_part map[LINUX_MAP_ENTRIES];
@ -127,7 +127,7 @@ acorn_partition_map_iterate (grub_disk_t disk,
part.offset = 6; part.offset = 6;
part.number = part.index = i; part.number = part.index = i;
if (hook (disk, &part)) if (hook (disk, &part, hook_data))
return grub_errno; return grub_errno;
} }

View File

@ -87,8 +87,8 @@ amiga_partition_map_checksum (void *buf, grub_size_t sz)
static grub_err_t static grub_err_t
amiga_partition_map_iterate (grub_disk_t disk, amiga_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)) void *hook_data)
{ {
struct grub_partition part; struct grub_partition part;
struct grub_amiga_rdsk rdsk; struct grub_amiga_rdsk rdsk;
@ -145,7 +145,7 @@ amiga_partition_map_iterate (grub_disk_t disk,
part.index = 0; part.index = 0;
part.partmap = &grub_amiga_partition_map; part.partmap = &grub_amiga_partition_map;
if (hook (disk, &part)) if (hook (disk, &part, hook_data))
return grub_errno; return grub_errno;
next = grub_be_to_cpu32 (apart.next); next = grub_be_to_cpu32 (apart.next);

View File

@ -101,8 +101,8 @@ static struct grub_partition_map grub_apple_partition_map;
static grub_err_t static grub_err_t
apple_partition_map_iterate (grub_disk_t disk, apple_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)) void *hook_data)
{ {
struct grub_partition part; struct grub_partition part;
struct grub_apple_header aheader; struct grub_apple_header aheader;
@ -163,7 +163,7 @@ apple_partition_map_iterate (grub_disk_t disk,
grub_be_to_cpu32 (apart.first_phys_block), grub_be_to_cpu32 (apart.first_phys_block),
grub_be_to_cpu32 (apart.blockcnt)); grub_be_to_cpu32 (apart.blockcnt));
if (hook (disk, &part)) if (hook (disk, &part, hook_data))
return grub_errno; return grub_errno;
pos += grub_be_to_cpu16 (aheader.blocksize); pos += grub_be_to_cpu16 (aheader.blocksize);

View File

@ -41,8 +41,7 @@ static struct grub_partition_map grub_openbsdlabel_partition_map;
static grub_err_t static grub_err_t
iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd, iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd,
struct grub_partition_map *pmap, struct grub_partition_map *pmap,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook, void *hook_data)
const grub_partition_t partition))
{ {
struct grub_partition_bsd_disk_label label; struct grub_partition_bsd_disk_label label;
struct grub_partition p; struct grub_partition p;
@ -116,7 +115,7 @@ iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd,
p.start -= delta; p.start -= delta;
if (hook (disk, &p)) if (hook (disk, &p, hook_data))
return grub_errno; return grub_errno;
} }
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
@ -124,14 +123,14 @@ iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd,
static grub_err_t static grub_err_t
bsdlabel_partition_map_iterate (grub_disk_t disk, bsdlabel_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)) void *hook_data)
{ {
if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos") if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos")
== 0 && disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_FREEBSD) == 0 && disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_FREEBSD)
return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 1, return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 1,
&grub_bsdlabel_partition_map, hook); &grub_bsdlabel_partition_map, hook, hook_data);
if (disk->partition if (disk->partition
&& (grub_strcmp (disk->partition->partmap->name, "msdos") == 0 && (grub_strcmp (disk->partition->partmap->name, "msdos") == 0
@ -141,7 +140,44 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported"); return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0,
&grub_bsdlabel_partition_map, hook); &grub_bsdlabel_partition_map, hook, hook_data);
}
/* Context for netopenbsdlabel_partition_map_iterate. */
struct netopenbsdlabel_ctx
{
grub_uint8_t type;
struct grub_partition_map *pmap;
grub_partition_iterate_hook_t hook;
void *hook_data;
int count;
};
/* Helper for netopenbsdlabel_partition_map_iterate. */
static int
check_msdos (grub_disk_t dsk, const grub_partition_t partition, void *data)
{
struct netopenbsdlabel_ctx *ctx = data;
grub_err_t err;
if (partition->msdostype != ctx->type)
return 0;
err = iterate_real (dsk, partition->start
+ GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, ctx->pmap,
ctx->hook, ctx->hook_data);
if (err == GRUB_ERR_NONE)
{
ctx->count++;
return 1;
}
if (err == GRUB_ERR_BAD_PART_TABLE)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
grub_print_error ();
return 0;
} }
/* This is a total breakage. Even when net-/openbsd label is inside partition /* This is a total breakage. Even when net-/openbsd label is inside partition
@ -150,45 +186,26 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
static grub_err_t static grub_err_t
netopenbsdlabel_partition_map_iterate (grub_disk_t disk, grub_uint8_t type, netopenbsdlabel_partition_map_iterate (grub_disk_t disk, grub_uint8_t type,
struct grub_partition_map *pmap, struct grub_partition_map *pmap,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)) void *hook_data)
{ {
int count = 0; int count = 0;
auto int check_msdos (grub_disk_t dsk,
const grub_partition_t partition);
int check_msdos (grub_disk_t dsk,
const grub_partition_t partition)
{
grub_err_t err;
if (partition->msdostype != type)
return 0;
err = iterate_real (dsk, partition->start
+ GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, pmap, hook);
if (err == GRUB_ERR_NONE)
{
count++;
return 1;
}
if (err == GRUB_ERR_BAD_PART_TABLE)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
grub_print_error ();
return 0;
}
if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos") if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos")
== 0) == 0)
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported"); return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
{ {
struct netopenbsdlabel_ctx ctx = {
.type = type,
.pmap = pmap,
.hook = hook,
.hook_data = hook_data,
.count = count
};
grub_err_t err; grub_err_t err;
err = grub_partition_msdos_iterate (disk, check_msdos);
err = grub_partition_msdos_iterate (disk, check_msdos, &ctx);
if (err) if (err)
return err; return err;
@ -200,24 +217,24 @@ netopenbsdlabel_partition_map_iterate (grub_disk_t disk, grub_uint8_t type,
static grub_err_t static grub_err_t
netbsdlabel_partition_map_iterate (grub_disk_t disk, netbsdlabel_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)) void *hook_data)
{ {
return netopenbsdlabel_partition_map_iterate (disk, return netopenbsdlabel_partition_map_iterate (disk,
GRUB_PC_PARTITION_TYPE_NETBSD, GRUB_PC_PARTITION_TYPE_NETBSD,
&grub_netbsdlabel_partition_map, &grub_netbsdlabel_partition_map,
hook); hook, hook_data);
} }
static grub_err_t static grub_err_t
openbsdlabel_partition_map_iterate (grub_disk_t disk, openbsdlabel_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)) void *hook_data)
{ {
return netopenbsdlabel_partition_map_iterate (disk, return netopenbsdlabel_partition_map_iterate (disk,
GRUB_PC_PARTITION_TYPE_OPENBSD, GRUB_PC_PARTITION_TYPE_OPENBSD,
&grub_openbsdlabel_partition_map, &grub_openbsdlabel_partition_map,
hook); hook, hook_data);
} }

View File

@ -64,8 +64,7 @@ grub_dvh_is_valid (grub_uint32_t *label)
static grub_err_t static grub_err_t
dvh_partition_map_iterate (grub_disk_t disk, dvh_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook, void *hook_data)
const grub_partition_t partition))
{ {
struct grub_partition p; struct grub_partition p;
union union
@ -101,7 +100,7 @@ dvh_partition_map_iterate (grub_disk_t disk,
p.start = grub_be_to_cpu32 (block.dvh.parts[partnum].start); p.start = grub_be_to_cpu32 (block.dvh.parts[partnum].start);
p.len = grub_be_to_cpu32 (block.dvh.parts[partnum].length); p.len = grub_be_to_cpu32 (block.dvh.parts[partnum].length);
p.number = p.index = partnum; p.number = p.index = partnum;
if (hook (disk, &p)) if (hook (disk, &p, hook_data))
break; break;
} }

View File

@ -48,8 +48,8 @@ static struct grub_partition_map grub_gpt_partition_map;
grub_err_t grub_err_t
grub_gpt_partition_map_iterate (grub_disk_t disk, grub_gpt_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)) void *hook_data)
{ {
struct grub_partition part; struct grub_partition part;
struct grub_gpt_header gpt; struct grub_gpt_header gpt;
@ -113,7 +113,7 @@ grub_gpt_partition_map_iterate (grub_disk_t disk,
(unsigned long long) part.start, (unsigned long long) part.start,
(unsigned long long) part.len); (unsigned long long) part.len);
if (hook (disk, &part)) if (hook (disk, &part, hook_data))
return grub_errno; return grub_errno;
} }
@ -129,71 +129,81 @@ grub_gpt_partition_map_iterate (grub_disk_t disk,
} }
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
/* Context for gpt_partition_map_embed. */
struct gpt_partition_map_embed_ctx
{
grub_disk_addr_t start, len;
};
/* Helper for gpt_partition_map_embed. */
static int
find_usable_region (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p, void *data)
{
struct gpt_partition_map_embed_ctx *ctx = data;
struct grub_gpt_partentry gptdata;
grub_partition_t p2;
p2 = disk->partition;
disk->partition = p->parent;
if (grub_disk_read (disk, p->offset, p->index,
sizeof (gptdata), &gptdata))
{
disk->partition = p2;
return 0;
}
disk->partition = p2;
/* If there's an embed region, it is in a dedicated partition. */
if (! grub_memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16))
{
ctx->start = p->start;
ctx->len = p->len;
return 1;
}
return 0;
}
static grub_err_t static grub_err_t
gpt_partition_map_embed (struct grub_disk *disk_, unsigned int *nsectors, gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
unsigned int max_nsectors, unsigned int max_nsectors,
grub_embed_type_t embed_type, grub_embed_type_t embed_type,
grub_disk_addr_t **sectors) grub_disk_addr_t **sectors)
{ {
grub_disk_addr_t start = 0, len = 0; struct gpt_partition_map_embed_ctx ctx = {
.start = 0,
.len = 0
};
unsigned i; unsigned i;
grub_err_t err; grub_err_t err;
auto int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk,
const grub_partition_t p);
int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p)
{
struct grub_gpt_partentry gptdata;
grub_partition_t p2;
p2 = disk->partition;
disk->partition = p->parent;
if (grub_disk_read (disk, p->offset, p->index,
sizeof (gptdata), &gptdata))
{
disk->partition = p2;
return 0;
}
disk->partition = p2;
/* If there's an embed region, it is in a dedicated partition. */
if (! grub_memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16))
{
start = p->start;
len = p->len;
return 1;
}
return 0;
}
if (embed_type != GRUB_EMBED_PCBIOS) if (embed_type != GRUB_EMBED_PCBIOS)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"GPT currently supports only PC-BIOS embedding"); "GPT currently supports only PC-BIOS embedding");
err = grub_gpt_partition_map_iterate (disk_, find_usable_region); err = grub_gpt_partition_map_iterate (disk, find_usable_region, &ctx);
if (err) if (err)
return err; return err;
if (len == 0) if (ctx.len == 0)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, return grub_error (GRUB_ERR_FILE_NOT_FOUND,
N_("this GPT partition label contains no BIOS Boot Partition;" N_("this GPT partition label contains no BIOS Boot Partition;"
" embedding won't be possible")); " embedding won't be possible"));
if (len < *nsectors) if (ctx.len < *nsectors)
return grub_error (GRUB_ERR_OUT_OF_RANGE, return grub_error (GRUB_ERR_OUT_OF_RANGE,
N_("your BIOS Boot Partition is too small;" N_("your BIOS Boot Partition is too small;"
" embedding won't be possible")); " embedding won't be possible"));
*nsectors = len; *nsectors = ctx.len;
if (*nsectors > max_nsectors) if (*nsectors > max_nsectors)
*nsectors = max_nsectors; *nsectors = max_nsectors;
*sectors = grub_malloc (*nsectors * sizeof (**sectors)); *sectors = grub_malloc (*nsectors * sizeof (**sectors));
if (!*sectors) if (!*sectors)
return grub_errno; return grub_errno;
for (i = 0; i < *nsectors; i++) for (i = 0; i < *nsectors; i++)
(*sectors)[i] = start + i; (*sectors)[i] = ctx.start + i;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }

View File

@ -100,8 +100,8 @@ struct embed_signature embed_signatures[] =
grub_err_t grub_err_t
grub_partition_msdos_iterate (grub_disk_t disk, grub_partition_msdos_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)) void *hook_data)
{ {
struct grub_partition p; struct grub_partition p;
struct grub_msdos_partition_mbr mbr; struct grub_msdos_partition_mbr mbr;
@ -186,7 +186,7 @@ grub_partition_msdos_iterate (grub_disk_t disk,
{ {
p.number++; p.number++;
if (hook (disk, &p)) if (hook (disk, &p, hook_data))
return grub_errno; return grub_errno;
} }
else if (p.number < 4) else if (p.number < 4)

View File

@ -31,8 +31,8 @@ static struct grub_partition_map grub_plan_partition_map;
static grub_err_t static grub_err_t
plan_partition_map_iterate (grub_disk_t disk, plan_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)) void *hook_data)
{ {
struct grub_partition p; struct grub_partition p;
int ptr = 0; int ptr = 0;
@ -92,7 +92,7 @@ plan_partition_map_iterate (grub_disk_t disk,
if (c != '\n') if (c != '\n')
break; break;
p.len -= p.start; p.len -= p.start;
if (hook (disk, &p)) if (hook (disk, &p, hook_data))
return grub_errno; return grub_errno;
} }
if (p.number == 0) if (p.number == 0)

View File

@ -86,8 +86,7 @@ grub_sun_is_valid (grub_uint16_t *label)
static grub_err_t static grub_err_t
sun_partition_map_iterate (grub_disk_t disk, sun_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook, void *hook_data)
const grub_partition_t partition))
{ {
struct grub_partition p; struct grub_partition p;
union union
@ -128,7 +127,7 @@ sun_partition_map_iterate (grub_disk_t disk,
p.number = p.index = partnum; p.number = p.index = partnum;
if (p.len) if (p.len)
{ {
if (hook (disk, &p)) if (hook (disk, &p, hook_data))
partnum = GRUB_PARTMAP_SUN_MAX_PARTS; partnum = GRUB_PARTMAP_SUN_MAX_PARTS;
} }
} }

View File

@ -68,8 +68,8 @@ grub_sun_is_valid (grub_uint16_t *label)
static grub_err_t static grub_err_t
sun_pc_partition_map_iterate (grub_disk_t disk, sun_pc_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)) void *hook_data)
{ {
grub_partition_t p; grub_partition_t p;
union union
@ -122,7 +122,7 @@ sun_pc_partition_map_iterate (grub_disk_t disk,
p->number = partnum; p->number = partnum;
if (p->len) if (p->len)
{ {
if (hook (disk, p)) if (hook (disk, p, hook_data))
partnum = GRUB_PARTMAP_SUN_PC_MAX_PARTS; partnum = GRUB_PARTMAP_SUN_PC_MAX_PARTS;
} }
} }

View File

@ -255,7 +255,12 @@ struct grub_arc_system_parameter_block
#define GRUB_ARC_STDIN 0 #define GRUB_ARC_STDIN 0
#define GRUB_ARC_STDOUT 1 #define GRUB_ARC_STDOUT 1
int EXPORT_FUNC (grub_arc_iterate_devs) (int (*hook) (const char *name, const struct grub_arc_component *comp), int alt_names); typedef int (*grub_arc_iterate_devs_hook_t)
(const char *name, const struct grub_arc_component *comp, void *data);
int EXPORT_FUNC (grub_arc_iterate_devs) (grub_arc_iterate_devs_hook_t hook,
void *hook_data,
int alt_names);
#define FOR_ARC_CHILDREN(comp, parent) for (comp = GRUB_ARC_FIRMWARE_VECTOR->getchild (parent); comp; comp = GRUB_ARC_FIRMWARE_VECTOR->getpeer (comp)) #define FOR_ARC_CHILDREN(comp, parent) for (comp = GRUB_ARC_FIRMWARE_VECTOR->getchild (parent); comp; comp = GRUB_ARC_FIRMWARE_VECTOR->getpeer (comp))

View File

@ -193,10 +193,12 @@ struct grub_ata
typedef struct grub_ata *grub_ata_t; typedef struct grub_ata *grub_ata_t;
typedef int (*grub_ata_dev_iterate_hook_t) (int id, int bus, void *data);
struct grub_ata_dev struct grub_ata_dev
{ {
/* Call HOOK with each device name, until HOOK returns non-zero. */ /* Call HOOK with each device name, until HOOK returns non-zero. */
int (*iterate) (int (*hook) (int id, int bus), int (*iterate) (grub_ata_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull); grub_disk_pull_t pull);
/* Open the device named NAME, and set up SCSI. */ /* Open the device named NAME, and set up SCSI. */

View File

@ -33,8 +33,11 @@ struct grub_device
}; };
typedef struct grub_device *grub_device_t; typedef struct grub_device *grub_device_t;
typedef int (*grub_device_iterate_hook_t) (const char *name, void *data);
grub_device_t EXPORT_FUNC(grub_device_open) (const char *name); grub_device_t EXPORT_FUNC(grub_device_open) (const char *name);
grub_err_t EXPORT_FUNC(grub_device_close) (grub_device_t device); grub_err_t EXPORT_FUNC(grub_device_close) (grub_device_t device);
int EXPORT_FUNC(grub_device_iterate) (int (*hook) (const char *name)); int EXPORT_FUNC(grub_device_iterate) (grub_device_iterate_hook_t hook,
void *hook_data);
#endif /* ! GRUB_DEVICE_HEADER */ #endif /* ! GRUB_DEVICE_HEADER */

View File

@ -56,6 +56,8 @@ typedef enum
GRUB_DISK_PULL_MAX GRUB_DISK_PULL_MAX
} grub_disk_pull_t; } grub_disk_pull_t;
typedef int (*grub_disk_dev_iterate_hook_t) (const char *name, void *data);
/* Disk device. */ /* Disk device. */
struct grub_disk_dev struct grub_disk_dev
{ {
@ -66,7 +68,7 @@ struct grub_disk_dev
enum grub_disk_dev_id id; enum grub_disk_dev_id id;
/* Call HOOK with each device name, until HOOK returns non-zero. */ /* Call HOOK with each device name, until HOOK returns non-zero. */
int (*iterate) (int (*hook) (const char *name), int (*iterate) (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull); grub_disk_pull_t pull);
/* Open the device named NAME, and set up DISK. */ /* Open the device named NAME, and set up DISK. */
@ -158,14 +160,14 @@ void grub_disk_cache_invalidate_all (void);
void EXPORT_FUNC(grub_disk_dev_register) (grub_disk_dev_t dev); void EXPORT_FUNC(grub_disk_dev_register) (grub_disk_dev_t dev);
void EXPORT_FUNC(grub_disk_dev_unregister) (grub_disk_dev_t dev); void EXPORT_FUNC(grub_disk_dev_unregister) (grub_disk_dev_t dev);
static inline int static inline int
grub_disk_dev_iterate (int (*hook) (const char *name)) grub_disk_dev_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data)
{ {
grub_disk_dev_t p; grub_disk_dev_t p;
grub_disk_pull_t pull; grub_disk_pull_t pull;
for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++) for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
for (p = grub_disk_dev_list; p; p = p->next) for (p = grub_disk_dev_list; p; p = p->next)
if (p->iterate && (p->iterate) (hook, pull)) if (p->iterate && (p->iterate) (hook, hook_data, pull))
return 1; return 1;
return 0; return 0;

View File

@ -80,8 +80,8 @@ struct grub_gpt_partentry
grub_err_t grub_err_t
grub_gpt_partition_map_iterate (grub_disk_t disk, grub_gpt_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)); void *hook_data);
#endif /* ! GRUB_GPT_PARTITION_HEADER */ #endif /* ! GRUB_GPT_PARTITION_HEADER */

View File

@ -120,7 +120,7 @@ grub_msdos_partition_is_extended (int type)
grub_err_t grub_err_t
grub_partition_msdos_iterate (grub_disk_t disk, grub_partition_msdos_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)); void *hook_data);
#endif /* ! GRUB_PC_PARTITION_HEADER */ #endif /* ! GRUB_PC_PARTITION_HEADER */

View File

@ -33,6 +33,10 @@ typedef enum
} grub_embed_type_t; } grub_embed_type_t;
#endif #endif
typedef int (*grub_partition_iterate_hook_t) (struct grub_disk *disk,
const grub_partition_t partition,
void *data);
/* Partition map type. */ /* Partition map type. */
struct grub_partition_map struct grub_partition_map
{ {
@ -45,8 +49,7 @@ struct grub_partition_map
/* Call HOOK with each partition, until HOOK returns non-zero. */ /* Call HOOK with each partition, until HOOK returns non-zero. */
grub_err_t (*iterate) (struct grub_disk *disk, grub_err_t (*iterate) (struct grub_disk *disk,
int (*hook) (struct grub_disk *disk, grub_partition_iterate_hook_t hook, void *hook_data);
const grub_partition_t partition));
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
/* Determine sectors available for embedding. */ /* Determine sectors available for embedding. */
grub_err_t (*embed) (struct grub_disk *disk, unsigned int *nsectors, grub_err_t (*embed) (struct grub_disk *disk, unsigned int *nsectors,
@ -89,8 +92,8 @@ struct grub_partition
grub_partition_t EXPORT_FUNC(grub_partition_probe) (struct grub_disk *disk, grub_partition_t EXPORT_FUNC(grub_partition_probe) (struct grub_disk *disk,
const char *str); const char *str);
int EXPORT_FUNC(grub_partition_iterate) (struct grub_disk *disk, int EXPORT_FUNC(grub_partition_iterate) (struct grub_disk *disk,
int (*hook) (struct grub_disk *disk, grub_partition_iterate_hook_t hook,
const grub_partition_t partition)); void *hook_data);
char *EXPORT_FUNC(grub_partition_get_name) (const grub_partition_t partition); char *EXPORT_FUNC(grub_partition_get_name) (const grub_partition_t partition);

View File

@ -49,10 +49,13 @@ grub_make_scsi_id (int subsystem, int bus, int lun)
| (bus << GRUB_SCSI_ID_BUS_SHIFT) | (lun << GRUB_SCSI_ID_LUN_SHIFT); | (bus << GRUB_SCSI_ID_BUS_SHIFT) | (lun << GRUB_SCSI_ID_LUN_SHIFT);
} }
typedef int (*grub_scsi_dev_iterate_hook_t) (int id, int bus, int luns,
void *data);
struct grub_scsi_dev struct grub_scsi_dev
{ {
/* Call HOOK with each device name, until HOOK returns non-zero. */ /* Call HOOK with each device name, until HOOK returns non-zero. */
int (*iterate) (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns), int (*iterate) (grub_scsi_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull); grub_disk_pull_t pull);
/* Open the device named NAME, and set up SCSI. */ /* Open the device named NAME, and set up SCSI. */

View File

@ -2198,6 +2198,36 @@ grub_util_get_os_disk (const char *os_dev)
return convert_system_partition_to_system_disk (os_dev, &st, &is_part); return convert_system_partition_to_system_disk (os_dev, &st, &is_part);
} }
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__sun__)
/* Context for grub_util_biosdisk_get_grub_dev. */
struct grub_util_biosdisk_get_grub_dev_ctx
{
char *partname;
grub_disk_addr_t start;
};
/* Helper for grub_util_biosdisk_get_grub_dev. */
static int
find_partition (grub_disk_t dsk __attribute__ ((unused)),
const grub_partition_t partition, void *data)
{
struct grub_util_biosdisk_get_grub_dev_ctx *ctx = data;
grub_disk_addr_t part_start = 0;
grub_util_info ("Partition %d starts from %" PRIuGRUB_UINT64_T,
partition->number, partition->start);
part_start = grub_partition_get_start (partition);
if (ctx->start == part_start)
{
ctx->partname = grub_partition_get_name (partition);
return 1;
}
return 0;
}
#endif
char * char *
grub_util_biosdisk_get_grub_dev (const char *os_dev) grub_util_biosdisk_get_grub_dev (const char *os_dev)
{ {
@ -2250,29 +2280,9 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
For NetBSD and FreeBSD, proceed as for Linux, except that the start For NetBSD and FreeBSD, proceed as for Linux, except that the start
sector is obtained from the disk label. */ sector is obtained from the disk label. */
{ {
char *name, *partname; char *name;
grub_disk_t disk; grub_disk_t disk;
grub_disk_addr_t start; struct grub_util_biosdisk_get_grub_dev_ctx ctx;
auto int find_partition (grub_disk_t dsk,
const grub_partition_t partition);
int find_partition (grub_disk_t dsk __attribute__ ((unused)),
const grub_partition_t partition)
{
grub_disk_addr_t part_start = 0;
grub_util_info ("Partition %d starts from %" PRIuGRUB_UINT64_T,
partition->number, partition->start);
part_start = grub_partition_get_start (partition);
if (start == part_start)
{
partname = grub_partition_get_name (partition);
return 1;
}
return 0;
}
name = make_device_name (drive, -1, -1); name = make_device_name (drive, -1, -1);
@ -2284,16 +2294,16 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
* different, we know that os_dev cannot be a floppy device. */ * different, we know that os_dev cannot be a floppy device. */
# endif /* !defined(HAVE_DIOCGDINFO) */ # endif /* !defined(HAVE_DIOCGDINFO) */
start = grub_hostdisk_find_partition_start (os_dev); ctx.start = grub_hostdisk_find_partition_start (os_dev);
if (grub_errno != GRUB_ERR_NONE) if (grub_errno != GRUB_ERR_NONE)
{ {
free (name); free (name);
return 0; return 0;
} }
grub_util_info ("%s starts from %" PRIuGRUB_UINT64_T, os_dev, start); grub_util_info ("%s starts from %" PRIuGRUB_UINT64_T, os_dev, ctx.start);
if (start == 0 && !is_part) if (ctx.start == 0 && !is_part)
return name; return name;
grub_util_info ("opening the device %s", name); grub_util_info ("opening the device %s", name);
@ -2325,20 +2335,20 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
return 0; return 0;
} }
name = grub_util_get_ldm (disk, start); name = grub_util_get_ldm (disk, ctx.start);
if (name) if (name)
return name; return name;
partname = NULL; ctx.partname = NULL;
grub_partition_iterate (disk, find_partition); grub_partition_iterate (disk, find_partition, &ctx);
if (grub_errno != GRUB_ERR_NONE) if (grub_errno != GRUB_ERR_NONE)
{ {
grub_disk_close (disk); grub_disk_close (disk);
return 0; return 0;
} }
if (partname == NULL) if (ctx.partname == NULL)
{ {
grub_disk_close (disk); grub_disk_close (disk);
grub_util_info ("cannot find the partition of `%s'", os_dev); grub_util_info ("cannot find the partition of `%s'", os_dev);
@ -2347,8 +2357,8 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
return 0; return 0;
} }
name = grub_xasprintf ("%s,%s", disk->name, partname); name = grub_xasprintf ("%s,%s", disk->name, ctx.partname);
free (partname); free (ctx.partname);
grub_disk_close (disk); grub_disk_close (disk);
return name; return name;
} }

View File

@ -138,6 +138,44 @@ write_rootdev (grub_device_t root_dev,
#define BOOT_SECTOR 0 #define BOOT_SECTOR 0
#endif #endif
#ifdef GRUB_SETUP_BIOS
/* Context for setup/identify_partmap. */
struct identify_partmap_ctx
{
grub_partition_map_t dest_partmap;
grub_partition_t container;
int multiple_partmaps;
};
/* Helper for setup/identify_partmap.
Unlike root_dev, with dest_dev we're interested in the partition map even
if dest_dev itself is a whole disk. */
static int
identify_partmap (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p, void *data)
{
struct identify_partmap_ctx *ctx = data;
if (p->parent != ctx->container)
return 0;
/* NetBSD and OpenBSD subpartitions have metadata inside a partition,
so they are safe to ignore.
*/
if (grub_strcmp (p->partmap->name, "netbsd") == 0
|| grub_strcmp (p->partmap->name, "openbsd") == 0)
return 0;
if (ctx->dest_partmap == NULL)
{
ctx->dest_partmap = p->partmap;
return 0;
}
if (ctx->dest_partmap == p->partmap)
return 0;
ctx->multiple_partmaps = 1;
return 1;
}
#endif
static void static void
setup (const char *dir, setup (const char *dir,
const char *boot_file, const char *core_file, const char *boot_file, const char *core_file,
@ -337,9 +375,11 @@ setup (const char *dir,
#ifdef GRUB_SETUP_BIOS #ifdef GRUB_SETUP_BIOS
{ {
grub_partition_map_t dest_partmap = NULL; struct identify_partmap_ctx ctx = {
grub_partition_t container = dest_dev->disk->partition; .dest_partmap = NULL,
int multiple_partmaps = 0; .container = dest_dev->disk->partition,
.multiple_partmaps = 0
};
int is_ldm; int is_ldm;
grub_err_t err; grub_err_t err;
grub_disk_addr_t *sectors; grub_disk_addr_t *sectors;
@ -347,38 +387,13 @@ setup (const char *dir,
grub_fs_t fs; grub_fs_t fs;
unsigned int nsec, maxsec; unsigned int nsec, maxsec;
/* Unlike root_dev, with dest_dev we're interested in the partition map even grub_partition_iterate (dest_dev->disk, identify_partmap, &ctx);
if dest_dev itself is a whole disk. */
auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk,
const grub_partition_t p);
int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p)
{
if (p->parent != container)
return 0;
/* NetBSD and OpenBSD subpartitions have metadata inside a partition,
so they are safe to ignore.
*/
if (grub_strcmp (p->partmap->name, "netbsd") == 0
|| grub_strcmp (p->partmap->name, "openbsd") == 0)
return 0;
if (dest_partmap == NULL)
{
dest_partmap = p->partmap;
return 0;
}
if (dest_partmap == p->partmap)
return 0;
multiple_partmaps = 1;
return 1;
}
grub_partition_iterate (dest_dev->disk, identify_partmap); if (ctx.container
&& grub_strcmp (ctx.container->partmap->name, "msdos") == 0
if (container && grub_strcmp (container->partmap->name, "msdos") == 0 && ctx.dest_partmap
&& dest_partmap && (ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_NETBSD
&& (container->msdostype == GRUB_PC_PARTITION_TYPE_NETBSD || ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_OPENBSD))
|| container->msdostype == GRUB_PC_PARTITION_TYPE_OPENBSD))
{ {
grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet.")); grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet."));
goto unable_to_embed; goto unable_to_embed;
@ -392,7 +407,7 @@ setup (const char *dir,
if (fs_probe) if (fs_probe)
{ {
if (!fs && !dest_partmap) if (!fs && !ctx.dest_partmap)
grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"),
dest_dev->disk->name); dest_dev->disk->name);
if (fs && !fs->reserved_first_sector) if (fs && !fs->reserved_first_sector)
@ -403,20 +418,20 @@ setup (const char *dir,
"by grub-setup (--skip-fs-probe disables this " "by grub-setup (--skip-fs-probe disables this "
"check, use at your own risk)"), dest_dev->disk->name, fs->name); "check, use at your own risk)"), dest_dev->disk->name, fs->name);
if (dest_partmap && strcmp (dest_partmap->name, "msdos") != 0 if (ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0
&& strcmp (dest_partmap->name, "gpt") != 0 && strcmp (ctx.dest_partmap->name, "gpt") != 0
&& strcmp (dest_partmap->name, "bsd") != 0 && strcmp (ctx.dest_partmap->name, "bsd") != 0
&& strcmp (dest_partmap->name, "netbsd") != 0 && strcmp (ctx.dest_partmap->name, "netbsd") != 0
&& strcmp (dest_partmap->name, "openbsd") != 0 && strcmp (ctx.dest_partmap->name, "openbsd") != 0
&& strcmp (dest_partmap->name, "sunpc") != 0) && strcmp (ctx.dest_partmap->name, "sunpc") != 0)
/* TRANSLATORS: Partition map may reserve the space just GRUB isn't sure about it. */ /* TRANSLATORS: Partition map may reserve the space just GRUB isn't sure about it. */
grub_util_error (_("%s appears to contain a %s partition map which isn't known to " grub_util_error (_("%s appears to contain a %s partition map which isn't known to "
"reserve space for DOS-style boot. Installing GRUB there could " "reserve space for DOS-style boot. Installing GRUB there could "
"result in FILESYSTEM DESTRUCTION if valuable data is overwritten " "result in FILESYSTEM DESTRUCTION if valuable data is overwritten "
"by grub-setup (--skip-fs-probe disables this " "by grub-setup (--skip-fs-probe disables this "
"check, use at your own risk)"), dest_dev->disk->name, dest_partmap->name); "check, use at your own risk)"), dest_dev->disk->name, ctx.dest_partmap->name);
if (is_ldm && dest_partmap && strcmp (dest_partmap->name, "msdos") != 0 if (is_ldm && ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0
&& strcmp (dest_partmap->name, "gpt") != 0) && strcmp (ctx.dest_partmap->name, "gpt") != 0)
grub_util_error (_("%s appears to contain a %s partition map and " grub_util_error (_("%s appears to contain a %s partition map and "
"LDM which isn't known to be a safe combination." "LDM which isn't known to be a safe combination."
" Installing GRUB there could " " Installing GRUB there could "
@ -424,12 +439,12 @@ setup (const char *dir,
" is overwritten " " is overwritten "
"by grub-setup (--skip-fs-probe disables this " "by grub-setup (--skip-fs-probe disables this "
"check, use at your own risk)"), "check, use at your own risk)"),
dest_dev->disk->name, dest_partmap->name); dest_dev->disk->name, ctx.dest_partmap->name);
} }
/* Copy the partition table. */ /* Copy the partition table. */
if (dest_partmap || if (ctx.dest_partmap ||
(!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk))) (!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk)))
memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC,
tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC,
@ -437,21 +452,21 @@ setup (const char *dir,
free (tmp_img); free (tmp_img);
if (! dest_partmap && ! fs && !is_ldm) if (! ctx.dest_partmap && ! fs && !is_ldm)
{ {
grub_util_warn ("%s", _("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.")); grub_util_warn ("%s", _("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea."));
goto unable_to_embed; goto unable_to_embed;
} }
if (multiple_partmaps || (dest_partmap && fs) || (is_ldm && fs)) if (ctx.multiple_partmaps || (ctx.dest_partmap && fs) || (is_ldm && fs))
{ {
grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet.")); grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet."));
goto unable_to_embed; goto unable_to_embed;
} }
if (dest_partmap && !dest_partmap->embed) if (ctx.dest_partmap && !ctx.dest_partmap->embed)
{ {
grub_util_warn (_("Partition style `%s' doesn't support embedding"), grub_util_warn (_("Partition style `%s' doesn't support embedding"),
dest_partmap->name); ctx.dest_partmap->name);
goto unable_to_embed; goto unable_to_embed;
} }
@ -473,9 +488,9 @@ setup (const char *dir,
if (is_ldm) if (is_ldm)
err = grub_util_ldm_embed (dest_dev->disk, &nsec, maxsec, err = grub_util_ldm_embed (dest_dev->disk, &nsec, maxsec,
GRUB_EMBED_PCBIOS, &sectors); GRUB_EMBED_PCBIOS, &sectors);
else if (dest_partmap) else if (ctx.dest_partmap)
err = dest_partmap->embed (dest_dev->disk, &nsec, maxsec, err = ctx.dest_partmap->embed (dest_dev->disk, &nsec, maxsec,
GRUB_EMBED_PCBIOS, &sectors); GRUB_EMBED_PCBIOS, &sectors);
else else
err = fs->embed (dest_dev, &nsec, maxsec, err = fs->embed (dest_dev, &nsec, maxsec,
GRUB_EMBED_PCBIOS, &sectors); GRUB_EMBED_PCBIOS, &sectors);
@ -507,12 +522,12 @@ setup (const char *dir,
grub_util_error ("%s", _("no terminator in the core image")); grub_util_error ("%s", _("no terminator in the core image"));
} }
save_first_sector (sectors[0] + grub_partition_get_start (container), save_first_sector (sectors[0] + grub_partition_get_start (ctx.container),
0, GRUB_DISK_SECTOR_SIZE); 0, GRUB_DISK_SECTOR_SIZE);
block = first_block; block = first_block;
for (i = 1; i < nsec; i++) for (i = 1; i < nsec; i++)
save_blocklists (sectors[i] + grub_partition_get_start (container), save_blocklists (sectors[i] + grub_partition_get_start (ctx.container),
0, GRUB_DISK_SECTOR_SIZE); 0, GRUB_DISK_SECTOR_SIZE);
/* Make sure that the last blocklist is a terminator. */ /* Make sure that the last blocklist is a terminator. */