summaryrefslogtreecommitdiffstats
path: root/discover/grub2/grub2.c
diff options
context:
space:
mode:
Diffstat (limited to 'discover/grub2/grub2.c')
-rw-r--r--discover/grub2/grub2.c110
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);
OpenPOWER on IntegriCloud