Skip to content

Commit b9f2b65

Browse files
admin: Add an esp-upgrade subcommand
The files in the EFI System Partition (ESP) are never updated by OSTree, users will always have the same ESP that was created during installation. This happens because the ESP uses a vfat filesystem which doesn't support symbolic links so the upgrade can't be atomic and part of the transaction. But since the ESP contains the bootloader components (shim, grub, etc) and other important EFI binaries like the ones used for firmware update, there should be a way to upgrade the ESP with the latest version of these files. These binaries are stored in the /usr/lib/ostree-boot/efi directory of a deployment, because rpm-ostree places there everything that is in /boot. Add a ostree-admin-esp-upgrade subcommand that just copies the content of /usr/lib/ostree-boot/efi to /boot/efi, so users can update the ESP and get the latest version of the files that are present in the current deployment. This sub-command only works on a system that was booted with EFI and has the ESP mounted in /boot/efi. Closes: #1649
1 parent 8d0ab6d commit b9f2b65

8 files changed

+247
-1
lines changed

Makefile-man.am

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ ostree-admin-config-diff.1 ostree-admin-deploy.1 \
2626
ostree-admin-init-fs.1 ostree-admin-instutil.1 ostree-admin-os-init.1 \
2727
ostree-admin-status.1 ostree-admin-set-origin.1 ostree-admin-switch.1 \
2828
ostree-admin-undeploy.1 ostree-admin-upgrade.1 ostree-admin-unlock.1 \
29-
ostree-admin-pin.1 \
29+
ostree-admin-pin.1 ostree-admin-esp-upgrade.1 \
3030
ostree-admin.1 ostree-cat.1 ostree-checkout.1 ostree-checksum.1 \
3131
ostree-commit.1 ostree-create-usb.1 ostree-export.1 ostree-gpg-sign.1 \
3232
ostree-config.1 ostree-diff.1 ostree-find-remotes.1 ostree-fsck.1 \

Makefile-ostree.am

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ ostree_SOURCES += \
7979
src/ostree/ot-admin-builtin-status.c \
8080
src/ostree/ot-admin-builtin-switch.c \
8181
src/ostree/ot-admin-builtin-pin.c \
82+
src/ostree/ot-admin-builtin-esp-upgrade.c \
8283
src/ostree/ot-admin-builtin-upgrade.c \
8384
src/ostree/ot-admin-builtin-unlock.c \
8485
src/ostree/ot-admin-builtins.h \

Makefile-tests.am

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ _installed_or_uninstalled_test_scripts = \
100100
tests/test-admin-deploy-karg.sh \
101101
tests/test-admin-deploy-switch.sh \
102102
tests/test-admin-deploy-etcmerge-cornercases.sh \
103+
tests/test-admin-esp-upgrade.sh \
103104
tests/test-admin-deploy-uboot.sh \
104105
tests/test-admin-deploy-grub2.sh \
105106
tests/test-admin-deploy-none.sh \

man/ostree-admin-esp-upgrade.xml

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?xml version='1.0'?> <!--*-nxml-*-->
2+
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
3+
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
4+
5+
<!--
6+
Copyright 2019 Red Hat, Inc.
7+
8+
SPDX-License-Identifier: LGPL-2.0+
9+
10+
This library is free software; you can redistribute it and/or
11+
modify it under the terms of the GNU Lesser General Public
12+
License as published by the Free Software Foundation; either
13+
version 2 of the License, or (at your option) any later version.
14+
15+
This library is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18+
Lesser General Public License for more details.
19+
20+
You should have received a copy of the GNU Lesser General Public
21+
License along with this library; if not, write to the
22+
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23+
Boston, MA 02111-1307, USA.
24+
-->
25+
26+
<refentry id="ostree">
27+
28+
<refentryinfo>
29+
<title>ostree admin esp-upgrade</title>
30+
<productname>OSTree</productname>
31+
32+
<authorgroup>
33+
<author>
34+
<contrib>Developer</contrib>
35+
<firstname>Javier</firstname>
36+
<surname>Martinez Canillas</surname>
37+
<email>javierm@redhat.com</email>
38+
</author>
39+
</authorgroup>
40+
</refentryinfo>
41+
42+
<refmeta>
43+
<refentrytitle>ostree admin esp-upgrade</refentrytitle>
44+
<manvolnum>1</manvolnum>
45+
</refmeta>
46+
47+
<refnamediv>
48+
<refname>ostree-admin-esp-upgrade</refname>
49+
<refpurpose>Upgrade the EFI System Partition (ESP) with files from the current deployment</refpurpose>
50+
</refnamediv>
51+
52+
<refsynopsisdiv>
53+
<cmdsynopsis>
54+
<command>ostree admin esp-upgrade</command>
55+
</cmdsynopsis>
56+
</refsynopsisdiv>
57+
58+
<refsect1>
59+
<title>Description</title>
60+
61+
<para>
62+
Upgrade the EFI System Partition (ESP) with the files in the /usr/lib/ostree-boot/efi directory of the current deployment.
63+
</para>
64+
</refsect1>
65+
66+
<refsect1>
67+
<title>Example</title>
68+
<para><command>$ ostree admin esp-upgrade</command></para>
69+
</refsect1>
70+
</refentry>
+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (C) 2019 Red Hat, Inc.
3+
*
4+
* SPDX-License-Identifier: LGPL-2.0+
5+
*
6+
* This library is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 2 of the License, or (at your option) any later version.
10+
*
11+
* This library is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this library; if not, write to the
18+
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19+
* Boston, MA 02111-1307, USA.
20+
*
21+
* Author: Javier Martinez Canillas <javierm@redhat.com>
22+
*/
23+
24+
#include "config.h"
25+
26+
#include "ostree-sysroot-private.h"
27+
#include "ot-main.h"
28+
#include "ot-admin-builtins.h"
29+
#include "ot-admin-functions.h"
30+
#include "otutil.h"
31+
32+
static GOptionEntry options[] = {
33+
{ NULL }
34+
};
35+
36+
gboolean
37+
ot_admin_builtin_esp_upgrade (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
38+
{
39+
g_autoptr(GOptionContext) context = g_option_context_new ("");
40+
41+
g_autoptr(OstreeSysroot) sysroot = NULL;
42+
if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
43+
OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED,
44+
invocation, &sysroot, cancellable, error))
45+
return FALSE;
46+
47+
g_autoptr(OstreeRepo) repo = NULL;
48+
if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
49+
return FALSE;
50+
51+
g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot);
52+
53+
if (deployments->len == 0)
54+
{
55+
g_print ("No deployments.\n");
56+
return TRUE;
57+
}
58+
59+
OstreeDeployment *deployment = ostree_sysroot_get_booted_deployment (sysroot);
60+
61+
if (!deployment)
62+
deployment = ot_admin_get_indexed_deployment (sysroot, 0, error);
63+
64+
struct stat stbuf;
65+
66+
if (!glnx_fstatat_allow_noent (sysroot->sysroot_fd, "sys/firmware/efi", &stbuf, AT_SYMLINK_NOFOLLOW, error))
67+
return FALSE;
68+
69+
if (errno == ENOENT)
70+
{
71+
g_print ("Not an EFI system.\n");
72+
return TRUE;
73+
}
74+
75+
if (!ot_is_rw_mount ("/boot/efi"))
76+
{
77+
if (ot_is_ro_mount ("/boot/efi"))
78+
g_print ("The ESP can't be updated because /boot/efi is a read-only mountpoint.\n");
79+
else
80+
g_print ("Only ESP mounted in /boot/efi is supported.\n");
81+
return TRUE;
82+
}
83+
84+
g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (sysroot, deployment);
85+
86+
g_autofree char *new_esp_path = g_strdup_printf ("%s/usr/lib/ostree-boot", deployment_path);
87+
88+
GLNX_AUTO_PREFIX_ERROR ("During copy files to the ESP", error);
89+
glnx_autofd int old_esp_fd = -1;
90+
if (!glnx_opendirat (sysroot->sysroot_fd, "boot", TRUE, &old_esp_fd, error))
91+
return FALSE;
92+
93+
glnx_autofd int new_esp_fd = -1;
94+
if (!glnx_opendirat (sysroot->sysroot_fd, new_esp_path, TRUE, &new_esp_fd, error))
95+
return FALSE;
96+
97+
/* The ESP filesystem is vfat so don't attempt to copy ownership, mode, and xattrs */
98+
const OstreeSysrootDebugFlags flags = sysroot->debug_flags | OSTREE_SYSROOT_DEBUG_NO_XATTRS;
99+
100+
if (!ot_copy_dir_recurse (new_esp_fd, old_esp_fd, "efi", flags , cancellable, error))
101+
return FALSE;
102+
103+
return TRUE;
104+
}

src/ostree/ot-admin-builtins.h

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ BUILTINPROTO(undeploy);
4040
BUILTINPROTO(deploy);
4141
BUILTINPROTO(cleanup);
4242
BUILTINPROTO(pin);
43+
BUILTINPROTO(esp_upgrade);
4344
BUILTINPROTO(finalize_staged);
4445
BUILTINPROTO(unlock);
4546
BUILTINPROTO(status);

src/ostree/ot-builtin-admin.c

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ static OstreeCommand admin_subcommands[] = {
5757
{ "pin", OSTREE_BUILTIN_FLAG_NO_REPO,
5858
ot_admin_builtin_pin,
5959
"Change the \"pinning\" state of a deployment" },
60+
{ "esp-upgrade", OSTREE_BUILTIN_FLAG_NO_REPO,
61+
ot_admin_builtin_esp_upgrade,
62+
"Upgrade the ESP with files from the current deployment" },
6063
{ "set-origin", OSTREE_BUILTIN_FLAG_NO_REPO,
6164
ot_admin_builtin_set_origin,
6265
"Set Origin and create a new origin file" },

tests/test-admin-esp-upgrade.sh

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/bin/bash
2+
#
3+
# Copyright (C) 2019 Red Hat, Inc
4+
#
5+
# SPDX-License-Identifier: LGPL-2.0+
6+
#
7+
# This library is free software; you can redistribute it and/or
8+
# modify it under the terms of the GNU Lesser General Public
9+
# License as published by the Free Software Foundation; either
10+
# version 2 of the License, or (at your option) any later version.
11+
#
12+
# This library is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
# Lesser General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU Lesser General Public
18+
# License along with this library; if not, write to the
19+
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20+
# Boston, MA 02111-1307, USA.
21+
22+
set -euo pipefail
23+
24+
. $(dirname $0)/libtest.sh
25+
26+
id=$(id -u)
27+
28+
if test ${id} != 0; then
29+
skip "this test needs to set up mount namespaces, rerun as root"
30+
fi
31+
32+
# Exports OSTREE_SYSROOT so --sysroot not needed.
33+
setup_os_repository "archive" "sysroot.bootloader none"
34+
35+
echo "1..1"
36+
37+
${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime
38+
rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime)
39+
export rev
40+
echo "rev=${rev}"
41+
${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmaster/x86_64-runtime
42+
assert_has_dir sysroot/boot/ostree/testos-${bootcsum}
43+
44+
usr=sysroot/ostree/deploy/testos/deploy/${rev}.0/usr
45+
46+
# Create /usr/lib/ostree-boot/efi dir and some test files
47+
mkdir -p ${usr}/lib/ostree-boot/efi/EFI
48+
touch ${usr}/lib/ostree-boot/efi/file-a
49+
touch ${usr}/lib/ostree-boot/efi/EFI/file-b
50+
51+
cd ${test_tmpdir}
52+
53+
# ostree-admin-esp-upgrade checks if /sys/firmware/efi exists
54+
# and /boot/efi is a mountpoint.
55+
mkdir -p sysroot/sys/firmware/efi
56+
mkdir -p sysroot/boot/efi
57+
mount --bind sysroot/boot/efi /boot/efi
58+
59+
${CMD_PREFIX} ostree admin esp-upgrade
60+
61+
assert_has_file sysroot/boot/efi/file-a
62+
assert_has_file sysroot/boot/efi/EFI/file-b
63+
64+
umount /boot/efi
65+
66+
echo "ok"

0 commit comments

Comments
 (0)