// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/host/spiflash/updater.h"

#include <algorithm>
#include <assert.h>
#include <string.h>
#include <unistd.h>

#include "cryptoc/sha256.h"

namespace opentitan {
namespace spiflash {
namespace {

/**
 * Populate target frame `f`.
 *
 * Populates frame `f` with `frame_number`, `code_offset`, and frame data
 * starting at `code_offset` from `code` buffer. Calculates SHA256 hash of
 * frame payload and it stores it in the frame header.
 *
 * @return the number of bytes loaded into the frame.
 */
uint32_t Populate(uint32_t frame_number, uint32_t code_offset,
                  const std::string &code, Frame *f) {
  assert(f);
  assert(code_offset < code.size());

  // Populate payload data. Initialize buffer to 0xff to minimize flash
  // writes.
  size_t copy_size =
      std::min<size_t>(f->PayloadSize(), code.size() - code_offset);
  memset(f->data, 0xff, f->PayloadSize());
  memcpy(f->data, code.data() + code_offset, copy_size);

  // Populate header number, offset and hash.
  f->hdr.frame_num = frame_number;
  f->hdr.offset = code_offset;
  return copy_size;
}

/**
 * Calculate hash for frame `f` and store it in the frame header hash field.
 */
void HashFrame(Frame *f) {
  LITE_SHA256_CTX sha256;
  SHA256_init(&sha256);
  SHA256_update(&sha256, &f->hdr.frame_num, sizeof(f->hdr.frame_num));
  SHA256_update(&sha256, &f->hdr.offset, sizeof(f->hdr.offset));
  SHA256_update(&sha256, f->data, f->PayloadSize());
  const uint8_t *result = SHA256_final(&sha256);
  memcpy(f->hdr.hash, result, SHA256_DIGEST_SIZE);
}

}  // namespace

bool Updater::Run() {
  std::cout << "Running SPI flash update." << std::endl;
  std::vector<Frame> frames;
  if (!GenerateFrames(options_.code, &frames)) {
    std::cerr << "Unable to process flash image." << std::endl;
    return false;
  }
  std::cout << "Image divided into " << frames.size() << " frames."
            << std::endl;

  std::string ack_expected;
  ack_expected.resize(sizeof(Frame), '\0');
  std::string ack;
  ack.resize(sizeof(Frame));
  for (uint32_t current_frame = 0; current_frame < frames.size();) {
    const Frame &f = frames[current_frame];

    std::cout << "frame: 0x" << std::setfill('0') << std::setw(8) << std::hex
              << f.hdr.frame_num << " to offset: 0x" << std::setfill('0')
              << std::setw(8) << std::hex << f.hdr.offset << std::endl;

    if (!spi_->TransmitFrame(reinterpret_cast<const uint8_t *>(&f),
                             sizeof(Frame))) {
      std::cerr << "Failed to transmit frame no: 0x" << std::setfill('0')
                << std::setw(8) << std::hex << f.hdr.frame_num << std::endl;
    }

    // After receiving and validating the first frame, the device is erasing
    // the Flash.
    if (current_frame == 0) {
      usleep(options_.flash_erase_delay_us);
    }

    // When we send each frame we wait for the correct hash before continuing.
    if (current_frame == frames.size() - 1 ||
        spi_->CheckHash(reinterpret_cast<const uint8_t *>(&f), sizeof(Frame))) {
      current_frame++;
    }
  }
  return true;
}

bool Updater::GenerateFrames(const std::string &code,
                             std::vector<Frame> *frames) {
  if (frames == nullptr) {
    return false;
  }
  uint32_t frame_number = 0;
  uint32_t code_offset = 0;
  while (code_offset < code.size()) {
    Frame frame;
    uint32_t bytes_copied = Populate(frame_number, code_offset, code, &frame);
    code_offset += bytes_copied;
    frame_number++;
    frames->emplace_back(frame);
  }
  // Update last frame to sentinel EOF value.
  Frame &last_frame = frames->back();
  last_frame.hdr.frame_num = 0x80000000 | last_frame.hdr.frame_num;

  for (Frame &f : *frames) {
    HashFrame(&f);
  }
  return true;
}

}  // namespace spiflash
}  // namespace opentitan
