+static void cleanup_load(struct load_url_result *result)
+{
+ if (!result)
+ return;
+ if (result->status != LOAD_OK)
+ return;
+ if (!result->cleanup_local)
+ return;
+ unlink(result->local);
+}
+
+static void boot_process(struct load_url_result *result, void *data)
+{
+ struct boot_task *task = data;
+ int rc = -1;
+
+ if (task->state == BOOT_STATE_INITIAL) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_INFO, "loading kernel");
+ task->image = load_url_async(task, task->image_url,
+ boot_process, task);
+ if (!task->image) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_ERROR,
+ "Couldn't load kernel image");
+ goto no_load;
+ }
+ task->state = BOOT_STATE_IMAGE_LOADING;
+ return;
+ }
+
+ if (task->state == BOOT_STATE_IMAGE_LOADING) {
+ if (result->status == LOAD_ERROR) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_ERROR,
+ "Error loading kernel image");
+ goto no_load;
+ }
+ task->state = BOOT_STATE_INITRD_LOADING;
+
+ if (task->initrd_url) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_INFO, "loading initrd");
+ task->initrd = load_url_async(task, task->initrd_url,
+ boot_process, task);
+ if (!task->initrd) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_ERROR,
+ "Couldn't load initrd image");
+ goto no_load;
+ }
+ return;
+ }
+ }
+
+ if (task->state == BOOT_STATE_INITRD_LOADING) {
+ if (result->status) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_ERROR,
+ "Error loading initrd");
+ goto no_load;
+ }
+ task->state = BOOT_STATE_DTB_LOADING;
+
+ if (task->dtb_url) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_INFO,
+ "loading device tree");
+ task->dtb = load_url_async(task, task->dtb_url,
+ boot_process, task);
+ if (!task->dtb) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_ERROR,
+ "Couldn't load device tree");
+ goto no_load;
+ }
+ return;
+ }
+ }
+
+ if (task->state == BOOT_STATE_DTB_LOADING) {
+ if (result->status) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_ERROR,
+ "Error loading dtb");
+ goto no_load;
+ }
+ task->state = BOOT_STATE_FINISH;
+ }
+
+
+ if (task->state != BOOT_STATE_FINISH) {
+ task->state = BOOT_STATE_UNKNOWN;
+ return;
+ }
+
+ run_boot_hooks(task);
+
+ update_status(task->status_fn, task->status_arg, BOOT_STATUS_INFO,
+ "performing kexec_load");
+
+ rc = kexec_load(task);
+ if (rc) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_ERROR, "kexec load failed");
+ }
+
+no_load:
+ cleanup_load(task->image);
+ cleanup_load(task->initrd);
+ cleanup_load(task->dtb);
+
+ if (!rc) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_INFO,
+ "performing kexec reboot");
+
+ rc = kexec_reboot(task);
+ if (rc) {
+ update_status(task->status_fn, task->status_arg,
+ BOOT_STATUS_ERROR,
+ "kexec reboot failed");
+ }
+ }
+
+ talloc_free(task);
+}
+