Usually the kernel and kernel modules are I<not> included in the
supermin appliance. When the appliance is instantiated, the kernel
modules from the host kernel are copied in, and it is booted using the
-host kernel. febootstrap-supermin-helper is able to choose the best
-host kernel available to boot the appliance.
+host kernel.
+
+febootstrap-supermin-helper is able to choose the best host kernel
+available to boot the appliance. Users can override this by setting
+environment variables (see L<febootstrap-supermin-helper(8)>).
=head2 BOOTING AND CACHING THE SUPERMIN APPLIANCE
=back
+=head1 ENVIRONMENT VARIABLES
+
+=over 4
+
+=item FEBOOTSTRAP_KERNEL
+
+If this environment variable is set, then automatic selection of the
+kernel is bypassed and this kernel is used.
+
+The environment variable should point to a kernel file,
+eg. C</boot/vmlinuz-3.0.x86_64>
+
+The corresponding module path is guessed from the kernel name, but you
+can override that by setting C<FEBOOTSTRAP_MODULES>.
+
+=item FEBOOTSTRAP_MODULES
+
+If C<FEBOOTSTRAP_KERNEL> and C<FEBOOTSTRAP_MODULES> are both set, then
+automatic selection of the kernel is bypassed and the kernel and
+module path are set to these values.
+
+The environment variable should point to a module directory,
+eg. C</lib/modules/3.0.x86_64/>
+
+This has no effect if C<FEBOOTSTRAP_KERNEL> is not set.
+
+=back
+
=head1 SEE ALSO
L<febootstrap(8)>.
}
static const char *create_kernel_archlinux (const char *hostcpu, const char *kernel);
+static const char *create_kernel_from_env (const char *hostcpu, const char *kernel, const char *kernel_env, const char *modpath_env);
/* Create the kernel. This chooses an appropriate kernel and makes a
* symlink to it.
const char *
create_kernel (const char *hostcpu, const char *kernel)
{
+ /* Override kernel selection using environment variables? */
+ char *kernel_env = getenv ("FEBOOTSTRAP_KERNEL");
+ if (kernel_env) {
+ char *modpath_env = getenv ("FEBOOTSTRAP_MODULES");
+ return create_kernel_from_env (hostcpu, kernel, kernel_env, modpath_env);
+ }
+
/* In ArchLinux, kernel is always named /boot/vmlinuz26. */
if (access ("/boot/vmlinuz26", F_OK) == 0)
return create_kernel_archlinux (hostcpu, kernel);
/* Return module path. */
return modpath;
}
+
+/* Select the kernel from environment variables set by the user.
+ * modpath_env may be NULL, in which case we attempt to work it out
+ * from kernel_env.
+ */
+static const char *
+create_kernel_from_env (const char *hostcpu, const char *kernel,
+ const char *kernel_env, const char *modpath_env)
+{
+ if (verbose) {
+ fprintf (stderr,
+ "febootstrap-supermin-helper: using environment variable(s) FEBOOTSTRAP_* to\n"
+ "select kernel %s", kernel_env);
+ if (modpath_env)
+ fprintf (stderr, " and module path %s", modpath_env);
+ fprintf (stderr, "\n");
+ }
+
+ if (!isfile (kernel_env)) {
+ fprintf (stderr,
+ "febootstrap-supermin-helper: %s: not a regular file\n"
+ "(what is $FEBOOTSTRAP_KERNEL set to?)\n", kernel_env);
+ exit (EXIT_FAILURE);
+ }
+
+ if (!modpath_env) {
+ /* Try to guess modpath from kernel path. */
+ const char *p = strrchr (kernel_env, '/');
+ if (p) p++; else p = kernel_env;
+
+ /* NB: We need the extra test to ensure calling get_modpath is safe. */
+ if (strncmp (p, "vmlinuz-", 8) != 0) {
+ fprintf (stderr,
+ "febootstrap-supermin-helper: cannot guess module path.\n"
+ "Set $FEBOOTSTRAP_MODULES to the modules directory corresponding to\n"
+ "kernel %s, or unset $FEBOOTSTRAP_KERNEL to autoselect a kernel.\n",
+ kernel_env);
+ exit (EXIT_FAILURE);
+ }
+
+ modpath_env = get_modpath (p);
+ }
+
+ if (!isdir (modpath_env)) {
+ fprintf (stderr,
+ "febootstrap-supermin-helper: %s: not a directory\n"
+ "(what is $FEBOOTSTRAP_MODULES set to?)\n", modpath_env);
+ exit (EXIT_FAILURE);
+ }
+
+ /* Create the symlink. */
+ if (kernel) {
+ if (verbose >= 2)
+ fprintf (stderr, "creating symlink %s -> %s\n", kernel_env, kernel);
+
+ if (symlink (kernel_env, kernel) == -1)
+ error (EXIT_FAILURE, errno, "symlink kernel");
+ }
+
+ return modpath_env;
+}