summaryrefslogtreecommitdiffstats
path: root/discover
diff options
context:
space:
mode:
Diffstat (limited to 'discover')
-rw-r--r--discover/Makefile.am7
-rw-r--r--discover/boot.c147
-rw-r--r--discover/device-handler.c2
-rw-r--r--discover/discover-server.c15
-rw-r--r--discover/elf.c86
-rw-r--r--discover/elf.h29
-rw-r--r--discover/event.c1
-rw-r--r--discover/grub2/blscfg.c19
-rw-r--r--discover/grub2/builtins.c208
-rw-r--r--discover/grub2/env.c2
-rw-r--r--discover/grub2/grub2-parser.y17
-rw-r--r--discover/grub2/grub2.c110
-rw-r--r--discover/grub2/grub2.h32
-rw-r--r--discover/grub2/script.c29
-rw-r--r--discover/ipmi.c1
-rw-r--r--discover/ipmi.h23
-rw-r--r--discover/paths.c3
-rw-r--r--discover/platform-powerpc.c187
-rw-r--r--discover/platform.c15
-rw-r--r--discover/platform.h5
-rw-r--r--discover/pxe-parser.c7
-rw-r--r--discover/user-event.c19
-rw-r--r--discover/yaboot-parser.c4
23 files changed, 775 insertions, 193 deletions
diff --git a/discover/Makefile.am b/discover/Makefile.am
index bfe33fa..2339203 100644
--- a/discover/Makefile.am
+++ b/discover/Makefile.am
@@ -58,7 +58,8 @@ discover_pb_discover_LDADD = \
discover/native/native-parser.ro \
discover/platform.ro \
$(core_lib) \
- $(UDEV_LIBS)
+ $(UDEV_LIBS) \
+ $(ELF_LIBS)
discover_pb_discover_LDFLAGS = \
$(AM_LDFLAGS) \
@@ -79,7 +80,9 @@ discover_platform_ro_SOURCES = \
discover/ipmi.h \
discover/dt.c \
discover/dt.h \
- discover/hostboot.h
+ discover/hostboot.h \
+ discover/elf.c \
+ discover/elf.h
if PLATFORM_ARM64
discover_platform_ro_SOURCES += discover/platform-arm64.c
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)
diff --git a/discover/device-handler.c b/discover/device-handler.c
index d41bb4b..d85f1af 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -1209,7 +1209,7 @@ void device_handler_add_ramdisk(struct device_handler *handler,
}
handler->ramdisks[i] = dev;
- i = handler->n_ramdisks++;
+ handler->n_ramdisks++;
}
struct ramdisk_device *device_handler_get_ramdisk(
diff --git a/discover/discover-server.c b/discover/discover-server.c
index 1a332cb..e29ce27 100644
--- a/discover/discover-server.c
+++ b/discover/discover-server.c
@@ -298,7 +298,7 @@ static int discover_server_handle_auth_message(struct client *client,
{
struct status *status;
char *hash;
- int rc;
+ int rc = 0;
status = talloc_zero(client, struct status);
@@ -403,7 +403,7 @@ static int discover_server_process_message(void *arg)
struct client *client = arg;
struct config *config;
char *url;
- int rc;
+ int rc = 0;
message = pb_protocol_read_message(client, client->fd);
@@ -460,7 +460,7 @@ static int discover_server_process_message(void *arg)
talloc_free(status);
}
}
- return 0;
+ return rc;
}
switch (message->action) {
@@ -537,7 +537,7 @@ static int discover_server_process_message(void *arg)
break;
}
- rc = discover_server_handle_auth_message(client, auth_msg);
+ discover_server_handle_auth_message(client, auth_msg);
talloc_free(auth_msg);
break;
default:
@@ -791,8 +791,11 @@ struct discover_server *discover_server_init(struct waitset *waitset)
/* Allow all clients to communicate on this socket */
group = getgrnam("petitgroup");
if (group) {
- chown(PB_SOCKET_PATH, 0, group->gr_gid);
- chmod(PB_SOCKET_PATH, 0660);
+ if (chown(PB_SOCKET_PATH, 0, group->gr_gid))
+ pb_log_fn("Error setting socket ownership: %m\n");
+ errno = 0;
+ if (chmod(PB_SOCKET_PATH, 0660))
+ pb_log_fn("Error setting socket permissions: %m\n");
}
if (listen(server->socket, 8)) {
diff --git a/discover/elf.c b/discover/elf.c
new file mode 100644
index 0000000..8c2711e
--- /dev/null
+++ b/discover/elf.c
@@ -0,0 +1,86 @@
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <log/log.h>
+#include "elf.h"
+
+Elf *elf_open_image(const char *image)
+{
+ int fd;
+ Elf *elf = NULL;
+ int err;
+
+ if (!image) {
+ pb_log_fn("kernel image path is null\n");
+ return NULL;
+ }
+
+ if ((elf_version(EV_CURRENT) == EV_NONE) ||
+ ((fd = open(image, O_RDONLY, 0)) == -1) ||
+ (!(elf = elf_begin(fd, ELF_C_READ, NULL)))) {
+ err = elf_errno();
+ if (err)
+ pb_log_fn("failed to read %s elf: %s\n",
+ image, elf_errmsg(err));
+ }
+
+ return elf;
+}
+
+static bool elf_getnote_offset(Elf_Data * const edata,
+ const char *namespace,
+ const uint32_t type, GElf_Nhdr *nhdr,
+ size_t *n_off, size_t *d_off)
+{
+ size_t off = 0;
+ size_t next;
+
+ /* Iterate through notes */
+ while ((next = gelf_getnote(edata, off, nhdr, n_off, d_off)) > 0) {
+ char *note_ns = (char *) edata->d_buf + (*n_off);
+ if ((strcmp(note_ns, namespace) == 0) && (nhdr->n_type == type))
+ return true;
+
+ off = next;
+ }
+ return false;
+}
+
+void *elf_getnote_desc(Elf *elf,
+ const char *namespace,
+ uint32_t type)
+{
+ Elf_Scn *scn = NULL;
+ Elf_Data *edata = NULL;
+ GElf_Shdr shdr;
+ GElf_Nhdr nhdr;
+
+ size_t n_off;
+ size_t d_off;
+ void *desc = NULL;
+
+ if (!elf || !namespace)
+ return NULL;
+
+ /* Iterate through sections */
+ while ((scn = elf_nextscn(elf, scn))) {
+ gelf_getshdr(scn, &shdr);
+
+ /* ELF might have more than one SHT_NOTE section but
+ only one has the 'namespace' note */
+ if (shdr.sh_type == SHT_NOTE) {
+ edata = elf_getdata(scn, NULL);
+ if (elf_getnote_offset(edata, namespace, type,
+ &nhdr, &n_off, &d_off)) {
+ desc = calloc(nhdr.n_descsz, sizeof(char));
+ memcpy(desc, edata->d_buf + d_off,
+ nhdr.n_descsz);
+ break;
+ }
+ }
+ }
+
+ return desc;
+}
+
diff --git a/discover/elf.h b/discover/elf.h
new file mode 100644
index 0000000..742b791
--- /dev/null
+++ b/discover/elf.h
@@ -0,0 +1,29 @@
+#ifndef _PB_ELF_H
+#define _PB_ELF_H
+
+#include <elfutils/libdw.h>
+#include <libelf.h>
+
+/*
+ * The PowerPC namespace in an ELF Note of the kernel binary is used to store
+ * capabilities and information which can be used by a bootloader or userland
+ *
+ * docs: Documentation/powerpc/elfnote.rst
+ */
+#define POWERPC_ELFNOTE_NAMESPACE "PowerPC"
+
+/*
+ * The capabilities supported/required by the kernel
+ * This type uses a bitmap as "desc" field.
+ */
+#define PPC_ELFNOTE_CAPABILITIES 0x1
+
+/* bitmap fields: */
+#define PPCCAP_ULTRAVISOR_BIT 0x1
+
+Elf *elf_open_image(const char *image);
+void *elf_getnote_desc(Elf *elf,
+ const char *namespace,
+ uint32_t type);
+
+#endif /* _PB_ELF_H */
diff --git a/discover/event.c b/discover/event.c
index ec5537a..4c46d41 100644
--- a/discover/event.c
+++ b/discover/event.c
@@ -101,7 +101,6 @@ static void event_parse_params(struct event *event, const char *buf, int len)
sep = memchr(buf, '=', param_len);
if (!sep) {
name_len = param_len;
- value_len = 0;
param->value = "";
} else {
name_len = sep - buf;
diff --git a/discover/grub2/blscfg.c b/discover/grub2/blscfg.c
index d4754aa..d08f8f0 100644
--- a/discover/grub2/blscfg.c
+++ b/discover/grub2/blscfg.c
@@ -166,7 +166,6 @@ static void bls_finish(struct conf_context *conf)
struct discover_context *dc = conf->dc;
struct discover_boot_option *opt = state->opt;
struct boot_option *option = opt->option;
- const char *root;
char *filename;
if (!state->image) {
@@ -192,23 +191,21 @@ static void bls_finish(struct conf_context *conf)
else
option->name = talloc_strdup(option, state->image);
- root = script_env_get(state->script, "root");
-
- opt->boot_image = create_grub2_resource(opt, conf->dc->device,
- root, state->image);
+ opt->boot_image = create_grub2_resource(state->script, opt,
+ state->image);
if (state->initrd)
- opt->initrd = create_grub2_resource(opt, conf->dc->device,
- root, state->initrd);
+ opt->initrd = create_grub2_resource(state->script, opt,
+ state->initrd);
if (state->dtb)
- opt->dtb = create_grub2_resource(opt, conf->dc->device,
- root, state->dtb);
+ opt->dtb = create_grub2_resource(state->script, opt,
+ state->dtb);
char* args_sigfile_default = talloc_asprintf(opt,
"%s.cmdline.sig", state->image);
- opt->args_sig_file = create_grub2_resource(opt, conf->dc->device,
- root, args_sigfile_default);
+ opt->args_sig_file = create_grub2_resource(state->script, opt,
+ args_sigfile_default);
talloc_free(args_sigfile_default);
option->is_default = option_is_default(state, option);
diff --git a/discover/grub2/builtins.c b/discover/grub2/builtins.c
index 7e92299..ab1407a 100644
--- a/discover/grub2/builtins.c
+++ b/discover/grub2/builtins.c
@@ -1,4 +1,7 @@
+#define _GNU_SOURCE
+
+#include <getopt.h>
#include <stdio.h>
#include <string.h>
@@ -43,7 +46,6 @@ static int builtin_linux(struct grub2_script *script,
int argc, char *argv[])
{
struct discover_boot_option *opt = script->opt;
- const char *root;
int i;
if (!opt) {
@@ -58,10 +60,7 @@ static int builtin_linux(struct grub2_script *script,
return -1;
}
- root = script_env_get(script, "root");
-
- opt->boot_image = create_grub2_resource(opt, script->ctx->device,
- root, argv[1]);
+ opt->boot_image = create_grub2_resource(script, opt, argv[1]);
opt->option->boot_args = NULL;
if (argc > 2)
@@ -74,8 +73,8 @@ static int builtin_linux(struct grub2_script *script,
char* args_sigfile_default = talloc_asprintf(opt,
"%s.cmdline.sig", argv[1]);
- opt->args_sig_file = create_grub2_resource(opt, script->ctx->device,
- root, args_sigfile_default);
+ opt->args_sig_file = create_grub2_resource(script, opt,
+ args_sigfile_default);
talloc_free(args_sigfile_default);
return 0;
}
@@ -85,7 +84,6 @@ static int builtin_initrd(struct grub2_script *script,
int argc, char *argv[])
{
struct discover_boot_option *opt = script->opt;
- const char *root;
if (!opt) {
pb_log("grub2 syntax error: 'initrd' statement outside "
@@ -99,35 +97,128 @@ static int builtin_initrd(struct grub2_script *script,
return -1;
}
- root = script_env_get(script, "root");
- opt->initrd = create_grub2_resource(opt, script->ctx->device,
- root, argv[1]);
+ opt->initrd = create_grub2_resource(script, opt, argv[1]);
return 0;
}
+static const struct option search_options[] = {
+ {
+ .name = "set",
+ .has_arg = required_argument,
+ .val = 's',
+ },
+ {
+ .name = "file",
+ .has_arg = no_argument,
+ .val = 'f',
+ },
+ {
+ .name = "label",
+ .has_arg = no_argument,
+ .val = 'l',
+ },
+ {
+ .name = "fs-uuid",
+ .has_arg = no_argument,
+ .val = 'u',
+ },
+ { 0 },
+};
+
static int builtin_search(struct grub2_script *script,
void *data __attribute__((unused)),
int argc, char *argv[])
{
- const char *env_var, *spec;
- int i;
-
- env_var = NULL;
+ const char *env_var, *spec, *res;
+ struct discover_device *dev;
+ enum {
+ LOOKUP_UUID = 'u',
+ LOOKUP_LABEL = 'l',
+ LOOKUP_FILE = 'f',
+ } lookup_type;
+
+ env_var = "root";
+ optind = 0;
+
+ /* Default to UUID, for backwards compat with earlier petitboot
+ * versions. This argument is non-optional in GRUB. */
+ lookup_type = LOOKUP_UUID;
+
+ for (;;) {
+ int c = getopt_long(argc, argv, ":flu", search_options, NULL);
+ if (c == -1)
+ break;
- for (i = 1; i < argc - 1; i++) {
- if (!strncmp(argv[i], "--set=", strlen("--set="))) {
- env_var = argv[i] + strlen("--set=");
+ switch (c) {
+ case 's':
+ env_var = optarg;
+ break;
+ case LOOKUP_UUID:
+ case LOOKUP_LABEL:
+ case LOOKUP_FILE:
+ lookup_type = c;
+ break;
+ case '?':
+ case ':':
break;
}
}
- if (!env_var)
+ if (!strlen(env_var))
return 0;
- spec = argv[argc - 1];
+ if (optind >= argc)
+ return -1;
+
+ spec = argv[optind];
+ res = NULL;
+
+ switch (lookup_type) {
+ case LOOKUP_UUID:
+ dev = device_lookup_by_uuid(script->ctx->handler,
+ spec);
+ res = dev ? dev->device->id : spec;
+ break;
+ case LOOKUP_LABEL:
+ dev = device_lookup_by_label(script->ctx->handler,
+ spec);
+ if (dev)
+ res = dev->device->id;
+ break;
+ case LOOKUP_FILE:
+ /* not yet implemented */
+ break;
+ }
+
+ if (res)
+ script_env_set(script, env_var, res);
+
+ return 0;
+}
+
+static int parse_to_device_path(struct grub2_script *script,
+ const char *desc, struct discover_device **devp,
+ char **pathp)
+{
+ struct discover_device *dev;
+ struct grub2_file *file;
+
+ file = grub2_parse_file(script, desc);
+ if (!file)
+ return -1;
+
+ dev = script->ctx->device;
+ if (file->dev)
+ dev = grub2_lookup_device(script->ctx->handler, file->dev);
+
+ if (!dev)
+ return -1;
+
+ *devp = dev;
+ *pathp = talloc_strdup(script, file->path);
- script_env_set(script, env_var, spec);
+ talloc_free(file);
return 0;
}
@@ -139,12 +230,17 @@ static int builtin_search(struct grub2_script *script,
static bool builtin_test_op_file(struct grub2_script *script, char op,
const char *file)
{
+ struct discover_device *dev;
+ struct stat statbuf;
bool result;
+ char *path;
int rc;
- struct stat statbuf;
- rc = parser_stat_path(script->ctx, script->ctx->device,
- file, &statbuf);
+ rc = parse_to_device_path(script, file, &dev, &path);
+ if (rc)
+ return false;
+
+ rc = parser_stat_path(script->ctx, dev, path, &statbuf);
if (rc)
return false;
@@ -172,16 +268,21 @@ static bool builtin_test_op_file(struct grub2_script *script, char op,
static bool builtin_test_op_dir(struct grub2_script *script, char op,
const char *dir)
{
- int rc;
+ struct discover_device *dev;
struct stat statbuf;
+ char *path;
+ int rc;
if (op != 'd')
return false;
- rc = parser_stat_path(script->ctx, script->ctx->device, dir, &statbuf);
- if (rc) {
+ rc = parse_to_device_path(script, dir, &dev, &path);
+ if (rc)
+ return false;
+
+ rc = parser_stat_path(script->ctx, dev, path, &statbuf);
+ if (rc)
return false;
- }
return S_ISDIR(statbuf.st_mode);
}
@@ -300,6 +401,51 @@ static int builtin_test(struct grub2_script *script,
return rc ? 0 : 1;
}
+static int builtin_source(struct grub2_script *script,
+ void *data __attribute__((unused)),
+ int argc, char *argv[])
+{
+ struct grub2_statements *statements;
+ struct discover_device *dev;
+ const char *filename;
+ char *path, *buf;
+ int rc, len;
+
+ if (argc != 2)
+ return false;
+
+ /* limit script recursion */
+ if (script->include_depth >= 10)
+ return false;
+
+ rc = parse_to_device_path(script, argv[1], &dev, &path);
+ if (rc)
+ return false;
+
+ rc = parser_request_file(script->ctx, dev, path, &buf, &len);
+ if (rc)
+ return false;
+
+ /* save current script state */
+ statements = script->statements;
+ filename = script->filename;
+ script->include_depth++;
+
+ rc = grub2_parser_parse(script->parser, argv[1], buf, len);
+
+ if (!rc)
+ statements_execute(script, script->statements);
+
+ talloc_free(script->statements);
+
+ /* restore state */
+ script->statements = statements;
+ script->filename = filename;
+ script->include_depth--;
+
+ return !rc;
+}
+
static int builtin_true(struct grub2_script *script __attribute__((unused)),
void *data __attribute__((unused)),
int argc __attribute__((unused)),
@@ -390,7 +536,11 @@ static struct {
{
.name = "blscfg",
.fn = builtin_blscfg,
- }
+ },
+ {
+ .name = "source",
+ .fn = builtin_source,
+ },
};
static const char *nops[] = {
diff --git a/discover/grub2/env.c b/discover/grub2/env.c
index 7eda095..74d5729 100644
--- a/discover/grub2/env.c
+++ b/discover/grub2/env.c
@@ -86,6 +86,8 @@ int builtin_load_env(struct grub2_script *script,
if (!rc) {
rc = parse_buf_to_env(script, buf, len);
+ if (rc)
+ pb_debug_fn("Failed to set env\n");
talloc_free(buf);
}
diff --git a/discover/grub2/grub2-parser.y b/discover/grub2/grub2-parser.y
index 527a61c..f99bbfd 100644
--- a/discover/grub2/grub2-parser.y
+++ b/discover/grub2/grub2-parser.y
@@ -331,14 +331,15 @@ struct grub2_parser *grub2_parser_create(struct discover_context *ctx)
return parser;
}
-void grub2_parser_parse(struct grub2_parser *parser, const char *filename,
+/* performs a parse on buf, setting parser->script->statements */
+int grub2_parser_parse(struct grub2_parser *parser, const char *filename,
char *buf, int len)
{
YY_BUFFER_STATE bufstate;
int rc;
if (!len)
- return;
+ return -1;
parser->script->filename = filename;
@@ -349,6 +350,18 @@ void grub2_parser_parse(struct grub2_parser *parser, const char *filename,
yy_delete_buffer(bufstate, parser->scanner);
+ parser->inter_word = false;
+
+ return rc;
+}
+
+void grub2_parser_parse_and_execute(struct grub2_parser *parser,
+ const char *filename, char *buf, int len)
+{
+ int rc;
+
+ rc = grub2_parser_parse(parser, filename, buf, len);
+
if (!rc)
script_execute(parser->script);
}
diff --git a/discover/grub2/grub2.c b/discover/grub2/grub2.c
index f62ccdd..b176ce2 100644
--- a/discover/grub2/grub2.c
+++ b/discover/grub2/grub2.c
@@ -33,18 +33,35 @@ static const char *const grub2_conf_files[] = {
NULL
};
-struct grub2_resource_info {
- char *root;
- char *path;
-};
+struct discover_device *grub2_lookup_device(struct device_handler *handler,
+ const char *desc)
+{
+ struct discover_device *dev;
+
+ if (!desc || !*desc)
+ return NULL;
+
+ dev = device_lookup_by_id(handler, desc);
+ if (dev)
+ return dev;
+
+ /* for now, only lookup by UUID */
+ dev = device_lookup_by_uuid(handler, desc);
+ if (dev)
+ return dev;
+
+ return NULL;
+}
/* we use slightly different resources for grub2 */
-struct resource *create_grub2_resource(struct discover_boot_option *opt,
- struct discover_device *orig_device,
- const char *root, const char *path)
+struct resource *create_grub2_resource(struct grub2_script *script,
+ struct discover_boot_option *opt,
+ const char *path)
{
- struct grub2_resource_info *info;
+ struct discover_device *dev;
+ struct grub2_file *file;
struct resource *res;
+ const char *root;
if (strstr(path, "://")) {
struct pb_url *url = pb_url_parse(opt, path);
@@ -52,19 +69,29 @@ struct resource *create_grub2_resource(struct discover_boot_option *opt,
return create_url_resource(opt, url);
}
+ file = grub2_parse_file(script, path);
+ if (!file)
+ return NULL;
+
res = talloc(opt, struct resource);
+ root = script_env_get(script, "root");
- if (root) {
- info = talloc(res, struct grub2_resource_info);
- talloc_reference(info, root);
- info->root = talloc_strdup(info, root);
- info->path = talloc_strdup(info, path);
+ if (!file->dev && root && strlen(root))
+ file->dev = talloc_strdup(file, root);
- res->resolved = false;
- res->info = info;
+ /* if we don't have a device specified, or the lookup succeeds now,
+ * then we can resolve the resource right away */
+ if (file->dev)
+ dev = grub2_lookup_device(script->ctx->handler, file->dev);
+ else
+ dev = script->ctx->device;
- } else
- resolve_resource_against_device(res, orig_device, path);
+ if (dev) {
+ resolve_resource_against_device(res, dev, file->path);
+ } else {
+ res->resolved = false;
+ res->info = talloc_steal(opt, file);
+ }
return res;
}
@@ -72,22 +99,59 @@ struct resource *create_grub2_resource(struct discover_boot_option *opt,
bool resolve_grub2_resource(struct device_handler *handler,
struct resource *res)
{
- struct grub2_resource_info *info = res->info;
+ struct grub2_file *file = res->info;
struct discover_device *dev;
assert(!res->resolved);
- dev = device_lookup_by_uuid(handler, info->root);
-
+ dev = grub2_lookup_device(handler, file->dev);
if (!dev)
return false;
- resolve_resource_against_device(res, dev, info->path);
- talloc_free(info);
+ resolve_resource_against_device(res, dev, file->path);
+ talloc_free(file);
return true;
}
+struct grub2_file *grub2_parse_file(struct grub2_script *script,
+ const char *str)
+{
+ struct grub2_file *file;
+ size_t dev_len;
+ char *pos;
+
+ if (!str)
+ return NULL;
+
+ file = talloc_zero(script, struct grub2_file);
+
+ if (*str != '(') {
+ /* just a path - no device, return path as-is */
+ file->path = talloc_strdup(file, str);
+
+ } else {
+ /* device plus path - split into components */
+
+ pos = strchr(str, ')');
+
+ /* no closing bracket, or zero-length path? */
+ if (!pos || *(pos+1) == '\0') {
+ talloc_free(file);
+ return NULL;
+ }
+
+ file->path = talloc_strdup(file, pos + 1);
+
+ dev_len = pos - str - 1;
+ if (dev_len)
+ file->dev = talloc_strndup(file, str + 1, dev_len);
+ }
+
+ return file;
+}
+
+
static int grub2_parse(struct discover_context *dc)
{
const char * const *filename;
@@ -105,7 +169,7 @@ static int grub2_parse(struct discover_context *dc)
continue;
parser = grub2_parser_create(dc);
- grub2_parser_parse(parser, *filename, buf, len);
+ grub2_parser_parse_and_execute(parser, *filename, buf, len);
device_handler_status_dev_info(dc->handler, dc->device,
_("Parsed GRUB configuration from %s"),
*filename);
diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h
index 68176fb..75f6aa0 100644
--- a/discover/grub2/grub2.h
+++ b/discover/grub2/grub2.h
@@ -91,6 +91,7 @@ struct grub2_statement_for {
};
struct grub2_script {
+ struct grub2_parser *parser;
struct grub2_statements *statements;
struct list environment;
struct list symtab;
@@ -99,6 +100,7 @@ struct grub2_script {
const char *filename;
unsigned int n_options;
struct list options;
+ int include_depth;
};
struct grub2_parser {
@@ -107,6 +109,14 @@ struct grub2_parser {
bool inter_word;
};
+/* References to files in grub2 consist of an optional device and a path
+ * (specified here by UUID). If the dev is unspecified, we fall back to a
+ * default - usually the 'root' environment variable. */
+struct grub2_file {
+ char *dev;
+ char *path;
+};
+
/* type for builtin functions */
typedef int (*grub2_function)(struct grub2_script *script, void *data,
int argc, char *argv[]);
@@ -156,6 +166,9 @@ void word_append(struct grub2_word *w1, struct grub2_word *w2);
/* script interface */
void script_execute(struct grub2_script *script);
+int statements_execute(struct grub2_script *script,
+ struct grub2_statements *stmts);
+
int statement_simple_execute(struct grub2_script *script,
struct grub2_statement *statement);
int statement_block_execute(struct grub2_script *script,
@@ -183,16 +196,25 @@ void script_register_function(struct grub2_script *script,
void register_builtins(struct grub2_script *script);
/* resources */
-struct resource *create_grub2_resource(struct discover_boot_option *opt,
- struct discover_device *orig_device,
- const char *root, const char *path);
+struct resource *create_grub2_resource(struct grub2_script *script,
+ struct discover_boot_option *opt, const char *path);
bool resolve_grub2_resource(struct device_handler *handler,
struct resource *res);
+/* grub-style device+path parsing */
+struct grub2_file *grub2_parse_file(struct grub2_script *script,
+ const char *str);
+struct discover_device *grub2_lookup_device(struct device_handler *handler,
+ const char *desc);
+
+/* internal parse api */
+int grub2_parser_parse(struct grub2_parser *parser, const char *filename,
+ char *buf, int len);
+
/* external parser api */
struct grub2_parser *grub2_parser_create(struct discover_context *ctx);
-void grub2_parser_parse(struct grub2_parser *parser, const char *filename,
- char *buf, int len);
+void grub2_parser_parse_and_execute(struct grub2_parser *parser,
+ const char *filename, char *buf, int len);
#endif /* GRUB2_H */
diff --git a/discover/grub2/script.c b/discover/grub2/script.c
index 1a802b9..14931f9 100644
--- a/discover/grub2/script.c
+++ b/discover/grub2/script.c
@@ -117,12 +117,10 @@ static bool option_is_default(struct grub2_script *script,
if (end != var && *end == '\0')
return default_idx == script->n_options;
- /* if we don't have an explicit id for this option, fall back to
- * the name */
- if (!id)
- id = opt->option->name;
+ if (id && !strcmp(id, var))
+ return true;
- return !strcmp(id, var);
+ return !strcmp(opt->option->name, var);
}
static void append_text_to_current_arg(struct grub2_argv *argv,
@@ -227,11 +225,11 @@ static void process_expansions(struct grub2_script *script,
}
/* we may have allocated an extra argv element but not populated it */
- if (!argv->argv[argv->argc - 1])
+ if (argv->argv && !argv->argv[argv->argc - 1])
argv->argc--;
}
-static int statements_execute(struct grub2_script *script,
+int statements_execute(struct grub2_script *script,
struct grub2_statements *stmts)
{
struct grub2_statement *stmt;
@@ -341,9 +339,16 @@ int statement_menuentry_execute(struct grub2_script *script,
* implementation to get --id= working.
*/
for (i = 1; i < st->argv->argc; ++i) {
- if (strncmp("--id=", st->argv->argv[i], 5) == 0) {
- id = st->argv->argv[i] + 5;
- break;
+ if (strncmp("--id", st->argv->argv[i], strlen("--id")) == 0) {
+ if (strlen(st->argv->argv[i]) > strlen("--id=")) {
+ id = st->argv->argv[i] + strlen("--id=");
+ break;
+ }
+
+ if (i + 1 < st->argv->argc) {
+ id = st->argv->argv[i + 1];
+ break;
+ }
}
}
if (st->argv->argc > 0)
@@ -489,6 +494,9 @@ void script_execute(struct grub2_script *script)
{
struct discover_boot_option *opt, *tmp;
+ if (!script)
+ return;
+
init_env(script);
statements_execute(script, script->statements);
@@ -510,6 +518,7 @@ struct grub2_script *create_script(struct grub2_parser *parser,
script = talloc_zero(parser, struct grub2_script);
script->ctx = ctx;
+ script->parser = parser;
list_init(&script->symtab);
list_init(&script->options);
diff --git a/discover/ipmi.c b/discover/ipmi.c
index ae02bb0..66b465e 100644
--- a/discover/ipmi.c
+++ b/discover/ipmi.c
@@ -306,7 +306,6 @@ int parse_ipmi_interface_override(struct config *config, uint8_t *buf,
return -1;
}
ifconf->static_config.gateway = gatewaystr;
- i += ipsize;
}
ifconf->override = true;
diff --git a/discover/ipmi.h b/discover/ipmi.h
index c8ccb46..f8672b0 100644
--- a/discover/ipmi.h
+++ b/discover/ipmi.h
@@ -29,6 +29,29 @@ enum ipmi_sensor_ids {
struct ipmi;
+#define CHASSIS_BOOT_MBOX_IANA_SZ 3
+#define CHASSIS_BOOT_MBOX_DATA_SZ 16
+#define CHASSIS_BOOT_MBOX_BLOCK0_DATA_SZ \
+ (CHASSIS_BOOT_MBOX_DATA_SZ - CHASSIS_BOOT_MBOX_IANA_SZ)
+
+typedef struct __attribute__((packed)) {
+ uint8_t iana[CHASSIS_BOOT_MBOX_IANA_SZ];
+ uint8_t data[CHASSIS_BOOT_MBOX_BLOCK0_DATA_SZ];
+} mbox_block0_t;
+
+typedef union {
+ uint8_t data[CHASSIS_BOOT_MBOX_DATA_SZ];
+ mbox_block0_t b0;
+} mbox_t;
+
+typedef struct __attribute__((packed)) {
+ uint8_t cc;
+ uint8_t param_version;
+ uint8_t param_valid;
+ uint8_t block_selector;
+ mbox_t mbox;
+} ipmi_mbox_response_t;
+
static const int ipmi_timeout = 10000; /* milliseconds. */
bool ipmi_present(void);
diff --git a/discover/paths.c b/discover/paths.c
index 54b843e..16fdd59 100644
--- a/discover/paths.c
+++ b/discover/paths.c
@@ -450,7 +450,8 @@ static void load_local(struct load_task *task)
result->status = LOAD_OK;
}
- task->async_cb(task->result, task->async_data);
+ if (task->async_cb)
+ task->async_cb(task->result, task->async_data);
}
static void load_url_async_start_pending(struct load_task *task, int flags)
diff --git a/discover/platform-powerpc.c b/discover/platform-powerpc.c
index 5d7cc59..c6ab416 100644
--- a/discover/platform-powerpc.c
+++ b/discover/platform-powerpc.c
@@ -21,6 +21,7 @@
#include "platform.h"
#include "ipmi.h"
#include "dt.h"
+#include "elf.h"
static const char *partition = "common";
static const char *sysparams_dir = "/sys/firmware/opal/sysparams/";
@@ -222,6 +223,13 @@ static void params_update_all(struct param_list *pl,
params_update_network_values(pl, "petitboot,network", config);
params_update_bootdev_values(pl, "petitboot,bootdevs", config);
+
+ if (config->preboot_check_enabled == defaults->preboot_check_enabled)
+ val = "";
+ else
+ val = config->preboot_check_enabled ? "true" : "false";
+
+ param_list_set_non_empty(pl, "petitboot,preboot-check", val, true);
}
static void config_set_ipmi_bootdev(struct config *config, enum ipmi_bootdev bootdev,
@@ -437,10 +445,10 @@ static int get_ipmi_bootdev_ipmi(struct platform_powerpc *platform,
}
static int get_ipmi_boot_mailbox_block(struct platform_powerpc *platform,
- char *buf, uint8_t block)
+ mbox_t *mailbox, uint8_t block)
{
size_t blocksize = 16;
- uint8_t resp[3 + 16];
+ ipmi_mbox_response_t ipmi_mbox_resp = { .cc = 0xFF };
uint16_t resp_len;
char *debug_buf;
int rc;
@@ -449,60 +457,71 @@ static int get_ipmi_boot_mailbox_block(struct platform_powerpc *platform,
block, /* set selector */
0x00, /* no block selector */
};
+ size_t ipmi_header_len = sizeof(ipmi_mbox_response_t) - sizeof(mbox_t);
- resp_len = sizeof(resp);
+ resp_len = sizeof(ipmi_mbox_response_t);
rc = ipmi_transaction(platform->ipmi, IPMI_NETFN_CHASSIS,
IPMI_CMD_CHASSIS_GET_SYSTEM_BOOT_OPTIONS,
req, sizeof(req),
- resp, &resp_len,
+ (uint8_t*)&ipmi_mbox_resp, &resp_len,
ipmi_timeout);
if (rc) {
pb_log("platform: error reading IPMI boot options\n");
return -1;
}
- if (resp_len < sizeof(resp)) {
- if (resp_len < 3) {
- pb_log("platform: unexpected length (%d) in "
- "boot options mailbox response\n",
- resp_len);
- return -1;
- }
-
- if (resp_len == 4) {
- pb_debug_fn("block %hu empty\n", block);
- return 0;
- }
+ if (resp_len > sizeof(ipmi_mbox_response_t)) {
+ pb_debug("platform: invalid mailbox response size!\n");
+ return -1;
+ }
- blocksize = sizeof(resp) - 3;
- pb_debug_fn("Mailbox block %hu returns only %zu bytes in block\n",
- block, blocksize);
+ if (resp_len < ipmi_header_len) {
+ pb_log("platform: unexpected length (%d) in "
+ "boot options mailbox response\n",
+ resp_len);
+ return -1;
}
- debug_buf = format_buffer(platform, resp, resp_len);
+ blocksize = resp_len - ipmi_header_len;
+ pb_debug_fn("Mailbox block %hu returns only %zu bytes in block\n",
+ block, blocksize);
+
+ debug_buf = format_buffer(platform, (uint8_t*)&ipmi_mbox_resp, resp_len);
pb_debug_fn("IPMI bootdev mailbox block %hu:\n%s\n", block, debug_buf);
talloc_free(debug_buf);
- if (resp[0] != 0) {
+ if (ipmi_mbox_resp.cc != 0) {
pb_log("platform: non-zero completion code %d from IPMI req\n",
- resp[0]);
+ ipmi_mbox_resp.cc);
return -1;
}
/* check for correct parameter version */
- if ((resp[1] & 0xf) != 0x1) {
+ if ((ipmi_mbox_resp.param_version & 0xf) != 0x1) {
pb_log("platform: unexpected version (0x%x) in "
- "boot mailbox response\n", resp[0]);
+ "boot mailbox response\n", ipmi_mbox_resp.param_version);
return -1;
}
/* check for valid paramters */
- if (resp[2] & 0x80) {
+ if (ipmi_mbox_resp.param_valid & 0x80) {
pb_debug("platform: boot mailbox parameters are invalid/locked\n");
return -1;
}
- memcpy(buf, &resp[3], blocksize);
+ /* check for block number */
+ if (ipmi_mbox_resp.block_selector != block) {
+ pb_debug("platform: returned boot mailbox block doesn't match "
+ "requested\n");
+ return -1;
+ }
+
+ if (!blocksize) {
+ pb_debug_fn("block %hu empty\n", block);
+ return 0;
+ }
+
+ memcpy(mailbox, &ipmi_mbox_resp.mbox, blocksize);
return blocksize;
}
@@ -511,12 +530,10 @@ static int get_ipmi_boot_mailbox(struct platform_powerpc *platform,
char **buf)
{
char *mailbox_buffer, *prefix;
- const size_t blocksize = 16;
- char block_buffer[blocksize];
+ mbox_t mailbox;
size_t mailbox_size;
int content_size;
uint8_t i;
- int rc;
mailbox_buffer = NULL;
mailbox_size = 0;
@@ -527,15 +544,16 @@ static int get_ipmi_boot_mailbox(struct platform_powerpc *platform,
* on higher numbers.
*/
for (i = 0; i < UCHAR_MAX; i++) {
- rc = get_ipmi_boot_mailbox_block(platform, block_buffer, i);
- if (rc < 3 && i == 0) {
+ uint8_t *boot_opt_data;
+ int block_size = get_ipmi_boot_mailbox_block(platform, &mailbox, i);
+ if (block_size < CHASSIS_BOOT_MBOX_IANA_SZ && i == 0) {
/*
* Immediate failure, no blocks read or missing IANA
* number.
*/
return -1;
}
- if (rc < 1) {
+ if (block_size < 1) {
/* Error or no bytes read */
break;
}
@@ -543,28 +561,33 @@ static int get_ipmi_boot_mailbox(struct platform_powerpc *platform,
if (i == 0) {
/*
* The first three bytes of block zero are an IANA
- * Enterprise ID number. Check it matches the IBM
- * number, '2'.
+ * Enterprise ID number
*/
- if (block_buffer[0] != 0x02 ||
- block_buffer[1] != 0x00 ||
- block_buffer[2] != 0x00) {
+ block_size -= CHASSIS_BOOT_MBOX_IANA_SZ;
+ boot_opt_data = &mailbox.b0.data;
+
+ /* Check IANA matches the IBM number, '2' */
+ if (mailbox.b0.iana[0] != 0x02 ||
+ mailbox.b0.iana[1] != 0x00 ||
+ mailbox.b0.iana[2] != 0x00) {
pb_log_fn("IANA number unrecognised: 0x%x:0x%x:0x%x\n",
- block_buffer[0],
- block_buffer[1],
- block_buffer[2]);
+ mailbox.b0.iana[0],
+ mailbox.b0.iana[1],
+ mailbox.b0.iana[2]);
return -1;
}
+ } else {
+ boot_opt_data = &mailbox.data;
}
mailbox_buffer = talloc_realloc(platform, mailbox_buffer,
- char, mailbox_size + rc);
+ char, mailbox_size + block_size);
if (!mailbox_buffer) {
pb_log_fn("Failed to allocate mailbox buffer\n");
return -1;
}
- memcpy(mailbox_buffer + mailbox_size, block_buffer, rc);
- mailbox_size += rc;
+ memcpy(mailbox_buffer + mailbox_size, boot_opt_data, block_size);
+ mailbox_size += block_size;
}
if (i < 5)
@@ -574,10 +597,10 @@ static int get_ipmi_boot_mailbox(struct platform_powerpc *platform,
else
pb_debug_fn("%hu blocks read (%zu bytes)\n", i, mailbox_size);
- if (mailbox_size < 3 + strlen("petitboot,bootdevs="))
+ if (mailbox_size < strlen("petitboot,bootdevs="))
return -1;
- prefix = talloc_strndup(mailbox_buffer, mailbox_buffer + 3,
+ prefix = talloc_strndup(mailbox_buffer, mailbox_buffer,
strlen("petitboot,bootdevs="));
if (!prefix) {
pb_log_fn("Couldn't check prefix\n");
@@ -595,9 +618,9 @@ static int get_ipmi_boot_mailbox(struct platform_powerpc *platform,
}
/* Don't include IANA number in buffer */
- content_size = mailbox_size - 3 - strlen("petitboot,bootdevs=");
+ content_size = mailbox_size - strlen("petitboot,bootdevs=");
*buf = talloc_memdup(platform,
- mailbox_buffer + 3 + strlen("petitboot,bootdevs="),
+ mailbox_buffer + strlen("petitboot,bootdevs="),
content_size + 1);
(*buf)[content_size] = '\0';
@@ -923,6 +946,72 @@ static void pre_boot(struct platform *p, const struct config *config)
platform->set_os_boot_sensor(platform);
}
+static bool preboot_check(struct platform *p,
+ const struct config *config,
+ const char *image,
+ char **err_msg)
+{
+ struct platform_powerpc *platform = p->platform_data;
+ unsigned int *ppc_cap_bitmap = NULL;
+ bool ultravisor_enabled;
+ struct stat statbuf;
+ bool ret = true;
+
+ /* check if ultravisor-system is enabled */
+ ultravisor_enabled = stat("/proc/device-tree/ibm,ultravisor",
+ &statbuf) == 0;
+
+ /* if ultravisor-system is disabled, continue the boot process */
+ if (!ultravisor_enabled)
+ return true;
+
+ ppc_cap_bitmap = elf_getnote_desc(elf_open_image(image),
+ POWERPC_ELFNOTE_NAMESPACE,
+ PPC_ELFNOTE_CAPABILITIES);
+
+ if ((ppc_cap_bitmap) && (*ppc_cap_bitmap & PPCCAP_ULTRAVISOR_BIT)) {
+ pb_debug("kernel capabilities: ultravisor mode found.\n");
+ } else {
+ ret = false;
+ pb_log_fn("kernel capabilities failed:"
+ " IBM Ultravisor mode is required.\n");
+ *err_msg = talloc_strdup(platform, "IBM Ultravisor capability"
+ " not found");
+ }
+ free(ppc_cap_bitmap);
+
+ /* if preboot_check is disabled, continue the boot process */
+ if (!config->preboot_check_enabled)
+ return true;
+
+ return ret;
+}
+
+static void get_sysinfo_stb(struct platform_powerpc *platform,
+ struct system_info *sysinfo)
+{
+ char *filename;
+ unsigned int i;
+ int rc;
+ struct {
+ const char *name;
+ bool *flag;
+ } props[] = {
+ { "secure-enabled", &sysinfo->stb_fw_enforcing },
+ { "trusted-enabled", &sysinfo->stb_fw_measurement },
+ { "os-secureboot-enforcing", &sysinfo->stb_os_enforcing },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(props); i++) {
+ struct stat statbuf;
+ filename = talloc_asprintf(platform, "%sibm,secureboot/%s",
+ devtree_dir, props[i].name);
+ rc = stat(filename, &statbuf);
+ *props[i].flag = (rc == 0);
+ talloc_free(filename);
+ }
+}
+
static int get_sysinfo(struct platform *p, struct system_info *sysinfo)
{
struct platform_powerpc *platform = p->platform_data;
@@ -951,6 +1040,9 @@ static int get_sysinfo(struct platform *p, struct system_info *sysinfo)
if (platform->get_platform_versions)
platform->get_platform_versions(sysinfo);
+ get_sysinfo_stb(platform, sysinfo);
+
+
return 0;
}
@@ -1028,6 +1120,7 @@ static struct platform platform_powerpc = {
.get_sysinfo = get_sysinfo,
.restrict_clients = restrict_clients,
.set_password = set_password,
+ .preboot_check = preboot_check,
};
register_platform(platform_powerpc);
diff --git a/discover/platform.c b/discover/platform.c
index 8ce52fc..38bd241 100644
--- a/discover/platform.c
+++ b/discover/platform.c
@@ -159,6 +159,7 @@ void config_set_defaults(struct config *config)
else
config->lang = NULL;
+ config->preboot_check_enabled = true;
}
int platform_init(void *ctx)
@@ -206,6 +207,17 @@ void platform_pre_boot(void)
platform->pre_boot(platform, config);
}
+bool platform_preboot_check(const char *image, char **err_msg)
+{
+ const struct config *config = config_get();
+
+ if (platform && config && platform->preboot_check)
+ return platform->preboot_check(platform, config,
+ image, err_msg);
+
+ return true;
+}
+
int platform_get_sysinfo(struct system_info *info)
{
if (platform && platform->get_sysinfo)
@@ -572,6 +584,9 @@ void config_populate_all(struct config *config, const struct param_list *pl)
val = param_list_get_value(pl, "petitboot,https_proxy");
if (val)
config->https_proxy = talloc_strdup(config, val);
+
+ val = param_list_get_value(pl, "petitboot,preboot-check");
+ config->preboot_check_enabled = !val || strcmp(val, "false");
}
static char *interface_config_str(void *ctx, struct interface_config *config)
diff --git a/discover/platform.h b/discover/platform.h
index 5a5c990..fe3d390 100644
--- a/discover/platform.h
+++ b/discover/platform.h
@@ -14,6 +14,10 @@ struct platform {
int (*get_sysinfo)(struct platform *, struct system_info *);
bool (*restrict_clients)(struct platform *);
int (*set_password)(struct platform *, const char *hash);
+ bool (*preboot_check)(struct platform *,
+ const struct config *,
+ const char *image,
+ char **err_msg);
uint16_t dhcp_arch_id;
void *platform_data;
};
@@ -25,6 +29,7 @@ int platform_get_sysinfo(struct system_info *info);
bool platform_restrict_clients(void);
int platform_set_password(const char *hash);
void platform_pre_boot(void);
+bool platform_preboot_check(const char *image, char **err_msg);
/* configuration interface */
const struct config *config_get(void);
diff --git a/discover/pxe-parser.c b/discover/pxe-parser.c
index ba0f81c..035794c 100644
--- a/discover/pxe-parser.c
+++ b/discover/pxe-parser.c
@@ -292,9 +292,14 @@ static bool ipxe_simple_parser(struct conf_context *ctx, char *buf, int len)
continue;
}
+ if (!name) {
+ pb_debug_fn("missing name from conf_get_pair\n");
+ continue;
+ }
+
/* All other parameters require a value */
if (!value) {
- pb_debug("%s: '%s' missing value\n", __func__, name);
+ pb_debug_fn("'%s' missing value\n", name);
continue;
}
diff --git a/discover/user-event.c b/discover/user-event.c
index d3d4a5e..cc03ffd 100644
--- a/discover/user-event.c
+++ b/discover/user-event.c
@@ -657,10 +657,10 @@ static void user_event_handle_message(struct user_event *uev, char *buf,
break;
case EVENT_ACTION_URL:
result = user_event_url(uev, event);
- goto out;
+ break;
case EVENT_ACTION_DHCP:
result = user_event_dhcp(uev, event);
- goto out;
+ break;
case EVENT_ACTION_BOOT:
result = user_event_boot(uev, event);
break;
@@ -671,13 +671,17 @@ static void user_event_handle_message(struct user_event *uev, char *buf,
result = user_event_plugin(uev, event);
break;
default:
+ result = -1;
break;
}
+ if (result)
+ pb_log_fn("failed to handle action %d\n", event->action);
+
/* user_event_url() and user_event_dhcp() will steal the event context,
* but all others still need to free */
- talloc_free(event);
-out:
+ if (talloc_parent(event) == uev)
+ talloc_free(event);
return;
}
@@ -751,8 +755,11 @@ struct user_event *user_event_init(struct device_handler *handler,
}
/* Don't allow events from non-priviledged users */
- chown(PBOOT_USER_EVENT_SOCKET, 0, 0);
- chmod(PBOOT_USER_EVENT_SOCKET, 0660);
+ if (chown(PBOOT_USER_EVENT_SOCKET, 0, 0))
+ pb_log_fn("Error setting socket ownership: %m\n");
+ errno = 0;
+ if (chmod(PBOOT_USER_EVENT_SOCKET, 0660))
+ pb_log_fn("Error setting socket permissions: %m\n");
waiter_register_io(waitset, uev->socket, WAIT_IN,
user_event_process, uev);
diff --git a/discover/yaboot-parser.c b/discover/yaboot-parser.c
index b06248f..d0a40b1 100644
--- a/discover/yaboot-parser.c
+++ b/discover/yaboot-parser.c
@@ -213,6 +213,8 @@ static void yaboot_process_pair(struct conf_context *conf, const char *name,
/* Then start the new image. */
opt = state_start_new_option(conf, state);
+ if (!opt)
+ pb_debug_fn("new opt is NULL\n");
state->boot_image = talloc_strdup(state, value);
@@ -235,6 +237,8 @@ static void yaboot_process_pair(struct conf_context *conf, const char *name,
/* Then start the new image. */
opt = state_start_new_option(conf, state);
+ if (!opt)
+ pb_debug_fn("new opt is NULL\n");
if (*value == '/') {
state->boot_image = talloc_strdup(state, value);
OpenPOWER on IntegriCloud