summaryrefslogtreecommitdiffstats
path: root/discover/boot.c
diff options
context:
space:
mode:
Diffstat (limited to 'discover/boot.c')
-rw-r--r--discover/boot.c147
1 files changed, 100 insertions, 47 deletions
diff --git a/discover/boot.c b/discover/boot.c
index 91fc46d..00507b7 100644
--- a/discover/boot.c
+++ b/discover/boot.c
@@ -25,6 +25,7 @@
#include "paths.h"
#include "resource.h"
#include "platform.h"
+#include "sysinfo.h"
#include <security/security.h>
@@ -60,30 +61,50 @@ static void __attribute__((format(__printf__, 4, 5))) update_status(
*/
static int kexec_load(struct boot_task *boot_task)
{
+ const char *load_args[] = {"-l", "-s"};
+ const struct system_info *sysinfo;
struct process *process;
char *s_initrd = NULL;
char *s_args = NULL;
const char *argv[8];
char *s_dtb = NULL;
const char **p;
+ char *err_buf;
int result;
+ size_t i;
+ sysinfo = system_info_get();
boot_task->local_initrd_override = NULL;
boot_task->local_dtb_override = NULL;
boot_task->local_image_override = NULL;
- if ((result = validate_boot_files(boot_task))) {
- if (result == KEXEC_LOAD_DECRYPTION_FALURE) {
- pb_log("%s: Aborting kexec due to"
- " decryption failure\n", __func__);
- }
- if (result == KEXEC_LOAD_SIGNATURE_FAILURE) {
- pb_log("%s: Aborting kexec due to signature"
- " verification failure\n", __func__);
+ result = validate_boot_files(boot_task);
+ if (result) {
+ const char *msg;
+
+ switch (result) {
+ case KEXEC_LOAD_DECRYPTION_FALURE:
+ msg = _("decryption failed");
+ break;
+ case KEXEC_LOAD_SIGNATURE_FAILURE:
+ msg = _("signature verification failed");
+ break;
+ case KEXEC_LOAD_SIG_SETUP_INVALID:
+ msg = _("invalid signature configuration");
+ break;
+ default:
+ msg = _("unknown verification failure");
}
- goto abort_kexec;
+ update_status(boot_task->status_fn, boot_task->status_arg,
+ STATUS_ERROR,
+ _("Boot verification failure: %s"), msg);
+ pb_log_fn("Aborting kexec due to verification failure: %s",
+ msg);
+
+ validate_boot_files_cleanup(boot_task);
+ return result;
}
const char* local_initrd = (boot_task->local_initrd_override) ?
@@ -93,20 +114,10 @@ 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;
- process = process_create(boot_task);
- if (!process) {
- pb_log_fn("failed to create process\n");
- return -1;
- }
-
- process->path = pb_system_apps.kexec;
- process->argv = argv;
- process->keep_stdout = true;
- process->add_stderr = true;
-
+ /* set up process arguments */
p = argv;
*p++ = pb_system_apps.kexec; /* 1 */
- *p++ = "-l"; /* 2 */
+ *p++ = NULL; /* 2; modified below */
if (pb_log_get_debug()) {
*p++ = "--debug"; /* 3 */
@@ -134,21 +145,57 @@ static int kexec_load(struct boot_task *boot_task)
*p++ = local_image; /* 7 */
*p++ = NULL; /* 8 */
- result = process_run_sync(process);
- if (result) {
- pb_log_fn("failed to run process\n");
- goto abort_kexec;
- }
+ err_buf = NULL;
- result = process->exit_status;
+ for (i = 0; i < ARRAY_SIZE(load_args); i++) {
+ /* our first argument is the action: -s or -l */
+ argv[1] = load_args[i];
- if (result) {
- pb_log_fn("failed: (%d)\n", result);
- update_status(boot_task->status_fn, boot_task->status_arg,
- STATUS_ERROR, "%s", process->stdout_buf);
+ /* if we're enforcing, we know a -l load will fail; skip */
+ if (sysinfo->stb_os_enforcing && argv[1][1] == 'l')
+ continue;
+
+ process = process_create(boot_task);
+ if (!process) {
+ result = -1;
+ pb_log_fn("failed to create process\n");
+ continue;
+ }
+
+ process->path = pb_system_apps.kexec;
+ process->argv = argv;
+ process->keep_stdout = true;
+ process->add_stderr = true;
+
+ result = process_run_sync(process);
+ if (result) {
+ pb_log_fn("failed to run process\n");
+ continue;
+ }
+
+ result = 0;
+
+ if (process_exit_ok(process))
+ break;
+
+ result = -1;
+
+ if (process->stdout_len)
+ err_buf = talloc_strndup(boot_task, process->stdout_buf,
+ process->stdout_len);
+
+ pb_log_fn("kexec load (%s) failed (rc %d): %s\n", argv[1],
+ WEXITSTATUS(process->exit_status),
+ err_buf ?: "");
+
+ process_release(process);
}
-abort_kexec:
+ if (result)
+ update_status(boot_task->status_fn, boot_task->status_arg,
+ STATUS_ERROR, _("kexec load failed: %s"),
+ err_buf ?: "(no output)");
+
validate_boot_files_cleanup(boot_task);
return result;
@@ -401,6 +448,24 @@ static void cleanup_cancellations(struct boot_task *task,
talloc_free(task);
}
+static bool preboot_check(struct boot_task *task)
+{
+ const char *local_image = (task->local_image_override) ?
+ task->local_image_override : task->local_image;
+
+ char *preboot_check_err_msg = NULL;
+ bool preboot_check_ret = platform_preboot_check(local_image,
+ &preboot_check_err_msg);
+
+ if (preboot_check_err_msg) {
+ update_status(task->status_fn, task->status_arg,
+ STATUS_ERROR, "%s", preboot_check_err_msg);
+ talloc_free(preboot_check_err_msg);
+ }
+
+ return preboot_check_ret;
+}
+
static void boot_process(struct load_url_result *result, void *data)
{
struct boot_task *task = data;
@@ -424,25 +489,13 @@ static void boot_process(struct load_url_result *result, void *data)
run_boot_hooks(task);
+ if (!preboot_check(task))
+ return;
+
update_status(task->status_fn, task->status_arg, STATUS_INFO,
_("Performing kexec load"));
rc = kexec_load(task);
- pb_log_fn("kexec_load returned %d\n", rc);
- if (rc == KEXEC_LOAD_DECRYPTION_FALURE) {
- update_status(task->status_fn, task->status_arg,
- STATUS_ERROR, _("Decryption failed"));
- }
- else if (rc == KEXEC_LOAD_SIGNATURE_FAILURE) {
- update_status(task->status_fn, task->status_arg,
- STATUS_ERROR,
- _("Signature verification failed"));
- }
- else if (rc == KEXEC_LOAD_SIG_SETUP_INVALID) {
- update_status(task->status_fn, task->status_arg,
- STATUS_ERROR,
- _("Invalid signature configuration"));
- }
no_load:
list_for_each_entry(&task->resources, resource, list)
OpenPOWER on IntegriCloud