// Copyright 2017 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 "garnet/bin/guest/vmm/arch/x64/acpi.h"

#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

#include <fbl/unique_fd.h>
#include <lib/fxl/logging.h>

extern "C" {
#include <acpica/acpi.h>
#include <acpica/actables.h>
#include <acpica/actypes.h>
}

#include "garnet/bin/guest/vmm/arch/x64/io_port.h"

static uint8_t acpi_checksum(void* table, uint32_t length) {
  uint8_t sum = 0;
  uint8_t* start = reinterpret_cast<uint8_t*>(table);
  uint8_t* end = start + length;
  for (; start != end; ++start) {
    sum = static_cast<uint8_t>(sum + *start);
  }
  return static_cast<uint8_t>(UINT8_MAX - sum + 1);
}

static void acpi_header(ACPI_TABLE_HEADER* header, const char* table_id,
                        const char* signature, uint32_t length) {
  memcpy(header->Signature, signature, ACPI_NAME_SIZE);
  header->Length = length;
  memcpy(header->OemId, "ZX", 2);
  memcpy(header->OemTableId, table_id, ACPI_OEM_TABLE_ID_SIZE);
  header->OemRevision = 0;
  header->Checksum = acpi_checksum(header, header->Length);
}

static zx_status_t load_file(const char* path, const PhysMem& phys_mem,
                             uint32_t off, uint32_t* actual) {
  fbl::unique_fd fd(open(path, O_RDONLY));
  if (!fd) {
    FXL_LOG(ERROR) << "Failed to open ACPI table " << path;
    return ZX_ERR_IO;
  }
  struct stat stat;
  ssize_t ret = fstat(fd.get(), &stat);
  if (ret < 0) {
    FXL_LOG(ERROR) << "Failed to stat ACPI table " << path;
    return ZX_ERR_IO;
  }
  ret = read(fd.get(), phys_mem.as<void>(off, stat.st_size), stat.st_size);
  if (ret != stat.st_size) {
    FXL_LOG(ERROR) << "Failed to read ACPI table " << path;
    return ZX_ERR_IO;
  }
  *actual = static_cast<uint32_t>(stat.st_size);
  return ZX_OK;
}

template <typename T>
static T* madt_subtable(void* base, uint32_t off, uint8_t type) {
  auto subtable = reinterpret_cast<T*>(static_cast<uint8_t*>(base) + off);
  subtable->Header.Type = type;
  subtable->Header.Length = sizeof(T);
  return subtable;
}

static zx_status_t create_madt(ACPI_TABLE_MADT* madt, zx_vaddr_t io_apic_addr,
                               uint8_t num_cpus, uint32_t* actual) {
  uint32_t table_size = static_cast<uint32_t>(
      sizeof(ACPI_TABLE_MADT) + (num_cpus * sizeof(ACPI_MADT_LOCAL_APIC)) +
      sizeof(ACPI_MADT_IO_APIC));
  acpi_header(&madt->Header, "ZX MADT", ACPI_SIG_MADT, table_size);

  uint32_t offset = sizeof(ACPI_TABLE_MADT);
  for (uint8_t id = 0; id < num_cpus; ++id) {
    auto local_apic = madt_subtable<ACPI_MADT_LOCAL_APIC>(
        madt, offset, ACPI_MADT_TYPE_LOCAL_APIC);
    local_apic->ProcessorId = id;
    local_apic->Id = id;
    local_apic->LapicFlags = ACPI_MADT_ENABLED;
    offset += static_cast<uint32_t>(sizeof(ACPI_MADT_LOCAL_APIC));
  }

  auto io_apic =
      madt_subtable<ACPI_MADT_IO_APIC>(madt, offset, ACPI_MADT_TYPE_IO_APIC);
  io_apic->Reserved = 0;
  io_apic->Address = static_cast<uint32_t>(io_apic_addr);
  io_apic->GlobalIrqBase = 0;

  *actual = table_size;
  return ZX_OK;
}

zx_status_t create_acpi_table(const AcpiConfig& cfg, const PhysMem& phys_mem) {
  if (phys_mem.size() < kAcpiOffset + PAGE_SIZE) {
    return ZX_ERR_BUFFER_TOO_SMALL;
  }

  const uint32_t rsdt_entries = 3;
  const uint32_t rsdt_length =
      sizeof(ACPI_TABLE_RSDT) + (rsdt_entries - 1) * sizeof(uint32_t);

  // RSDP. ACPI 1.0.
  auto rsdp = phys_mem.as<ACPI_RSDP_COMMON>(kAcpiOffset);
  ACPI_MAKE_RSDP_SIG(rsdp->Signature);
  memcpy(rsdp->OemId, "ZX", 2);
  rsdp->RsdtPhysicalAddress =
      static_cast<uint32_t>(kAcpiOffset + sizeof(ACPI_RSDP_COMMON));
  rsdp->Checksum = acpi_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH);

  // FADT.
  const uint32_t fadt_off = rsdp->RsdtPhysicalAddress + rsdt_length;
  auto fadt = phys_mem.as<ACPI_TABLE_FADT>(fadt_off);
  const uint32_t dsdt_off =
      static_cast<uint32_t>(fadt_off + sizeof(ACPI_TABLE_FADT));
  fadt->Dsdt = dsdt_off;
  fadt->Pm1aEventBlock = kPm1EventPort;
  fadt->Pm1EventLength =
      (ACPI_PM1_REGISTER_WIDTH / 8) * 2 /* enable and status registers */;
  fadt->Pm1aControlBlock = kPm1ControlPort;
  fadt->Pm1ControlLength = ACPI_PM1_REGISTER_WIDTH / 8;
  // Table ID must match RSDT.
  acpi_header(&fadt->Header, "ZX ACPI", ACPI_SIG_FADT, sizeof(ACPI_TABLE_FADT));

  // DSDT.
  uint32_t actual;
  zx_status_t status = load_file(cfg.dsdt_path, phys_mem, dsdt_off, &actual);
  if (status != ZX_OK) {
    return status;
  }

  // MADT.
  const uint32_t madt_off = dsdt_off + actual;
  status = create_madt(phys_mem.as<ACPI_TABLE_MADT>(madt_off), cfg.io_apic_addr,
                       cfg.cpus, &actual);
  if (status != ZX_OK) {
    return status;
  }

  // MCFG.
  const uint32_t mcfg_off = madt_off + actual;
  status = load_file(cfg.mcfg_path, phys_mem, mcfg_off, &actual);
  if (status != ZX_OK) {
    return status;
  }

  // RSDT.
  auto rsdt = phys_mem.as<ACPI_TABLE_RSDT>(rsdp->RsdtPhysicalAddress);
  rsdt->TableOffsetEntry[0] = fadt_off;
  rsdt->TableOffsetEntry[1] = madt_off;
  rsdt->TableOffsetEntry[2] = mcfg_off;
  // Table ID must match FADT.
  acpi_header(&rsdt->Header, "ZX ACPI", ACPI_SIG_RSDT, rsdt_length);
  return ZX_OK;
}
