5 #include "sw/device/silicon_creator/lib/bootstrap.h"
13 #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
14 #include "sw/device/silicon_creator/lib/drivers/rstmgr.h"
15 #include "sw/device/silicon_creator/lib/drivers/spi_device.h"
16 #include "sw/device/silicon_creator/lib/error.h"
17 #include "sw/device/silicon_creator/lib/stack_utilization.h"
19 #include "flash_ctrl_regs.h"
26 FLASH_CTRL_PARAM_BYTES_PER_BANK * FLASH_CTRL_PARAM_REG_NUM_BANKS,
29 static_assert(FLASH_CTRL_PARAM_REG_NUM_BANKS == 2,
"Flash must have 2 banks");
46 typedef enum bootstrap_state {
51 kBootstrapStateErase = 0xd4576543,
56 kBootstrapStateEraseVerify = 0xf3c71bac,
61 kBootstrapStateProgram = 0xbdd8ca60,
75 static rom_error_t bootstrap_sector_erase(uint32_t addr) {
76 static_assert(FLASH_CTRL_PARAM_BYTES_PER_PAGE == 2048,
77 "Page size must be 2 KiB");
82 kPageAddrMask = ~UINT32_C(4096) + 1,
85 if (addr >= kMaxAddress) {
86 return kErrorBootstrapEraseAddress;
88 addr &= kPageAddrMask;
91 .read = kMultiBitBool4False,
92 .write = kMultiBitBool4False,
93 .erase = kMultiBitBool4True,
95 rom_error_t err_0 = flash_ctrl_data_erase(addr, kFlashCtrlEraseTypePage);
96 rom_error_t err_1 = flash_ctrl_data_erase(
97 addr + FLASH_CTRL_PARAM_BYTES_PER_PAGE, kFlashCtrlEraseTypePage);
99 .read = kMultiBitBool4False,
100 .write = kMultiBitBool4False,
101 .erase = kMultiBitBool4False,
104 HARDENED_RETURN_IF_ERROR(err_0);
124 static rom_error_t bootstrap_page_program(uint32_t addr,
size_t byte_count,
126 static_assert(__builtin_popcount(FLASH_CTRL_PARAM_BYTES_PER_WORD) == 1,
127 "Bytes per flash word must be a power of two.");
132 kFlashWordMask = FLASH_CTRL_PARAM_BYTES_PER_WORD - 1,
136 kFlashProgPageSize = 256,
143 kFlashProgPageMask = kFlashProgPageSize - 1,
146 if (addr & kFlashWordMask || addr >= kMaxAddress) {
147 return kErrorBootstrapProgramAddress;
151 size_t flash_word_misalignment = byte_count & kFlashWordMask;
152 if (flash_word_misalignment > 0) {
153 size_t padding_byte_count =
154 FLASH_CTRL_PARAM_BYTES_PER_WORD - flash_word_misalignment;
155 for (
size_t i = 0; i < padding_byte_count; ++i) {
156 data[byte_count++] = 0xff;
159 size_t rem_word_count = byte_count /
sizeof(uint32_t);
162 .read = kMultiBitBool4False,
163 .write = kMultiBitBool4True,
164 .erase = kMultiBitBool4False,
168 rom_error_t err_0 = kErrorOk;
169 size_t prog_page_misalignment = addr & kFlashProgPageMask;
170 if (prog_page_misalignment > 0) {
172 (kFlashProgPageSize - prog_page_misalignment) /
sizeof(uint32_t);
173 if (word_count > rem_word_count) {
174 word_count = rem_word_count;
176 err_0 = flash_ctrl_data_write(addr, word_count, data);
177 rem_word_count -= word_count;
178 data += word_count *
sizeof(uint32_t);
181 addr &= ~(uint32_t)kFlashProgPageMask;
183 rom_error_t err_1 = kErrorOk;
184 if (rem_word_count > 0) {
185 err_1 = flash_ctrl_data_write(addr, rem_word_count, data);
188 .read = kMultiBitBool4False,
189 .write = kMultiBitBool4False,
190 .erase = kMultiBitBool4False,
193 HARDENED_RETURN_IF_ERROR(err_0);
208 static rom_error_t bootstrap_handle_erase(bootstrap_state_t *state) {
212 RETURN_IF_ERROR(spi_device_cmd_get(&cmd));
218 rom_error_t error = kErrorUnknown;
220 case kSpiDeviceOpcodeChipErase:
221 case kSpiDeviceOpcodeSectorErase:
222 error = bootstrap_chip_erase();
223 HARDENED_RETURN_IF_ERROR(error);
224 *state = kBootstrapStateEraseVerify;
231 spi_device_flash_status_clear();
247 static rom_error_t bootstrap_handle_erase_verify(bootstrap_state_t *state) {
250 const rom_error_t err = bootstrap_erase_verify();
251 HARDENED_RETURN_IF_ERROR(err);
253 spi_device_flash_status_clear();
255 *state = kBootstrapStateProgram;
266 static rom_error_t bootstrap_handle_program(bootstrap_state_t *state) {
269 "Payload must be word aligned.");
273 "Payload size must be a multiple of flash word size.");
278 RETURN_IF_ERROR(spi_device_cmd_get(&cmd));
280 if (cmd.
opcode != kSpiDeviceOpcodeReset &&
285 rom_error_t error = kErrorUnknown;
287 case kSpiDeviceOpcodeChipErase:
288 error = bootstrap_chip_erase();
290 case kSpiDeviceOpcodeSectorErase:
291 error = bootstrap_sector_erase(cmd.
address);
293 case kSpiDeviceOpcodePageProgram:
297 case kSpiDeviceOpcodeReset:
299 stack_utilization_print();
301 #ifdef OT_PLATFORM_RV32
306 error = kErrorUnknown;
315 HARDENED_RETURN_IF_ERROR(error);
317 spi_device_flash_status_clear();
321 rom_error_t enter_bootstrap(
void) {
325 bootstrap_state_t state = kBootstrapStateErase;
326 rom_error_t error = kErrorUnknown;
328 switch (launder32(state)) {
329 case kBootstrapStateErase:
331 error = bootstrap_handle_erase(&state);
333 case kBootstrapStateEraseVerify:
335 error = bootstrap_handle_erase_verify(&state);
337 case kBootstrapStateProgram:
339 error = bootstrap_handle_program(&state);
342 error = kErrorBootstrapInvalidState;
344 HARDENED_RETURN_IF_ERROR(error);