// Copyright 2023 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 "network.h"

#include <numeric>

#include <efi/protocol/managed-network.h>
#include <gigaboot/cpp/utils.h>

namespace gigaboot {

namespace {

// Given an efi_mac_addr, return a 6 byte octet "real" MAC address.
MacAddr MacAddrFromEfiMacAddr(efi_mac_addr const& addr) {
  MacAddr eth;
  static_assert(sizeof(addr.addr) >= eth.size(), "Error: source MAC is too small");
  std::copy(std::cbegin(addr.addr), std::cbegin(addr.addr) + eth.size(), std::begin(eth));
  return eth;
}

// Given a "real" MAC address, return an efi_mac_addr.
efi_mac_addr EfiMacAddrFromMacAddr(MacAddr addr) {
  efi_mac_addr eth = {};
  static_assert(addr.size() <= sizeof(eth.addr), "Error: source MAC is too large");
  std::copy(addr.cbegin(), addr.cend(), std::begin(eth.addr));
  return eth;
}

// Returns the first functional network interface found, configured to support unicast receive,
// or nullptr if there is no such interface.
EfiProtocolPtr<efi_managed_network_protocol> FindNetworkIntf() {
  auto managed_handles = EfiLocateHandleBufferByProtocol<efi_managed_network_protocol>();
  if (managed_handles.is_error()) {
    return nullptr;
  }

  for (auto handle : managed_handles->AsSpan()) {
    auto managed_proto = EfiOpenProtocol<efi_managed_network_protocol>(handle);
    if (managed_proto.is_error()) {
      continue;
    }

    efi_managed_network_config_data mnp_config_data;
    efi_simple_network_mode snp_mode_data;
    if (managed_proto->GetModeData(managed_proto.value().get(), &mnp_config_data, &snp_mode_data) !=
        EFI_SUCCESS) {
      continue;
    }

    if (!snp_mode_data.MediaPresent) {
      continue;
    }

    // Note: this managed network instance may already have been started by the TCP6 stack.
    // If that's the case, it should already have unicast receive enabled, and we don't
    // want to stop traffic to enable it.
    if (!mnp_config_data.EnableUnicastReceive) {
      if (managed_proto->Configure(managed_proto.value().get(), nullptr) != EFI_SUCCESS) {
        continue;
      }

      mnp_config_data.EnableUnicastReceive = true;
      if (managed_proto->Configure(managed_proto.value().get(), &mnp_config_data) != EFI_SUCCESS) {
        continue;
      }
    }

    return std::move(managed_proto.value());
  }

  return nullptr;
}

}  // namespace

Ip6Header::Ip6Header(uint16_t len, uint8_t next_hdr, const Ip6Addr& src, const Ip6Addr& dst)
    : vtcf(htonl(6 << 28)),
      length(htons(len)),
      next_header(next_hdr),
      hop_limit(0xFF),
      source(src),
      dest(dst) {}

uint16_t CalculateChecksum(cpp20::span<const uint8_t> data, uint64_t start) {
  cpp20::span<const uint16_t> tmp(reinterpret_cast<const uint16_t*>(data.data()),
                                  data.size() / sizeof(uint16_t));
  // The start and result are wider than a u16 to properly hold the overflow bits
  // from 1s complement addition.
  uint64_t sum = std::reduce(tmp.begin(), tmp.end(), start);
  if (data.size() % 2 == 1) {
    sum += data.back();
  }

  // 1s complement addition works by wrapping overflow bits and adding them.
  while (sum > 0xFFFF) {
    sum = (sum & 0xFFFF) + (sum >> 16);
  }

  return static_cast<uint16_t>(sum);
}

fit::result<efi_status, EthernetAgent> EthernetAgent::Create() {
  EfiProtocolPtr<efi_managed_network_protocol> mnp = FindNetworkIntf();
  if (!mnp) {
    return fit::error(EFI_NO_MEDIA);
  }

  efi_managed_network_config_data mnp_data;
  efi_simple_network_mode snp_data;
  if (efi_status res = mnp->GetModeData(mnp.get(), &mnp_data, &snp_data); res != EFI_SUCCESS) {
    return fit::error(res);
  }

  MacAddr mac_addr = MacAddrFromEfiMacAddr(snp_data.CurrentAddress);
  return fit::ok(EthernetAgent(std::move(mnp), mac_addr));
}

fit::result<efi_status> EthernetAgent::SendV6LocalFrame(
    MacAddr dst, cpp20::span<const uint8_t> data, efi_event callback,
    efi_managed_network_sync_completion_token* token) {
  if (!token) {
    return fit::error(EFI_INVALID_PARAMETER);
  }

  // Note: the efi_mac_addr struct is a 32 byte array, while real MAC addresses are 6 octets.
  // There is no obvious explanation for this discrepancy in the UEFI docs.
  // It's much more convenient to deal with normal sized MAC addresses, though,
  // so we convert to efi_mac_addr only when necessary.
  efi_mac_addr dest = EfiMacAddrFromMacAddr(dst);
  efi_mac_addr src = EfiMacAddrFromMacAddr(mac_addr_);
  efi_managed_network_transmit_data tx_data = {
      .DestinationAddress = &dest,
      .SourceAddress = &src,
      .ProtocolType = 0x86DD,  // IPv6 EtherType
      .DataLength = static_cast<uint32_t>(data.size()),
      .HeaderLength = 0,
      .FragmentCount = 1,
      .FragmentTable =
          {
              {
                  .FragmentLength = static_cast<uint32_t>(data.size()),
                  .FragmentBuffer = const_cast<uint8_t*>(data.data()),
              },
          },
  };

  *token = {.Event = callback, .Packet = {.TxData = &tx_data}};
  if (efi_status res = net_proto_->Transmit(net_proto_.get(), token); res != EFI_SUCCESS) {
    return fit::error(res);
  }

  return fit::ok();
}

}  // namespace gigaboot
