Skip to content

Commit

Permalink
Merge pull request #1215 from angeloc/master
Browse files Browse the repository at this point in the history
src/context: get current bootslot on custom bootloader
  • Loading branch information
jluebbe committed Aug 30, 2023
2 parents 2fcbf8d + d238ad6 commit 3ad4979
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 1 deletion.
4 changes: 3 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,16 @@ EXTRA_DIST += tap-t \
test/sharness.sh \
test/system.conf \
test/test.conf \
test/test-custom.conf \
test/test-global.conf \
test/test-datadir.conf \
test/test-dummy-handler.conf \
test/get-coverity.sh \
test/openssl-ca-create.sh \
test/openssl-ca-check.sh \
test/openssl-enc-create.sh \
test/run-coverity.sh
test/run-coverity.sh \
test/custom-state-current

librauctest_la_SOURCES = \
test/common.c \
Expand Down
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,11 @@ AC_CONFIG_LINKS([test/rauc.t:test/rauc.t])
AC_CONFIG_LINKS([test/rootfs.raucs:test/rootfs.raucs])
AC_CONFIG_LINKS([test/sharness.sh:test/sharness.sh])
AC_CONFIG_LINKS([test/test.conf:test/test.conf])
AC_CONFIG_LINKS([test/test-custom.conf:test/test-custom.conf])
AC_CONFIG_LINKS([test/test-global.conf:test/test-global.conf])
AC_CONFIG_LINKS([test/test-datadir.conf:test/test-datadir.conf])
AC_CONFIG_LINKS([test/test-dummy-handler.conf:test/test-dummy-handler.conf])
AC_CONFIG_LINKS([test/custom-state-current:test/custom-state-current])

AC_CONFIG_FILES([
Makefile
Expand Down
17 changes: 17 additions & 0 deletions docs/integration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,16 @@ See the `systemd-veritysetup-generator documentation
<https://www.freedesktop.org/software/systemd/man/systemd-veritysetup-generator.html#systemd.verity_root_data=>`_
for details.

Identification via custom backend
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

When using the custom bootloader backend and the information about the
currently booted slot cannot be derived from the kernel command line,
RAUC will try to query the custom bootloader backend to get this information.

See the :ref:`sec-custom-bootloader-backend` bootloader section on how
to implement a custom bootloader handler.

Barebox
~~~~~~~

Expand Down Expand Up @@ -1114,6 +1124,7 @@ RAUC to trigger the following actions:
* set the primary slot
* get the boot state
* set the boot state
* get the current booted slot (optional)

To get the primary slot, the handler is called with the argument ``get-primary``.
The handler must output the current primary slot's bootname on the `stdout`,
Expand Down Expand Up @@ -1147,6 +1158,12 @@ The ``<state>`` argument corresponds to one of the following values:
The return value must be ``0`` if the boot state was set successfully,
or non-zero if an error occurred.

To get the current running slot, the handler must be called with the argument
``get-current``. The handler must output the current running slot's bootname on
the `stdout`, and return ``0`` on exit, if no error occurred. Implementing this
is only needed when the /proc/cmdline is not providing information about current
booted slot.

Init System and Service Startup
-------------------------------

Expand Down
1 change: 1 addition & 0 deletions src/config_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -906,5 +906,6 @@ void free_config(RaucConfig *config)
g_free(config->encryption_key);
g_free(config->encryption_cert);
g_clear_pointer(&config->slots, g_hash_table_destroy);
g_free(config->custom_bootloader_backend);
g_free(config);
}
55 changes: 55 additions & 0 deletions src/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,57 @@ static gchar* get_cmdline_bootname(void)
return bootname;
}

static gchar* get_custom_bootname(void)
{
g_autoptr(GSubprocessLauncher) launcher = NULL;
g_autoptr(GSubprocess) handle = NULL;
g_autoptr(GDataInputStream) datainstream = NULL;
g_autoptr(GPtrArray) args_array = NULL;
g_autofree gchar *outline = NULL;
GError *ierror = NULL;
GInputStream *instream;
int res;

args_array = g_ptr_array_new();
g_ptr_array_add(args_array, context->config->custom_bootloader_backend);
g_ptr_array_add(args_array, (gchar *)("get-current"));
g_ptr_array_add(args_array, NULL);

launcher = g_subprocess_launcher_new(G_SUBPROCESS_FLAGS_STDOUT_PIPE);
handle = r_subprocess_launcher_spawnv(launcher, args_array, NULL);

if (handle == NULL) {
g_message("Failed to run custom backend '%s'",
context->config->custom_bootloader_backend);
return NULL;
}

instream = g_subprocess_get_stdout_pipe(handle);
datainstream = g_data_input_stream_new(instream);

outline = g_data_input_stream_read_line(datainstream, NULL, NULL, &ierror);

if (ierror) {
g_message("Failed to read custom backend output");
return NULL;
}

res = g_subprocess_wait_check(handle, NULL, NULL);
if (!res) {
g_message("Failed to get custom backend output");
return NULL;
}

if (!outline) {
g_message("Failed to get custom backend bootname: no output");
return NULL;
}

g_debug("Resolved custom backend bootname to %s", outline);

return g_steal_pointer(&outline);
}

/**
* Launches a handler and obtains variables from output by looking for
* 'RAUC_<SOMETHING>=value' lines to put them into a key/value store (GHashTable).
Expand Down Expand Up @@ -362,6 +413,10 @@ static gboolean r_context_configure_target(GError **error)
context->bootslot = get_cmdline_bootname();
}

if (context->bootslot == NULL && (g_strcmp0(context->config->system_bootloader, "custom") == 0)) {
context->bootslot = get_custom_bootname();
}

g_clear_pointer(&context->boot_id, g_free);
g_clear_pointer(&context->machine_id, g_free);

Expand Down
9 changes: 9 additions & 0 deletions test/bin/custom-bootloader-script
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ function custom_set_primary ()
sed -i "s/\(PRIMARY=\).*/\1${bootname}/" "${CUSTOM_STATE_PATH}"
}

function custom_get_current ()
{
echo $(grep CURRENT "$CUSTOM_STATE_PATH" | sed 's/.*=\(.*\)/\1/')
}


if [ "$1" = "get-state" ]; then
shift
custom_get_state "$@"
Expand All @@ -45,4 +51,7 @@ elif [ "$1" = "get-primary" ]; then
elif [ "$1" = "set-primary" ]; then
shift
custom_set_primary "$@"
elif [ "$1" = "get-current" ]; then
shift
custom_get_current "$@"
fi
15 changes: 15 additions & 0 deletions test/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,19 @@ static void test_bootslot_no_bootslot(void)
r_context_clean();
}

static void test_bootslot_custom_bootloader(void)
{
r_context_conf()->configpath = g_strdup("test/test-custom.conf");
r_context_conf()->configmode = R_CONTEXT_CONFIG_MODE_REQUIRED;
g_assert_true(g_setenv("CUSTOM_STATE_PATH", "test/custom-state-current", TRUE));
r_context_conf()->mock.proc_cmdline = "quiet";
g_clear_pointer(&r_context_conf()->bootslot, g_free);

g_assert_cmpstr(r_context()->bootslot, ==, "A");

r_context_clean();
}


/* Tests that the infos provided by the configured system-info handler make it
* into RAUC's system information.
Expand Down Expand Up @@ -125,6 +138,8 @@ int main(int argc, char *argv[])

g_test_add_func("/context/bootslot/no-bootslot", test_bootslot_no_bootslot);

g_test_add_func("/context/bootslot/custom-bootslot", test_bootslot_custom_bootloader);

g_test_add_func("/context/system-info", test_context_system_info);

g_test_add_func("/context/system-info-dummy", test_context_system_info_dummy);
Expand Down
1 change: 1 addition & 0 deletions test/custom-state-current
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CURRENT=A
23 changes: 23 additions & 0 deletions test/test-custom.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# testsuite system configuration

[system]
compatible=Test Config
bootloader=custom
variant-name=Default Variant

[handlers]
bootloader-custom-backend=bin/custom-bootloader-script

[keyring]
path=openssl-ca/dev-ca.pem
check-crl=true

[slot.rootfs.0]
device=images/rootfs-0
type=raw
bootname=system0

[slot.rootfs.1]
device=images/rootfs-1
type=raw
bootname=system1

0 comments on commit 3ad4979

Please sign in to comment.