6 #include <pb-protocol/pb-protocol.h>
7 #include <system/system.h>
8 #include <talloc/talloc.h>
11 #include "device-handler.h"
26 * kexec_load - kexec load helper.
28 static int kexec_load(struct boot_task *boot_task)
33 char *s_initrd = NULL;
38 *p++ = pb_system_apps.kexec; /* 1 */
41 if (boot_task->local_initrd) {
42 s_initrd = talloc_asprintf(NULL, "--initrd=%s",
43 boot_task->local_initrd);
45 *p++ = s_initrd; /* 3 */
48 if (boot_task->local_dtb) {
49 s_dtb = talloc_asprintf(NULL, "--dtb=%s", boot_task->local_dtb);
54 if (boot_task->args) {
55 s_args = talloc_asprintf(NULL, "--append=%s", boot_task->args);
57 *p++ = s_args; /* 5 */
60 *p++ = boot_task->local_image; /* 6 */
63 result = pb_run_cmd(argv, 1, boot_task->dry_run);
66 pb_log("%s: failed: (%d)\n", __func__, result);
68 talloc_free(s_initrd);
76 * kexec_reboot - Helper to boot the new kernel.
78 * Must only be called after a successful call to kexec_load().
81 static int kexec_reboot(bool dry_run)
87 /* First try running shutdown. Init scripts should run 'exec -e' */
90 *p++ = pb_system_apps.shutdown; /* 1 */
95 result = pb_run_cmd(argv, 1, dry_run);
97 /* On error, force a kexec with the -e option */
101 *p++ = pb_system_apps.kexec; /* 1 */
105 result = pb_run_cmd(argv, 1, 0);
109 pb_log("%s: failed: (%d)\n", __func__, result);
111 /* okay, kexec -e -f */
114 *p++ = pb_system_apps.kexec; /* 1 */
119 result = pb_run_cmd(argv, 1, 0);
123 pb_log("%s: failed: (%d)\n", __func__, result);
129 static void update_status(boot_status_fn fn, void *arg, int type,
132 struct boot_status status;
135 status.message = message;
136 status.progress = -1;
137 status.detail = NULL;
142 int boot(void *ctx, struct discover_boot_option *opt, struct boot_command *cmd,
143 int dry_run, boot_status_fn status_fn, void *status_arg)
145 struct boot_task boot_task;
146 struct pb_url *image, *initrd, *dtb;
147 unsigned int clean_image = 0;
148 unsigned int clean_initrd = 0;
149 unsigned int clean_dtb = 0;
155 boot_task.dry_run = dry_run;
157 if (cmd && cmd->boot_image_file) {
158 image = pb_url_parse(opt, cmd->boot_image_file);
159 } else if (opt && opt->boot_image) {
160 image = opt->boot_image->url;
162 pb_log("%s: no image specified", __func__);
166 if (cmd && cmd->initrd_file) {
167 initrd = pb_url_parse(opt, cmd->initrd_file);
168 } else if (opt && opt->initrd) {
169 initrd = opt->initrd->url;
172 if (cmd && cmd->dtb_file) {
173 dtb = pb_url_parse(opt, cmd->dtb_file);
174 } else if (opt && opt->dtb) {
178 if (cmd && cmd->boot_args) {
179 boot_task.args = talloc_strdup(ctx, cmd->boot_args);
180 } else if (opt && opt->option->boot_args) {
181 boot_task.args = talloc_strdup(ctx, opt->option->boot_args);
183 boot_task.args = NULL;
188 update_status(status_fn, status_arg, BOOT_STATUS_INFO,
190 boot_task.local_image = load_url(NULL, image, &clean_image);
191 if (!boot_task.local_image) {
192 update_status(status_fn, status_arg, BOOT_STATUS_ERROR,
193 "Couldn't load kernel image");
197 boot_task.local_initrd = NULL;
199 update_status(status_fn, status_arg, BOOT_STATUS_INFO,
201 boot_task.local_initrd = load_url(NULL, initrd, &clean_initrd);
202 if (!boot_task.local_initrd) {
203 update_status(status_fn, status_arg, BOOT_STATUS_ERROR,
204 "Couldn't load initrd image");
209 boot_task.local_dtb = NULL;
211 update_status(status_fn, status_arg, BOOT_STATUS_INFO,
212 "loading device tree");
213 boot_task.local_dtb = load_url(NULL, dtb, &clean_dtb);
214 if (!boot_task.local_dtb) {
215 update_status(status_fn, status_arg, BOOT_STATUS_ERROR,
216 "Couldn't load device tree");
221 update_status(status_fn, status_arg, BOOT_STATUS_INFO,
222 "performing kexec_load");
224 result = kexec_load(&boot_task);
227 update_status(status_fn, status_arg, BOOT_STATUS_ERROR,
228 "kexec load failed");
233 unlink(boot_task.local_image);
235 unlink(boot_task.local_initrd);
237 unlink(boot_task.local_dtb);
239 talloc_free(boot_task.local_image);
240 talloc_free(boot_task.local_initrd);
241 talloc_free(boot_task.local_dtb);
244 update_status(status_fn, status_arg, BOOT_STATUS_INFO,
245 "performing kexec reboot");
247 result = kexec_reboot(boot_task.dry_run);
250 update_status(status_fn, status_arg, BOOT_STATUS_ERROR,
251 "kexec reboot failed");