diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 46984a75e1..4b412fec97 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -117,6 +117,8 @@ libostree_1_la_SOURCES = \ src/libostree/ostree-bootloader.c \ src/libostree/ostree-bootloader-grub2.h \ src/libostree/ostree-bootloader-grub2.c \ + src/libostree/ostree-bootloader-zipl.h \ + src/libostree/ostree-bootloader-zipl.c \ src/libostree/ostree-bootloader-syslinux.h \ src/libostree/ostree-bootloader-syslinux.c \ src/libostree/ostree-bootloader-uboot.h \ diff --git a/src/libostree/ostree-bootloader-zipl.c b/src/libostree/ostree-bootloader-zipl.c new file mode 100644 index 0000000000..281c4331e8 --- /dev/null +++ b/src/libostree/ostree-bootloader-zipl.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2019 Colin Walters + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the licence or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "ostree-sysroot-private.h" +#include "ostree-bootloader-zipl.h" +#include "otutil.h" + +#include + +/* This is specific to zipl today, but in the future we could also + * use it for the grub2-mkconfig case. + */ +static const char zipl_requires_execute_path[] = "boot/ostree-bootloader-update.stamp"; + +struct _OstreeBootloaderZipl +{ + GObject parent_instance; + + OstreeSysroot *sysroot; +}; + +typedef GObjectClass OstreeBootloaderZiplClass; + +static void _ostree_bootloader_zipl_bootloader_iface_init (OstreeBootloaderInterface *iface); +G_DEFINE_TYPE_WITH_CODE (OstreeBootloaderZipl, _ostree_bootloader_zipl, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (OSTREE_TYPE_BOOTLOADER, _ostree_bootloader_zipl_bootloader_iface_init)); + +static gboolean +_ostree_bootloader_zipl_query (OstreeBootloader *bootloader, + gboolean *out_is_active, + GCancellable *cancellable, + GError **error) +{ + /* We don't auto-detect this one; should be explicitly chosen right now. + * see also https://github.com/coreos/coreos-assembler/pull/849 + */ + *out_is_active = FALSE; + return TRUE; +} + +static const char * +_ostree_bootloader_zipl_get_name (OstreeBootloader *bootloader) +{ + return "zipl"; +} + +static gboolean +_ostree_bootloader_zipl_write_config (OstreeBootloader *bootloader, + int bootversion, + GPtrArray *new_deployments, + GCancellable *cancellable, + GError **error) +{ + OstreeBootloaderZipl *self = OSTREE_BOOTLOADER_ZIPL (bootloader); + + /* Write our stamp file */ + if (!glnx_file_replace_contents_at (self->sysroot->sysroot_fd, zipl_requires_execute_path, + (guint8*)"", 0, GLNX_FILE_REPLACE_NODATASYNC, + cancellable, error)) + return FALSE; + + return TRUE; +} + +static gboolean +_ostree_bootloader_zipl_post_bls_sync (OstreeBootloader *bootloader, + GCancellable *cancellable, + GError **error) +{ + OstreeBootloaderZipl *self = OSTREE_BOOTLOADER_ZIPL (bootloader); + + /* Note that unlike the grub2-mkconfig backend, we make no attempt to + * chroot(). + */ + g_assert (self->sysroot->booted_deployment); + + const char *const zipl_argv[] = {"zipl", NULL}; + int estatus; + if (!g_spawn_sync (NULL, (char**)zipl_argv, NULL, G_SPAWN_SEARCH_PATH, + NULL, NULL, NULL, NULL, &estatus, error)) + return FALSE; + if (!g_spawn_check_exit_status (estatus, error)) + return FALSE; + if (!glnx_unlinkat (self->sysroot->sysroot_fd, zipl_requires_execute_path, 0, error)) + return FALSE; + return TRUE; +} + +static void +_ostree_bootloader_zipl_finalize (GObject *object) +{ + OstreeBootloaderZipl *self = OSTREE_BOOTLOADER_ZIPL (object); + + g_clear_object (&self->sysroot); + + G_OBJECT_CLASS (_ostree_bootloader_zipl_parent_class)->finalize (object); +} + +void +_ostree_bootloader_zipl_init (OstreeBootloaderZipl *self) +{ +} + +static void +_ostree_bootloader_zipl_bootloader_iface_init (OstreeBootloaderInterface *iface) +{ + iface->query = _ostree_bootloader_zipl_query; + iface->get_name = _ostree_bootloader_zipl_get_name; + iface->write_config = _ostree_bootloader_zipl_write_config; + iface->post_bls_sync = _ostree_bootloader_zipl_post_bls_sync; +} + +void +_ostree_bootloader_zipl_class_init (OstreeBootloaderZiplClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = _ostree_bootloader_zipl_finalize; +} + +OstreeBootloaderZipl * +_ostree_bootloader_zipl_new (OstreeSysroot *sysroot) +{ + OstreeBootloaderZipl *self = g_object_new (OSTREE_TYPE_BOOTLOADER_ZIPL, NULL); + self->sysroot = g_object_ref (sysroot); + return self; +} diff --git a/src/libostree/ostree-bootloader-zipl.h b/src/libostree/ostree-bootloader-zipl.h new file mode 100644 index 0000000000..79e8491214 --- /dev/null +++ b/src/libostree/ostree-bootloader-zipl.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 Colin Walters + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the licence or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include "ostree-bootloader.h" + +G_BEGIN_DECLS + +#define OSTREE_TYPE_BOOTLOADER_ZIPL (_ostree_bootloader_zipl_get_type ()) +#define OSTREE_BOOTLOADER_ZIPL(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), OSTREE_TYPE_BOOTLOADER_ZIPL, OstreeBootloaderZipl)) +#define OSTREE_IS_BOOTLOADER_ZIPL(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), OSTREE_TYPE_BOOTLOADER_ZIPL)) + +typedef struct _OstreeBootloaderZipl OstreeBootloaderZipl; + +GType _ostree_bootloader_zipl_get_type (void) G_GNUC_CONST; + +OstreeBootloaderZipl * _ostree_bootloader_zipl_new (OstreeSysroot *sysroot); + +G_END_DECLS diff --git a/src/libostree/ostree-bootloader.c b/src/libostree/ostree-bootloader.c index 5b8125dcc4..76b7bb8201 100644 --- a/src/libostree/ostree-bootloader.c +++ b/src/libostree/ostree-bootloader.c @@ -65,6 +65,19 @@ _ostree_bootloader_write_config (OstreeBootloader *self, cancellable, error); } +gboolean +_ostree_bootloader_post_bls_sync (OstreeBootloader *self, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), FALSE); + + if (OSTREE_BOOTLOADER_GET_IFACE (self)->post_bls_sync) + return OSTREE_BOOTLOADER_GET_IFACE (self)->post_bls_sync (self, cancellable, error); + + return TRUE; +} + gboolean _ostree_bootloader_is_atomic (OstreeBootloader *self) { diff --git a/src/libostree/ostree-bootloader.h b/src/libostree/ostree-bootloader.h index 5af2dcc8a3..48a7a9cdaa 100644 --- a/src/libostree/ostree-bootloader.h +++ b/src/libostree/ostree-bootloader.h @@ -47,6 +47,9 @@ struct _OstreeBootloaderInterface GPtrArray *new_deployments, GCancellable *cancellable, GError **error); + gboolean (* post_bls_sync) (OstreeBootloader *self, + GCancellable *cancellable, + GError **error); gboolean (* is_atomic) (OstreeBootloader *self); }; G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeBootloader, g_object_unref) @@ -66,6 +69,10 @@ gboolean _ostree_bootloader_write_config (OstreeBootloader *self, GCancellable *cancellable, GError **error); +gboolean _ostree_bootloader_post_bls_sync (OstreeBootloader *self, + GCancellable *cancellable, + GError **error); + gboolean _ostree_bootloader_is_atomic (OstreeBootloader *self); G_END_DECLS diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index c342d7e004..64074dbe1e 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -1830,6 +1830,7 @@ prepare_new_bootloader_link (OstreeSysroot *sysroot, /* Update the /boot/loader symlink to point to /boot/loader.$new_bootversion */ static gboolean swap_bootloader (OstreeSysroot *sysroot, + OstreeBootloader *bootloader, int current_bootversion, int new_bootversion, GCancellable *cancellable, @@ -1863,6 +1864,15 @@ swap_bootloader (OstreeSysroot *sysroot, if (fsync (boot_dfd) != 0) return glnx_throw_errno_prefix (error, "fsync(boot)"); + /* TODO: In the future also execute this automatically via a systemd unit + * if we detect it's necessary. + **/ + if (bootloader) + { + if (!_ostree_bootloader_post_bls_sync (bootloader, cancellable, error)) + return FALSE; + } + return TRUE; } @@ -2129,7 +2139,7 @@ write_deployments_bootswap (OstreeSysroot *self, if (!full_system_sync (self, out_syncstats, cancellable, error)) return FALSE; - if (!swap_bootloader (self, self->bootversion, new_bootversion, + if (!swap_bootloader (self, bootloader, self->bootversion, new_bootversion, cancellable, error)) return FALSE;