discover/boot: Improve kexec error reporting
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>
Fri, 2 Dec 2016 04:18:36 +0000 (15:18 +1100)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Tue, 20 Dec 2016 05:40:21 +0000 (16:40 +1100)
Update kexec_load() to preserve output from the call to `kexec -l`. On
error retrieve the resulting error message and update the status line
with it to provide a more informative error message.

Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
discover/boot.c

index 82fba2f1da39279696a2564680904f780c6634e9..5347fd7c1d45bbfbe748deaa12b44cdb2c4d930c 100644 (file)
@@ -34,17 +34,38 @@ enum {
        BOOT_HOOK_EXIT_UPDATE   = 2,
 };
 
        BOOT_HOOK_EXIT_UPDATE   = 2,
 };
 
+static void __attribute__((format(__printf__, 4, 5))) update_status(
+               boot_status_fn fn, void *arg, int type, char *fmt, ...)
+{
+       struct status status;
+       va_list ap;
+
+       va_start(ap, fmt);
+       status.message = talloc_vasprintf(NULL, fmt, ap);
+       va_end(ap);
+
+       status.type = type;
+
+       pb_debug("boot status: [%d] %s\n", type, status.message);
+
+       fn(arg, &status);
+
+       talloc_free(status.message);
+}
+
 /**
  * kexec_load - kexec load helper.
  */
 static int kexec_load(struct boot_task *boot_task)
 {
 /**
  * kexec_load - kexec load helper.
  */
 static int kexec_load(struct boot_task *boot_task)
 {
-       int result;
-       const char *argv[7];
-       const char **p;
+       struct process *process;
        char *s_initrd = NULL;
        char *s_initrd = NULL;
-       char *s_dtb = NULL;
        char *s_args = NULL;
        char *s_args = NULL;
+       const char *argv[7];
+       char *s_dtb = NULL;
+       const char **p;
+       int result;
+
 
        boot_task->local_initrd_override = NULL;
        boot_task->local_dtb_override = NULL;
 
        boot_task->local_initrd_override = NULL;
        boot_task->local_dtb_override = NULL;
@@ -70,6 +91,17 @@ static int kexec_load(struct boot_task *boot_task)
        const char* local_image = (boot_task->local_image_override) ?
                boot_task->local_image_override : boot_task->local_image;
 
        const char* local_image = (boot_task->local_image_override) ?
                boot_task->local_image_override : boot_task->local_image;
 
+       process = process_create(boot_task);
+       if (!process) {
+               pb_log("%s: failed to create process\n", __func__);
+               return -1;
+       }
+
+       process->path = pb_system_apps.kexec;
+       process->argv = argv;
+       process->keep_stdout = true;
+       process->add_stderr = true;
+
        p = argv;
        *p++ = pb_system_apps.kexec;    /* 1 */
        *p++ = "-l";                    /* 2 */
        p = argv;
        *p++ = pb_system_apps.kexec;    /* 1 */
        *p++ = "-l";                    /* 2 */
@@ -96,10 +128,19 @@ static int kexec_load(struct boot_task *boot_task)
        *p++ = local_image;             /* 6 */
        *p++ = NULL;                    /* 7 */
 
        *p++ = local_image;             /* 6 */
        *p++ = NULL;                    /* 7 */
 
-       result = process_run_simple_argv(boot_task, argv);
+       result = process_run_sync(process);
+       if (result) {
+               pb_log("%s: failed to run process\n", __func__);
+               goto abort_kexec;
+       }
+
+       result = process->exit_status;
 
 
-       if (result)
+       if (result) {
                pb_log("%s: failed: (%d)\n", __func__, result);
                pb_log("%s: failed: (%d)\n", __func__, result);
+               update_status(boot_task->status_fn, boot_task->status_arg,
+                               STATUS_ERROR, "%s", process->stdout_buf);
+       }
 
 abort_kexec:
        gpg_validate_boot_files_cleanup(boot_task);
 
 abort_kexec:
        gpg_validate_boot_files_cleanup(boot_task);
@@ -143,25 +184,6 @@ static int kexec_reboot(struct boot_task *task)
        return result;
 }
 
        return result;
 }
 
-static void __attribute__((format(__printf__, 4, 5))) update_status(
-               boot_status_fn fn, void *arg, int type, char *fmt, ...)
-{
-       struct status status;
-       va_list ap;
-
-       va_start(ap, fmt);
-       status.message = talloc_vasprintf(NULL, fmt, ap);
-       va_end(ap);
-
-       status.type = type;
-
-       pb_debug("boot status: [%d] %s\n", type, status.message);
-
-       fn(arg, &status);
-
-       talloc_free(status.message);
-}
-
 static void boot_hook_update_param(void *ctx, struct boot_task *task,
                const char *name, const char *value)
 {
 static void boot_hook_update_param(void *ctx, struct boot_task *task,
                const char *name, const char *value)
 {
@@ -452,6 +474,7 @@ static void boot_process(struct load_url_result *result, void *data)
                        _("Performing kexec load"));
 
        rc = kexec_load(task);
                        _("Performing kexec load"));
 
        rc = kexec_load(task);
+       pb_log("%s: kexec_load returned %d\n", __func__, rc);
        if (rc == KEXEC_LOAD_DECRYPTION_FALURE) {
                update_status(task->status_fn, task->status_arg,
                                STATUS_ERROR, _("Decryption failed"));
        if (rc == KEXEC_LOAD_DECRYPTION_FALURE) {
                update_status(task->status_fn, task->status_arg,
                                STATUS_ERROR, _("Decryption failed"));
@@ -466,10 +489,6 @@ static void boot_process(struct load_url_result *result, void *data)
                                STATUS_ERROR,
                                _("Invalid signature configuration"));
        }
                                STATUS_ERROR,
                                _("Invalid signature configuration"));
        }
-       else if (rc) {
-               update_status(task->status_fn, task->status_arg,
-                               STATUS_ERROR, _("kexec load failed"));
-       }
 
 no_sig_load:
        cleanup_load(task->image_signature);
 
 no_sig_load:
        cleanup_load(task->image_signature);