// 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();
    }

    fidl::ClientEnd<AddressSpaceDevice> channel{
        zx::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));

    auto child_driver_ends =
        fidl::CreateEndpoints<::llcpp::fuchsia::hardware::goldfish::AddressSpaceChildDriver>();
    if (!child_driver_ends.is_ok()) {
        ALOGE("%s: zx_channel_create failed: %d", __FUNCTION__, child_driver_ends.status_value());
        return;
    }

    auto result = m_device->OpenChildDriver(
        static_cast<AddressSpaceChildDriverType>(0 /* graphics */),
        std::move(child_driver_ends->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_ends->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();
    }

    bool nonzeroOffsetInPage = host_addr & (PAGE_SIZE - 1);
    uint64_t extraBytes = nonzeroOffsetInPage ? PAGE_SIZE : 0;
    m_size += extraBytes;

    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() {
    fidl::ClientEnd<AddressSpaceDevice> channel{
        zx::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);

    auto child_driver_ends =
        fidl::CreateEndpoints<::llcpp::fuchsia::hardware::goldfish::AddressSpaceChildDriver>();
    if (!child_driver_ends.is_ok()) {
        ALOGE("%s: zx_channel_create failed: %d", __FUNCTION__, child_driver_ends.status_value());
        return false;
    }

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

    AddressSpaceChildDriver::SyncClient*
        childSync = new AddressSpaceChildDriver::SyncClient(std::move(child_driver_ends->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;
}
