// Copyright 2020 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.

#ifndef LIB_UART_ALL_H_
#define LIB_UART_ALL_H_

#include <stdio.h>
#include <zircon/boot/image.h>

#include <utility>
#include <variant>

#include <hwreg/internal.h>

#include "amlogic.h"
#include "ns8250.h"
#include "null.h"
#include "pl011.h"
#include "uart.h"

namespace uart {

namespace internal {

struct DummyDriver : public null::Driver {
  template <typename... Args>
  static std::optional<DummyDriver> MaybeCreate(Args&&...) {
    return {};
  }

  void Unparse(FILE*) const { ZX_PANIC("DummyDriver should never be called!"); }
};

// std::visit is not pure-PIC-friendly.  hwreg implements a limited version
// that is pure-PIC-friendly and that works for the cases here.  Reach in and
// steal that instead of copying the implementation here, since there isn't
// any particularly good "public" place to move it into instead.
using hwreg::internal::Visit;

}  // namespace internal

namespace all {

// uart::all::WithAllDrivers<Template, Args...> instantiates the template class
// Template<Args..., foo::Driver, bar::Driver, ...> for all the drivers
// supported by this kernel build (foo, bar, ...).  Using a template that takes
// a template template parameter is the only real way (short of macros) to have
// a single list of the supported uart::xyz::Driver implementations.
template <template <class... Drivers> class Template, typename... Args>
using WithAllDrivers = Template<
    // Any additional template arguments precede the arguments for each driver.
    Args...,
    // A default-constructed variant gets the null driver.
    null::Driver,
#if defined(__aarch64__) || UART_ALL_DRIVERS
    amlogic::Driver,
    pl011::Driver,  // TODO(fxbug.dev/49423): many more...
#endif
#if defined(__x86_64__) || defined(__i386__) || UART_ALL_DRIVERS
    ns8250::MmioDriver, ns8250::PioDriver,
#endif
    // This is never used but permits a trailing comma above.
    internal::DummyDriver>;

// The hardware support object underlying whichever KernelDriver type is the
// active variant can be extracted into this type and then used to construct a
// new uart::all::KernelDriver instantiation in a different environment.
//
// The underlying UartDriver types and ktl::variant (aka std::variant) hold
// only non-pointer data that can be transferred directly from one environment
// to another, e.g. to hand off from physboot to the kernel.
using Driver = WithAllDrivers<std::variant>;

// uart::all::KernelDriver is a variant across all the KernelDriver types.
template <template <typename> class IoProvider, typename Sync>
class KernelDriver {
 public:
  using uart_type = Driver;

  // In default-constructed state, it's the null driver.
  KernelDriver() = default;

  // It can be copy-constructed from one of the supported uart::xyz::Driver
  // types to hand off the hardware state from a different instantiation.
  template <typename T>
  explicit KernelDriver(const T& uart) : variant_(uart) {}

  // ...or from another all::KernelDriver::uart() result.
  explicit KernelDriver(const uart_type& uart) { *this = uart; }

  // Assignment is another way to reinitialize the configuration.
  KernelDriver& operator=(const uart_type& uart) {
    internal::Visit(
        [this](auto&& uart) {
          using ThisUart = std::decay_t<decltype(uart)>;
          variant_.template emplace<OneDriver<ThisUart>>(uart);
        },
        uart);
    return *this;
  }

  // If this ZBI item matches a supported driver, instantiate that driver and
  // return true.  If nothing matches, leave the existing driver (default null)
  // in place and return false.  The expected procedure is to apply this to
  // each ZBI item in order, so that the latest one wins (e.g. one appended by
  // the boot loader will supersede one embedded in the original complete ZBI).
  bool Match(const zbi_header_t& header, const void* payload) { return DoMatch(header, payload); }

  // This is like Match, but instead of matching a ZBI item, it matches a
  // string value for the "kernel.serial" boot option.
  bool Parse(std::string_view option) { return DoMatch(option); }

  // Write out a string that Parse() can read back to recreate the driver
  // state.  This doesn't preserve the driver state, only the configuration.
  void Unparse(FILE* out = stdout) const {
    Visit([out](const auto& active) { active.Unparse(out); });
  }

  // Apply f to selected driver.
  template <typename T, typename... Args>
  void Visit(T&& f, Args... args) {
    internal::Visit(std::forward<T>(f), variant_, std::forward<Args>(args)...);
  }

  // Apply f to selected driver.
  template <typename T, typename... Args>
  void Visit(T&& f, Args... args) const {
    internal::Visit(std::forward<T>(f), variant_, std::forward<Args>(args)...);
  }

  // Extract the hardware configuration and state.  The return type is const
  // just to make clear that this never returns a mutable reference like normal
  // accessors do, it always copies.
  const uart_type uart() const {
    uart_type driver;
    Visit([&driver](auto&& active) {
      const auto& uart = active.uart();
      driver.emplace<std::decay_t<decltype(uart)>>(uart);
    });
    return driver;
  }

 private:
  template <class Uart>
  using OneDriver = uart::KernelDriver<Uart, IoProvider, Sync>;
  template <class... Uart>
  using Variant = std::variant<OneDriver<Uart>...>;
  WithAllDrivers<Variant> variant_;

  template <size_t I, typename... Args>
  bool TryOneMatch(Args&&... args) {
    using Try = std::variant_alternative_t<I, decltype(variant_)>;
    if (auto driver = Try::uart_type::MaybeCreate(std::forward<Args>(args)...)) {
      variant_.template emplace<I>(*driver);
      return true;
    }
    return false;
  }

  template <size_t... I, typename... Args>
  bool DoMatchHelper(std::index_sequence<I...>, Args&&... args) {
    return (TryOneMatch<I>(std::forward<Args>(args)...) || ...);
  }

  template <typename... Args>
  bool DoMatch(Args&&... args) {
    constexpr auto n = std::variant_size_v<decltype(variant_)>;
    return DoMatchHelper(std::make_index_sequence<n>(), std::forward<Args>(args)...);
  }
};

}  // namespace all
}  // namespace uart

#endif  // LIB_UART_ALL_H_
