Skip to content

Commit

Permalink
[sw] Implement ROM_EXT recovery
Browse files Browse the repository at this point in the history
Issue #19151

Signed-off-by: Dan McArdle <dmcardle@opentitan.org>
  • Loading branch information
dmcardle committed Jul 31, 2023
1 parent 833ddc6 commit 81e5a3c
Show file tree
Hide file tree
Showing 17 changed files with 1,233 additions and 236 deletions.
20 changes: 17 additions & 3 deletions sw/device/silicon_creator/lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,16 @@ cc_library(
)

cc_library(
name = "error_test_util",
hdrs = ["error_test_util.h"],
name = "error_unittest_util",
hdrs = ["error_unittest_util.h"],
)

cc_test(
name = "error_unittest",
srcs = ["error_unittest.cc"],
deps = [
":error",
":error_test_util",
":error_unittest_util",
"@googletest//:gtest_main",
],
)
Expand Down Expand Up @@ -422,3 +422,17 @@ filegroup(
"bootstrap.h",
],
)

cc_library(
name = "bootstrap_unittest_util",
srcs = ["bootstrap_unittest_util.cc"],
hdrs = ["bootstrap_unittest_util.h"],
deps = [
":bootstrap",
"//hw/ip/gpio/data:gpio_regs",
"//hw/ip/otp_ctrl/data:otp_ctrl_regs",
"//hw/top_earlgrey/ip/flash_ctrl/data/autogen:flash_ctrl_regs",
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/silicon_creator/lib/base:chip",
],
)
37 changes: 8 additions & 29 deletions sw/device/silicon_creator/lib/bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

#include "sw/device/silicon_creator/lib/bootstrap.h"

#include <assert.h>
#include <stdalign.h>
#include <stdint.h>

#include "sw/device/lib/base/abs_mmio.h"
#include "sw/device/lib/base/bitfield.h"
#include "sw/device/lib/base/hardened.h"
#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
Expand Down Expand Up @@ -59,23 +60,6 @@ typedef enum bootstrap_state {
kBootstrapStateProgram = 0xbdd8ca60,
} bootstrap_state_t;

/**
* Handles access permissions and erases both data banks of the embedded flash.
*
* @return Result of the operation.
*/
OT_WARN_UNUSED_RESULT
static rom_error_t bootstrap_chip_erase(void) {
flash_ctrl_bank_erase_perms_set(kHardenedBoolTrue);
rom_error_t err_0 = flash_ctrl_data_erase(0, kFlashCtrlEraseTypeBank);
rom_error_t err_1 = flash_ctrl_data_erase(FLASH_CTRL_PARAM_BYTES_PER_BANK,
kFlashCtrlEraseTypeBank);
flash_ctrl_bank_erase_perms_set(kHardenedBoolFalse);

HARDENED_RETURN_IF_ERROR(err_0);
return err_1;
}

/**
* Handles access permissions and erases a 4 KiB region in the data partition of
* the embedded flash.
Expand Down Expand Up @@ -262,15 +246,13 @@ OT_WARN_UNUSED_RESULT
static rom_error_t bootstrap_handle_erase_verify(bootstrap_state_t *state) {
HARDENED_CHECK_EQ(*state, kBootstrapStateEraseVerify);

rom_error_t err_0 = flash_ctrl_data_erase_verify(0, kFlashCtrlEraseTypeBank);
rom_error_t err_1 = flash_ctrl_data_erase_verify(
FLASH_CTRL_PARAM_BYTES_PER_BANK, kFlashCtrlEraseTypeBank);
HARDENED_RETURN_IF_ERROR(err_0);
HARDENED_RETURN_IF_ERROR(err_1);
const rom_error_t err = bootstrap_erase_verify();
HARDENED_RETURN_IF_ERROR(err);

*state = kBootstrapStateProgram;
spi_device_flash_status_clear();
return err_0;

*state = kBootstrapStateProgram;
return err;
}

/**
Expand Down Expand Up @@ -333,10 +315,7 @@ static rom_error_t bootstrap_handle_program(bootstrap_state_t *state) {
return error;
}

rom_error_t enter_bootstrap(hardened_bool_t protect_rom_ext) {
// TODO(lowRISC/opentitan#19151): Implement `protect_rom_ext` behavior.
HARDENED_CHECK_EQ(protect_rom_ext, kHardenedBoolFalse);

rom_error_t enter_bootstrap(void) {
spi_device_init();

// Bootstrap event loop.
Expand Down
45 changes: 38 additions & 7 deletions sw/device/silicon_creator/lib/bootstrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,62 @@
#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_BOOTSTRAP_H_
#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_BOOTSTRAP_H_

#include "sw/device/lib/base/hardened.h"
#include "sw/device/silicon_creator/lib/drivers/spi_device.h"
#include "sw/device/silicon_creator/lib/error.h"

#ifdef __cplusplus
extern "C" {
#endif

#include "sw/device/lib/base/hardened.h"
#include "sw/device/silicon_creator/lib/error.h"

/**
* @public
* Enters flash programming mode. This function initializes the SPI device and
* uses incoming SPI commands to drive an internal state machine.
*
* Dependent code should use this function as the main entry point to bootstrap.
* The dependent code must provide implementations for the following functions:
* - `bootstrap_chip_erase()`
* - `bootstrap_erase_verify()`
*
* Bootstrapping uses the typical SPI flash EEPROM commands. A typical session
* involves:
* - Asserting bootstrap pins to enter bootstrap mode,
* - Erasing the chip (WREN, CHIP_ERASE, busy loop ...),
* - Programming the chip (WREN, PAGE_PROGRAM, busy loop ...), and
* - Resetting the chip (RESET).
*
* This function only returns on error since a successful session ends with a
* chip reset.
* This function only returns on error; a successful session ends with a chip
* reset.
*
* @param protect_rom_ext Whether to prevent changes to to ROM_EXT.
* @return The result of the flash loop.
*/
rom_error_t enter_bootstrap(hardened_bool_t protect_rom_ext);
OT_WARN_UNUSED_RESULT
rom_error_t enter_bootstrap(void);

/**
* @private @pure
* Handles access permissions and erases both data banks of the embedded flash.
*
* NOTE: This abstract function must be implemented by dependent code.
*
* @return Result of the operation.
*/
OT_WARN_UNUSED_RESULT
rom_error_t bootstrap_chip_erase(void);

/**
* @private @pure
* Verify that all data banks have been erased.
*
* This function also clears the WIP and WEN bits of the flash status register.
*
* NOTE: This abstract function must be implemented by dependent code.
*
* @return Result of the operation.
*/
OT_WARN_UNUSED_RESULT
rom_error_t bootstrap_erase_verify(void);

#ifdef __cplusplus
}
Expand Down
153 changes: 153 additions & 0 deletions sw/device/silicon_creator/lib/bootstrap_unittest_util.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/silicon_creator/lib/bootstrap_unittest_util.h"

#include <stdint.h>
#include <string.h>

#include "sw/device/silicon_creator/lib/base/chip.h"

#include "flash_ctrl_regs.h"
#include "gpio_regs.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "otp_ctrl_regs.h"

bool operator==(flash_ctrl_perms_t lhs, flash_ctrl_perms_t rhs) {
return memcmp(&lhs, &rhs, sizeof(flash_ctrl_perms_t)) == 0;
}

namespace bootstrap_unittest_util {

namespace {
using ::testing::DoAll;
using ::testing::NotNull;
using ::testing::Return;
using ::testing::SetArgPointee;
} // namespace

void BootstrapTest::ExpectBootstrapRequestCheck(bool requested) {
EXPECT_CALL(otp_,
read32(OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_BOOTSTRAP_DIS_OFFSET))
.WillOnce(Return(kHardenedBoolFalse));
uint32_t pins = SW_STRAP_BOOTSTRAP;
if (!requested) {
pins = ~pins;
}
EXPECT_ABS_READ32(TOP_EARLGREY_GPIO_BASE_ADDR + GPIO_DATA_IN_REG_OFFSET,
pins);
}

void BootstrapTest::ExpectSpiCmd(spi_device_cmd_t cmd) {
EXPECT_CALL(spi_device_, CmdGet(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(cmd), Return(kErrorOk)));
}

void BootstrapTest::ExpectSpiFlashStatusGet(bool wel) {
EXPECT_CALL(spi_device_, FlashStatusGet())
.WillOnce(Return(wel << kSpiDeviceWelBit));
}

void BootstrapTest::ExpectFlashCtrlWriteEnable() {
EXPECT_CALL(flash_ctrl_, DataDefaultPermsSet((flash_ctrl_perms_t){
.read = kMultiBitBool4False,
.write = kMultiBitBool4True,
.erase = kMultiBitBool4False,
}));
}

void BootstrapTest::ExpectFlashCtrlEraseEnable() {
EXPECT_CALL(flash_ctrl_, DataDefaultPermsSet((flash_ctrl_perms_t){
.read = kMultiBitBool4False,
.write = kMultiBitBool4False,
.erase = kMultiBitBool4True,
}));
}

void BootstrapTest::ExpectFlashCtrlAllDisable() {
EXPECT_CALL(flash_ctrl_, DataDefaultPermsSet((flash_ctrl_perms_t){
.read = kMultiBitBool4False,
.write = kMultiBitBool4False,
.erase = kMultiBitBool4False,
}));
}

void BootstrapTest::ExpectFlashCtrlChipErase(rom_error_t err0,
rom_error_t err1) {
EXPECT_CALL(flash_ctrl_, BankErasePermsSet(kHardenedBoolTrue));
EXPECT_CALL(flash_ctrl_, DataErase(0, kFlashCtrlEraseTypeBank))
.WillOnce(Return(err0));
EXPECT_CALL(flash_ctrl_, DataErase(FLASH_CTRL_PARAM_BYTES_PER_BANK,
kFlashCtrlEraseTypeBank))
.WillOnce(Return(err1));
EXPECT_CALL(flash_ctrl_, BankErasePermsSet(kHardenedBoolFalse));
}

void BootstrapTest::ExpectFlashCtrlSectorErase(rom_error_t err0,
rom_error_t err1,
uint32_t addr) {
EXPECT_CALL(flash_ctrl_, DataDefaultPermsSet((flash_ctrl_perms_t){
.read = kMultiBitBool4False,
.write = kMultiBitBool4False,
.erase = kMultiBitBool4True,
}));
EXPECT_CALL(flash_ctrl_, DataErase(addr, kFlashCtrlEraseTypePage))
.WillOnce(Return(err0));
EXPECT_CALL(flash_ctrl_, DataErase(addr + FLASH_CTRL_PARAM_BYTES_PER_PAGE,
kFlashCtrlEraseTypePage))
.WillOnce(Return(err1));
ExpectFlashCtrlAllDisable();
}

void BootstrapTest::ExpectFlashCtrlEraseVerify(rom_error_t err0,
rom_error_t err1) {
EXPECT_CALL(flash_ctrl_, DataEraseVerify(0, kFlashCtrlEraseTypeBank))
.WillOnce(Return(err0));
EXPECT_CALL(flash_ctrl_, DataEraseVerify(FLASH_CTRL_PARAM_BYTES_PER_BANK,
kFlashCtrlEraseTypeBank))
.WillOnce(Return(err1));
}

spi_device_cmd_t ChipEraseCmd() {
return {
.opcode = kSpiDeviceOpcodeChipErase,
.address = kSpiDeviceNoAddress,
.payload_byte_count = 0,
.payload = {},
};
}

spi_device_cmd_t SectorEraseCmd(uint32_t address) {
return {
.opcode = kSpiDeviceOpcodeSectorErase,
.address = address,
.payload_byte_count = 0,
.payload = {},
};
}

spi_device_cmd_t PageProgramCmd(uint32_t address, size_t payload_byte_count) {
spi_device_cmd_t cmd{
.opcode = kSpiDeviceOpcodePageProgram,
.address = address,
.payload_byte_count = payload_byte_count,
};
EXPECT_LE(payload_byte_count, kSpiDevicePayloadAreaNumBytes);
for (size_t i = 0; i < payload_byte_count; ++i) {
cmd.payload[i] = static_cast<uint8_t>(i);
}

return cmd;
}

spi_device_cmd_t ResetCmd() {
return {
.opcode = kSpiDeviceOpcodeReset,
.address = kSpiDeviceNoAddress,
.payload_byte_count = 0,
.payload = {},
};
}

} // namespace bootstrap_unittest_util

0 comments on commit 81e5a3c

Please sign in to comment.