]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
lib/vfscore: Embedded initrd
authorSimon Kuenzer <simon@unikraft.io>
Mon, 28 Aug 2023 13:14:54 +0000 (15:14 +0200)
committerRazvan Deaconescu <razvand@unikraft.io>
Fri, 20 Oct 2023 16:35:55 +0000 (19:35 +0300)
This commit introduces the ability to embed a CPIO initrd in a unikernel
image. This can be useful to hard link an initrd content to an
unikernel. An additionally provided initrd can then be used freely with the
fstab function.

Checkpatch-Ignore: AVOID_EXTERNS
Signed-off-by: Simon Kuenzer <simon@unikraft.io>
Reviewed-by: Cezar Craciunoiu <cezar.craciunoiu@unikraft.io>
Reviewed-by: Sergiu Moga <sergiu@unikraft.io>
Reviewed-by: Marco Schlumpp <marco@unikraft.io>
Approved-by: Marco Schlumpp <marco@unikraft.io>
GitHub-Closes: #1070

lib/vfscore/Config.uk
lib/vfscore/Makefile.uk
lib/vfscore/automount.c
lib/vfscore/einitrd.S [new file with mode: 0644]

index 3a12a4356ec58454c1c62b822ebf87af69b39df0..96779588e932d0dc59db68c89f0af5f032806088 100644 (file)
@@ -51,6 +51,13 @@ if LIBVFSCORE_AUTOMOUNT_ROOTFS
                select LIBRAMFS
                select LIBUKCPIO
 
+               config LIBVFSCORE_ROOTFS_EINITRD
+               bool "Embedded InitRD"
+               select LIBRAMFS
+               select LIBUKCPIO
+               help
+                       Embeds a CPIO initrd into the unikernel image.
+
                config LIBVFSCORE_ROOTFS_CUSTOM
                bool "Custom argument"
                help
@@ -75,37 +82,44 @@ if LIBVFSCORE_AUTOMOUNT_ROOTFS
        default "ramfs" if LIBVFSCORE_ROOTFS_RAMFS
        default "9pfs" if LIBVFSCORE_ROOTFS_9PFS
        default "initrd" if LIBVFSCORE_ROOTFS_INITRD
+       default "einitrd" if LIBVFSCORE_ROOTFS_EINITRD
        default LIBVFSCORE_ROOTFS_CUSTOM_ARG if LIBVFSCORE_ROOTFS_CUSTOM
        default ""
 
-       # The root device option is hidden for RamFS and 9PFS
-       config LIBVFSCORE_ROOTDEV
-       string "Default root device"
-       depends on !LIBVFSCORE_ROOTFS_RAMFS && !LIBVFSCORE_ROOTFS_INITRD
-       default "fs0" if LIBVFSCORE_ROOTFS_9PFS
-       default ""
-       help
-               Device to mount the filesystem from (e.g., on 9PFS this
-               is the name of the shared filesystem). Depending on the
-               selected filesystem, this option may not be required.
-
-       # The root flags is hidden for RamFS
-       config LIBVFSCORE_ROOTFLAGS
-       hex "Default root mount flags"
-       depends on !LIBVFSCORE_ROOTFS_RAMFS && !LIBVFSCORE_ROOTFS_INITRD
-       default 0x0
-       help
-               Mount flags.
+       # The following options are hidden to RamFS, initrd, and einitrd
+       if !LIBVFSCORE_ROOTFS_RAMFS && !LIBVFSCORE_ROOTFS_INITRD && !LIBVFSCORE_ROOTFS_EINITRD
+               config LIBVFSCORE_ROOTDEV
+               string "Default root device"
+               default "fs0" if LIBVFSCORE_ROOTFS_9PFS
+               default ""
+               help
+                       Device to mount the filesystem from (e.g., on 9PFS this
+                       is the name of the shared filesystem). Depending on the
+                       selected filesystem, this option may not be required.
 
-       # The root options are hidden for RamFS
-       config LIBVFSCORE_ROOTOPTS
-       string "Default root mount options"
-       depends on !LIBVFSCORE_ROOTFS_RAMFS && !LIBVFSCORE_ROOTFS_INITRD
-       default ""
-       help
-               Usually a comma-separated list of additional mount
-               options that are directly interpreted by the target
-               filesystem.
+               config LIBVFSCORE_ROOTFLAGS
+               hex "Default root mount flags"
+               default 0x0
+               help
+                       Mount flags.
+
+               config LIBVFSCORE_ROOTOPTS
+               string "Default root mount options"
+               default ""
+               help
+                       Usually a comma-separated list of additional mount
+                       options that are directly interpreted by the target
+                       filesystem.
+       endif
+
+       if LIBVFSCORE_ROOTFS_EINITRD
+               config LIBVFSCORE_ROOTFS_EINITRD_PATH
+               string "Path to initrd (fully qualified)"
+               default "$(UK_APP)/initrd.cpio"
+               help
+                       Path of a CPIO initrd image to be embedded in the unikernel
+                       image and mounted under '/'.
+       endif
 endif
 
 config LIBVFSCORE_FSTAB
index 473a72b01ffb3504caed9c7b250d4e1b7d3b93b6..6c9fd54e8ddf2abbf055a86b5b0caa2cf8b62f7e 100644 (file)
@@ -22,6 +22,8 @@ LIBVFSCORE_SRCS-y += $(LIBVFSCORE_BASE)/eventpoll.c
 LIBVFSCORE_SRCS-y += $(LIBVFSCORE_BASE)/extra.ld
 ifneq (,$(findstring y, $(CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS) $(CONFIG_LIBVFSCORE_FSTAB)))
 LIBVFSCORE_SRCS-y += $(LIBVFSCORE_BASE)/automount.c
+LIBVFSCORE_SRCS-$(CONFIG_LIBVFSCORE_ROOTFS_EINITRD) += $(LIBVFSCORE_BASE)/einitrd.S
+LIBVFSCORE_EINITRD_CDEPS += $(CONFIG_LIBVFSCORE_ROOTFS_EINITRD_PATH)
 endif
 
 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += write-3 writev-3 pwrite64-4
index 7d981cd6bc4e0f845bb824ad371bd3e810e3150f..a16f3413ec5d04fe0d31e070a5adf406f316ff8a 100644 (file)
@@ -39,6 +39,7 @@
  */
 #include <stdlib.h>
 #include <string.h>
+#include <inttypes.h>
 #include <sys/mount.h>
 #include <uk/assert.h>
 #ifdef CONFIG_LIBUKCPIO
@@ -152,44 +153,71 @@ static void vfscore_fstab_fetch_volume_args(char *v, struct vfscore_volume *vv)
 #endif /* CONFIG_LIBVFSCORE_FSTAB */
 
 #if CONFIG_LIBUKCPIO && CONFIG_LIBRAMFS
-static int vfscore_mount_initrd_volume(struct vfscore_volume *vv)
+static int do_mount_initrd(const void *initrd, size_t len, const char *path)
 {
-       struct ukplat_memregion_desc *initrd;
        int rc;
 
-       UK_ASSERT(vv);
-
-       /* TODO: Support multiple Initial RAM Disks */
-       rc = ukplat_memregion_find_initrd0(&initrd);
-       if (unlikely(rc < 0)) {
-               uk_pr_crit("Could not find an initrd!\n");
+       UK_ASSERT(path);
 
+       rc = mount("", path, "ramfs", 0x0, NULL);
+       if (unlikely(rc)) {
+               uk_pr_crit("Failed to mount ramfs to \"%s\": %d\n",
+                          path, errno);
                return -1;
        }
 
-       rc = mount(vv->sdev, vv->path, "ramfs", vv->flags, vv->opts);
+       uk_pr_info("Extracting initrd @ %p (%"__PRIsz" bytes) to %s...\n",
+                  (void *)initrd, len, path);
+       rc = ukcpio_extract(path, (void *)initrd, len);
        if (unlikely(rc)) {
-               uk_pr_crit("Failed to mount ramfs to /: %d\n", errno);
-
+               uk_pr_crit("Failed to extract cpio archive to %s: %d\n",
+                          path, rc);
                return -1;
        }
 
-       uk_pr_info("Extracting initrd @ %p (%"__PRIsz" bytes) to %s...\n",
-                  (void *)initrd->vbase, initrd->len, vv->path);
+       return 0;
+}
+#endif /* CONFIG_LIBUKCPIO && CONFIG_LIBRAMFS */
 
-       rc = ukcpio_extract(vv->path, (void *)initrd->vbase, initrd->len);
-       if (unlikely(rc)) {
-               uk_pr_crit("Failed to extract cpio archive to %s: %d\n",
-                          vv->path, rc);
+#if CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS
+#if CONFIG_LIBVFSCORE_ROOTFS_EINITRD
+extern const char vfscore_einitrd_start[];
+extern const char vfscore_einitrd_end;
+
+static int vfscore_automount_rootfs(void)
+{
+       const void *initrd;
+       size_t len;
+
+       initrd = (const void *)vfscore_einitrd_start;
+       len    = (size_t)((uintptr_t)&vfscore_einitrd_end
+                         - (uintptr_t)vfscore_einitrd_start);
+
+       return do_mount_initrd(initrd, len, "/");
+}
+
+#else /* !CONFIG_LIBVFSCORE_ROOTFS_EINITRD */
+#if CONFIG_LIBUKCPIO && CONFIG_LIBRAMFS
+static int vfscore_mount_initrd_volume(struct vfscore_volume *vv)
+{
+       struct ukplat_memregion_desc *initrd;
+       int rc;
+
+       UK_ASSERT(vv);
+
+       /* TODO: Support multiple Initial RAM Disks */
+       rc = ukplat_memregion_find_initrd0(&initrd);
+       if (unlikely(rc < 0)) {
+               uk_pr_crit("Could not find an initrd!\n");
 
                return -1;
        }
 
-       return 0;
+       return do_mount_initrd((void *)initrd->vbase, initrd->len,
+                              vv->path);
 }
 #endif /* CONFIG_LIBUKCPIO && CONFIG_LIBRAMFS */
 
-#ifdef CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS
 static int vfscore_automount_rootfs(void)
 {
        /* Convert to `struct vfscore_volume` */
@@ -236,6 +264,7 @@ static int vfscore_automount_rootfs(void)
 
        return rc;
 }
+#endif /* !CONFIG_LIBVFSCORE_ROOTFS_EINITRD */
 #else /* CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS */
 static int vfscore_automount_rootfs(void)
 {
diff --git a/lib/vfscore/einitrd.S b/lib/vfscore/einitrd.S
new file mode 100644 (file)
index 0000000..e90ab7f
--- /dev/null
@@ -0,0 +1,13 @@
+#include <uk/config.h>
+
+.globl vfscore_einitrd_start
+.globl vfscore_einitrd_end
+
+.section .rodata
+
+.balign 16
+vfscore_einitrd_start:
+.incbin CONFIG_LIBVFSCORE_ROOTFS_EINITRD_PATH
+.balign 1
+vfscore_einitrd_end:
+.byte 0