Skip to content

Commit

Permalink
Merge pull request #45 from jluebbe/uboot-support
Browse files Browse the repository at this point in the history
bootchooser: add support for uboot via fw_setenv
  • Loading branch information
Enrico Jorns committed May 4, 2016
2 parents ed36b58 + 9760752 commit ce900eb
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 1 deletion.
39 changes: 39 additions & 0 deletions contrib/uboot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
test -n "${BOOT_ORDER}" || setenv BOOT_ORDER "A B"
test -n "${BOOT_A_LEFT}" || setenv BOOT_A_LEFT 3
test -n "${BOOT_B_LEFT}" || setenv BOOT_B_LEFT 3

setenv bootargs
for BOOT_SLOT in "${BOOT_ORDER}"; do
if test "x${bootargs}" != "x"; then
# skip remaining slots
elif test "x${BOOT_SLOT}" = "xA"; then
if test ${BOOT_A_LEFT} -gt 0; then
expr BOOT_A_LEFT ${BOOT_A_LEFT} - 1
echo "Found valid slot A, ${BOOT_A_LEFT} attempts remaining"
setenv load_kernel "nand read ${kernel_loadaddr} ${kernel_a_nandoffset} ${kernel_size}"
setenv bootargs "${default_bootargs} root=/dev/mmcblk0p1 rauc.slot=A"
fi
elif test "x${BOOT_SLOT}" = "xB"; then
if test ${BOOT_B_LEFT} -gt 0; then
expr BOOT_B_LEFT ${BOOT_B_LEFT} - 1
echo "Found valid slot B, ${BOOT_B_LEFT} attempts remaining"
setenv load_kernel "nand read ${kernel_loadaddr} ${kernel_b_nandoffset} ${kernel_size}"
setenv bootargs "${default_bootargs} root=/dev/mmcblk0p2 rauc.slot=B"
fi
fi
done

if test -n "${bootargs}"; then
saveenv
else
echo "No vaild slot found, resetting tries to 3"
setenv BOOT_A_LEFT 3
setenv BOOT_B_LEFT 3
saveenv
reset
fi

echo "Loading kernel"
run load_kernel
echo " Starting kernel"
bootm ${loadaddr_kernel}
95 changes: 95 additions & 0 deletions src/bootchooser.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "install.h"

#define BAREBOX_STATE_NAME "barebox-state"
#define UBOOT_FWSETENV_NAME "fw_setenv"

#if 0
static gboolean barebox_state_get_int(const gchar* name, int *value) {
Expand Down Expand Up @@ -279,11 +280,103 @@ static gboolean grub_set_primary(RaucSlot *slot) {
return res;
}

static gboolean uboot_env_set(const gchar *key, const gchar *value) {
GSubprocess *sub;
GError *error = NULL;
gboolean res = FALSE;

g_assert_nonnull(key);
g_assert_nonnull(value);

sub = g_subprocess_new(G_SUBPROCESS_FLAGS_NONE, &error, UBOOT_FWSETENV_NAME,
key, value, NULL);
if (!sub) {
g_warning("starting fw_setenv failed: %s", error->message);
g_clear_error(&error);
goto out;
}

res = g_subprocess_wait_check(sub, NULL, &error);
if (!res) {
g_warning("fw_setenv failed: %s", error->message);
g_clear_error(&error);
goto out;
}

out:
return res;
}

/* Set slot status values */
static gboolean uboot_set_state(RaucSlot *slot, gboolean good) {
gboolean res = FALSE;
gchar *key = NULL;

g_assert_nonnull(slot);

key = g_strdup_printf("BOOT_%s_LEFT", slot->bootname);

res = uboot_env_set(key, good ? "3" : "0");
if (!res) {
g_warning("failed marking as %s", good ? "good" : "bad");
goto out;
}

out:
g_free(key);
return res;
}

/* Set slot as primary boot slot */
static gboolean uboot_set_primary(RaucSlot *slot) {
GString *order = g_string_sized_new(10);
gboolean res = FALSE;
gchar *key = NULL;
GList *slots;

g_assert_nonnull(slot);

g_string_append(order, slot->bootname);

/* Iterate over class members */
slots = g_hash_table_get_values(r_context()->config->slots);
for (GList *l = slots; l != NULL; l = l->next) {
RaucSlot *s = l->data;
if (s == slot)
continue;
if (s->sclass != slot->sclass)
continue;

g_string_append_c(order, ' ');
g_string_append(order, s->bootname);
}

key = g_strdup_printf("BOOT_%s_LEFT", slot->bootname);

res = uboot_env_set(key, "3");
if (!res) {
g_warning("failed marking as good");
goto out;
}
res = uboot_env_set("BOOT_ORDER", order->str);
if (!res) {
g_warning("failed marking as primary");
goto out;
}

out:
g_string_free(order, TRUE);
g_free(key);
return res;
}

gboolean r_boot_set_state(RaucSlot *slot, gboolean good) {
if (g_strcmp0(r_context()->config->system_bootloader, "barebox") == 0) {
return barebox_set_state(slot, good);
} else if (g_strcmp0(r_context()->config->system_bootloader, "grub") == 0) {
return grub_set_state(slot, good);
} else if (g_strcmp0(r_context()->config->system_bootloader, "uboot") == 0) {
return uboot_set_state(slot, good);
}

g_error("bootloader type '%s' not supported yet", r_context()->config->system_bootloader);
Expand All @@ -295,6 +388,8 @@ gboolean r_boot_set_primary(RaucSlot *slot) {
return barebox_set_primary(slot);
} else if (g_strcmp0(r_context()->config->system_bootloader, "grub") == 0) {
return grub_set_primary(slot);
} else if (g_strcmp0(r_context()->config->system_bootloader, "uboot") == 0) {
return uboot_set_primary(slot);
}

g_error("bootloader type '%s' not supported yet", r_context()->config->system_bootloader);
Expand Down
2 changes: 1 addition & 1 deletion src/config_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ gboolean default_config(RaucConfig **config) {
return TRUE;
}

static const gchar *supported_bootloaders[] = {"barebox", "grub", NULL};
static const gchar *supported_bootloaders[] = {"barebox", "grub", "uboot", NULL};

gboolean load_config(const gchar *filename, RaucConfig **config, GError **error) {
GError *ierror = NULL;
Expand Down
29 changes: 29 additions & 0 deletions test/bin/fw_setenv
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash

# Command line checking
if [ $# -ne 2 ]; then
echo "Invalid arguments $*"
exit 1
fi

if [ "$1" = "BOOT_ORDER" ]; then
if ! [ "$2" = "A B" -o "$2" = "B A" ]; then
echo "Invalid argument for BOOT_ORDER: '$2'"
exit 1
fi
elif [ "$1" = "BOOT_A_LEFT" ]; then
if ! [ "$2" -ge 0 -a "$2" -le 3 ]; then
echo "Invalid argument for BOOT_A_LEFT: '$2'"
exit 1
fi
elif [ "$1" = "BOOT_B_LEFT" ]; then
if ! [ "$2" -ge 0 -a "$2" -le 3 ]; then
echo "Invalid argument for BOOT_B_LEFT: '$2'"
exit 1
fi
else
echo "Invalid key: '$1'"
exit 1
fi

exit 0
53 changes: 53 additions & 0 deletions test/bootchooser.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,55 @@ bootname=B\n";
g_assert_true(r_boot_set_primary(slot));
}

static void bootchooser_uboot(BootchooserFixture *fixture,
gconstpointer user_data)
{
RaucSlot *slot;

const gchar *cfg_file = "\
[system]\n\
compatible=FooCorp Super BarBazzer\n\
bootloader=uboot\n\
mountprefix=/mnt/myrauc/\n\
\n\
[keyring]\n\
path=/etc/rauc/keyring/\n\
\n\
[slot.rescue.0]\n\
device=/dev/mtd4\n\
type=raw\n\
bootname=R\n\
readonly=true\n\
\n\
[slot.rootfs.0]\n\
device=/dev/sda0\n\
type=ext4\n\
bootname=A\n\
\n\
[slot.rootfs.1]\n\
device=/dev/sda1\n\
type=ext4\n\
bootname=B\n";

gchar* pathname = write_tmp_file(fixture->tmpdir, "uboot.conf", cfg_file, NULL);
g_assert_nonnull(pathname);

g_clear_pointer(&r_context_conf()->configpath, g_free);
r_context_conf()->configpath = pathname;
r_context();

slot = find_config_slot_by_device(r_context()->config, "/dev/sda0");
g_assert_nonnull(slot);

g_assert_true(r_boot_set_state(slot, TRUE));
g_assert_true(r_boot_set_state(slot, FALSE));

slot = find_config_slot_by_device(r_context()->config, "/dev/sda1");
g_assert_nonnull(slot);

g_assert_true(r_boot_set_primary(slot));
}

int main(int argc, char *argv[])
{
gchar *path;
Expand All @@ -144,5 +193,9 @@ int main(int argc, char *argv[])
bootchooser_fixture_set_up, bootchooser_grub,
bootchooser_fixture_tear_down);

g_test_add("/bootchoser/uboot", BootchooserFixture, NULL,
bootchooser_fixture_set_up, bootchooser_uboot,
bootchooser_fixture_tear_down);

return g_test_run ();
}

0 comments on commit ce900eb

Please sign in to comment.