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

#include "zircon/system/utest/device-enumeration/aemu.h"

#include <errno.h>
#include <fcntl.h>
#include <fidl/fuchsia.hardware.acpi/cpp/wire.h>
#include <lib/fdio/fdio.h>
#include <lib/zx/channel.h>
#include <string.h>
#include <unistd.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <cstdlib>
#include <cstring>
#include <string_view>

#include <fbl/array.h>
#include <fbl/unique_fd.h>

namespace device_enumeration {

namespace {

using fuchsia_hardware_acpi::Acpi;
using fuchsia_hardware_acpi::wire::TableInfo;

const char* kAcpiDevicePath = "/dev/sys/platform/platform-passthrough/acpi";
const char* kAcpiDsdtTableName = "DSDT";

template <typename T>
bool FindPattern(const fbl::Array<T>& haystack, const fbl::Array<T>& needle) {
  if (needle.size() > haystack.size()) {
    return false;
  }
  for (size_t start = 0; start + needle.size() <= haystack.size(); ++start) {
    if (memcmp(needle.data(), haystack.data() + start, needle.size()) == 0) {
      return true;
    }
  }
  return false;
}

// Fetch raw data for a table.
zx_status_t FetchTable(const zx::channel& channel, const TableInfo& table,
                       fbl::Array<uint8_t>* data) {
  // Allocate a VMO for the read.
  zx::vmo vmo;
  if (zx_status_t status = zx::vmo::create(table.size, /*options=*/0, &vmo); status != ZX_OK) {
    return status;
  }

  // Make a copy to send to the driver.
  zx::vmo vmo_copy;
  if (zx_status_t status = vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &vmo_copy); status != ZX_OK) {
    return status;
  }

  // Fetch the data.
  fidl::WireResult<Acpi::ReadNamedTable> result =
      fidl::WireCall<Acpi>(channel.borrow())->ReadNamedTable(table.name, 0, std::move(vmo_copy));
  if (!result.ok()) {
    return result.status();
  }

  // Copy the data into memory.
  uint32_t size = result->value()->size;
  auto table_data = fbl::Array<uint8_t>(new uint8_t[size], size);
  if (zx_status_t status = vmo.read(table_data.data(), 0, size); status != ZX_OK) {
    return status;
  }

  *data = std::move(table_data);
  return ZX_OK;
}

// Find a certain byte sequence |keyword| in ACPI table |table_name|.
//
// Returns false if it cannot access the ACPI data, or none of the ACPI
// tables with name |table_name| has the keyword.
bool AcpiTableHasKeyword(const zx::channel& acpi_channel, std::string_view table_name,
                         const fbl::Array<uint8_t>& keyword) {
  // List ACPI entries.
  fidl::WireResult<Acpi::ListTableEntries> result =
      fidl::WireCall<Acpi>(zx::unowned_channel(acpi_channel))->ListTableEntries();
  if (!result.ok()) {
    fprintf(stderr, "Could not list ACPI table entries: %s.\n",
            zx_status_get_string(result.status()));
    return false;
  }
  if (result.value().is_error()) {
    fprintf(stderr, "Call to list ACPI table entries failed: %s.\n",
            zx_status_get_string(result.value().error_value()));
    return false;
  }

  auto& entries = result->value()->entries;
  for (auto table : entries) {
    if (std::string_view(reinterpret_cast<const char*>(table.name.begin()), table.name.size()) !=
        table_name) {
      continue;
    }

    // Fetch table contents.
    fbl::Array<uint8_t> table_data;
    zx_status_t status = FetchTable(acpi_channel, table, &table_data);
    if (status != ZX_OK) {
      fprintf(stderr, "Call to FetchTable failed: %s.\n", zx_status_get_string(status));
      continue;
    }

    // There can be multiple tables with the same name. So we continue
    // searching for the keyword if it is missing in the current table.
    if (FindPattern(table_data, keyword)) {
      return true;
    }
  }
  return false;
}

}  // namespace

// AEMU and QEMU boards have the same board name, but AEMU boards also have
// some AEMU-specific ACPI devices which can be used for AEMU board detection.
//
// In this function we find Goldfish pipe device, with ACPI HID |GFSH0002|,
// in the ACPI DSDT (Differentiated System Description Table) table. This
// device can be found if and only if it's an AEMU board.
bool IsAemuBoard() {
  // Open up channel to ACPI device.
  fbl::unique_fd fd(open(kAcpiDevicePath, O_RDWR));
  if (!fd.is_valid()) {
    return false;
  }

  zx::channel channel;
  if (fdio_get_service_handle(fd.release(), channel.reset_and_get_address()) != ZX_OK) {
    return false;
  }

  // Look for |GFSH0002| in ACPI table.
  constexpr size_t kAemuAcpiKeywordLen = 8;
  constexpr uint8_t kAemuAcpiKeyword[] = "GFSH0002";
  fbl::Array<uint8_t> aemu_acpi_keyword(new uint8_t[kAemuAcpiKeywordLen], kAemuAcpiKeywordLen);
  memcpy(aemu_acpi_keyword.data(), kAemuAcpiKeyword, kAemuAcpiKeywordLen);

  return AcpiTableHasKeyword(channel, kAcpiDsdtTableName, aemu_acpi_keyword);
}

}  // namespace device_enumeration
