// 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);

  // Reverse the order of the bytes to make them little-endian and be consistent
  // with the code signing tool.
  std::reverse(f->hdr.hash, f->hdr.hash + 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
