Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/htool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,10 @@ static const struct htool_cmd CMDS[] = {
.desc = "A .fwupdate file compatible with this device."},
{HTOOL_FLAG_VALUE, .name = "reset",
.desc = "warm, cold, or none", .default_value = "warm"},
{HTOOL_FLAG_BOOL, .ch = 'f', .name = "force",
.default_value = "false",
.desc = "always attempt dfu update twice regardless of the "
"RoT state"},
{}},
.func = htool_dfu_update,
},
Expand Down
99 changes: 54 additions & 45 deletions examples/htool_dfu.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,47 @@
#include "protocol/dfu_hostcmd.h"
#include "protocol/opentitan_version.h"

static int dfu_update_count(struct opentitan_image_version* desired_romext,
struct opentitan_image_version* desired_app,
struct opentitan_get_version_resp* resp) {
// Determine the stage slot for each ot get version to compare
uint32_t rom_ext_boot_slot = bootslot_int(resp->rom_ext.booted_slot);
uint32_t rom_ext_stage_slot = rom_ext_boot_slot == 0 ? 1 : 0;
uint32_t app_boot_slot = bootslot_int(resp->app.booted_slot);
uint32_t app_stage_slot = app_boot_slot == 0 ? 1 : 0;

struct opentitan_image_version* booted_romext =
&resp->rom_ext.slots[rom_ext_boot_slot];
struct opentitan_image_version* staged_romext =
&resp->rom_ext.slots[rom_ext_stage_slot];
struct opentitan_image_version* booted_app = &resp->app.slots[app_boot_slot];
struct opentitan_image_version* staged_app = &resp->app.slots[app_stage_slot];

bool booted_needs_update =
!libhoth_ot_version_eq(booted_app, desired_app) ||
!libhoth_ot_version_eq(booted_romext, desired_romext);

if (booted_needs_update) {
printf(
"The current bootslot is not the desired version. Performing DFU "
"update x2...\n");
return 2;
}

bool staging_needs_update =
!libhoth_ot_version_eq(staged_app, desired_app) ||
!libhoth_ot_version_eq(staged_romext, desired_romext);

if (staging_needs_update) {
printf(
"Only the staging slot needs updating. Performing DFU update x1...\n ");
return 1;
}

printf("Device is already at the desired version. No DFU update needed.\n");
return 0;
}

int htool_dfu_update(const struct htool_invocation* inv) {
struct libhoth_device* dev = htool_libhoth_device();
if (!dev) {
Expand Down Expand Up @@ -59,6 +100,11 @@ int htool_dfu_update(const struct htool_invocation* inv) {
return -1;
}

bool force;
if (htool_get_param_bool(inv, "force", &force)) {
return -1;
}

const char* fwupdate_file;
if (htool_get_param_string(inv, "fwupdate-file", &fwupdate_file)) {
return -1;
Expand Down Expand Up @@ -106,52 +152,15 @@ int htool_dfu_update(const struct htool_invocation* inv) {
goto cleanup2;
}

// Determine the stage slot for each ot get version to compare
uint32_t rom_ext_boot_slot = bootslot_int(resp.rom_ext.booted_slot);
uint32_t rom_ext_stage_slot = rom_ext_boot_slot == 0 ? 1 : 0;
uint32_t app_boot_slot = bootslot_int(resp.app.booted_slot);
uint32_t app_stage_slot = app_boot_slot == 0 ? 1 : 0;
int update_cnt =
force ? 2 : dfu_update_count(&desired_rom_ext, &desired_app, &resp);

// Compare the desired version with the current bootslot version
// If they are different, we need to automatically perform the x2 update
// If both are the same & the staged slot is different, we need to perform a
// single update For all other cases, no update is needed
if (libhoth_ot_version_eq(&resp.rom_ext.slots[rom_ext_boot_slot],
&desired_rom_ext) == false ||
libhoth_ot_version_eq(&resp.app.slots[app_boot_slot], &desired_app) ==
false) {
printf(
"The current bootslot is not the desired version. Performing DFU "
"update x2...\n");
// Peform the DFU update twice to update both slots
// First update will stage to the non-booted slot, second update correct the
// newly staged slot.
for (int i = 0; i < 2; i++) {
retval = libhoth_dfu_update(dev, image, statbuf.st_size, complete_flags);

if (retval != 0) {
fprintf(stderr, "DFU update failed\n");
goto cleanup2;
}
}
} else {
if (libhoth_ot_version_eq(&resp.rom_ext.slots[rom_ext_stage_slot],
&desired_rom_ext) == false ||
libhoth_ot_version_eq(&resp.app.slots[app_stage_slot], &desired_app) ==
false) {
printf(
"The staged slot is not the desired version. Performing DFU update "
"x1...\n");
// Perform a single DFU update to update the staged slot
retval = libhoth_dfu_update(dev, image, statbuf.st_size, complete_flags);

if (retval != 0) {
fprintf(stderr, "DFU update failed\n");
goto cleanup2;
}
} else {
printf(
"Device is already at the desired version. No DFU update needed.\n");
for (int i = 0; i < update_cnt; i++) {
retval = libhoth_dfu_update(dev, image, statbuf.st_size, complete_flags);

if (retval != 0) {
fprintf(stderr, "DFU update failed\n");
goto cleanup2;
}
}

Expand Down
Loading