// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "video_firmware_session.h"

#include <lib/zx/vmo.h>
#include <zircon/assert.h>

#include <cinttypes>

#include <fbl/algorithm.h>

#include "macros.h"

namespace amlogic_decoder {

namespace {

// Defined by video_firmware TA.
enum VideoFirmwareCommandIds {
  // Firmware for video decode HW.
  kVideoFirmwareCommandIdLoadVideoFirmware = 0,
  // Firmware for video encode HW.
  kVideoFirmwareCommandIdLoadVideoFirmwareEncoder = 1,
  // For normal builds of the TA, this isn't that useful, but it is a command.  We probably won't
  // need to implement a method for this command.
  kVideoFirmwareCommandIdDebugVideoFirmware = 2,
};

zx::vmo CreateVmo(uint64_t size) {
  zx::vmo result;
  zx_status_t status = zx::vmo::create(size, /*options=*/0, &result);
  ZX_ASSERT(status == ZX_OK);

  return result;
}

fpromise::result<fuchsia::tee::Buffer, zx_status_t> CreateBufferParameter(
    const uint8_t* data, uint64_t size, fuchsia::tee::Direction direction) {
  zx::vmo vmo = CreateVmo(size);

  zx_status_t status = vmo.write(data, /*offset=*/0, static_cast<size_t>(size));
  if (status != ZX_OK) {
    LOG(ERROR, "Failed to write to parameter to VMO - status: %d", status);
    return fpromise::error(status);
  }

  fuchsia::tee::Buffer buffer;
  buffer.set_vmo(std::move(vmo)).set_direction(direction).set_offset(0).set_size(size);

  return fpromise::ok(std::move(buffer));
}

}  // namespace

fpromise::result<VideoFirmwareSession, fuchsia::tee::ApplicationSyncPtr>
VideoFirmwareSession::TryOpen(fuchsia::tee::ApplicationSyncPtr tee_connection) {
  if (!tee_connection.is_bound()) {
    return fpromise::error(std::move(tee_connection));
  }

  fuchsia::tee::OpResult result;
  uint32_t session_id = 0;
  auto params = std::vector<fuchsia::tee::Parameter>();

  if (zx_status_t status = tee_connection->OpenSession2(std::move(params), &session_id, &result);
      status != ZX_OK) {
    LOG(ERROR, "OpenSession channel call failed (status: %d)", status);
    return fpromise::error(std::move(tee_connection));
  }

  if (!result.has_return_code() || !result.has_return_origin()) {
    LOG(ERROR, "OpenSession returned with result codes missing");
    return fpromise::error(std::move(tee_connection));
  }

  if (result.return_code() != TEEC_SUCCESS) {
    LOG(ERROR, "OpenSession to video_firmware failed (result: %" PRIx64 ", origin: %" PRIu32 ").",
        result.return_code(), static_cast<uint32_t>(result.return_origin()));
  }

  return fpromise::ok(VideoFirmwareSession{session_id, std::move(tee_connection)});
}

VideoFirmwareSession::~VideoFirmwareSession() {
  if (tee_connection_.is_bound()) {
    tee_connection_->CloseSession(session_id_);
  }
}

zx_status_t VideoFirmwareSession::LoadVideoFirmware(const uint8_t* data, uint32_t size) {
  constexpr uint32_t kSignatureSize = 256;
  if (size < kSignatureSize) {
    LOG(ERROR, "size < kSignatureSize -- size: %u", size);
    return ZX_ERR_INVALID_ARGS;
  }

  const uint8_t* payload_data = data + kSignatureSize;
  const size_t payload_size = size - kSignatureSize;
  auto payload_buffer_result =
      CreateBufferParameter(payload_data, payload_size, fuchsia::tee::Direction::INPUT);
  if (!payload_buffer_result.is_ok()) {
    return payload_buffer_result.error();
  }

  const uint8_t* signature_data = data;
  auto signature_buffer_result =
      CreateBufferParameter(signature_data, kSignatureSize, fuchsia::tee::Direction::INPUT);
  if (!signature_buffer_result.is_ok()) {
    return signature_buffer_result.error();
  }

  constexpr size_t kNumParams = 2;
  auto params = std::vector<fuchsia::tee::Parameter>();
  params.reserve(kNumParams);
  params.push_back(fuchsia::tee::Parameter::WithBuffer(payload_buffer_result.take_value()));
  params.push_back(fuchsia::tee::Parameter::WithBuffer(signature_buffer_result.take_value()));

  fuchsia::tee::OpResult result;
  if (zx_status_t status = tee_connection_->InvokeCommand(
          session_id_, kVideoFirmwareCommandIdLoadVideoFirmware, std::move(params), &result);
      status != ZX_OK) {
    LOG(ERROR, "InvokeCommand channel call failed - status: %d", status);
    return status;
  }

  if (!result.has_return_code() || !result.has_return_origin()) {
    LOG(ERROR, "InvokeCommand returned with result codes missing");
    return ZX_ERR_INTERNAL;
  }

  auto tee_status = static_cast<const TEEC_Result>(result.return_code());

  if (tee_status != TEEC_SUCCESS) {
    LOG(ERROR, "kVideoFirmwareCommandIdLoadVideoFirmware failed - TEEC_Result: 0x%" PRIx32,
        tee_status);
    return ZX_ERR_INTERNAL;
  }
  return ZX_OK;
}

zx_status_t VideoFirmwareSession::LoadVideoFirmwareEncoder(uint8_t* data, uint32_t size) {
  constexpr uint32_t kAesIvSize = 16;
  constexpr uint32_t kSignatureSize = 256;
  if (size < kAesIvSize + kSignatureSize) {
    LOG(ERROR, "size < kAesIvSize + kSignatureSize -- size: %u", size);
    return ZX_ERR_INVALID_ARGS;
  }

  const uint8_t* iv_data = data;
  auto iv_buffer_result =
      CreateBufferParameter(iv_data, kAesIvSize, fuchsia::tee::Direction::INPUT);
  if (!iv_buffer_result.is_ok()) {
    return iv_buffer_result.error();
  }

  const uint8_t* signature_data = data + kAesIvSize;
  auto signature_buffer_result =
      CreateBufferParameter(signature_data, kSignatureSize, fuchsia::tee::Direction::INPUT);
  if (!signature_buffer_result.is_ok()) {
    return signature_buffer_result.error();
  }

  const uint8_t* payload_data = data + kAesIvSize + kSignatureSize;
  const size_t payload_size = size - kSignatureSize - kAesIvSize;
  auto payload_buffer_result =
      CreateBufferParameter(payload_data, payload_size, fuchsia::tee::Direction::INPUT);
  if (!payload_buffer_result.is_ok()) {
    return payload_buffer_result.error();
  }

  constexpr size_t kNumParams = 3;
  auto params = std::vector<fuchsia::tee::Parameter>();
  params.reserve(kNumParams);
  params.push_back(fuchsia::tee::Parameter::WithBuffer(iv_buffer_result.take_value()));
  params.push_back(fuchsia::tee::Parameter::WithBuffer(signature_buffer_result.take_value()));
  params.push_back(fuchsia::tee::Parameter::WithBuffer(payload_buffer_result.take_value()));

  fuchsia::tee::OpResult result;
  if (zx_status_t status = tee_connection_->InvokeCommand(
          session_id_, kVideoFirmwareCommandIdLoadVideoFirmwareEncoder, std::move(params), &result);
      status != ZX_OK) {
    LOG(ERROR, "InvokeCommand channel call failed - status: %d)", status);
    return status;
  }

  if (!result.has_return_code() || !result.has_return_origin()) {
    LOG(ERROR, "InvokeCommand returned with result codes missing");
    return ZX_ERR_INTERNAL;
  }

  auto tee_status = static_cast<const TEEC_Result>(result.return_code());
  if (tee_status != TEEC_SUCCESS) {
    LOG(ERROR, "kVideoFirmwareCommandIdLoadVideoFirmwareEncoder failed - TEEC_Result: 0x%" PRIx32,
        tee_status);
    return ZX_ERR_INTERNAL;
  }
  return ZX_OK;
}

}  // namespace amlogic_decoder
