+ handler->sec_to_boot = config_get()->autoboot_timeout_sec;
+ handler->default_boot_option = opt;
+
+ pb_log("Boot option %s set as default, timeout %u sec.\n",
+ opt->option->id, handler->sec_to_boot);
+
+ default_timeout(handler);
+}
+
+static bool resource_is_resolved(struct resource *res)
+{
+ return !res || res->resolved;
+}
+
+/* We only use this in an assert, which will disappear if we're compiling
+ * with NDEBUG, so we need the 'used' attribute for these builds */
+static bool __attribute__((used)) boot_option_is_resolved(
+ struct discover_boot_option *opt)
+{
+ return resource_is_resolved(opt->boot_image) &&
+ resource_is_resolved(opt->initrd) &&
+ resource_is_resolved(opt->dtb) &&
+ resource_is_resolved(opt->icon);
+}
+
+static bool resource_resolve(struct resource *res, const char *name,
+ struct discover_boot_option *opt,
+ struct device_handler *handler)
+{
+ struct parser *parser = opt->source;
+
+ if (resource_is_resolved(res))
+ return true;
+
+ pb_debug("Attempting to resolve resource %s->%s with parser %s\n",
+ opt->option->id, name, parser->name);
+ parser->resolve_resource(handler, res);
+
+ return res->resolved;
+}
+
+static bool boot_option_resolve(struct discover_boot_option *opt,
+ struct device_handler *handler)
+{
+ return resource_resolve(opt->boot_image, "boot_image", opt, handler) &&
+ resource_resolve(opt->initrd, "initrd", opt, handler) &&
+ resource_resolve(opt->dtb, "dtb", opt, handler) &&
+ resource_resolve(opt->icon, "icon", opt, handler);
+}
+
+static void boot_option_finalise(struct device_handler *handler,
+ struct discover_boot_option *opt)
+{
+ assert(boot_option_is_resolved(opt));
+
+ /* check that the parsers haven't set any of the final data */
+ assert(!opt->option->boot_image_file);
+ assert(!opt->option->initrd_file);
+ assert(!opt->option->dtb_file);
+ assert(!opt->option->icon_file);
+ assert(!opt->option->device_id);
+
+ if (opt->boot_image)
+ opt->option->boot_image_file = opt->boot_image->url->full;
+ if (opt->initrd)
+ opt->option->initrd_file = opt->initrd->url->full;
+ if (opt->dtb)
+ opt->option->dtb_file = opt->dtb->url->full;
+ if (opt->icon)
+ opt->option->icon_file = opt->icon->url->full;
+
+ opt->option->device_id = opt->device->device->id;
+
+ if (opt->option->is_default)
+ set_default(handler, opt);
+}
+
+static void notify_boot_option(struct device_handler *handler,
+ struct discover_boot_option *opt)
+{
+ struct discover_device *dev = opt->device;
+
+ if (!dev->notified)
+ discover_server_notify_device_add(handler->server,
+ opt->device->device);
+ dev->notified = true;
+ discover_server_notify_boot_option_add(handler->server, opt->option);
+}
+
+static void process_boot_option_queue(struct device_handler *handler)
+{
+ struct discover_boot_option *opt, *tmp;
+
+ list_for_each_entry_safe(&handler->unresolved_boot_options,
+ opt, tmp, list) {
+
+ pb_debug("queue: attempting resolution for %s\n",
+ opt->option->id);
+
+ if (!boot_option_resolve(opt, handler))
+ continue;
+
+ pb_debug("\tresolved!\n");
+
+ list_remove(&opt->list);
+ list_add_tail(&opt->device->boot_options, &opt->list);
+ talloc_steal(opt->device, opt);
+ boot_option_finalise(handler, opt);
+ notify_boot_option(handler, opt);