// 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 "src/devices/board/drivers/x86/x86.h"

#include <fidl/fuchsia.hardware.acpi/cpp/wire.h>
#include <fidl/fuchsia.hardware.platform.bus/cpp/driver/fidl.h>
#include <fidl/fuchsia.hardware.platform.bus/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/ddk/binding_driver.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/driver.h>
#include <lib/ddk/metadata.h>
#include <lib/ddk/platform-defs.h>
#include <lib/driver-unit-test/utils.h>
#include <lib/fdf/cpp/dispatcher.h>
#include <stdlib.h>
#include <string.h>
#include <zircon/status.h>

#include <acpica/acpi.h>
#include <ddktl/fidl.h>
#include <fbl/alloc_checker.h>
#include <fbl/vector.h>

#include "src/devices/board/drivers/x86/include/acpi.h"
#include "src/devices/board/drivers/x86/include/sysmem.h"
#include "src/devices/board/lib/acpi/manager-fuchsia.h"
#include "src/devices/board/lib/smbios/smbios.h"

using fuchsia_acpi_tables::wire::kMaxAcpiTableEntries;
using fuchsia_acpi_tables::wire::TableInfo;

zx_handle_t mmio_resource_handle;
zx_handle_t ioport_resource_handle;
zx_handle_t irq_resource_handle;
zx_handle_t power_resource_handle;

namespace x86 {

void SysSuspender::Callback(CallbackRequestView request, CallbackCompleter::Sync& completer) {
  uint8_t out_state;
  zx_status_t status = acpi_suspend(device_, request->requested_state, request->enable_wake,
                                    request->suspend_reason, &out_state);
  completer.Reply(status, out_state);
}

namespace fpbus = fuchsia_hardware_platform_bus;

X86::~X86() {
  if (acpica_initialized_) {
    AcpiTerminate();
  }
}

zx_status_t X86::DoInit() {
  // Create the ACPI manager.
  acpi_manager_ = std::make_unique<acpi::FuchsiaManager>(acpi_.get(), &iommu_manager_, zxdev());

  zx_status_t status = SysmemInit();
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: SysmemInit() failed: %d", __func__, status);
    return status;
  }

  status = publish_acpi_devices(acpi_manager_.get(), parent(), zxdev());
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: publish_acpi_devices() failed: %d", __func__, status);
    return status;
  }

  status = GoldfishControlInit();
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: GoldfishControlInit() failed: %d", __func__, status);
    return status;
  }
  return ZX_OK;
}

void X86::DdkInit(ddk::InitTxn txn) {
  async::PostTask(fdf::Dispatcher::GetCurrent()->async_dispatcher(),
                  [txn = std::move(txn), this]() mutable {
                    zx_status_t status = DoInit();
                    txn.Reply(status);
                  });
}

void X86::DdkRelease() { delete this; }

zx_status_t X86::Create(void* ctx, zx_device_t* parent, std::unique_ptr<X86>* out) {
  auto endpoints = fdf::CreateEndpoints<fpbus::PlatformBus>();
  if (endpoints.is_error()) {
    return endpoints.error_value();
  }

  zx_status_t status = device_connect_runtime_protocol(
      parent, fpbus::Service::PlatformBus::ServiceName, fpbus::Service::PlatformBus::Name,
      endpoints->server.TakeHandle().release());
  if (status != ZX_OK) {
    zxlogf(ERROR, "Failed to connect to platform bus: %s", zx_status_get_string(status));
    return status;
  }

  ZX_ASSERT(zx_handle_duplicate(get_ioport_resource(parent), ZX_RIGHT_SAME_RIGHTS,
                                &ioport_resource_handle) == ZX_OK);

  ZX_ASSERT(zx_handle_duplicate(get_mmio_resource(parent), ZX_RIGHT_SAME_RIGHTS,
                                &mmio_resource_handle) == ZX_OK);

  ZX_ASSERT(zx_handle_duplicate(get_irq_resource(parent), ZX_RIGHT_SAME_RIGHTS,
                                &irq_resource_handle) == ZX_OK);

  ZX_ASSERT(zx_handle_duplicate(get_power_resource(parent), ZX_RIGHT_SAME_RIGHTS,
                                &power_resource_handle) == ZX_OK);

  fbl::AllocChecker ac;
  *out = fbl::make_unique_checked<X86>(&ac, parent, std::move(endpoints->client),
                                       std::make_unique<acpi::AcpiImpl>());
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  return ZX_OK;
}

zx_status_t X86::CreateAndBind(void* ctx, zx_device_t* parent) {
  std::unique_ptr<X86> board;

  zx_status_t status = Create(ctx, parent, &board);
  if (status != ZX_OK) {
    return status;
  }

  status = board->Bind();
  if (status == ZX_OK) {
    // DevMgr now owns this pointer, release it to avoid destroying the
    // object when device goes out of scope.
    [[maybe_unused]] auto* ptr = board.release();
  }
  return status;
}

static void SetField(const char* label, const std::string& value, std::optional<std::string>& out) {
  if (value.empty()) {
    zxlogf(ERROR, "acpi: smbios %s could not be read", label);
  } else if (value.size() >= fpbus::kMaxInfoStringLength) {
    zxlogf(INFO, "acpi: smbios %s too big for sysinfo: %s", label, value.data());
  } else {
    out = value;
  }
}

zx_status_t X86::Bind() {
  // Do early init of ACPICA etc.
  zx_status_t status = EarlyInit();
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: failed to perform early initialization %d ", __func__, status);
    return status;
  }

  // publish the board as ACPI root under /dev/sys/platform. PCI will get created under /dev/sys
  // (to preserve compatibility).
  status = DdkAdd("acpi", DEVICE_ADD_NON_BINDABLE);

  if (status != ZX_OK) {
    zxlogf(ERROR, "acpi: error %d in device_add(sys/platform/pt/acpi)", status);
    return status;
  }

  fpbus::BoardInfo board_info;
  board_info.board_name() = "x64";
  board_info.board_revision() = 0;
  fpbus::BootloaderInfo bootloader_info;
  bootloader_info.vendor() = "<unknown>";

  // Load SMBIOS information.
  smbios::SmbiosInfo smbios;
  status = smbios.Load(zx::unowned_resource(get_mmio_resource(parent())));
  if (status == ZX_OK) {
    SetField("board name", smbios.board_name(), board_info.board_name());
    SetField("vendor", smbios.vendor(), bootloader_info.vendor());
  }

  fdf::Arena arena('X86I');
  {
    // Inform the platform bus of our board info.
    fidl::Arena fidl_arena;
    auto result = pbus_.buffer(arena)->SetBoardInfo(fidl::ToWire(fidl_arena, board_info));
    if (!result.ok()) {
      zxlogf(ERROR, "SetBoardInfo request failed: %s", result.FormatDescription().data());
    } else if (result->is_error()) {
      zxlogf(ERROR, "SetBoardInfo failed: %s", zx_status_get_string(result->error_value()));
    }
  }

  {
    // Inform the platform bus of our bootloader info.
    fidl::Arena fidl_arena;
    auto result = pbus_.buffer(arena)->SetBootloaderInfo(fidl::ToWire(fidl_arena, bootloader_info));
    if (!result.ok()) {
      zxlogf(ERROR, "SetBootloaderInfo request failed: %s", result.FormatDescription().data());
    } else if (result->is_error()) {
      zxlogf(ERROR, "SetBootloaderInfo failed: %s", zx_status_get_string(result->error_value()));
    }
  }

  // Set the "sys" suspend op in platform-bus.
  // The devmgr coordinator code that arranges ordering in which the suspend hooks
  // are called makes sure the suspend hook attached to sys/ is called dead last,
  // (coordinator.cpp:BuildSuspendList()). If move this suspend hook elsewhere,
  // we must make sure that the coordinator code arranges for this suspend op to be
  // called last.
  auto endpoints = fidl::CreateEndpoints<fpbus::SysSuspend>();
  if (endpoints.is_error()) {
    zxlogf(ERROR, "%s: Could not create suspend callback endpoints: %s", __func__,
           endpoints.status_string());
  } else {
    suspender_loop_.StartThread("sys suspender");
    fidl::BindServer(suspender_loop_.dispatcher(), std::move(endpoints->server), &suspender_);
    auto result = pbus_.buffer(arena)->RegisterSysSuspendCallback(std::move(endpoints->client));
    if (!result.ok()) {
      zxlogf(ERROR, "RegisterSysSuspendCallback request failed: %s",
             result.FormatDescription().data());
    } else if (result->is_error()) {
      zxlogf(ERROR, "RegisterSysSuspendCallback failed: %s",
             zx_status_get_string(result->error_value()));
    }
  }

  return ZX_OK;
}

bool X86::RunUnitTests(void* ctx, zx_device_t* parent, zx_handle_t channel) {
  return driver_unit_test::RunZxTests("X86Tests", parent, channel);
}

zx_status_t X86::GetAcpiTableEntries(fbl::Vector<TableInfo>* entries) {
  ZX_DEBUG_ASSERT(acpica_initialized_);

  for (uint32_t i = 0; i < kMaxAcpiTableEntries; i++) {
    // Fetch the next table entry.
    ACPI_TABLE_HEADER* table;
    ACPI_STATUS status = AcpiGetTableByIndex(i, &table);
    if (status == AE_BAD_PARAMETER) {
      // End of iteration.
      break;
    } else if (status != AE_OK) {
      // Unexpected error.
      return ZX_ERR_INTERNAL;
    }

    // Create an ACPI table header entry.
    TableInfo info;
    static_assert(sizeof(info.name) == sizeof(table->Signature));
    memcpy(info.name.data(), table->Signature, sizeof(table->Signature));
    info.size = table->Length;

    // Add it to the list.
    fbl::AllocChecker ac;
    entries->push_back(info, &ac);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
  }

  return ZX_OK;
}

void X86::ListTableEntries(ListTableEntriesCompleter::Sync& completer) {
  ZX_DEBUG_ASSERT(acpica_initialized_);

  // Fetch the entries.
  fbl::Vector<TableInfo> entries;
  zx_status_t status = GetAcpiTableEntries(&entries);
  if (status != ZX_OK) {
    completer.ReplyError(status);
    return;
  }

  // Send them back to the user.
  completer.ReplySuccess(fidl::VectorView<TableInfo>::FromExternal(entries.data(), entries.size()));
}

void X86::ReadNamedTable(ReadNamedTableRequestView request,
                         ReadNamedTableCompleter::Sync& completer) {
  // Fetch the requested table.
  ACPI_TABLE_HEADER* table;
  if (ACPI_STATUS status =
          AcpiGetTable(reinterpret_cast<char*>(request->name.data()), request->instance, &table);
      status != AE_OK) {
    completer.ReplyError(status == AE_NOT_FOUND ? ZX_ERR_NOT_FOUND : ZX_ERR_INTERNAL);
    return;
  }

  // Copy it into the VMO.
  if (zx_status_t status =
          request->result.write(reinterpret_cast<uint8_t*>(table), /*offset=*/0, table->Length);
      status != ZX_OK) {
    completer.ReplyError(status);
    return;
  }

  completer.ReplySuccess(table->Length);
}

static zx_driver_ops_t x86_driver_ops = []() {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = X86::CreateAndBind;
  ops.run_unit_tests = X86::RunUnitTests;
  return ops;
}();

}  // namespace x86

ZIRCON_DRIVER(acpi_bus, x86::x86_driver_ops, "zircon", "0.1");
