diff options
Diffstat (limited to 'discover/grub2/grub2.c')
-rw-r--r-- | discover/grub2/grub2.c | 110 |
1 files changed, 87 insertions, 23 deletions
diff --git a/discover/grub2/grub2.c b/discover/grub2/grub2.c index f62ccdd..b176ce2 100644 --- a/discover/grub2/grub2.c +++ b/discover/grub2/grub2.c @@ -33,18 +33,35 @@ static const char *const grub2_conf_files[] = { NULL }; -struct grub2_resource_info { - char *root; - char *path; -}; +struct discover_device *grub2_lookup_device(struct device_handler *handler, + const char *desc) +{ + struct discover_device *dev; + + if (!desc || !*desc) + return NULL; + + dev = device_lookup_by_id(handler, desc); + if (dev) + return dev; + + /* for now, only lookup by UUID */ + dev = device_lookup_by_uuid(handler, desc); + if (dev) + return dev; + + return NULL; +} /* we use slightly different resources for grub2 */ -struct resource *create_grub2_resource(struct discover_boot_option *opt, - struct discover_device *orig_device, - const char *root, const char *path) +struct resource *create_grub2_resource(struct grub2_script *script, + struct discover_boot_option *opt, + const char *path) { - struct grub2_resource_info *info; + struct discover_device *dev; + struct grub2_file *file; struct resource *res; + const char *root; if (strstr(path, "://")) { struct pb_url *url = pb_url_parse(opt, path); @@ -52,19 +69,29 @@ struct resource *create_grub2_resource(struct discover_boot_option *opt, return create_url_resource(opt, url); } + file = grub2_parse_file(script, path); + if (!file) + return NULL; + res = talloc(opt, struct resource); + root = script_env_get(script, "root"); - if (root) { - info = talloc(res, struct grub2_resource_info); - talloc_reference(info, root); - info->root = talloc_strdup(info, root); - info->path = talloc_strdup(info, path); + if (!file->dev && root && strlen(root)) + file->dev = talloc_strdup(file, root); - res->resolved = false; - res->info = info; + /* if we don't have a device specified, or the lookup succeeds now, + * then we can resolve the resource right away */ + if (file->dev) + dev = grub2_lookup_device(script->ctx->handler, file->dev); + else + dev = script->ctx->device; - } else - resolve_resource_against_device(res, orig_device, path); + if (dev) { + resolve_resource_against_device(res, dev, file->path); + } else { + res->resolved = false; + res->info = talloc_steal(opt, file); + } return res; } @@ -72,22 +99,59 @@ struct resource *create_grub2_resource(struct discover_boot_option *opt, bool resolve_grub2_resource(struct device_handler *handler, struct resource *res) { - struct grub2_resource_info *info = res->info; + struct grub2_file *file = res->info; struct discover_device *dev; assert(!res->resolved); - dev = device_lookup_by_uuid(handler, info->root); - + dev = grub2_lookup_device(handler, file->dev); if (!dev) return false; - resolve_resource_against_device(res, dev, info->path); - talloc_free(info); + resolve_resource_against_device(res, dev, file->path); + talloc_free(file); return true; } +struct grub2_file *grub2_parse_file(struct grub2_script *script, + const char *str) +{ + struct grub2_file *file; + size_t dev_len; + char *pos; + + if (!str) + return NULL; + + file = talloc_zero(script, struct grub2_file); + + if (*str != '(') { + /* just a path - no device, return path as-is */ + file->path = talloc_strdup(file, str); + + } else { + /* device plus path - split into components */ + + pos = strchr(str, ')'); + + /* no closing bracket, or zero-length path? */ + if (!pos || *(pos+1) == '\0') { + talloc_free(file); + return NULL; + } + + file->path = talloc_strdup(file, pos + 1); + + dev_len = pos - str - 1; + if (dev_len) + file->dev = talloc_strndup(file, str + 1, dev_len); + } + + return file; +} + + static int grub2_parse(struct discover_context *dc) { const char * const *filename; @@ -105,7 +169,7 @@ static int grub2_parse(struct discover_context *dc) continue; parser = grub2_parser_create(dc); - grub2_parser_parse(parser, *filename, buf, len); + grub2_parser_parse_and_execute(parser, *filename, buf, len); device_handler_status_dev_info(dc->handler, dc->device, _("Parsed GRUB configuration from %s"), *filename); |