Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
15 changes: 8 additions & 7 deletions sw/device/silicon_creator/lib/ownership/datatypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,12 +389,12 @@ typedef struct owner_rescue_config {
*/
uint8_t protocol;
/**
* The gpio configuration (if relevant, depending on `detect`).
* The misc & gpio configuration (if relevant, depending on `detect`).
*
* 7 2 1 0
* +---------------+--------+-------+
* | Reserved | PullEn | Value |
* +---------------+--------+-------+
* 7 6 2 1 0
* +-----+---------+--------+-------+
* | WDT | Reserved| PullEn | Value |
* +-----+---------+--------+-------+
*/
uint8_t gpio;
/**
Expand Down Expand Up @@ -443,8 +443,9 @@ OT_ASSERT_SIZE(owner_rescue_config_t, 16);

#define RESCUE_ENTER_ON_FAIL_BIT 7
#define RESCUE_TIMEOUT_SECONDS ((bitfield_field32_t){.mask = 0x7F, .index = 0})
#define RESCUE_GPIO_PULL_EN_BIT 1
#define RESCUE_GPIO_VALUE_BIT 0
#define RESCUE_MISC_GPIO_WATCHDOG_TIMEOUT_EN_BIT 7
#define RESCUE_MISC_GPIO_PULL_EN_BIT 1
#define RESCUE_MISC_GPIO_VALUE_BIT 0
#define RESCUE_DETECT ((bitfield_field32_t){.mask = 0x03, .index = 6})
#define RESCUE_DETECT_INDEX ((bitfield_field32_t){.mask = 0x3F, .index = 0})

Expand Down
6 changes: 4 additions & 2 deletions sw/device/silicon_creator/lib/ownership/owner_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,10 @@ rom_error_t owner_block_info_isfb_erase_enable(
rom_error_t owner_block_rescue_apply(const owner_rescue_config_t *rescue) {
rescue_detect_t detect = bitfield_field32_read(rescue->detect, RESCUE_DETECT);
uint32_t index = bitfield_field32_read(rescue->detect, RESCUE_DETECT_INDEX);
bool pull_en = bitfield_bit32_read(rescue->gpio, RESCUE_GPIO_PULL_EN_BIT);
bool gpio_value = bitfield_bit32_read(rescue->gpio, RESCUE_GPIO_VALUE_BIT);
bool pull_en =
bitfield_bit32_read(rescue->gpio, RESCUE_MISC_GPIO_PULL_EN_BIT);
bool gpio_value =
bitfield_bit32_read(rescue->gpio, RESCUE_MISC_GPIO_VALUE_BIT);
switch (detect) {
case kRescueDetectGpio:
if (index <= kTopEarlgreyMuxedPadsLast) {
Expand Down
6 changes: 3 additions & 3 deletions sw/device/silicon_creator/lib/ownership/test_owner.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@

// The following preprocessor symbols are only relevant when
// WITH_RESCUE_PROTOCOL is defined.
#ifndef WITH_RESCUE_GPIO_PARAM
#define WITH_RESCUE_GPIO_PARAM 0
#ifndef WITH_RESCUE_MISC_GPIO_PARAM
#define WITH_RESCUE_MISC_GPIO_PARAM 0
#endif
#ifndef WITH_RESCUE_INDEX
#define WITH_RESCUE_INDEX 0
Expand Down Expand Up @@ -279,7 +279,7 @@ rom_error_t sku_creator_owner_init(boot_data_t *bootdata) {
.length = sizeof(owner_rescue_config_t),
},
.protocol = WITH_RESCUE_PROTOCOL,
.gpio = WITH_RESCUE_GPIO_PARAM,
.gpio = WITH_RESCUE_MISC_GPIO_PARAM,
.timeout = WITH_RESCUE_TIMEOUT,
.detect = (WITH_RESCUE_TRIGGER << 6) | WITH_RESCUE_INDEX,
.start = WITH_RESCUE_START,
Expand Down
13 changes: 11 additions & 2 deletions sw/device/silicon_creator/lib/rescue/rescue.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,8 @@ void rescue_skip_next_boot(void) {
boot_svc_enter_rescue_req_init(kHardenedBoolTrue, &msg->enter_rescue_req);
}

hardened_bool_t rescue_detect_entry(const owner_rescue_config_t *config) {
hardened_bool_t rescue_detect_entry(const owner_rescue_config_t *config,
uint32_t reset_reasons) {
switch (rescue_requested) {
case kRescueRequestEnter:
return kHardenedBoolTrue;
Expand All @@ -410,16 +411,24 @@ hardened_bool_t rescue_detect_entry(const owner_rescue_config_t *config) {
rescue_detect_t detect = kRescueDetectBreak;
uint32_t index = 0;
uint32_t gpio_val = 0;
uint32_t wdt_enable = 0;
if ((hardened_bool_t)config != kHardenedBoolFalse) {
protocol = config->protocol;
detect = bitfield_field32_read(config->detect, RESCUE_DETECT);
index = bitfield_field32_read(config->detect, RESCUE_DETECT_INDEX);
gpio_val = bitfield_bit32_read(config->gpio, RESCUE_GPIO_VALUE_BIT);
gpio_val = bitfield_bit32_read(config->gpio, RESCUE_MISC_GPIO_VALUE_BIT);
wdt_enable = bitfield_bit32_read(config->gpio,
RESCUE_MISC_GPIO_WATCHDOG_TIMEOUT_EN_BIT);
}
dbg_printf("info: rescue protocol %c\r\n", rescue_type);
if (protocol != rescue_type) {
dbg_printf("warning: rescue configured for protocol %c\r\n", protocol);
}

if (wdt_enable && bitfield_bit32_read(reset_reasons, kRstmgrReasonWatchdog)) {
return kHardenedBoolTrue;
}

switch (detect) {
case kRescueDetectNone:
break;
Expand Down
4 changes: 3 additions & 1 deletion sw/device/silicon_creator/lib/rescue/rescue.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,10 @@ void rescue_skip_next_boot(void);
* Detect rescue entry.
*
* @param config The ownership rescue config (if any).
* @param reset_reasons The reset reaons value from the rstmgr.
* @return kHardenedBoolTrue if we should enter rescue mode.
*/
hardened_bool_t rescue_detect_entry(const owner_rescue_config_t *config);
hardened_bool_t rescue_detect_entry(const owner_rescue_config_t *config,
uint32_t reset_reasons);

#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_RESCUE_RESCUE_H_
18 changes: 14 additions & 4 deletions sw/device/silicon_creator/rom_ext/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ TEST_OWNER_CONFIGS = {
"WITH_RESCUE_INDEX=2",
# GPIO param 3 means enable the internal pull resistor and trigger
# rescue when the GPIO is high.
"WITH_RESCUE_GPIO_PARAM=3",
"WITH_RESCUE_MISC_GPIO_PARAM=3",
# Timeout: 0x80=enter_on_fail, 0x05 = 5 seconds.
"WITH_RESCUE_TIMEOUT=0x85",
],
Expand All @@ -147,6 +147,16 @@ TEST_OWNER_CONFIGS = {
],
"rescue_module": ["//sw/device/silicon_creator/lib/rescue:rescue_xmodem"],
},
"xmodem_enter_on_watchdog": {
# Enable Xmodem rescue with enter-on-fail and a timeout.
"owner_defines": [
# 0x58 is 'X'modem.
"WITH_RESCUE_PROTOCOL=0x58",
# misc_gpio: 0x80=enter_on_watchdog.
"WITH_RESCUE_MISC_GPIO_PARAM=0x80",
],
"rescue_module": ["//sw/device/silicon_creator/lib/rescue:rescue_xmodem"],
},
"spidfu_restricted_commands": {
# Enable USB-DFU triggered by SW_STRAPS value 3.
"owner_defines": [
Expand All @@ -159,7 +169,7 @@ TEST_OWNER_CONFIGS = {
"WITH_RESCUE_INDEX=2",
# GPIO param 3 means enable the internal pull resistor and trigger
# rescue when the GPIO is high.
"WITH_RESCUE_GPIO_PARAM=3",
"WITH_RESCUE_MISC_GPIO_PARAM=3",
# Timeout: 0x80=enter_on_fail, 0x00 = No timeout.
"WITH_RESCUE_TIMEOUT=0x80",
# Restrict rescue to only one command
Expand Down Expand Up @@ -188,7 +198,7 @@ TEST_OWNER_CONFIGS = {
"WITH_RESCUE_INDEX=2",
# GPIO param 3 means enable the internal pull resistor and trigger
# rescue when the GPIO is high.
"WITH_RESCUE_GPIO_PARAM=3",
"WITH_RESCUE_MISC_GPIO_PARAM=3",
# Timeout: 0x80=enter_on_fail, 0x05 = 5 seconds.
"WITH_RESCUE_TIMEOUT=0x85",
# Disallow all the rescue commands.
Expand All @@ -207,7 +217,7 @@ TEST_OWNER_CONFIGS = {
"WITH_RESCUE_INDEX=2",
# GPIO param 3 means enable the internal pull resistor and trigger
# rescue when the GPIO is high.
"WITH_RESCUE_GPIO_PARAM=3",
"WITH_RESCUE_MISC_GPIO_PARAM=3",
# Timeout: 0x80=enter_on_fail, 0x05 = 5 seconds.
"WITH_RESCUE_TIMEOUT=0x85",
# Set rescue start and size to 0 to test writing past the end of the flash.
Expand Down
66 changes: 66 additions & 0 deletions sw/device/silicon_creator/rom_ext/e2e/rescue/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -796,3 +796,69 @@ opentitan_test(
test_harness = "//sw/host/tests/rescue:dfu_rescue_error_handling",
),
)

# Check that when we are not configured to rescue on watchdog timeout that
# a watchdog timeout event simply boots the firmware normally.
opentitan_test(
name = "rescue_watchdog_disabled_test",
srcs = [
"watchdog_test.c",
],
exec_env = {
"//hw/top_earlgrey:fpga_hyper310_rom_ext": None,
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
},
fpga = fpga_params(
changes_otp = True,
exit_failure = "(FAIL|BFV:|mode: RESQ).*",
rom_ext = "//sw/device/silicon_creator/rom_ext:rom_ext_dice_x509_slot_a",
test_cmd = """
--exec="transport init"
--exec="fpga clear-bitstream"
--exec="fpga load-bitstream {bitstream}"
--exec="bootstrap --clear-uart=true {firmware}"
--exec="console --non-interactive --exit-success='{exit_success}' --exit-failure='{exit_failure}'"
no-op
""",
),
deps = [
"//sw/device/lib/base:status",
"//sw/device/lib/testing/test_framework:ottf_main",
"//sw/device/silicon_creator/lib/drivers:retention_sram",
"//sw/device/silicon_creator/lib/drivers:rstmgr",
"//sw/device/silicon_creator/lib/drivers:watchdog",
],
)

# Check that when we are configured to rescue on watchdog timeout that
# a watchdog timeout event triggers rescue mode.
opentitan_test(
name = "rescue_watchdog_enabled_test",
srcs = [
"watchdog_test.c",
],
exec_env = {
"//hw/top_earlgrey:fpga_hyper310_rom_ext": None,
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
},
fpga = fpga_params(
changes_otp = True,
exit_success = "mode: RESQ",
rom_ext = "//sw/device/silicon_creator/rom_ext:rom_ext_xmodem_enter_on_watchdog",
test_cmd = """
--exec="transport init"
--exec="fpga clear-bitstream"
--exec="fpga load-bitstream {bitstream}"
--exec="bootstrap --clear-uart=true {firmware}"
--exec="console --non-interactive --exit-success='{exit_success}' --exit-failure='{exit_failure}'"
no-op
""",
),
deps = [
"//sw/device/lib/base:status",
"//sw/device/lib/testing/test_framework:ottf_main",
"//sw/device/silicon_creator/lib/drivers:retention_sram",
"//sw/device/silicon_creator/lib/drivers:rstmgr",
"//sw/device/silicon_creator/lib/drivers:watchdog",
],
)
63 changes: 63 additions & 0 deletions sw/device/silicon_creator/rom_ext/e2e/rescue/watchdog_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/silicon_creator/lib/drivers/watchdog.h"

#include <stdbool.h>
#include <stdint.h>

#include "sw/device/lib/arch/device.h"
#include "sw/device/lib/base/math.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/runtime/print.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
#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/error.h"

static uint32_t compute_ticks_per_ms(uint64_t hz) {
const uint64_t kTicksPerMs = udiv64_slow(hz, 1000, NULL);
CHECK(kTicksPerMs <= UINT32_MAX, "kTicksPerMs exceeds UINT32_MAX");
return (uint32_t)kTicksPerMs;
}

// Setup the watchdog to bite.
static status_t watchdog_bite_setup(void) {
// Set watchdog bite threshold to 5ms.
uint32_t bite_threshold = 5 * compute_ticks_per_ms(kClockFreqAonHz);
uint32_t bark_threshold = 9 * bite_threshold / 8;
LOG_INFO("bite threshold = %d", bite_threshold);
LOG_INFO("bark threshold = %d", bark_threshold);
watchdog_configure((watchdog_config_t){
.bite_threshold = bite_threshold,
.bark_threshold = bark_threshold,
.enable = kHardenedBoolTrue,
});

// Sleep for 6ms.
busy_spin_micros(6 * 1000);

watchdog_disable();
return UNKNOWN();
}

OTTF_DEFINE_TEST_CONFIG();

bool test_main(void) {
status_t result = OK_STATUS();
const retention_sram_t *rr = retention_sram_get();
uint32_t reason = rr->creator.reset_reasons;

if (bitfield_bit32_read(reason, kRstmgrReasonPowerOn)) {
LOG_INFO("Configure watchdog to bite.");
result = watchdog_bite_setup();
} else if (bitfield_bit32_read(reason, kRstmgrReasonWatchdog)) {
LOG_INFO("Got watchdog reset.");
result = OK_STATUS();
} else {
LOG_ERROR("Unknown reset reason");
result = UNKNOWN();
}
return status_ok(result);
}
7 changes: 4 additions & 3 deletions sw/device/silicon_creator/rom_ext/rom_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,9 +588,10 @@ static rom_error_t rom_ext_start(boot_data_t *boot_data, boot_log_t *boot_log) {
HARDENED_RETURN_IF_ERROR(ownership_seal_clear());

// We don't want to enter rescue mode if this is a low-power wakeup.
hardened_bool_t want_rescue = waking_from_low_power != kHardenedBoolTrue
? rescue_detect_entry(owner_config.rescue)
: kHardenedBoolFalse;
hardened_bool_t want_rescue =
waking_from_low_power != kHardenedBoolTrue
? rescue_detect_entry(owner_config.rescue, reset_reasons)
: kHardenedBoolFalse;
hardened_bool_t boot_attempted = kHardenedBoolFalse;

if (want_rescue == kHardenedBoolFalse) {
Expand Down
1 change: 1 addition & 0 deletions sw/host/opentitanlib/src/ownership/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@ r#"00000000: 4f 57 4e 52 00 08 00 00 00 00 00 00 4c 4e 45 58 OWNR........LNEX
trigger_index: 0,
gpio_pull_en: false,
gpio_value: false,
enter_on_watchdog: false,
enter_on_failure: false,
timeout: 0,
start: 32,
Expand Down
Loading
Loading