// 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 "android/base/synchronization/AndroidLock.h"
#include "services/service_connector.h"

#include <unordered_map>

#define GET_STATUS_SAFE(result, member) \
    ((result).ok() ? ((result).Unwrap()->member) : ZX_OK)

using android::base::guest::AutoLock;
using android::base::guest::Lock;

using llcpp::fuchsia::hardware::goldfish::AddressSpaceChildDriver;
using llcpp::fuchsia::hardware::goldfish::AddressSpaceDevice;
using llcpp::fuchsia::hardware::goldfish::AddressSpaceChildDriverType;
using llcpp::fuchsia::hardware::goldfish::AddressSpaceChildDriverPingMessage;

GoldfishAddressSpaceBlockProvider::GoldfishAddressSpaceBlockProvider(GoldfishAddressSpaceSubdeviceType subdevice) {

    if (subdevice != GoldfishAddressSpaceSubdeviceType::NoSubdevice) {
        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 = std::make_unique<AddressSpaceDevice::SyncClient>(std::move(channel));

    zx::channel child_driver_server, child_driver_client;
    zx_status_t status = zx::channel::create(0, &child_driver_server, &child_driver_client);
    if (status != ZX_OK) {
        ALOGE("%s: zx_channel_create failed: %d", __FUNCTION__, status);
        return;
    }

    auto result = m_device->OpenChildDriver(
        static_cast<AddressSpaceChildDriverType>(0 /* graphics */),
        std::move(child_driver_server));
    if (!result.ok()) {
        ALOGE("%s: failed to open child driver: %d",
              __FUNCTION__, result.status());
        return;
    }
    m_child_driver = std::make_unique<AddressSpaceChildDriver::SyncClient>(std::move(child_driver_client));
}

GoldfishAddressSpaceBlockProvider::~GoldfishAddressSpaceBlockProvider()
{
}

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

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

GoldfishAddressSpaceBlock::GoldfishAddressSpaceBlock()
    : m_driver(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_driver = rhs.m_driver;

    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;
    }

    AddressSpaceChildDriver::SyncClient* driver = provider->m_child_driver.get();

    auto result = driver->AllocateBlock(size);
    if (!result.ok() || result.Unwrap()->res != ZX_OK) {
        ALOGE("%s: allocate block failed: %d:%d", __func__, result.status(), GET_STATUS_SAFE(result, res));
        return false;
    }
    m_phys_addr = result.Unwrap()->paddr;
    m_vmo = result.Unwrap()->vmo.release();

    m_size = size;
    m_offset = 0;
    m_is_shared_mapping = false;

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

    m_driver = driver;
    return true;
}

bool GoldfishAddressSpaceBlock::claimShared(GoldfishAddressSpaceBlockProvider *provider, uint64_t offset, uint64_t size)
{
    ALOGE("%s: FATAL: not supported\n", __func__);
    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;
    }

    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;
        if (m_is_shared_mapping) {
            // TODO
            ALOGE("%s: unsupported: GoldfishAddressSpaceBlock destroy() for shared regions\n", __func__);
            abort();
            // int32_t res = ZX_OK;
            // auto result = m_driver->UnclaimShared(m_offset);
            // if (!result.ok() || result.Unwrap()->res != ZX_OK) {
            //     ALOGE("%s: unclaim shared block failed: %d:%d", __func__,
            //           result.status(), GET_STATUS_SAFE(result, res));
            // }
        } else {
            auto result = m_driver->DeallocateBlock(m_phys_addr);
            if (!result.ok() || result.Unwrap()->res != ZX_OK) {
                ALOGE("%s: deallocate block failed: %d:%d", __func__,
                      result.status(), GET_STATUS_SAFE(result, res));
            }
        }
        m_driver = NULL;
        m_phys_addr = 0;
        m_host_addr = 0;
        m_offset = 0;
        m_size = 0;
    }
}

GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator(bool useSharedSlots)
  : m_provider(GoldfishAddressSpaceSubdeviceType::HostMemoryAllocator) { }

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

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

class VmoStore {
public:
    struct Info {
        zx_handle_t vmo = ZX_HANDLE_INVALID;
        uint64_t phys_addr = 0;
    };

    void add(uint64_t offset, const Info& info) {
        AutoLock lock(mLock);
        mInfo[offset] = info;
    }

    void remove(uint64_t offset) {
        AutoLock lock(mLock);
        mInfo.erase(offset);
    }

    Info get(uint64_t offset) {
        Info res;
        AutoLock lock(mLock);
        auto it = mInfo.find(offset);
        if (it == mInfo.end()) {
            ALOGE("VmoStore::%s cannot find info on offset 0x%llx\n", __func__,
                  (unsigned long long)offset);
            return res;
        }
        res = it->second;
        return res;
    }

private:
    Lock mLock;
    std::unordered_map<uint64_t, Info> mInfo;
};

static Lock sVmoStoreInitLock;
static VmoStore* sVmoStore = nullptr;

static VmoStore* getVmoStore() {
    AutoLock lock(sVmoStoreInitLock);
    if (!sVmoStore) sVmoStore = new VmoStore;
    return sVmoStore;
}

address_space_handle_t goldfish_address_space_open() {
    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 0;
    }
    AddressSpaceDevice::SyncClient*
        deviceSync = new AddressSpaceDevice::SyncClient(std::move(channel));
    return (address_space_handle_t)deviceSync;
}

void goldfish_address_space_close(address_space_handle_t handle) {
    AddressSpaceDevice::SyncClient* deviceSync =
        reinterpret_cast<
            AddressSpaceDevice::SyncClient*>(handle);
    delete deviceSync;
}

bool goldfish_address_space_set_subdevice_type(
    address_space_handle_t handle, GoldfishAddressSpaceSubdeviceType type,
    address_space_handle_t* handle_out) {

    AddressSpaceDevice::SyncClient* deviceSync =
        reinterpret_cast<
            AddressSpaceDevice::SyncClient*>(handle);

    zx::channel child_driver_server, child_driver_client;
    zx_status_t status = zx::channel::create(0, &child_driver_server, &child_driver_client);    
    if (status != ZX_OK) {
        ALOGE("%s: zx_channel_create failed: %d", __FUNCTION__, status);
        return false;
    }

    deviceSync->OpenChildDriver(
        static_cast<AddressSpaceChildDriverType>(type),
        std::move(child_driver_server));

    AddressSpaceChildDriver::SyncClient*
        childSync = new AddressSpaceChildDriver::SyncClient(std::move(child_driver_client));

    // On creating a subdevice, in our use cases we wont be needing the
    // original device sync anymore, so get rid of it.
    delete deviceSync;

    *handle_out = (void*)childSync;

    return true;
}

bool goldfish_address_space_allocate(
    address_space_handle_t handle,
    size_t size, uint64_t* phys_addr, uint64_t* offset) {
    AddressSpaceChildDriver::SyncClient* deviceSync =
        reinterpret_cast<
            AddressSpaceChildDriver::SyncClient*>(handle);

    zx::vmo vmo;
    auto result = deviceSync->AllocateBlock(size);
    if (!result.ok() || result.Unwrap()->res != ZX_OK) {
        ALOGE("%s: allocate block failed: %d:%d", __func__, result.status(), GET_STATUS_SAFE(result, res));
        return false;
    }
    *phys_addr = result.Unwrap()->paddr;
    vmo = std::move(result.Unwrap()->vmo);

    *offset = 0;

    VmoStore::Info info = {
        vmo.release(),
        *phys_addr,
    };

    getVmoStore()->add(*offset, info);
    return true;
}

bool goldfish_address_space_free(
    address_space_handle_t handle, uint64_t offset) {
    auto info = getVmoStore()->get(offset);
    if (info.vmo == ZX_HANDLE_INVALID) return false;
    zx_handle_close(info.vmo);

    AddressSpaceChildDriver::SyncClient* deviceSync =
        reinterpret_cast<
            AddressSpaceChildDriver::SyncClient*>(handle);

    auto result = deviceSync->DeallocateBlock(info.phys_addr);
    if (!result.ok() || result.Unwrap()->res != ZX_OK) {
        ALOGE("%s: deallocate block failed: %d:%d", __func__, result.status(), GET_STATUS_SAFE(result, res));
        return false;
    }

    return true;
}

bool goldfish_address_space_claim_shared(
    address_space_handle_t handle, uint64_t offset, uint64_t size) {

    AddressSpaceChildDriver::SyncClient* deviceSync =
        reinterpret_cast<
            AddressSpaceChildDriver::SyncClient*>(handle);

    zx::vmo vmo;
    auto result = deviceSync->ClaimSharedBlock(offset, size);
    if (!result.ok() || result.Unwrap()->res != ZX_OK) {
        ALOGE("%s: claim shared failed: %d:%d", __func__, result.status(), GET_STATUS_SAFE(result, res));
        return false;
    }
    vmo = std::move(result.Unwrap()->vmo);

    VmoStore::Info info = {
        vmo.release(),
    };

    getVmoStore()->add(offset, info);

    return true;
}

bool goldfish_address_space_unclaim_shared(
    address_space_handle_t handle, uint64_t offset) {
    AddressSpaceChildDriver::SyncClient* deviceSync =
        reinterpret_cast<
            AddressSpaceChildDriver::SyncClient*>(handle);

    auto result = deviceSync->UnclaimSharedBlock(offset);
    if (!result.ok() || result.Unwrap()->res != ZX_OK) {
        ALOGE("%s: unclaim shared failed: %d:%d", __func__, result.status(), GET_STATUS_SAFE(result, res));
        return false;
    }

    getVmoStore()->remove(offset);
    return true;
}

// pgoff is the offset into the page to return in the result
void* goldfish_address_space_map(
    address_space_handle_t handle,
    uint64_t offset, uint64_t size,
    uint64_t pgoff) {

    auto info = getVmoStore()->get(offset);
    if (info.vmo == ZX_HANDLE_INVALID) return nullptr;

    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, info.vmo,
                    0, size,
                    &ptr);
    return (void*)(((char*)ptr) + (uintptr_t)(pgoff & (PAGE_SIZE - 1)));
}

void goldfish_address_space_unmap(void* ptr, uint64_t size) {
    zx_vmar_unmap(zx_vmar_root_self(),
                  (zx_vaddr_t)(((uintptr_t)ptr) & (uintptr_t)(~(PAGE_SIZE - 1))),
                  size);
}

bool goldfish_address_space_ping(
    address_space_handle_t handle,
    struct address_space_ping* ping) {

    AddressSpaceChildDriverPingMessage fuchsiaPing =
        *(AddressSpaceChildDriverPingMessage*)ping;

    AddressSpaceChildDriver::SyncClient* deviceSync =
        reinterpret_cast<
            AddressSpaceChildDriver::SyncClient*>(handle);

    AddressSpaceChildDriverPingMessage res;
    auto result = deviceSync->Ping(fuchsiaPing);
    if (!result.ok() || result.Unwrap()->res != ZX_OK) {
        return false;
    }
    res = std::move(result.Unwrap()->ping);

    *ping = *(struct address_space_ping*)(&res);
    return true;
}
