blob: ec0485c77bd0e33101982bad58b2c6716a7a1585 [file] [log] [blame]
lowRISC Contributors802543a2019-08-31 12:12:56 +01001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5#include "bootstrap.h"
6
7#include "common.h"
8#include "flash_ctrl.h"
9#include "gpio.h"
10#include "spi_device.h"
11#include "uart.h" // TODO: Wrap uart in DEBUG macros.
12
13/* Checks if flash is blank to determine if bootstrap is needed. */
14/* TODO: Update this to check bootstrap pin instead in Verilator. */
15static int bootstrap_requested(void) {
16// The following flash empty-sniff-check is done this way due to the lack of
17// clear eflash reset in SIM environments.
18#if defined(SIMULATION)
19 return !!(REG32(FLASH_MEM_BASE_ADDR) == 0 ||
20 REG32(FLASH_MEM_BASE_ADDR) == 0xFFFFFFFF);
21#else
22 return !!(gpio_read() & GPIO_BOOTSTRAP_BIT_MASK);
23#endif
24}
25
26/* Erase all flash, and verify blank. */
27static int erase_flash(void) {
28 if (flash_bank_erase(FlashBank0)) {
29 return E_BS_ERASE;
30 }
31 if (flash_bank_erase(FlashBank1)) {
32 return E_BS_ERASE;
33 }
34 if (!flash_check_empty()) {
35 return E_BS_NOTEMPTY;
36 }
37 return 0;
38}
39
40/* Processes frames received via spid interface and writes them to flash. */
41static int bootstrap_flash(void) {
42 static frame_t f;
43 static uint8_t ack[32] = {0};
44 uint32_t expected_frame_no = 0;
45 for (;;) {
46 if (spid_bytes_available() >= sizeof(f)) {
47 spid_read_nb(&f, sizeof(f));
48 uart_send_str("Processing frame no: ");
49 uart_send_uint(f.hdr.frame_num, 32);
50 uart_send_str(" exp no: ");
51 uart_send_uint(expected_frame_no, 32);
52 uart_send_str("\r\n");
53
54 // TODO: Add hash check.
55 if (FRAME_NO(f.hdr.frame_num) == expected_frame_no) {
56 // TODO: Add ack computation.
57 spid_send(ack, sizeof(ack));
58
59 if (expected_frame_no == 0) {
60 // TODO: Add signed header checks.
61 flash_default_region_access(/*rd_en=*/1, /*prog_en=*/1,
62 /*erase_en=*/1);
63 int rv = erase_flash();
64 if (rv) {
65 return rv;
66 }
67 }
68 if (flash_write(f.hdr.flash_offset, f.data, ARRAYSIZE(f.data))) {
69 return E_BS_WRITE;
70 }
71
72 ++expected_frame_no;
73 if (f.hdr.frame_num & FRAME_EOF_MARKER) {
74 break;
75 }
76 } else {
77 // Send previous ack if unable to verify current frame.
78 spid_send(ack, sizeof(ack));
79 }
80 }
81 }
82 uart_send_str("bootstrap: DONE!\r\n");
83 return 0;
84}
85
86int bootstrap(void) {
87 if (!bootstrap_requested()) {
88 return 0;
89 }
90 // SPI device is only initialized in bootstrap mode.
91 spid_init();
92 flash_init_block();
93
94 int rv = bootstrap_flash();
95
96 // Always make sure to revert flash_ctrl access to default settings.
97 // bootstrap_flash enables access to flash to perform update.
98 flash_default_region_access(/*rd_en=*/0, /*prog_en=*/0, /*erase_en=*/0);
99 return rv;
100}