lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 1 | // Copyright lowRISC contributors. |
| 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | // SPDX-License-Identifier: Apache-2.0 |
| 4 | |
Miguel Young de la Sota | 3fbb28a | 2019-10-16 15:15:07 -0500 | [diff] [blame] | 5 | #include "sw/host/spiflash/verilator_spi_interface.h" |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 6 | |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 7 | #include <cstring> |
Miguel Osorio | 4359ef3 | 2021-05-25 20:56:01 -0700 | [diff] [blame] | 8 | #include <fcntl.h> |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 9 | #include <iostream> |
| 10 | #include <string> |
Miguel Osorio | 4359ef3 | 2021-05-25 20:56:01 -0700 | [diff] [blame] | 11 | #include <termios.h> |
| 12 | #include <unistd.h> |
Jon Flatley | ed09deb | 2020-02-26 16:18:47 -0500 | [diff] [blame] | 13 | #include <vector> |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 14 | |
Miguel Osorio | 4359ef3 | 2021-05-25 20:56:01 -0700 | [diff] [blame] | 15 | #include "cryptoc/sha256.h" |
| 16 | |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 17 | namespace opentitan { |
| 18 | namespace spiflash { |
| 19 | namespace { |
| 20 | |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 21 | // TODO: If transmission is not successful, adapt this by an argument. |
Miguel Osorio | dbc6e27 | 2020-06-28 17:53:31 -0700 | [diff] [blame] | 22 | /** Required delay to synchronize transactions with simulation environment. */ |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 23 | constexpr int kWriteReadDelay = 20000000; |
| 24 | |
Miguel Osorio | dbc6e27 | 2020-06-28 17:53:31 -0700 | [diff] [blame] | 25 | /** Configure `fd` as a serial port with baud rate 9600. */ |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 26 | bool SetTermOpts(int fd) { |
| 27 | struct termios options; |
| 28 | if (tcgetattr(fd, &options) != 0) { |
| 29 | return false; |
| 30 | } |
| 31 | cfmakeraw(&options); |
| 32 | // The current Verilator configuration uses 9600 baud rate. |
| 33 | if (cfsetispeed(&options, B9600) != 0) { |
| 34 | return false; |
| 35 | } |
| 36 | if (cfsetospeed(&options, B9600) != 0) { |
| 37 | return false; |
| 38 | } |
| 39 | if (tcsetattr(fd, TCSANOW, &options) != 0) { |
| 40 | return false; |
| 41 | } |
| 42 | return true; |
| 43 | } |
| 44 | |
Miguel Osorio | dbc6e27 | 2020-06-28 17:53:31 -0700 | [diff] [blame] | 45 | /** |
| 46 | * Returns file handle on success, or -1 on failure. This function |
| 47 | * configures de file handle to behave as a serial port with baud rate 9600, |
| 48 | * which is the baud rate supported by Verilator. |
| 49 | */ |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 50 | int OpenDevice(const std::string &filename) { |
| 51 | int fd = open(filename.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC); |
| 52 | if (fd < 0) { |
| 53 | std::cerr << "Failed to open device: " << filename << std::endl; |
| 54 | return fd; |
| 55 | } |
| 56 | if (!SetTermOpts(fd)) { |
| 57 | close(fd); |
| 58 | return -1; |
| 59 | } |
| 60 | return fd; |
| 61 | } |
| 62 | |
Miguel Osorio | dbc6e27 | 2020-06-28 17:53:31 -0700 | [diff] [blame] | 63 | /** |
| 64 | * Reads `size` bytes into `rx` buffer from `fd`. Returns the number of bytes |
| 65 | * read. |
| 66 | */ |
Jon Flatley | ed09deb | 2020-02-26 16:18:47 -0500 | [diff] [blame] | 67 | size_t ReadBytes(int fd, uint8_t *rx, size_t size) { |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 68 | size_t bytes_read = 0; |
| 69 | while (bytes_read != size) { |
Jon Flatley | ed09deb | 2020-02-26 16:18:47 -0500 | [diff] [blame] | 70 | ssize_t read_size = read(fd, &rx[bytes_read], size - bytes_read); |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 71 | switch (read_size) { |
| 72 | case -1: |
| 73 | if (errno == EAGAIN || errno == EWOULDBLOCK) { |
| 74 | continue; |
| 75 | } |
| 76 | break; |
| 77 | default: |
| 78 | bytes_read += read_size; |
| 79 | } |
| 80 | } |
| 81 | return bytes_read; |
| 82 | } |
| 83 | |
| 84 | } // namespace |
| 85 | |
| 86 | VerilatorSpiInterface::~VerilatorSpiInterface() { |
| 87 | if (fd_ != -1) { |
| 88 | close(fd_); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | bool VerilatorSpiInterface::Init() { |
| 93 | fd_ = OpenDevice(spi_filename_); |
| 94 | if (fd_ < 0) { |
| 95 | return false; |
| 96 | } |
| 97 | return true; |
| 98 | } |
| 99 | |
Jon Flatley | ed09deb | 2020-02-26 16:18:47 -0500 | [diff] [blame] | 100 | bool VerilatorSpiInterface::TransmitFrame(const uint8_t *tx, size_t size) { |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 101 | size_t bytes_written = write(fd_, tx, size); |
| 102 | if (bytes_written != size) { |
| 103 | std::cerr << "Failed to write bytes to spi interface. Bytes written: " |
| 104 | << bytes_written << " expected: " << size << std::endl; |
| 105 | return false; |
| 106 | } |
| 107 | usleep(kWriteReadDelay); |
Jon Flatley | ed09deb | 2020-02-26 16:18:47 -0500 | [diff] [blame] | 108 | return true; |
| 109 | } |
| 110 | |
| 111 | bool VerilatorSpiInterface::CheckHash(const uint8_t *tx, size_t size) { |
Miguel Osorio | 4359ef3 | 2021-05-25 20:56:01 -0700 | [diff] [blame] | 112 | uint8_t hash[SHA256_DIGEST_SIZE]; |
| 113 | SHA256_hash(tx, size, hash); |
Jon Flatley | ed09deb | 2020-02-26 16:18:47 -0500 | [diff] [blame] | 114 | |
| 115 | std::vector<uint8_t> rx(size); |
| 116 | size_t bytes_read = ReadBytes(fd_, &rx[0], size); |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 117 | if (bytes_read < size) { |
| 118 | std::cerr << "Failed to read bytes from spi interface. Bytes read: " |
| 119 | << bytes_read << " expected: " << size << std::endl; |
| 120 | } |
Jon Flatley | ed09deb | 2020-02-26 16:18:47 -0500 | [diff] [blame] | 121 | |
Miguel Osorio | 4359ef3 | 2021-05-25 20:56:01 -0700 | [diff] [blame] | 122 | return !std::memcmp(&rx[0], hash, SHA256_DIGEST_SIZE); |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 123 | } |
| 124 | } // namespace spiflash |
| 125 | } // namespace opentitan |