Skip to content

Commit 717e20b

Browse files
cfrantzpamaury
authored andcommitted
[rescue] Report errors for disallowed configurations
Rework the `validate_mode` function to set flags in the DFU context that represent whether a DFU `DnLoad` or `UpLoad` operation is allowed. Report an error in the download/upload handler when an unsupported operation is attempted. Signed-off-by: Chris Frantz <cfrantz@google.com> (cherry picked from commit c0a40fe)
1 parent 70e4060 commit 717e20b

File tree

2 files changed

+53
-37
lines changed

2 files changed

+53
-37
lines changed

sw/device/silicon_creator/lib/rescue/dfu.c

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,32 @@
1515
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
1616

1717
typedef struct rescue_mode_properties {
18+
// The FourCC of the mode we want to set.
19+
// When pairing modes, the UpLoad mode must be the `mode` and the DnLoad mode
20+
// must be the `paired` mode. This is because the validate_mode function
21+
// only examines the `mode` for staging the upload data.
1822
uint32_t mode;
19-
bool dnload;
20-
bool upload;
23+
// Non-zero if there is a paired mode.
24+
uint32_t paired;
25+
// Whether the mode support DFU DnLoad or UpLoad or both.
26+
// Element 0 describes the Up- or Dn-Load status of the mode.
27+
// Element 1 describes whether the "paired" mode supports Up- or Dn-Load.
28+
// E.g. OwnerPage0 is paired with OwnerBlock.
29+
uint8_t allow[2];
2130
} rescue_mode_properties_t;
2231

32+
// clang-format off
2333
static const rescue_mode_properties_t mode_by_altsetting[] = {
24-
{kRescueModeFirmware, true, false},
25-
{kRescueModeFirmwareSlotB, true, false},
26-
{kRescueModeOpenTitanID, false, true},
27-
{kRescueModeBootLog, false, true},
28-
{kRescueModeBootSvcRsp, true, true},
29-
{kRescueModeOwnerPage0, true, true},
30-
//{ kRescueModeOwnerPage1, false, true },
34+
{kRescueModeFirmware, 0, { kDfuAllowDnLoad, 0 }},
35+
{kRescueModeFirmwareSlotB, 0, { kDfuAllowDnLoad, 0 }},
36+
{kRescueModeOpenTitanID, 0, { kDfuAllowUpLoad, 0 }},
37+
{kRescueModeBootLog, 0, { kDfuAllowUpLoad, 0 }},
38+
{kRescueModeBootSvcRsp, kRescueModeBootSvcReq, { kDfuAllowUpLoad, kDfuAllowDnLoad }},
39+
{kRescueModeOwnerPage0, kRescueModeOwnerBlock, { kDfuAllowUpLoad, kDfuAllowDnLoad }},
3140
};
41+
// clang-format on
3242

33-
static rom_error_t validate_mode(uint32_t setting, rescue_state_t *state) {
43+
static rom_error_t validate_mode(uint32_t setting, dfu_ctx_t *ctx) {
3444
// Allow the `setting` to be either an index or a FourCC code.
3545
// The the integer value is less than the arraysize, then its clearly an
3646
// index.
@@ -56,38 +66,37 @@ static rom_error_t validate_mode(uint32_t setting, rescue_state_t *state) {
5666
// same target, we handle the "send" services first to stage data into the
5767
// rescue buffer.
5868
const rescue_mode_properties_t *mode = &mode_by_altsetting[setting];
59-
rom_error_t error2 = kErrorOk;
60-
rom_error_t error = rescue_validate_mode(mode->mode, state);
69+
rom_error_t error = rescue_validate_mode(mode->mode, &ctx->state);
6170

62-
// If the service exclusively supports either upload or download operation,
63-
// report bad mode immediately if a prior error occurred.
64-
if (!(mode->upload && mode->dnload)) {
65-
if (error != kErrorOk) {
66-
return kErrorRescueBadMode;
71+
uint8_t allow = 0;
72+
if (error == kErrorOk) {
73+
allow = mode->allow[0];
74+
if (allow & kDfuAllowUpLoad) {
75+
// DFU upload means send to the host. We stage the data that would
76+
// be sent to the rescue buffer.
77+
rescue_send_handler(&ctx->state);
6778
}
6879
}
6980

70-
if (error == kErrorOk && mode->upload) {
71-
// DFU upload means send to the host. We stage the data that would
72-
// be sent to the rescue buffer.
73-
rescue_send_handler(state);
74-
}
7581
// BootSvc and OwnerPage are also recv (from the host) services. Make sure
7682
// we're set up to process a DFU download for those services.
77-
if (mode->mode == kRescueModeBootSvcRsp) {
78-
error2 = rescue_validate_mode(kRescueModeBootSvcReq, state);
79-
} else if (mode->mode == kRescueModeOwnerPage0) {
80-
error2 = rescue_validate_mode(kRescueModeOwnerBlock, state);
83+
if (mode->paired) {
84+
rom_error_t error2 = rescue_validate_mode(mode->paired, &ctx->state);
85+
if (error2 == kErrorOk) {
86+
allow |= mode->allow[1];
87+
}
8188
}
8289

83-
if (error == kErrorOk || error2 == kErrorOk) {
84-
// If either the send or recv mode is ok, then setting the mode is ok.
85-
// If only one is Ok, the send or recv handler will report the error when we
86-
// try an unauthorized operation.
90+
// If either the send or recv mode is ok, then setting the mode is ok.
91+
// If only one is Ok, the send or recv handler will report the error when we
92+
// try an unauthorized operation.
93+
// If neither is Ok, the report bad mode.
94+
if (allow) {
95+
ctx->allow = allow;
8796
return kErrorOk;
97+
} else {
98+
return kErrorRescueBadMode;
8899
}
89-
// If neither is Ok, the report bad mode.
90-
return kErrorRescueBadMode;
91100
}
92101

93102
static rom_error_t dfu_control(dfu_ctx_t *ctx, usb_setup_data_t *setup) {
@@ -125,8 +134,8 @@ static rom_error_t dfu_control(dfu_ctx_t *ctx, usb_setup_data_t *setup) {
125134
ctx->dfu_state = tr->next[setup->length == 0 ? 0 : 1];
126135
// Length is good and the request is either upload/download.
127136
if (setup->length <= sizeof(ctx->state.data) &&
128-
(setup->request == kDfuReqDnLoad ||
129-
setup->request == kDfuReqUpLoad)) {
137+
((setup->request == kDfuReqDnLoad && ctx->allow & kDfuAllowDnLoad) ||
138+
(setup->request == kDfuReqUpLoad && ctx->allow & kDfuAllowUpLoad))) {
130139
if (setup->request == kDfuReqDnLoad) {
131140
if (setup->length == 0 ||
132141
ctx->state.offset < ctx->state.flash_limit) {
@@ -193,7 +202,7 @@ static rom_error_t vendor_request(dfu_ctx_t *ctx, usb_setup_data_t *setup) {
193202
// FourCC from the value and index fields.
194203
case kDfuVendorSetMode: {
195204
uint32_t mode = ((uint32_t)setup->value << 16) | setup->index;
196-
if (validate_mode(mode, &ctx->state) == kErrorOk) {
205+
if (validate_mode(mode, ctx) == kErrorOk) {
197206
dfu_transport_data(ctx, kUsbDirIn, NULL, 0, 0);
198207
} else {
199208
return kErrorUsbBadSetup;
@@ -208,7 +217,7 @@ static rom_error_t vendor_request(dfu_ctx_t *ctx, usb_setup_data_t *setup) {
208217
static rom_error_t interface_request(dfu_ctx_t *ctx, usb_setup_data_t *setup) {
209218
switch (setup->request) {
210219
case kUsbSetupReqSetInterface:
211-
if (validate_mode(setup->value, &ctx->state) == kErrorOk) {
220+
if (validate_mode(setup->value, ctx) == kErrorOk) {
212221
// A typical OS USB stack will issue SET_INTERFACE to activate
213222
// AltSetting 0. Since this probably is not real user activity,
214223
// we won't cancel the inactivity deadline for this action when it
@@ -237,7 +246,7 @@ static rom_error_t set_configuration(dfu_ctx_t *ctx) {
237246
ctx->dfu_error = kDfuErrOk;
238247
ctx->dfu_state = kDfuStateIdle;
239248
ctx->interface = 0;
240-
validate_mode(ctx->interface, &ctx->state);
249+
validate_mode(ctx->interface, ctx);
241250
ctx->ep0.configuration = ctx->ep0.next.configuration;
242251
return kErrorOk;
243252
}

sw/device/silicon_creator/lib/rescue/dfu.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ typedef enum dfu_action_t {
8181
kDfuActionReset,
8282
} dfu_action_t;
8383

84+
typedef enum dfu_allow {
85+
kDfuAllowDnLoad = 1,
86+
kDfuAllowUpLoad = 2,
87+
} dfu_allow_t;
88+
8489
/**
8590
* A DFU state transition.
8691
*
@@ -141,6 +146,8 @@ typedef struct dfu_ctx {
141146
uint8_t dfu_error;
142147
/** Currenty selected usb interface setting. */
143148
uint8_t interface;
149+
/** A `dfu_allow_t` describing whether dnload or upload are allowed. */
150+
uint8_t allow;
144151
} dfu_ctx_t;
145152

146153
/**

0 commit comments

Comments
 (0)