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

#include "sw/device/lib/dif/dif_csrng.h"

#include "sw/device/lib/base/bitfield.h"
#include "sw/device/lib/base/memory.h"
#include "sw/device/lib/base/mmio.h"

#include "csrng_regs.h"  // Generated

enum {
  /**
   * CSRNG genbits buffer size in uint32_t words.
   */
  kCsrngGenBitsBufferSize = 4,
};

/**
 * Supported CSRNG application commands.
 * See https://docs.opentitan.org/hw/ip/csrng/doc/#command-header for
 * details.
 */
typedef enum csrng_app_cmd_id {
  kCsrngAppCmdInstantiate = 1,
  kCsrngAppCmdReseed = 2,
  kCsrngAppCmdGenerate = 3,
  kCsrngAppCmdUpdate = 4,
  kCsrngAppCmdUnisntantiate = 5,
} csrng_app_cmd_id_t;

/**
 * CSRNG application interface command header parameters.
 */
typedef struct csrng_app_cmd {
  /**
   * Application command.
   */
  csrng_app_cmd_id_t id;
  /**
   * Entropy source enable.
   *
   * Mapped to flag0 in the hardware command interface.
   */
  dif_csrng_entropy_src_toggle_t entropy_src_enable;
  /**
   * Seed material. Only used in `kCsrngAppCmdInstantiate`, `kCsrngAppCmdReseed`
   * and `kCsrngAppCmdUpdate` commands.
   */
  const dif_csrng_seed_material_t *seed_material;
  /**
   * Generate length. Specified as number of 128bit blocks.
   */
  uint32_t generate_len;
} csrng_app_cmd_t;

/**
 * Writes application command `cmd` to the CSRNG_CMD_REQ_REG register.
 * Returns the result of the operation.
 */
static dif_csrng_result_t write_application_command(
    const dif_csrng_t *csrng, const csrng_app_cmd_t *cmd) {
  if (csrng == NULL || cmd == NULL) {
    return kDifCsrngBadArg;
  }

  // The application command header is not specified as a register in the
  // hardware specification, so the fields are mapped here by hand. The
  // command register also accepts arbitrary 32bit data.
  const uint32_t kAppCmdBitFlag0 = 8;
  const bitfield_field32_t kAppCmdFieldCmdId = {.mask = 0xf, .index = 0};
  const bitfield_field32_t kAppCmdFieldCmdLen = {.mask = 0xf, .index = 4};
  const bitfield_field32_t kAppCmdFieldGlen = {.mask = 0x7ffff, .index = 12};

  uint32_t cmd_len =
      cmd->seed_material == NULL ? 0 : cmd->seed_material->seed_material_len;

  if (cmd_len & ~kAppCmdFieldCmdLen.mask) {
    return kDifCsrngBadArg;
  }

  // Build and write application command header.
  uint32_t reg = bitfield_field32_write(0, kAppCmdFieldCmdId, cmd->id);
  reg = bitfield_field32_write(reg, kAppCmdFieldCmdLen, cmd_len);
  reg = bitfield_bit32_write(reg, kAppCmdBitFlag0, cmd->entropy_src_enable);
  reg = bitfield_field32_write(reg, kAppCmdFieldGlen, cmd->generate_len);
  mmio_region_write32(csrng->params.base_addr, CSRNG_CMD_REQ_REG_OFFSET, reg);

  for (size_t i = 0; i < cmd_len; ++i) {
    mmio_region_write32(csrng->params.base_addr, CSRNG_CMD_REQ_REG_OFFSET,
                        cmd->seed_material->seed_material[i]);
  }
  return kDifCsrngOk;
}

/**
 * Reads the output data register status.
 */
static void get_output_status(const dif_csrng_t *csrng,
                              dif_csrng_output_status_t *status) {
  uint32_t reg =
      mmio_region_read32(csrng->params.base_addr, CSRNG_GENBITS_VLD_REG_OFFSET);
  status->valid_data =
      bitfield_bit32_read(reg, CSRNG_GENBITS_VLD_GENBITS_VLD_BIT);
  status->fips_mode =
      bitfield_bit32_read(reg, CSRNG_GENBITS_VLD_GENBITS_FIPS_BIT);
}

/**
 * Returns true if the data register has valid data.
 */
static bool is_output_ready(const dif_csrng_t *csrng) {
  dif_csrng_output_status_t status;
  get_output_status(csrng, &status);
  return status.valid_data;
}

dif_csrng_result_t dif_csrng_init(dif_csrng_params_t params,
                                  dif_csrng_t *csrng) {
  if (csrng == NULL) {
    return kDifCsrngBadArg;
  }
  *csrng = (dif_csrng_t){.params = params};
  return kDifCsrngOk;
}

dif_csrng_result_t dif_csrng_configure(const dif_csrng_t *csrng) {
  if (csrng == NULL) {
    return kDifCsrngBadArg;
  }
  mmio_region_write32(csrng->params.base_addr, CSRNG_CTRL_REG_OFFSET, 0xaa);
  return kDifCsrngOk;
}

dif_csrng_result_t dif_csrng_instantiate(
    const dif_csrng_t *csrng, dif_csrng_entropy_src_toggle_t entropy_src_enable,
    const dif_csrng_seed_material_t *seed_material) {
  const csrng_app_cmd_t app_cmd = {
      .id = kCsrngAppCmdInstantiate,
      .entropy_src_enable = entropy_src_enable,
      .seed_material = seed_material,
      .generate_len = 0,
  };
  return write_application_command(csrng, &app_cmd);
}

dif_csrng_result_t dif_csrng_reseed(
    const dif_csrng_t *csrng, const dif_csrng_seed_material_t *seed_material) {
  const csrng_app_cmd_t app_cmd = {
      .id = kCsrngAppCmdReseed,
      .entropy_src_enable = false,
      .seed_material = seed_material,
      .generate_len = 0,
  };
  return write_application_command(csrng, &app_cmd);
}

dif_csrng_result_t dif_csrng_update(
    const dif_csrng_t *csrng, const dif_csrng_seed_material_t *seed_material) {
  const csrng_app_cmd_t app_cmd = {
      .id = kCsrngAppCmdUpdate,
      .entropy_src_enable = false,
      .seed_material = seed_material,
      .generate_len = 0,
  };
  return write_application_command(csrng, &app_cmd);
}

dif_csrng_result_t dif_csrng_generate_start(const dif_csrng_t *csrng,
                                            size_t len) {
  if (len == 0) {
    return kDifCsrngBadArg;
  }

  // Round up the number of 128bit blocks. Aligning with respect to uint32_t.
  // TODO(#6112): Consider using a canonical reference for alignment operations.
  const uint32_t num_128bit_blocks = (len + 3) / 4;

  const csrng_app_cmd_t app_cmd = {
      .id = kCsrngAppCmdGenerate,
      .entropy_src_enable = false,
      .seed_material = NULL,
      .generate_len = num_128bit_blocks,
  };
  return write_application_command(csrng, &app_cmd);
}

dif_csrng_result_t dif_csrng_generate_end(const dif_csrng_t *csrng,
                                          uint32_t *buf, size_t len) {
  if (csrng == NULL || buf == NULL) {
    return kDifCsrngBadArg;
  }

  // Wait until there is data ready.
  while (!is_output_ready(csrng)) {
  }

  for (size_t i = 0, rd_cnt = 0; i < len; ++i, ++rd_cnt) {
    // Block until there is more data available in the genbits buffer.
    if (rd_cnt == kCsrngGenBitsBufferSize) {
      while (!is_output_ready(csrng)) {
      }
      rd_cnt = 0;
    }
    buf[i] =
        mmio_region_read32(csrng->params.base_addr, CSRNG_GENBITS_REG_OFFSET);
  }
  return kDifCsrngOk;
}

dif_csrng_result_t dif_csrng_uninstantiate(const dif_csrng_t *csrng) {
  const csrng_app_cmd_t app_cmd = {
      .id = kCsrngAppCmdUnisntantiate,
      .entropy_src_enable = false,
      .seed_material = NULL,
      .generate_len = 0,
  };
  return write_application_command(csrng, &app_cmd);
}

dif_csrng_result_t dif_csrng_get_cmd_interface_status(
    const dif_csrng_t *csrng, dif_csrng_cmd_status_t *status) {
  if (csrng == NULL || status == NULL) {
    return kDifCsrngBadArg;
  }

  uint32_t reg =
      mmio_region_read32(csrng->params.base_addr, CSRNG_SW_CMD_STS_REG_OFFSET);
  bool cmd_ready = bitfield_bit32_read(reg, CSRNG_SW_CMD_STS_CMD_RDY_BIT);
  bool cmd_error = bitfield_bit32_read(reg, CSRNG_SW_CMD_STS_CMD_STS_BIT);

  // The function prioritizes error detection to avoid masking errors
  // when `cmd_ready` is set to true.
  if (cmd_error) {
    *status = kDifCsrngCmdStatusError;
    return kDifCsrngOk;
  }

  if (cmd_ready) {
    *status = kDifCsrngCmdStatusReady;
    return kDifCsrngOk;
  }

  *status = kDifCsrngCmdStatusBusy;
  return kDifCsrngOk;
}

dif_csrng_result_t dif_csrng_get_output_status(
    const dif_csrng_t *csrng, dif_csrng_output_status_t *status) {
  if (csrng == NULL || status == NULL) {
    return kDifCsrngBadArg;
  }
  get_output_status(csrng, status);
  return kDifCsrngOk;
}

DIF_WARN_UNUSED_RESULT
dif_csrng_result_t dif_csrng_get_internal_state(
    const dif_csrng_t *csrng, dif_csrng_internal_state_id_t instance_id,
    dif_csrng_internal_state_t *state) {
  if (csrng == NULL || state == NULL) {
    return kDifCsrngBadArg;
  }

  // Select the instance id to read the internal state from, request a state
  // machine halt, and wait for the internal registers to be ready to be read.
  uint32_t reg = bitfield_field32_write(
      0, CSRNG_INT_STATE_NUM_INT_STATE_NUM_FIELD, instance_id);
  mmio_region_write32(csrng->params.base_addr, CSRNG_INT_STATE_NUM_REG_OFFSET,
                      reg);

  // Read the internal state.
  state->reseed_counter = mmio_region_read32(csrng->params.base_addr,
                                             CSRNG_INT_STATE_VAL_REG_OFFSET);

  for (size_t i = 0; i < ARRAYSIZE(state->v); ++i) {
    state->v[i] = mmio_region_read32(csrng->params.base_addr,
                                     CSRNG_INT_STATE_VAL_REG_OFFSET);
  }

  for (size_t i = 0; i < ARRAYSIZE(state->key); ++i) {
    state->key[i] = mmio_region_read32(csrng->params.base_addr,
                                       CSRNG_INT_STATE_VAL_REG_OFFSET);
  }

  uint32_t flags = mmio_region_read32(csrng->params.base_addr,
                                      CSRNG_INT_STATE_VAL_REG_OFFSET);

  // The following bit indexes are defined in
  // https://docs.opentitan.org/hw/ip/csrng/doc/#working-state-values
  state->instantiated = bitfield_bit32_read(flags, /*bit_index=*/0u);
  state->fips_compliance = bitfield_bit32_read(flags, /*bit_index=*/1u);

  return kDifCsrngOk;
}
