From e9fd07f945135224708253845a2fa08943755b53 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Thu, 20 Jun 2013 10:33:29 +0800 Subject: [PATCH] discover/boot: Add boot hooks Add a method of running pre-boot hooks. Executable files in /etc/petitboot/boot.d/ are run (in order) before we start the boot process. Signed-off-by: Jeremy Kerr --- discover/boot.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/discover/boot.c b/discover/boot.c index ae44717..8c2e8e1 100644 --- a/discover/boot.c +++ b/discover/boot.c @@ -1,6 +1,13 @@ +#define _GNU_SOURCE + #include +#include #include +#include +#include +#include +#include #include #include @@ -13,6 +20,8 @@ #include "paths.h" #include "resource.h" +static const char *boot_hook_dir = PKG_SYSCONF_DIR "/boot.d"; + struct boot_task { char *local_image; char *local_initrd; @@ -139,6 +148,58 @@ static void update_status(boot_status_fn fn, void *arg, int type, fn(arg, &status); } +static int hook_filter(const struct dirent *dirent) +{ + return dirent->d_type == DT_REG || dirent->d_type == DT_LNK; +} + +static int hook_cmp(const struct dirent **a, const struct dirent **b) +{ + return strcmp((*a)->d_name, (*b)->d_name); +} + +static void run_boot_hooks(void *ctx, struct boot_task *task, + boot_status_fn status_fn, void *status_arg) +{ + struct dirent **hooks; + int i, n; + + n = scandir(boot_hook_dir, &hooks, hook_filter, hook_cmp); + if (n < 1) + return; + + update_status(status_fn, status_arg, BOOT_STATUS_INFO, + "running boot hooks"); + + /* pass boot data to hooks */ + setenv("boot_image", task->local_image, 1); + if (task->local_initrd) + setenv("boot_initrd", task->local_initrd, 1); + if (task->local_dtb) + setenv("boot_dtb", task->local_dtb, 1); + if (task->args) + setenv("boot_args", task->args, 1); + + for (i = 0; i < n; i++) { + char *path; + const char *argv[2] = { NULL, NULL }; + + path = join_paths(ctx, boot_hook_dir, hooks[i]->d_name); + + if (access(path, X_OK)) + continue; + + pb_log("running boot hook %s\n", hooks[i]->d_name); + + argv[0] = path; + pb_run_cmd(argv, 1, task->dry_run); + + talloc_free(path); + } + + free(hooks); +} + int boot(void *ctx, struct discover_boot_option *opt, struct boot_command *cmd, int dry_run, boot_status_fn status_fn, void *status_arg) { @@ -218,6 +279,8 @@ int boot(void *ctx, struct discover_boot_option *opt, struct boot_command *cmd, } } + run_boot_hooks(ctx, &boot_task, status_fn, status_arg); + update_status(status_fn, status_arg, BOOT_STATUS_INFO, "performing kexec_load"); -- 2.39.2