Skip to content

Commit c8b444c

Browse files
committed
[examples] Modify DFU update to add skip logic
For htools dfu, we seek to add some type of logic to skip an update. With the opentitan get version, we can compare the versions and make the decision to proceed or return with no actions. Signed-off-by: Ellis Sarza-Nguyen <sarzanguyen@google.com>
1 parent b5d251f commit c8b444c

4 files changed

Lines changed: 153 additions & 14 deletions

File tree

examples/htool_dfu.c

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@
1414
#include "htool.h"
1515
#include "htool_cmd.h"
1616
#include "protocol/dfu_hostcmd.h"
17+
#include "protocol/opentitan_version.h"
1718

1819
int htool_dfu_update(const struct htool_invocation* inv) {
1920
struct libhoth_device* dev = htool_libhoth_device();
2021
if (!dev) {
2122
return -1;
2223
}
2324

25+
struct opentitan_image_version desired_rom_ext = {0};
26+
struct opentitan_image_version desired_app = {0};
27+
struct opentitan_get_version_resp resp = {0};
28+
2429
uint32_t complete_flags = 0;
2530
const char* reset_arg;
2631
if (htool_get_param_string(inv, "reset", &reset_arg)) {
@@ -68,25 +73,80 @@ int htool_dfu_update(const struct htool_invocation* inv) {
6873
if (image == MAP_FAILED) {
6974
fprintf(stderr, "mmap error: %s\n", strerror(errno));
7075
goto cleanup;
76+
}
77+
78+
// Populate rom_ext and app with the desired extracted versions from the image
79+
retval = libhoth_extract_ot_bundle(image, &desired_rom_ext, &desired_app);
80+
81+
if(retval != 0) {
82+
fprintf(stderr, "Failed to extract bundle\n");
83+
goto cleanup2;
7184
}
7285

73-
if (libhoth_dfu_update(dev, image, statbuf.st_size, complete_flags) != 0) {
74-
fprintf(stderr, "DFU update failed.\n");
86+
// Get the current version of the device
87+
retval = libhoth_opentitan_version(dev, &resp);
88+
89+
if(retval != 0) {
90+
fprintf(stderr, "Failed to get current version\n");
7591
goto cleanup2;
7692
}
77-
retval = 0;
93+
94+
// Determine the stage slot for each ot get version to compare
95+
uint32_t rom_ext_boot_slot = bootslot_int(resp.rom_ext.booted_slot);
96+
uint32_t rom_ext_stage_slot = rom_ext_boot_slot == 0 ? 1 : 0;
97+
uint32_t app_boot_slot = bootslot_int(resp.app.booted_slot);
98+
uint32_t app_stage_slot = app_boot_slot == 0 ? 1 : 0;
99+
100+
// Compare the desired version with the current bootslot version
101+
// If they are different, we need to automatically perform the x2 update
102+
// If both are the same & the staged slot is different, we need to perform a single update
103+
// For all other cases, no update is needed
104+
if(libhoth_ot_version_eq(&resp.rom_ext.slots[rom_ext_boot_slot], &desired_rom_ext) == false ||
105+
libhoth_ot_version_eq(&resp.app.slots[app_boot_slot], &desired_app) == false ) {
106+
printf("The current bootslot is not the desired version. Performing DFU update x2...\n");
107+
// Peform the DFU update twice to update both slots
108+
// First update will stage to the non-booted slot, second update correct the newly staged slot.
109+
for(int i = 0; i < 2; i++){
110+
retval = libhoth_dfu_update(
111+
dev, image, statbuf.st_size, complete_flags);
112+
113+
if(retval != 0) {
114+
fprintf(stderr, "DFU update failed\n");
115+
goto cleanup2;
116+
}
117+
}
118+
}
119+
else{
120+
if(libhoth_ot_version_eq(&resp.rom_ext.slots[rom_ext_stage_slot], &desired_rom_ext) == false ||
121+
libhoth_ot_version_eq(&resp.app.slots[app_stage_slot], &desired_app) == false ) {
122+
printf("The staged slot is not the desired version. Performing DFU update x1...\n");
123+
// Perform a single DFU update to update the staged slot
124+
retval = libhoth_dfu_update(
125+
dev, image, statbuf.st_size, complete_flags);
126+
127+
if(retval != 0) {
128+
fprintf(stderr, "DFU update failed\n");
129+
goto cleanup2;
130+
}
131+
}
132+
else{
133+
printf("Device is already at the desired version. No DFU update needed.\n");
134+
}
135+
}
78136

79137
int ret;
80-
cleanup2:
81-
ret = munmap(image, statbuf.st_size);
82-
if (ret != 0) {
83-
fprintf(stderr, "munmap error: %d\n", ret);
84-
}
85138

86-
cleanup:
87-
ret = close(fd);
88-
if (ret != 0) {
89-
fprintf(stderr, "close error: %d\n", ret);
90-
}
139+
cleanup2:
140+
ret = munmap(image, statbuf.st_size);
141+
if (ret != 0) {
142+
fprintf(stderr, "munmap error: %d\n", ret);
143+
}
144+
145+
cleanup:
146+
ret = close(fd);
147+
if (ret != 0) {
148+
fprintf(stderr, "close error: %d\n", ret);
149+
}
150+
91151
return retval;
92-
}
152+
}

examples/htool_dfu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#ifndef LIBHOTH_EXAMPLES_HTOOL_DFU_H_
1616
#define LIBHOTH_EXAMPLES_HTOOL_DFU_H_
1717

18+
#include "protocol/opentitan_version.h"
19+
1820
#ifdef __cplusplus
1921
extern "C" {
2022
#endif

protocol/opentitan_version.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414

1515
#include <stddef.h>
16+
#include <stdbool.h>
1617

1718
#include "opentitan_version.h"
1819

@@ -32,6 +33,51 @@ int libhoth_opentitan_version(struct libhoth_device * dev,
3233
return rv;
3334
}
3435

36+
int libhoth_extract_ot_bundle(const uint8_t* image,
37+
struct opentitan_image_version * rom_ext,
38+
struct opentitan_image_version * app) {
39+
40+
// Check if the image is valid
41+
if(image == NULL) {
42+
fprintf(stderr, "Image is NULL\n");
43+
return -1;
44+
}
45+
46+
// Check if the image has the correct magic number
47+
char magic[] = "_OTFWUPDATE_";
48+
for(int i = 0; i < (sizeof(magic) - 1); i++) {
49+
if(image[i] != magic[i]) {
50+
fprintf(stderr, "Image does not have the correct magic number\n");
51+
return -1;
52+
}
53+
}
54+
55+
// Extract the offset that contains the ROM_EXT version information
56+
// We will have the desired ROM_EXT version be stored on slot index 0 and keep slot index 1 with 0xDEADBEEF
57+
uint32_t offset = (image[OPENTITAN_OFFSET_HEADER_DATA] | image[OPENTITAN_OFFSET_HEADER_DATA + 1] << 8 | image[OPENTITAN_OFFSET_HEADER_DATA + 2] << 16 | image[OPENTITAN_OFFSET_HEADER_DATA + 3] << 24);
58+
rom_ext->major = image[offset + OPENTITAN_OFFSET_VERSION_MAJOR] | image[offset + OPENTITAN_OFFSET_VERSION_MAJOR + 1] << 8 | image[offset + OPENTITAN_OFFSET_VERSION_MAJOR + 2] << 16 | image[offset + OPENTITAN_OFFSET_VERSION_MAJOR + 3] << 24;
59+
rom_ext->minor = image[offset + OPENTITAN_OFFSET_VERSION_MINOR] | image[offset + OPENTITAN_OFFSET_VERSION_MINOR + 1] << 8 | image[offset + OPENTITAN_OFFSET_VERSION_MINOR + 2] << 16 | image[offset + OPENTITAN_OFFSET_VERSION_MINOR + 3] << 24;
60+
61+
// Extract the offset that contains the APP version information
62+
// We will have the desired APP version be stored on slot index 0 and keep slot index 1 empty
63+
uint32_t offset_app = offset + OPENTITAN_OFFSET_APP_FW;
64+
app->major = image[offset_app + OPENTITAN_OFFSET_VERSION_MAJOR] | image[offset_app + OPENTITAN_OFFSET_VERSION_MAJOR + 1] << 8 | image[offset_app + OPENTITAN_OFFSET_VERSION_MAJOR + 2] << 16 | image[offset_app + OPENTITAN_OFFSET_VERSION_MAJOR + 3] << 24;
65+
app->minor = image[offset_app + OPENTITAN_OFFSET_VERSION_MINOR] | image[offset_app + OPENTITAN_OFFSET_VERSION_MINOR + 1] << 8 | image[offset_app + OPENTITAN_OFFSET_VERSION_MINOR + 2] << 16 | image[offset_app + OPENTITAN_OFFSET_VERSION_MINOR + 3] << 24;
66+
67+
return 0;
68+
}
69+
70+
bool libhoth_ot_version_eq(const struct opentitan_image_version * a,
71+
const struct opentitan_image_version * b) {
72+
73+
if(a->major == b->major && a->minor == b->minor) {
74+
return true;
75+
} else {
76+
return false;
77+
}
78+
79+
}
80+
3581
char * bootslot_str(enum opentitan_boot_slot input) {
3682

3783
// Primary BL0 slot values are hardcoded in pie_rot
@@ -44,5 +90,19 @@ char * bootslot_str(enum opentitan_boot_slot input) {
4490
} else {
4591
return "Unknown boot slot";
4692
}
93+
}
94+
95+
int bootslot_int(enum opentitan_boot_slot input) {
96+
97+
// Primary BL0 slot values are hardcoded in pie_rot
98+
// Boot slotA: 0x5f5f4141
99+
// Boot slotB: 0x42425f5f)
100+
if (input == kOpentitanBootSlotA) {
101+
return 0x0;
102+
} else if (input == kOpentitanBootSlotB) {
103+
return 0x1;
104+
} else {
105+
return 0x0;
106+
}
47107

48108
}

protocol/opentitan_version.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <stdint.h>
1919
#include <assert.h>
20+
#include <stdbool.h>
2021

2122
#include "host_cmd.h"
2223
#include "transports/libhoth_device.h"
@@ -30,6 +31,13 @@ extern "C" {
3031
#define OPENTITAN_VERSION_HASH_SIZE 8
3132
#define OPENTITAN_NUM_SLOTS 2
3233

34+
#define OPENTITAN_OFFSET_HEADER_DATA 36
35+
#define OPENTITAN_OFFSET_APP_FW 65536
36+
#define OPENTITAN_OFFSET_VERSION_MAJOR 836
37+
#define OPENTITAN_OFFSET_VERSION_MINOR 840
38+
#define OPENTITAN_OFFSET_VERSION_SECURITY 844
39+
#define OPENTITAN_OFFSET_TIMESTAMP 848
40+
3341
typedef uint32_t opentitan_boot_slot_t;
3442

3543
enum opentitan_boot_slot {
@@ -91,8 +99,17 @@ static_assert(sizeof(struct opentitan_get_version_resp) == 344, "");
9199
int libhoth_opentitan_version(struct libhoth_device *device,
92100
struct opentitan_get_version_resp *response);
93101

102+
int libhoth_extract_ot_bundle(const uint8_t* image,
103+
struct opentitan_image_version * rom_ext,
104+
struct opentitan_image_version * app);
105+
106+
bool libhoth_ot_version_eq(const struct opentitan_image_version * a,
107+
const struct opentitan_image_version * b);
108+
94109
char *bootslot_str(enum opentitan_boot_slot input);
95110

111+
int bootslot_int(enum opentitan_boot_slot input);
112+
96113
#ifdef __cplusplus
97114
}
98115
#endif

0 commit comments

Comments
 (0)