Skip to content

Commit b16c75e

Browse files
committed
[examples] Add DFU update check
We seek to add a DFU update check to be able to examine a fwupdate file without making any new modifications to it. This would allows generate some formated text and errors. Signed-off-by: Ellis Sarza-Nguyen <sarzanguyen@google.com>
1 parent b5d251f commit b16c75e

7 files changed

Lines changed: 177 additions & 0 deletions

File tree

examples/htool.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,18 @@ static const struct htool_cmd CMDS[] = {
10051005
{}},
10061006
.func = htool_dfu_update,
10071007
},
1008+
{
1009+
.verbs = (const char*[]){"dfu", "check", NULL},
1010+
.desc = "Check a PIE-RoT fwupdate.",
1011+
.params =
1012+
(const struct htool_param[]){
1013+
{HTOOL_POSITIONAL, .name = "fwupdate-file",
1014+
.desc = "A .fwupdate file compatible with this device."},
1015+
{HTOOL_FLAG_VALUE, .name = "reset",
1016+
.desc = "warm, cold, or none", .default_value = "warm"},
1017+
{}},
1018+
.func = htool_dfu_check,
1019+
},
10081020
{.verbs = (const char*[]){"flash_spi_info", NULL},
10091021
.desc = "Get SPI NOR flash info.",
10101022
.params = (const struct htool_param[]){{}},

examples/htool_dfu.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,70 @@ int htool_dfu_update(const struct htool_invocation* inv) {
9090
}
9191
return retval;
9292
}
93+
94+
int htool_dfu_check(const struct htool_invocation* inv) {
95+
struct libhoth_device* dev = htool_libhoth_device();
96+
if (!dev) {
97+
return -1;
98+
}
99+
100+
struct opentitan_get_version_resp resp = {0};
101+
uint32_t complete_flags = 0;
102+
const char* reset_arg;
103+
104+
const char* fwupdate_file;
105+
if (htool_get_param_string(inv, "fwupdate-file", &fwupdate_file)) {
106+
return -1;
107+
}
108+
109+
int fd = open(fwupdate_file, O_RDONLY, 0);
110+
if (fd == -1) {
111+
fprintf(stderr, "Error opening file %s: %s\n", fwupdate_file,
112+
strerror(errno));
113+
return -1;
114+
}
115+
116+
int retval = -1;
117+
118+
struct stat statbuf;
119+
if (fstat(fd, &statbuf)) {
120+
fprintf(stderr, "fstat error: %s\n", strerror(errno));
121+
goto cleanup;
122+
}
123+
if (statbuf.st_size > SIZE_MAX) {
124+
fprintf(stderr, "file too large\n");
125+
goto cleanup;
126+
}
127+
128+
uint8_t* image = mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
129+
if (image == MAP_FAILED) {
130+
fprintf(stderr, "mmap error: %s\n", strerror(errno));
131+
goto cleanup;
132+
}
133+
134+
if (libhoth_opentitan_version(dev, &resp) != 0) {
135+
fprintf(stderr, "Failed to get current version\n");
136+
goto cleanup2;
137+
}
138+
139+
if (libhoth_dfu_check(dev, image, statbuf.st_size, &resp) != 0) {
140+
fprintf(stderr, "DFU check failed.\n");
141+
goto cleanup2;
142+
}
143+
144+
retval = 0;
145+
146+
int ret;
147+
cleanup2:
148+
ret = munmap(image, statbuf.st_size);
149+
if (ret != 0) {
150+
fprintf(stderr, "munmap error: %d\n", ret);
151+
}
152+
153+
cleanup:
154+
ret = close(fd);
155+
if (ret != 0) {
156+
fprintf(stderr, "close error: %d\n", ret);
157+
}
158+
return retval;
159+
}

examples/htool_dfu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ extern "C" {
2222
struct htool_invocation;
2323

2424
int htool_dfu_update(const struct htool_invocation* inv);
25+
int htool_dfu_check(const struct htool_invocation* inv);
2526

2627
#ifdef __cplusplus
2728
}

protocol/BUILD

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,4 +433,14 @@ cc_library(
433433
":host_cmd",
434434
"//transports:libhoth_device",
435435
],
436+
)
437+
438+
cc_library(
439+
name = "dfu_check",
440+
srcs = ["dfu_check.c"],
441+
hdrs = ["dfu_check.h"],
442+
deps = [
443+
":host_cmd",
444+
"//transports:libhoth_device",
445+
],
436446
)

protocol/dfu_check.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
2+
#include "dfu_check.h"
3+
4+
#include <assert.h>
5+
#include <stdbool.h>
6+
#include <stddef.h>
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
#include <string.h>
10+
// for MIN()
11+
#include <sys/param.h>
12+
#include <sys/random.h>
13+
#include <time.h>
14+
#include <unistd.h>
15+
16+
#include "protocol/host_cmd.h"
17+
#include "protocol/opentitan_version.h"
18+
19+
int libhoth_dfu_check(struct libhoth_device* dev, const uint8_t* image,
20+
size_t image_size, struct opentitan_get_version_resp resp) {
21+
22+
int retval = 0;
23+
struct opentitan_image_version desired_rom_ext = {0};
24+
struct opentitan_image_version desired_app = {0};
25+
26+
// Populate rom_ext and app with the desired extracted versions from the image
27+
retval = libhoth_extract_ot_bundle(image, &desired_rom_ext, &desired_app);
28+
29+
if(retval != 0) {
30+
fprintf(stderr, "Failed to extract bundle\n");
31+
}
32+
33+
// Determine the stage slot for each ot get version to compare
34+
uint32_t rom_ext_boot_slot = bootslot_int(resp.rom_ext.booted_slot);
35+
uint32_t rom_ext_stage_slot = rom_ext_boot_slot == 0 ? 1 : 0;
36+
uint32_t app_boot_slot = bootslot_int(resp.app.booted_slot);
37+
uint32_t app_stage_slot = app_boot_slot == 0 ? 1 : 0;
38+
39+
// Compare the desired version with the current bootslot version
40+
// If they are different, we need to automatically perform the x2 update
41+
// If both are the same & the staged slot is different, we need to perform a single update
42+
// For all other cases, no update is needed
43+
if(libhoth_ot_version_eq(&resp.rom_ext.slots[rom_ext_boot_slot], &desired_rom_ext) == 0 ||
44+
libhoth_ot_version_eq(&resp.app.slots[app_boot_slot], &desired_app) == 0 ) {
45+
printf("The current bootslot is not the desired version.\n");
46+
47+
}
48+
else{
49+
if(libhoth_ot_version_eq(&resp.rom_ext.slots[rom_ext_stage_slot], &desired_rom_ext) == 0 ||
50+
libhoth_ot_version_eq(&resp.app.slots[app_stage_slot], &desired_app) == 0 ) {
51+
printf("The staged slot is not the desired version.\n");
52+
}
53+
else{
54+
printf("Device is already at the desired version.\n");
55+
}
56+
}
57+
58+
}

protocol/dfu_check.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef LIBHOTH_EXAMPLES_HTOOL_DFU_CHECK_H_
16+
#define LIBHOTH_EXAMPLES_HTOOL_DFU_CHECK_H_
17+
18+
#ifdef __cplusplus
19+
extern "C" {
20+
#endif
21+
22+
int libhoth_dfu_check(struct libhoth_device* dev, const uint8_t* image,
23+
size_t image_size, struct opentitan_get_version_resp resp);
24+
#ifdef __cplusplus
25+
}
26+
#endif
27+
28+
#endif // LIBHOTH_EXAMPLES_HTOOL_DFU_CHECKH_

protocol/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ protocol_srcs = [
2020
'secure_boot.c',
2121
'command_version.c',
2222
'dfu_hostcmd.c',
23+
'dfu_check.c',
2324
]
2425

2526
incdir = include_directories('..')

0 commit comments

Comments
 (0)