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
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
*/
#include <stdlib.h>
#include <string.h>
+#include <inttypes.h>
#include <sys/mount.h>
#include <uk/assert.h>
#ifdef CONFIG_LIBUKCPIO
#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` */
return rc;
}
+#endif /* !CONFIG_LIBVFSCORE_ROOTFS_EINITRD */
#else /* CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS */
static int vfscore_automount_rootfs(void)
{