// Copyright 2018 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 "shared-memory.h"

#include <ddk/debug.h>
#include <fbl/algorithm.h>
#include <fbl/auto_call.h>

namespace optee {

std::optional<SharedMemoryView> SharedMemoryRangeTraits::SliceByVaddr(zx_vaddr_t start,
                                                                      zx_vaddr_t end) const {
    if (end <= start || !ContainsVaddr(start) || !ContainsVaddr(end - 1)) {
        return std::nullopt;
    }

    zx_off_t offset = start - vaddr();
    return std::make_optional(SharedMemoryView(start, paddr() + offset, end - start));
}

std::optional<SharedMemoryView> SharedMemoryRangeTraits::SliceByPaddr(zx_paddr_t start,
                                                                      zx_paddr_t end) const {
    if (end <= start || !ContainsPaddr(start) || !ContainsPaddr(end - 1)) {
        return std::nullopt;
    }

    zx_off_t offset = start - paddr();
    return std::make_optional(SharedMemoryView(vaddr() + offset, start, end - start));
}

zx_status_t SharedMemoryManager::Create(zx_paddr_t shared_mem_start,
                                        size_t shared_mem_size,
                                        ddk::MmioBuffer secure_world_memory,
                                        zx::bti bti,
                                        fbl::unique_ptr<SharedMemoryManager>* out_manager) {
    ZX_DEBUG_ASSERT(out_manager != nullptr);

    // Round the start and end to the nearest page boundaries within the range and calculate a
    // new size.
    shared_mem_start = fbl::round_up(shared_mem_start, static_cast<uint32_t>(PAGE_SIZE));
    const zx_paddr_t shared_mem_end = fbl::round_down(shared_mem_start + shared_mem_size,
                                                      static_cast<uint32_t>(PAGE_SIZE));
    if (shared_mem_end <= shared_mem_start) {
        zxlogf(ERROR, "optee: no shared memory available from secure world\n");
        return ZX_ERR_NO_RESOURCES;
    }
    shared_mem_size = shared_mem_end - shared_mem_start;

    std::optional<ddk::MmioPinnedBuffer> pinned;
    zx_status_t status = secure_world_memory.Pin(bti, &pinned);
    if (status != ZX_OK) {
        zxlogf(ERROR, "optee: unable to pin secure world memory\n");
        return status;
    }

    // The secure world shared memory exists within some subrange of the secure_world_memory.
    // Get the addresses from the io_buffer and validate that the requested subrange is within
    // the mmio range.
    const zx_vaddr_t secure_world_vaddr = reinterpret_cast<zx_vaddr_t>(secure_world_memory.get());
    const zx_paddr_t secure_world_paddr = pinned->get_paddr();
    const size_t secure_world_size = secure_world_memory.get_size();

    if ((shared_mem_start < secure_world_paddr) ||
        (shared_mem_end > secure_world_paddr + secure_world_size)) {
        zxlogf(ERROR, "optee: shared memory not within secure os memory\n");
        return ZX_ERR_INTERNAL;
    }

    if (shared_mem_size < 2 * kDriverPoolSize) {
        zxlogf(ERROR, "optee: shared memory is not large enough\n");
        return ZX_ERR_NO_RESOURCES;
    }

    const zx_off_t shared_mem_offset = shared_mem_start - secure_world_paddr;

    fbl::AllocChecker ac;
    fbl::unique_ptr<SharedMemoryManager> manager(new (&ac) SharedMemoryManager(
        secure_world_vaddr + shared_mem_offset,
        secure_world_paddr + shared_mem_offset,
        shared_mem_size,
        std::move(secure_world_memory),
        *std::move(pinned)));

    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }

    *out_manager = std::move(manager);
    return ZX_OK;
}

SharedMemoryManager::SharedMemoryManager(zx_vaddr_t base_vaddr,
                                         zx_paddr_t base_paddr,
                                         size_t total_size,
                                         ddk::MmioBuffer secure_world_memory,
                                         ddk::MmioPinnedBuffer secure_world_memory_pin)
    : secure_world_memory_(std::move(secure_world_memory)),
      secure_world_memory_pin_(std::move(secure_world_memory_pin)),
      driver_pool_(base_vaddr, base_paddr, kDriverPoolSize),
      client_pool_(base_vaddr + kDriverPoolSize,
                   base_paddr + kDriverPoolSize,
                   total_size - kDriverPoolSize) {}

} // namespace optee
