/*
 * Copyright 2018 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 "lpc_nuvoton.hpp"

#include "mapper_errors.hpp"
#include "window_hw_interface.hpp"

#include <fcntl.h>
#include <sys/mman.h>

#include <cerrno>
#include <cinttypes>
#include <cstdint>
#include <cstdio>
#include <memory>
#include <utility>
#include <vector>

namespace ipmi_flash
{
using std::uint16_t;
using std::uint32_t;
using std::uint8_t;

std::unique_ptr<HardwareMapperInterface> LpcMapperNuvoton::createNuvotonMapper(
    std::uint32_t regionAddress, std::uint32_t regionSize)
{
    /* NOTE: Considered making one factory for both types. */
    return std::make_unique<LpcMapperNuvoton>(regionAddress, regionSize);
}

MemorySet LpcMapperNuvoton::open()
{
    static constexpr auto devmem = "/dev/mem";

    mappedFd = sys->open(devmem, O_RDWR | O_SYNC);
    if (mappedFd == -1)
    {
        throw MapperException("Unable to open /dev/mem");
    }

    mapped = reinterpret_cast<uint8_t*>(sys->mmap(
        0, memoryRegionSize, PROT_READ, MAP_SHARED, mappedFd, regionAddress));
    if (mapped == MAP_FAILED)
    {
        sys->close(mappedFd);
        mappedFd = -1;
        mapped = nullptr;

        throw MapperException("Unable to map region");
    }

    MemorySet output;
    output.mappedFd = mappedFd;
    output.mapped = mapped;

    return output;
}

void LpcMapperNuvoton::close()
{
    if (mapped)
    {
        sys->munmap(mapped, memoryRegionSize);
        mapped = nullptr;
    }

    if (mappedFd != -1)
    {
        sys->close(mappedFd);
        mappedFd = -1;
    }
}

/*
 * The host buffer address is configured by host through
 * SuperIO. On BMC side the max memory can be mapped is 4kB with the caveat that
 * first byte of the buffer is reserved as host/BMC semaphore and not usable as
 * shared memory.
 *
 * Mapper returns success for (addr, len) where (addr & 0x7) == 4 and len <=
 * (4096 - 4). Otherwise, mapper returns either
 *   - WindowOffset = 4 and WindowSize = len - 4 if (addr & 0x7) == 0
 *   - WindowSize = 0 means that the region cannot be mapped otherwise
 */
WindowMapResult LpcMapperNuvoton::mapWindow(std::uint32_t address,
                                            std::uint32_t length)
{
    WindowMapResult result = {};

    /* We reserve the first 4 bytes from the mapped region; the first byte
     * is shared semaphore, and the number of 4 is for alignment.
     */
    const uint32_t bmcMapReserveBytes = 4;
    const uint32_t bmcMapMaxSizeBytes = 4 * 1024 - bmcMapReserveBytes;

    if (length <= bmcMapReserveBytes)
    {
        std::fprintf(stderr, "window size %" PRIx32 " too small to map.\n",
                     length);
        result.response = EINVAL;
        return result;
    }

    if (length > bmcMapMaxSizeBytes)
    {
        std::fprintf(stderr,
                     "window size %" PRIx32 " not supported. Max size 4k.\n",
                     length);
        length = bmcMapMaxSizeBytes;
    }

    /* If host requested region starts at an aligned address, return offset of 4
     * bytes so as to skip the semaphore register.
     */
    uint32_t windowOffset = bmcMapReserveBytes;
    // uint32_t windowSize = length;

    result.response = 0;
    result.windowOffset = windowOffset;
    result.windowSize = length;

    const uint32_t addressOffset = address & 0x7;

    if (addressOffset == 0)
    {
        std::fprintf(stderr, "Map address offset should be 4 for Nuvoton.\n");

        result.response = EFBIG;
        return result;
    }
    else if (addressOffset != bmcMapReserveBytes)
    {
        std::fprintf(stderr, "Map address offset should be 4 for Nuvoton.\n");

        result.response = EINVAL;
        return result;
    }

    /* TODO: need a kernel driver to handle mapping configuration.
     * Until then program the register through /dev/mem.
     */
    int fd;
    if ((fd = sys->open("/dev/mem", O_RDWR | O_SYNC)) == -1)
    {
        std::fprintf(stderr, "Failed to open /dev/mem\n");
        sys->close(fd);

        result.response = EINVAL;
        return result;
    }

    const uint32_t bmcMapConfigBaseAddr = 0xc0001000;
    const uint32_t bmcMapConfigWindowSizeOffset = 0x7;
    const uint32_t bmcMapConfigWindowBaseOffset = 0xa;
    const uint8_t bmcWindowSizeValue = 0xc;     // 4k
    const uint16_t bmcWindowBaseValue = 0x8000; // BMC phyAddr from 0xc0008000

    int pageSize = sys->getpagesize();

    auto mapBasePtr = reinterpret_cast<uint8_t*>(
        sys->mmap(nullptr, pageSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
                  bmcMapConfigBaseAddr));

    uint8_t* bmcWindowSize = mapBasePtr + bmcMapConfigWindowSizeOffset;
    uint16_t* bmcWindowBase =
        reinterpret_cast<uint16_t*>(mapBasePtr + bmcMapConfigWindowBaseOffset);

    *bmcWindowSize = bmcWindowSizeValue;
    *bmcWindowBase = bmcWindowBaseValue;

    sys->munmap(mapBasePtr, pageSize);
    sys->close(fd);

    return result;
}

} // namespace ipmi_flash
