diff --git a/src/libostree/ostree-deployment-private.h b/src/libostree/ostree-deployment-private.h index ad77317d79..000c0bbc8d 100644 --- a/src/libostree/ostree-deployment-private.h +++ b/src/libostree/ostree-deployment-private.h @@ -47,6 +47,7 @@ struct _OstreeDeployment char *csum; int deployserial; char *bootcsum; + char **additional_initrds; int bootserial; OstreeBootconfigParser *bootconfig; GKeyFile *origin; @@ -56,4 +57,9 @@ struct _OstreeDeployment void _ostree_deployment_set_bootcsum (OstreeDeployment *self, const char *bootcsum); +void _ostree_deployment_set_additional_initrds (OstreeDeployment *self, + char **additional_initrds); +char** +_ostree_deployment_get_additional_initrds (OstreeDeployment *self); + G_END_DECLS diff --git a/src/libostree/ostree-deployment.c b/src/libostree/ostree-deployment.c index 70e1bc4928..6de1f0f43b 100644 --- a/src/libostree/ostree-deployment.c +++ b/src/libostree/ostree-deployment.c @@ -158,6 +158,20 @@ _ostree_deployment_set_bootcsum (OstreeDeployment *self, self->bootcsum = g_strdup (bootcsum); } +void +_ostree_deployment_set_additional_initrds (OstreeDeployment *self, + char **additional_initrds) +{ + g_strfreev (self->additional_initrds); + self->additional_initrds = g_strdupv (additional_initrds); +} + +char** +_ostree_deployment_get_additional_initrds (OstreeDeployment *self) +{ + return self->additional_initrds; +} + /** * ostree_deployment_clone: * @self: Deployment @@ -238,6 +252,7 @@ ostree_deployment_finalize (GObject *object) g_free (self->bootcsum); g_clear_object (&self->bootconfig); g_clear_pointer (&self->origin, g_key_file_unref); + g_strfreev (self->additional_initrds); G_OBJECT_CLASS (ostree_deployment_parent_class)->finalize (object); } diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 4f09d30192..ab35303a85 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -1859,6 +1859,42 @@ install_deployment_kernel (OstreeSysroot *sysroot, } } + g_autoptr(GPtrArray) additional_initrds = NULL; + for (char **it = _ostree_deployment_get_additional_initrds (deployment); it && *it; it++) + { + char *initrd = *it; + + /* Additional initrds are not part of the bootcsum; they're not part of the tree + * proper. But they're named by their csum. Doing it this way allows sharing the same + * bootcsum dir for multiple deployments with the only change being in additional + * initrds. The downside is that we would need to implement our own GC based on + * referenced overlays from all the bootconfigs; that said, they're tiny overlays and + * will get blown away on each kernel/initrd update. */ + + g_autofree char *checksum = + ot_checksum_file_at (AT_FDCWD, initrd, G_CHECKSUM_SHA256, cancellable, error); + if (checksum == NULL) + return glnx_prefix_error (error, "Checksumming %s", initrd); + + g_autofree char *destpath = + g_strdup_printf ("/%s/initramfs-overlay-%s.img", bootcsumdir, checksum); + + const char *base_destpath = glnx_basename (destpath); + if (!glnx_fstatat_allow_noent (bootcsum_dfd, base_destpath, &stbuf, 0, error)) + return FALSE; + + if (errno == ENOENT) + { + if (!install_into_boot (repo, sepolicy, AT_FDCWD, initrd, bootcsum_dfd, + base_destpath, sysroot->debug_flags, cancellable, error)) + return FALSE; + } + + if (additional_initrds == NULL) + additional_initrds = g_ptr_array_new_with_free_func (g_free); + g_ptr_array_add (additional_initrds, g_steal_pointer (&destpath)); + } + g_autofree char *contents = NULL; if (!glnx_fstatat_allow_noent (deployment_dfd, "usr/lib/os-release", &stbuf, 0, error)) return FALSE; @@ -1938,6 +1974,12 @@ install_deployment_kernel (OstreeSysroot *sysroot, g_autofree char * initrd_boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->initramfs_namever, NULL); ostree_bootconfig_parser_set (bootconfig, "initrd", initrd_boot_relpath); + + if (additional_initrds) + { + for (guint i = 0; i < additional_initrds->len; i++) + ostree_bootconfig_parser_add_initrd (bootconfig, additional_initrds->pdata[i]); + } } else { @@ -2716,6 +2758,7 @@ sysroot_initialize_deployment (OstreeSysroot *self, _ostree_deployment_set_bootcsum (new_deployment, kernel_layout->bootcsum); _ostree_deployment_set_bootconfig_from_kargs (new_deployment, opts->override_kernel_argv); + _ostree_deployment_set_additional_initrds (new_deployment, opts->additional_initrds); if (!prepare_deployment_etc (self, repo, new_deployment, deployment_dfd, cancellable, error)) @@ -3116,6 +3159,9 @@ ostree_sysroot_stage_tree_with_options (OstreeSysroot *self, if (opts->override_kernel_argv) g_variant_builder_add (builder, "{sv}", "kargs", g_variant_new_strv ((const char *const*)opts->override_kernel_argv, -1)); + if (opts->additional_initrds) + g_variant_builder_add (builder, "{sv}", "additional-initrds", + g_variant_new_strv ((const char *const*)opts->additional_initrds, -1)); const char *parent = dirname (strdupa (_OSTREE_SYSROOT_RUNSTATE_STAGED)); if (!glnx_shutil_mkdir_p_at (AT_FDCWD, parent, 0755, cancellable, error)) diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index b211fea723..9c7b41522a 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -966,8 +966,10 @@ _ostree_sysroot_reload_staged (OstreeSysroot *self, /* Parse it */ g_autoptr(GVariant) target = NULL; g_autofree char **kargs = NULL; + g_autofree char **additional_initrds = NULL; g_variant_dict_lookup (staged_deployment_dict, "target", "@a{sv}", &target); g_variant_dict_lookup (staged_deployment_dict, "kargs", "^a&s", &kargs); + g_variant_dict_lookup (staged_deployment_dict, "additional-initrds", "^a&s", &additional_initrds); if (target) { g_autoptr(OstreeDeployment) staged = @@ -979,6 +981,8 @@ _ostree_sysroot_reload_staged (OstreeSysroot *self, if (!load_origin (self, staged, NULL, error)) return FALSE; + _ostree_deployment_set_additional_initrds (staged, additional_initrds); + self->staged_deployment = g_steal_pointer (&staged); self->staged_deployment_data = g_steal_pointer (&staged_deployment_data); /* We set this flag for ostree_deployment_is_staged() because that API diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h index 45d6d63cc4..3092b60bd0 100644 --- a/src/libostree/ostree-sysroot.h +++ b/src/libostree/ostree-sysroot.h @@ -190,7 +190,8 @@ typedef struct { gboolean unused_bools[8]; int unused_ints[8]; char **override_kernel_argv; - gpointer unused_ptrs[7]; + char **additional_initrds; + gpointer unused_ptrs[6]; } OstreeSysrootDeployTreeOpts; _OSTREE_PUBLIC