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

#include <cerrno>
#include <cstring>
#include <ipmiblob/blob_errors.hpp>

namespace host_tool
{

bool LpcDataHandler::sendContents(const std::string& input,
                                  std::uint16_t session)
{
    LpcRegion host_lpc_buf;
    host_lpc_buf.address = address;
    host_lpc_buf.length = length;

    std::vector<std::uint8_t> payload(sizeof(host_lpc_buf));

    while (true)
    {
        /* If the writeMeta() is rejected we need to call sessionStat on it. */
        try
        {
            std::fprintf(stderr, "sending writeMeta\n");

            std::memcpy(payload.data(), &host_lpc_buf, sizeof(host_lpc_buf));
            blob->writeMeta(session, 0x00, payload);

            std::fprintf(stderr, "writemeta sent\n");

            break;
        }
        catch (...)
        {
            std::fprintf(stderr, "caught exception\n");

            ipmiblob::StatResponse resp = blob->getStat(session);
            if (resp.metadata.empty())
            {
                std::fprintf(stderr, "Received no metadata bytes back!");
                return false;
            }

            struct MemoryMapResultDetails
            {
                std::uint8_t code;
                std::uint32_t offset;
                std::uint32_t length;
            } __attribute__((packed));

            struct MemoryMapResultDetails bytes;

            if (resp.metadata.size() != sizeof(bytes))
            {
                std::fprintf(
                    stderr,
                    "Received insufficient bytes back on expected return!\n");
                return false;
            }

            std::memcpy(&bytes, resp.metadata.data(), sizeof(bytes));

            if (bytes.code == EFBIG)
            {
                std::fprintf(stderr, "EFBIG returned!\n");

                host_lpc_buf.length = bytes.length;
                host_lpc_buf.address += bytes.offset;
            }
            else if (bytes.code == 0)
            {
                /* We're good, continue! */
                break;
            }
        }
    }

    /* For data blockss, stage data, and send blob write command. */
    int inputFd = sys->open(input.c_str(), 0);
    if (inputFd < 0)
    {
        return false;
    }

    /* For Nuvoton the maximum is 4K */
    auto readBuffer = std::make_unique<std::uint8_t[]>(host_lpc_buf.length);
    if (nullptr == readBuffer)
    {
        sys->close(inputFd);
        std::fprintf(stderr, "Unable to allocate memory for read buffer.\n");
        return false;
    }

    /* TODO: This is similar to PCI insomuch as how it sends data, so combine.
     */
    try
    {
        int bytesRead = 0;
        std::uint32_t offset = 0;

        do
        {
            bytesRead =
                sys->read(inputFd, readBuffer.get(), host_lpc_buf.length);
            if (bytesRead > 0)
            {
                if (!io->write(host_lpc_buf.address, bytesRead,
                               readBuffer.get()))
                {
                    std::fprintf(stderr,
                                 "Failed to write to region in memory!\n");
                }

                struct ipmi_flash::ExtChunkHdr chunk;
                chunk.length = bytesRead;
                std::vector<std::uint8_t> chunkBytes(sizeof(chunk));
                std::memcpy(chunkBytes.data(), &chunk, sizeof(chunk));

                /* This doesn't return anything on success. */
                blob->writeBytes(session, offset, chunkBytes);
                offset += bytesRead;
            }
        } while (bytesRead > 0);
    }
    catch (const ipmiblob::BlobException& b)
    {
        sys->close(inputFd);
        return false;
    }

    sys->close(inputFd);
    return true;
}

} // namespace host_tool
