+const struct discover_device *device_handler_get_device(
+ const struct device_handler *handler, unsigned int index)
+{
+ if (index >= handler->n_devices) {
+ assert(0 && "bad index");
+ return NULL;
+ }
+
+ return handler->devices[index];
+}
+
+struct discover_boot_option *discover_boot_option_create(
+ struct discover_context *ctx,
+ struct discover_device *device)
+{
+ struct discover_boot_option *opt;
+
+ opt = talloc_zero(ctx, struct discover_boot_option);
+ opt->option = talloc_zero(opt, struct boot_option);
+ opt->device = device;
+
+ return opt;
+}
+
+static int device_match_path(struct discover_device *dev, const char *path)
+{
+ return dev->device_path && !strcmp(dev->device_path, path);
+}
+
+static int device_match_uuid(struct discover_device *dev, const char *uuid)
+{
+ return dev->uuid && !strcmp(dev->uuid, uuid);
+}
+
+static int device_match_label(struct discover_device *dev, const char *label)
+{
+ return dev->label && !strcmp(dev->label, label);
+}
+
+static int device_match_id(struct discover_device *dev, const char *id)
+{
+ return !strcmp(dev->device->id, id);
+}
+
+static struct discover_device *device_lookup(
+ struct device_handler *device_handler,
+ int (match_fn)(struct discover_device *, const char *),
+ const char *str)
+{
+ struct discover_device *dev;
+ unsigned int i;
+
+ if (!str)
+ return NULL;
+
+ for (i = 0; i < device_handler->n_devices; i++) {
+ dev = device_handler->devices[i];
+
+ if (match_fn(dev, str))
+ return dev;
+ }
+
+ return NULL;
+}
+
+struct discover_device *device_lookup_by_name(struct device_handler *handler,
+ const char *name)
+{
+ struct discover_device *dev;
+ char *path;
+
+ if (strncmp(name, "/dev/", strlen("/dev/")))
+ path = talloc_asprintf(NULL, "/dev/%s", name);
+ else
+ path = talloc_strdup(NULL, name);
+
+ dev = device_lookup_by_path(handler, path);
+
+ talloc_free(path);
+
+ return dev;
+}
+
+struct discover_device *device_lookup_by_path(
+ struct device_handler *device_handler,
+ const char *path)
+{
+ return device_lookup(device_handler, device_match_path, path);
+}
+
+struct discover_device *device_lookup_by_uuid(
+ struct device_handler *device_handler,
+ const char *uuid)
+{
+ return device_lookup(device_handler, device_match_uuid, uuid);
+}
+
+struct discover_device *device_lookup_by_label(
+ struct device_handler *device_handler,
+ const char *label)
+{
+ return device_lookup(device_handler, device_match_label, label);
+}
+
+struct discover_device *device_lookup_by_id(
+ struct device_handler *device_handler,
+ const char *id)
+{
+ return device_lookup(device_handler, device_match_id, id);
+}
+
+void device_handler_destroy(struct device_handler *handler)
+{
+ talloc_free(handler);
+}
+
+#ifdef PETITBOOT_TEST
+
+/* we have a simplified interface for petitboot testing, but still want
+ * to keep struct device_handler opaque. */
+struct device_handler *device_handler_init(
+ struct discover_server *server __attribute__((unused)),
+ struct waitset *waitset __attribute__((unused)),
+ int dry_run __attribute__((unused)))
+{
+ struct device_handler *handler;
+
+ handler = talloc_zero(NULL, struct device_handler);
+ list_init(&handler->unresolved_boot_options);
+
+ return handler;
+}
+
+void device_handler_add_device(struct device_handler *handler,
+ struct discover_device *dev)