Skip to content

Commit

Permalink
WIP: Add a zipl bootloader backend
Browse files Browse the repository at this point in the history
zipl is a bit special in that it parses the BLS config files
directly *but* we need to run the command to update the "boot block".

Hence, we're not generating a separate config file like the other
backends.  Instead, extend the bootloader interface with a `post_bls_sync`
method that is run in the same place we swap the `boot/loader` symlink.

We write a "stamp file" in `/boot` that says we need to run this command.
This opens the door to making things eventually-consistent/reconcilable
by later adding a systemd unit to run `zipl` if we're interrupted via
a systemd unit - I think we should eventually take this approach
everywhere rather than requiring `/boot/loader` to be a symlink.
  • Loading branch information
cgwalters committed Oct 14, 2019
1 parent f203a4f commit cd7b553
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Makefile-libostree.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
145 changes: 145 additions & 0 deletions src/libostree/ostree-bootloader-zipl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* Copyright (C) 2019 Colin Walters <[email protected]>
*
* 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 <string.h>

/* 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;
}
36 changes: 36 additions & 0 deletions src/libostree/ostree-bootloader-zipl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2019 Colin Walters <[email protected]>
*
* 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
13 changes: 13 additions & 0 deletions src/libostree/ostree-bootloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
7 changes: 7 additions & 0 deletions src/libostree/ostree-bootloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
12 changes: 11 additions & 1 deletion src/libostree/ostree-sysroot-deploy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit cd7b553

Please sign in to comment.