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
1 change: 1 addition & 0 deletions examples/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ cc_binary(
"//protocol:chipinfo",
"//protocol:controlled_storage",
"//protocol:dfu_hostcmd",
"//protocol:dfu_check",
"//protocol:hello",
"//protocol:host_cmd",
"//protocol:i2c",
Expand Down
10 changes: 10 additions & 0 deletions examples/htool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,16 @@ static const struct htool_cmd CMDS[] = {
{}},
.func = htool_dfu_update,
},
{
.verbs = (const char*[]){"dfu", "check", NULL},
.desc = "Check that the device is running firmware matching a fwupdate bundle.",
.params =
(const struct htool_param[]){
{HTOOL_POSITIONAL, .name = "fwupdate-file",
.desc = "A .fwupdate file compatible with this device."},
{}},
.func = htool_dfu_check,
},
{.verbs = (const char*[]){"flash_spi_info", NULL},
.desc = "Get SPI NOR flash info.",
.params = (const struct htool_param[]){{}},
Expand Down
66 changes: 66 additions & 0 deletions examples/htool_dfu.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "htool_cmd.h"
#include "protocol/dfu_hostcmd.h"
#include "protocol/opentitan_version.h"
#include "protocol/dfu_check.h"

int htool_dfu_update(const struct htool_invocation* inv) {
struct libhoth_device* dev = htool_libhoth_device();
Expand Down Expand Up @@ -149,4 +150,69 @@ int htool_dfu_update(const struct htool_invocation* inv) {
}

return retval;
}

int htool_dfu_check(const struct htool_invocation* inv) {
struct libhoth_device* dev = htool_libhoth_device();
if (!dev) {
return -1;
}

struct opentitan_get_version_resp resp = {0};

const char* fwupdate_file;
if (htool_get_param_string(inv, "fwupdate-file", &fwupdate_file)) {
return -1;
}

int fd = open(fwupdate_file, O_RDONLY, 0);
if (fd == -1) {
fprintf(stderr, "Error opening file %s: %s\n", fwupdate_file,
strerror(errno));
return -1;
}

int retval = -1;

struct stat statbuf;
if (fstat(fd, &statbuf)) {
fprintf(stderr, "fstat error: %s\n", strerror(errno));
goto cleanup;
}
if (statbuf.st_size > SIZE_MAX) {
fprintf(stderr, "file too large\n");
goto cleanup;
}

uint8_t* image = mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (image == MAP_FAILED) {
fprintf(stderr, "mmap error: %s\n", strerror(errno));
goto cleanup;
}

if (libhoth_opentitan_version(dev, &resp) != 0) {
fprintf(stderr, "Failed to get current version\n");
goto cleanup2;
}

if (libhoth_dfu_check(image, statbuf.st_size, &resp) != 0) {
fprintf(stderr, "DFU check failed.\n");
goto cleanup2;
}

retval = 0;

int ret;
cleanup2:
ret = munmap(image, statbuf.st_size);
if (ret != 0) {
fprintf(stderr, "munmap error: %d\n", ret);
}

cleanup:
ret = close(fd);
if (ret != 0) {
fprintf(stderr, "close error: %d\n", ret);
}
return retval;
}
1 change: 1 addition & 0 deletions examples/htool_dfu.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ extern "C" {
struct htool_invocation;

int htool_dfu_update(const struct htool_invocation* inv);
int htool_dfu_check(const struct htool_invocation* inv);

#ifdef __cplusplus
}
Expand Down
11 changes: 11 additions & 0 deletions protocol/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -433,4 +433,15 @@ cc_library(
":host_cmd",
"//transports:libhoth_device",
],
)

cc_library(
name = "dfu_check",
srcs = ["dfu_check.c"],
hdrs = ["dfu_check.h",
"opentitan_version.h"],
deps = [
":host_cmd",
"//transports:libhoth_device",
],
)
55 changes: 55 additions & 0 deletions protocol/dfu_check.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

#include "dfu_check.h"

#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
// for MIN()
#include <sys/param.h>
#include <sys/random.h>
#include <time.h>
#include <unistd.h>

#include "protocol/host_cmd.h"
#include "protocol/opentitan_version.h"

int libhoth_dfu_check(const uint8_t* image, size_t image_size, struct opentitan_get_version_resp * resp) {

int retval = 0;
struct opentitan_image_version desired_rom_ext = {0};
struct opentitan_image_version desired_app = {0};

// Populate rom_ext and app with the desired extracted versions from the image
retval = libhoth_extract_ot_bundle(image, &desired_rom_ext, &desired_app);

if(retval != 0) {
fprintf(stderr, "Failed to extract bundle\n");
}

// 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;

bool booted_slot_eq = libhoth_ot_version_eq(&resp->rom_ext.slots[rom_ext_boot_slot], &desired_rom_ext) && libhoth_ot_version_eq(&resp->app.slots[app_boot_slot], &desired_app);
if(!booted_slot_eq) {
// TODO print failure message
printf("Booted slot does not match desired version.\n");
return -1;
}

bool staging_slot_eq = libhoth_ot_version_eq(&resp->rom_ext.slots[rom_ext_stage_slot], &desired_rom_ext) && libhoth_ot_version_eq(&resp->app.slots[app_stage_slot], &desired_app);
if(!staging_slot_eq) {
// TODO print failure message
printf("Staging slot does not match desired version.\n");
return -1;
}

return 0;

}
31 changes: 31 additions & 0 deletions protocol/dfu_check.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef LIBHOTH_EXAMPLES_HTOOL_DFU_CHECK_H_
#define LIBHOTH_EXAMPLES_HTOOL_DFU_CHECK_H_

#include <stdint.h>
#include <stddef.h>
#include "protocol/opentitan_version.h"

#ifdef __cplusplus
extern "C" {
#endif

int libhoth_dfu_check(const uint8_t* image, size_t image_size, struct opentitan_get_version_resp * resp);
#ifdef __cplusplus
}
#endif

#endif // LIBHOTH_EXAMPLES_HTOOL_DFU_CHECKH_
1 change: 1 addition & 0 deletions protocol/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ protocol_srcs = [
'secure_boot.c',
'command_version.c',
'dfu_hostcmd.c',
'dfu_check.c',
]

incdir = include_directories('..')
Expand Down
Loading