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 apt-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ srecord
tree
xmlstarlet
xsltproc
xxd
xz-utils
zip
zlib1g-dev
3 changes: 2 additions & 1 deletion sw/device/silicon_creator/lib/rescue/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ cc_library(
"//hw/top:flash_ctrl_c_regs",
"//sw/device/lib/base:memory",
"//sw/device/silicon_creator/lib:boot_data",
"//sw/device/silicon_creator/lib:boot_log",
"//sw/device/silicon_creator/lib:dbg_print",
"//sw/device/silicon_creator/lib:error",
"//sw/device/silicon_creator/lib:manifest",
"//sw/device/silicon_creator/lib/boot_svc:boot_svc_msg",
"//sw/device/silicon_creator/lib/drivers:flash_ctrl",
"//sw/device/silicon_creator/lib/drivers:lifecycle",
Expand Down Expand Up @@ -90,7 +92,6 @@ cc_library(
":rescue",
"//sw/device/lib/base:macros",
"//sw/device/lib/base:memory",
"//sw/device/silicon_creator/lib:boot_data",
"//sw/device/silicon_creator/lib:error",
"//sw/device/silicon_creator/lib/drivers:rstmgr",
"//sw/device/silicon_creator/lib/drivers:usb",
Expand Down
19 changes: 9 additions & 10 deletions sw/device/silicon_creator/lib/rescue/dfu.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ static const rescue_mode_properties_t mode_by_altsetting[] = {
//{ kRescueModeOwnerPage1, false, true },
};

static rom_error_t validate_mode(uint32_t setting, rescue_state_t *state,
boot_data_t *bootdata) {
static rom_error_t validate_mode(uint32_t setting, rescue_state_t *state) {
// Allow the `setting` to be either an index or a FourCC code.
// The the integer value is less than the arraysize, then its clearly an
// index.
Expand All @@ -58,18 +57,18 @@ static rom_error_t validate_mode(uint32_t setting, rescue_state_t *state,
// rescue buffer.
const rescue_mode_properties_t *mode = &mode_by_altsetting[setting];
rom_error_t error2 = kErrorOk;
rom_error_t error = rescue_validate_mode(mode->mode, state, bootdata);
rom_error_t error = rescue_validate_mode(mode->mode, state);
if (error == kErrorOk && mode->upload) {
// DFU upload means send to the host. We stage the data that would
// be sent to the rescue buffer.
rescue_send_handler(state, bootdata);
rescue_send_handler(state);
}
// BootSvc and OwnerPage are also recv (from the host) services. Make sure
// we're set up to process a DFU download for those services.
if (mode->mode == kRescueModeBootSvcRsp) {
error2 = rescue_validate_mode(kRescueModeBootSvcReq, state, bootdata);
error2 = rescue_validate_mode(kRescueModeBootSvcReq, state);
} else if (mode->mode == kRescueModeOwnerPage0) {
error2 = rescue_validate_mode(kRescueModeOwnerBlock, state, bootdata);
error2 = rescue_validate_mode(kRescueModeOwnerBlock, state);
}

if (error == kErrorOk || error2 == kErrorOk) {
Expand Down Expand Up @@ -180,7 +179,7 @@ static rom_error_t vendor_request(dfu_ctx_t *ctx, usb_setup_data_t *setup) {
// FourCC from the value and index fields.
case kDfuVendorSetMode: {
uint32_t mode = ((uint32_t)setup->value << 16) | setup->index;
if (validate_mode(mode, &ctx->state, ctx->bootdata) == kErrorOk) {
if (validate_mode(mode, &ctx->state) == kErrorOk) {
dfu_transport_data(ctx, kUsbDirIn, NULL, 0, 0);
} else {
return kErrorUsbBadSetup;
Expand All @@ -195,7 +194,7 @@ static rom_error_t vendor_request(dfu_ctx_t *ctx, usb_setup_data_t *setup) {
static rom_error_t interface_request(dfu_ctx_t *ctx, usb_setup_data_t *setup) {
switch (setup->request) {
case kUsbSetupReqSetInterface:
if (validate_mode(setup->value, &ctx->state, ctx->bootdata) == kErrorOk) {
if (validate_mode(setup->value, &ctx->state) == kErrorOk) {
ctx->interface = (uint8_t)setup->value;
dfu_transport_data(ctx, kUsbDirIn, NULL, 0, 0);
} else {
Expand All @@ -216,7 +215,7 @@ static rom_error_t set_configuration(dfu_ctx_t *ctx) {
ctx->dfu_error = kDfuErrOk;
ctx->dfu_state = kDfuStateIdle;
ctx->interface = 0;
validate_mode(ctx->interface, &ctx->state, ctx->bootdata);
validate_mode(ctx->interface, &ctx->state);
ctx->ep0.configuration = ctx->ep0.next.configuration;
return kErrorOk;
}
Expand Down Expand Up @@ -282,7 +281,7 @@ void dfu_protocol_handler(void *_ctx, uint8_t ep, usb_transfer_flags_t flags,
ctx->state.data[ctx->state.offset++] = 0xFF;
}
// Pass the rescue buffer to the rescue receive handler.
rom_error_t error = rescue_recv_handler(&ctx->state, ctx->bootdata);
rom_error_t error = rescue_recv_handler(&ctx->state);
switch (error) {
case kErrorOk:
ctx->dfu_error = kDfuErrOk;
Expand Down
3 changes: 0 additions & 3 deletions sw/device/silicon_creator/lib/rescue/dfu.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

#include <stdint.h>

#include "sw/device/silicon_creator/lib/boot_data.h"
#include "sw/device/silicon_creator/lib/drivers/usb.h"
#include "sw/device/silicon_creator/lib/rescue/rescue.h"

Expand Down Expand Up @@ -132,8 +131,6 @@ typedef struct dfu_ctx {
usb_control_ctx_t ep0;
/** Rescue state. */
rescue_state_t state;
/** Pointer to bootdata. */
boot_data_t *bootdata;
/** Expected receive length (upload) */
uint32_t expected_len;
/** Status buffer (used to respond to DfuReqGetStatus). */
Expand Down
78 changes: 58 additions & 20 deletions sw/device/silicon_creator/lib/rescue/rescue.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "sw/device/lib/arch/device.h"
#include "sw/device/lib/base/memory.h"
#include "sw/device/silicon_creator/lib/boot_data.h"
#include "sw/device/silicon_creator/lib/boot_log.h"
#include "sw/device/silicon_creator/lib/boot_svc/boot_svc_msg.h"
#include "sw/device/silicon_creator/lib/dbg_print.h"
#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
Expand All @@ -15,6 +16,7 @@
#include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
#include "sw/device/silicon_creator/lib/drivers/rstmgr.h"
#include "sw/device/silicon_creator/lib/drivers/uart.h"
#include "sw/device/silicon_creator/lib/manifest.h"
#include "sw/device/silicon_creator/lib/ownership/datatypes.h"
#include "sw/device/silicon_creator/lib/ownership/owner_block.h"

Expand All @@ -26,6 +28,20 @@ const uint32_t kFlashPageSize = FLASH_CTRL_PARAM_BYTES_PER_PAGE;
const uint32_t kFlashBankSize =
kFlashPageSize * FLASH_CTRL_PARAM_REG_PAGES_PER_BANK;

static inline bool is_rom_ext(const void *data) {
const manifest_t *manifest = (const manifest_t *)data;
return manifest->identifier == CHIP_ROM_EXT_IDENTIFIER;
}

static inline bool is_rom_ext_update_allowed(rescue_state_t *state) {
// A ROM_EXT update is allowed if the partition we're flashing is not the
// ROM_EXT active partition.
return (state->mode == kRescueModeFirmware &&
state->boot_log->rom_ext_slot == kBootSlotB) ||
(state->mode == kRescueModeFirmwareSlotB &&
state->boot_log->rom_ext_slot == kBootSlotA);
}

rom_error_t flash_firmware_block(rescue_state_t *state) {
uint32_t bank_offset =
state->mode == kRescueModeFirmwareSlotB ? kFlashBankSize : 0;
Expand All @@ -37,29 +53,48 @@ rom_error_t flash_firmware_block(rescue_state_t *state) {
.write = kMultiBitBool4True,
.erase = kMultiBitBool4True,
});
for (uint32_t addr = state->flash_start; addr < state->flash_limit;
// Detect if we're allowed to flash the ROM_EXT _and_ if the data stream
// starts with a ROM_EXT. If so, we start flashing at offset 0 in this
// bank.
state->flash_begin =
(is_rom_ext_update_allowed(state) && is_rom_ext(state->data))
? 0
: state->flash_start;

// Erase the allowed range in the requested partition.
for (uint32_t addr = state->flash_begin; addr < state->flash_limit;
addr += kFlashPageSize) {
HARDENED_RETURN_IF_ERROR(
flash_ctrl_data_erase(bank_offset + addr, kFlashCtrlEraseTypePage));
}
state->flash_offset = state->flash_start;
// Regardless of whether we're allowed to flash the ROM_EXT, set the flash
// offset to zero if the data stream contains a ROM_EXT, otherwise, set to
// flash_start. This will allow rescue to silently consume the ROM_EXT if
// we're in the ROM_EXT active partition.
state->flash_offset = is_rom_ext(state->data) ? 0 : state->flash_start;
}
if (state->flash_offset < state->flash_limit) {

if (state->flash_offset < state->flash_begin) {
// Before allowed beginning; silently consume the data without flashing.
state->flash_offset += sizeof(state->data);
} else if (state->flash_offset >= state->flash_limit) {
// Beyond the allowed limit; return an error.
return kErrorRescueImageTooBig;
} else {
// In the allowed range; flash the data.
HARDENED_RETURN_IF_ERROR(flash_ctrl_data_write(
bank_offset + state->flash_offset,
sizeof(state->data) / sizeof(uint32_t), state->data));
state->flash_offset += sizeof(state->data);
} else {
return kErrorRescueImageTooBig;
}
return kErrorOk;
}

rom_error_t flash_owner_block(rescue_state_t *state, boot_data_t *bootdata) {
if (bootdata->ownership_state == kOwnershipStateUnlockedAny ||
bootdata->ownership_state == kOwnershipStateUnlockedSelf ||
bootdata->ownership_state == kOwnershipStateUnlockedEndorsed ||
(bootdata->ownership_state == kOwnershipStateLockedOwner &&
rom_error_t flash_owner_block(rescue_state_t *state) {
if (state->bootdata->ownership_state == kOwnershipStateUnlockedAny ||
state->bootdata->ownership_state == kOwnershipStateUnlockedSelf ||
state->bootdata->ownership_state == kOwnershipStateUnlockedEndorsed ||
(state->bootdata->ownership_state == kOwnershipStateLockedOwner &&
owner_block_newversion_mode() == kHardenedBoolTrue)) {
HARDENED_RETURN_IF_ERROR(flash_ctrl_info_erase(
&kFlashCtrlInfoPageOwnerSlot1, kFlashCtrlEraseTypePage));
Expand Down Expand Up @@ -93,8 +128,7 @@ static void ownership_erase(void) {
}
#endif

rom_error_t rescue_validate_mode(uint32_t mode, rescue_state_t *state,
boot_data_t *bootdata) {
rom_error_t rescue_validate_mode(uint32_t mode, rescue_state_t *state) {
dbg_printf("\r\nmode: %C\r\n", bitfield_byteswap32(mode));
rom_error_t result = kErrorOk;

Expand Down Expand Up @@ -131,10 +165,11 @@ rom_error_t rescue_validate_mode(uint32_t mode, rescue_state_t *state,
dbg_printf("ok: send boot_svc request\r\n");
break;
case kRescueModeOwnerBlock:
if (bootdata->ownership_state == kOwnershipStateUnlockedAny ||
bootdata->ownership_state == kOwnershipStateUnlockedSelf ||
bootdata->ownership_state == kOwnershipStateUnlockedEndorsed ||
(bootdata->ownership_state == kOwnershipStateLockedOwner &&
if (state->bootdata->ownership_state == kOwnershipStateUnlockedAny ||
state->bootdata->ownership_state == kOwnershipStateUnlockedSelf ||
state->bootdata->ownership_state ==
kOwnershipStateUnlockedEndorsed ||
(state->bootdata->ownership_state == kOwnershipStateLockedOwner &&
owner_block_newversion_mode() == kHardenedBoolTrue)) {
dbg_printf("ok: send owner_block\r\n");
} else {
Expand Down Expand Up @@ -170,7 +205,7 @@ rom_error_t rescue_validate_mode(uint32_t mode, rescue_state_t *state,
return result;
}

rom_error_t rescue_send_handler(rescue_state_t *state, boot_data_t *bootdata) {
rom_error_t rescue_send_handler(rescue_state_t *state) {
hardened_bool_t allow =
owner_rescue_command_allowed(state->config, state->mode);
if (allow != kHardenedBoolTrue) {
Expand Down Expand Up @@ -219,7 +254,7 @@ rom_error_t rescue_send_handler(rescue_state_t *state, boot_data_t *bootdata) {
return kErrorRescueSendStart;
}

rom_error_t rescue_recv_handler(rescue_state_t *state, boot_data_t *bootdata) {
rom_error_t rescue_recv_handler(rescue_state_t *state) {
hardened_bool_t allow =
owner_rescue_command_allowed(state->config, state->mode);
if (allow != kHardenedBoolTrue) {
Expand Down Expand Up @@ -249,7 +284,7 @@ rom_error_t rescue_recv_handler(rescue_state_t *state, boot_data_t *bootdata) {
break;
case kRescueModeOwnerBlock:
if (state->offset == sizeof(state->data)) {
HARDENED_RETURN_IF_ERROR(flash_owner_block(state, bootdata));
HARDENED_RETURN_IF_ERROR(flash_owner_block(state));
state->offset = 0;
}
break;
Expand All @@ -268,8 +303,11 @@ rom_error_t rescue_recv_handler(rescue_state_t *state, boot_data_t *bootdata) {
return kErrorOk;
}

void rescue_state_init(rescue_state_t *state,
void rescue_state_init(rescue_state_t *state, boot_data_t *bootdata,
boot_log_t *boot_log,
const owner_rescue_config_t *config) {
state->boot_log = boot_log;
state->bootdata = bootdata;
state->config = config;
if ((hardened_bool_t)config == kHardenedBoolFalse) {
HARDENED_CHECK_EQ((hardened_bool_t)config, kHardenedBoolFalse);
Expand Down
28 changes: 19 additions & 9 deletions sw/device/silicon_creator/lib/rescue/rescue.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <stdint.h>

#include "sw/device/silicon_creator/lib/boot_data.h"
#include "sw/device/silicon_creator/lib/boot_log.h"
#include "sw/device/silicon_creator/lib/boot_svc/boot_svc_msg.h"
#include "sw/device/silicon_creator/lib/dbg_print.h"
#include "sw/device/silicon_creator/lib/error.h"
Expand Down Expand Up @@ -77,9 +78,18 @@ typedef struct RescueState {
uint16_t staged_len;
// Current flash write offset.
uint32_t flash_offset;
// Current flash beginning offset. This is the partition-relative offset
// where we're allowed to start writing to flash. Normally, this will be
// the same as `flash_start`, but if we're allowed to write the ROM_EXT
// and we've detected a ROM_EXT, this may be adjusted to zero.
uint32_t flash_begin;
// Range to erase and write for firmware rescue (inclusive).
uint32_t flash_start;
uint32_t flash_limit;
// Pointer to the current bootdata record.
boot_data_t *bootdata;
// Pointer to the boot log.
boot_log_t *boot_log;
// Rescue configuration.
const owner_rescue_config_t *config;
// Data buffer to hold xmodem upload data.
Expand All @@ -90,42 +100,41 @@ typedef struct RescueState {
* Handle rescue modes that involve sending data to the host.
*
* @param state Rescue state
* @param bootdata Boot data
* @return kErrorOk if nothing to do, kErrorRescueSendStart if the state->data
* buffer is ready to send, or an error.
*/
rom_error_t rescue_send_handler(rescue_state_t *state, boot_data_t *bootdata);
rom_error_t rescue_send_handler(rescue_state_t *state);

/**
* Handle rescue movdes that involve receiving data into the device.
*
* @param state Rescue state
* @param bootdata Boot data
* @return kErrorOk if no error or an error code indicating a problem with
* the received data.
*/
rom_error_t rescue_recv_handler(rescue_state_t *state, boot_data_t *bootdata);
rom_error_t rescue_recv_handler(rescue_state_t *state);

/**
* Validate a new rescue mode.
*
* @param mode The new mode.
* @param state Rescue state
* @param bootdata Boot data
* @return kErrorOk if the new mode was accepted, kErrorBadMode otherwise.
*
* The rescue state is updated: mode, offset and flash_offset.
*/
rom_error_t rescue_validate_mode(uint32_t mode, rescue_state_t *state,
boot_data_t *bootdata);
rom_error_t rescue_validate_mode(uint32_t mode, rescue_state_t *state);

/**
* Initialize the rescue state.
*
* @param state Rescue state
* @param bootdata Boot data
* @param boot_log The boot_log
* @param config The ownership rescue config (if any).
*/
void rescue_state_init(rescue_state_t *state,
void rescue_state_init(rescue_state_t *state, boot_data_t *bootdata,
boot_log_t *boot_log,
const owner_rescue_config_t *config);

/**
Expand All @@ -140,10 +149,11 @@ rom_error_t rescue_enter_handler(boot_svc_msg_t *msg);
* Perform the rescue protocol.
*
* @param bootdata Boot data
* @param boot_log The boot_log
* @param config The ownership rescue config (if any).
* @return Any error in processing the rescue protocol.
*/
rom_error_t rescue_protocol(boot_data_t *bootdata,
rom_error_t rescue_protocol(boot_data_t *bootdata, boot_log_t *boot_log,
const owner_rescue_config_t *config);

/**
Expand Down
5 changes: 2 additions & 3 deletions sw/device/silicon_creator/lib/rescue/rescue_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,14 @@ void dfu_transport_result(dfu_ctx_t *ctx, rom_error_t result) {
spi_device_flash_status_clear();
}

rom_error_t rescue_protocol(boot_data_t *bootdata,
rom_error_t rescue_protocol(boot_data_t *bootdata, boot_log_t *boot_log,
const owner_rescue_config_t *config) {
dfu_ctx_t ctx = {
.bootdata = bootdata,
.dfu_state = kDfuStateIdle,
.dfu_error = kDfuErrOk,
};
dbg_printf("SPI-DFU rescue ready\r\n");
rescue_state_init(&ctx.state, config);
rescue_state_init(&ctx.state, bootdata, boot_log, config);
spi_device_init(
/*log2_density=*/kRescueDensity, &kRescueSfdpTable,
sizeof(kRescueSfdpTable));
Expand Down
Loading
Loading