// Copyright (C) 2019 The Android Open Source Project
// Copyright (C) 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <memory>
#include <fcntl.h>
#include <lib/zx/channel.h>
#include <lib/zx/vmo.h>
#include <log/log.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/object.h>

#include "goldfish_address_space.h"
#include "services/service_connector.h"

GoldfishAddressSpaceBlockProvider::GoldfishAddressSpaceBlockProvider(uint64_t subdevice) {

    if (subdevice != SUBDEVICE_TYPE_NO_SUBDEVICE_ID) {
        ALOGE("%s: Tried to use a nontrivial subdevice when support has not been added\n", __func__);
        abort();
    }

    zx::channel channel(GetConnectToServiceFunction()(GOLDFISH_ADDRESS_SPACE_DEVICE_NAME));
    if (!channel) {
        ALOGE("%s: failed to get service handle for " GOLDFISH_ADDRESS_SPACE_DEVICE_NAME,
              __FUNCTION__);
        return;
    }
    m_device.Bind(std::move(channel));
}

GoldfishAddressSpaceBlockProvider::~GoldfishAddressSpaceBlockProvider()
{
}

bool GoldfishAddressSpaceBlockProvider::is_opened() const
{
    return m_device.is_bound();
}

// void GoldfishAddressSpaceBlockProvider::close() - not implemented
// address_space_handle_t GoldfishAddressSpaceBlockProvider::release() - not imeplemented

GoldfishAddressSpaceBlock::GoldfishAddressSpaceBlock()
    : m_device(NULL)
    , m_vmo(ZX_HANDLE_INVALID)
    , m_mmaped_ptr(NULL)
    , m_phys_addr(0)
    , m_host_addr(0)
    , m_offset(0)
    , m_size(0) {}

GoldfishAddressSpaceBlock::~GoldfishAddressSpaceBlock()
{
    destroy();
}

GoldfishAddressSpaceBlock &GoldfishAddressSpaceBlock::operator=(const GoldfishAddressSpaceBlock &rhs)
{
    m_vmo = rhs.m_vmo;
    m_mmaped_ptr = rhs.m_mmaped_ptr;
    m_phys_addr = rhs.m_phys_addr;
    m_host_addr = rhs.m_host_addr;
    m_offset = rhs.m_offset;
    m_size = rhs.m_size;
    m_device = rhs.m_device;

    return *this;
}

bool GoldfishAddressSpaceBlock::allocate(GoldfishAddressSpaceBlockProvider *provider, size_t size)
{
    ALOGD("%s: Ask for block of size 0x%llx\n", __func__,
         (unsigned long long)size);

    destroy();

    if (!provider->is_opened()) {
        return false;
    }

    fuchsia::hardware::goldfish::AddressSpaceDeviceSyncPtr* device = &provider->m_device;

    int32_t res = ZX_OK;
    zx::vmo vmo;
    zx_status_t status = (*device)->AllocateBlock(size, &res, &m_phys_addr, &vmo);
    if (status != ZX_OK || res != ZX_OK) {
        ALOGE("%s: allocate block failed: %d:%d", __func__, status, res);
        return false;
    }

    m_offset = 0;
    m_size = size;
    m_vmo = vmo.release();

    ALOGD("%s: allocate returned offset 0x%llx size 0x%llx\n", __func__,
          (unsigned long long)m_offset,
          (unsigned long long)m_size);

    m_device = device;
    return true;
}

bool GoldfishAddressSpaceBlock::claimShared(GoldfishAddressSpaceBlockProvider *provider, uint64_t offset, uint64_t size)
{
    ALOGD("%s: Ask to claim region [0x%llx 0x%llx]\n", __func__,
         (unsigned long long)offset,
         (unsigned long long)offset + size);
    ALOGE("%s: FATAL: claimShared not supported!\n");
    abort();
}

uint64_t GoldfishAddressSpaceBlock::physAddr() const
{
    return m_phys_addr;
}

uint64_t GoldfishAddressSpaceBlock::hostAddr() const
{
    return m_host_addr;
}

void *GoldfishAddressSpaceBlock::mmap(uint64_t host_addr)
{
    if (m_size == 0) {
        ALOGE("%s: called with zero size\n", __func__);
        return NULL;
    }
    if (m_mmaped_ptr) {
        ALOGE("'mmap' called for an already mmaped address block");
        ::abort();
    }

    zx_vaddr_t ptr = 0;
    zx_status_t status = zx_vmar_map(zx_vmar_root_self(),
                                     ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
                                     0, m_vmo,
                                     m_offset,
                                     m_size,
                                     &ptr);
    if (status != ZX_OK) {
        ALOGE("%s: host memory map failed with size 0x%llx "
              "off 0x%llx status %d\n",
              __func__,
              (unsigned long long)m_size,
              (unsigned long long)m_offset, status);
        return NULL;
    } else {
        m_mmaped_ptr = (void*)ptr;
        m_host_addr = host_addr;
        return guestPtr();
    }
}

void *GoldfishAddressSpaceBlock::guestPtr() const
{
    return reinterpret_cast<char *>(m_mmaped_ptr) + (m_host_addr & (PAGE_SIZE - 1));
}

void GoldfishAddressSpaceBlock::destroy()
{
    if (m_mmaped_ptr && m_size) {
        zx_vmar_unmap(zx_vmar_root_self(),
                      (zx_vaddr_t)m_mmaped_ptr,
                      m_size);
        m_mmaped_ptr = NULL;
    }

    if (m_size) {
        zx_handle_close(m_vmo);
        m_vmo = ZX_HANDLE_INVALID;
        int32_t res = ZX_OK;
        zx_status_t status = (*m_device)->DeallocateBlock(m_phys_addr, &res);
        if (status != ZX_OK || res != ZX_OK) {
            ALOGE("%s: deallocate block failed: %d:%d", __func__, status, res);
        }
        m_device = NULL;
        m_phys_addr = 0;
        m_host_addr = 0;
        m_offset = 0;
        m_size = 0;
    }
}

GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator()
  : m_provider(GoldfishAddressSpaceBlockProvider::SUBDEVICE_TYPE_HOST_MEMORY_ALLOCATOR_ID)
{
}

long GoldfishAddressSpaceHostMemoryAllocator::hostMalloc(GoldfishAddressSpaceBlock *block, size_t size)
{
    return 0;
}

void GoldfishAddressSpaceHostMemoryAllocator::hostFree(GoldfishAddressSpaceBlock *block)
{
}

// TODO: Implement address_space_handle_t interface
address_space_handle_t goldfish_address_space_open() {
    ALOGE("%s: not implemented!\n", __func__);
    abort();
}

void goldfish_address_space_close(address_space_handle_t handle) {
    ALOGE("%s: not implemented!\n", __func__);
    abort();
}

bool goldfish_address_space_allocate(
    address_space_handle_t,
    size_t, uint64_t*, uint64_t*) {
    ALOGE("%s: not implemented!\n", __func__);
    abort();
}

bool goldfish_address_space_free(
    address_space_handle_t, uint64_t) {
    ALOGE("%s: not implemented!\n", __func__);
    abort();
}

bool goldfish_address_space_claim_shared(
    address_space_handle_t, uint64_t, uint64_t) {
    ALOGE("%s: not implemented!\n", __func__);
    abort();
}

bool goldfish_address_space_unclaim_shared(
    address_space_handle_t, uint64_t) {
    ALOGE("%s: not implemented!\n", __func__);
    abort();
}

// pgoff is the offset into the page to return in the result
void* goldfish_address_space_map(
    address_space_handle_t,
    uint64_t, uint64_t,
    uint64_t) {
    ALOGE("%s: not implemented!\n", __func__);
    abort();
}

void goldfish_address_space_unmap(void*, uint64_t) {
    ALOGE("%s: not implemented!\n", __func__);
    abort();
}

bool goldfish_address_space_ping(
    address_space_handle_t handle,
    struct goldfish_address_space_ping* ping) {
    ALOGE("%s: not implemented!\n", __func__);
    abort();
}
