// Copyright 2024 Google LLC
//
// 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 "payload_update.hpp"

#include "google3/host_commands.h"

#include "message_util.hpp"
#include "sys.hpp"

#include <fcntl.h>
#include <unistd.h>

#include <boost/endian/conversion.hpp>
#include <stdplus/print.hpp>
#include <stdplus/raw.hpp>
#include <xyz/openbmc_project/Control/Hoth/error.hpp>

#include <array>
#include <cstdint>
#include <format>
#include <memory>
#include <span>
#include <string>
#include <vector>

namespace google
{
namespace hoth
{
namespace internal
{

enum hoth_status : uint16_t
{
    /*
      There is no update payload pending confirmation
    */
    HOTH_PAYLOAD_UPDATE_CONFIRM_NO_PENDING_PAYLOAD = 0xD004,
};

using sdbusplus::error::xyz::openbmc_project::control::hoth::ResponseFailure;

void PayloadUpdateImpl::initiate() const
{
    sendCommand(PAYLOAD_UPDATE_INITIATE);
}

void PayloadUpdateImpl::erase(const uint32_t offset, const uint32_t size) const
{
    sendCommand(PAYLOAD_UPDATE_ERASE, offset, size);
}

bool PayloadUpdateImpl::findDescriptor(const std::string& path,
                                       uint32_t* desc_offset) const
{
    Fd fd(sys->open(path.c_str(), O_RDONLY), sys);

    if (*fd < 0)
    {
        (void)fd.release();
        throw errnoException(std::format("Failed to open file {}", path));
    }

    auto seekRet = sys->lseek(*fd, 0, SEEK_END);
    size_t fsize = seekRet;

    if (seekRet < 0)
    {
        throw errnoException(std::format("Error seeking on file", path));
    }

    uint64_t read_data = 0;
    bool desc_found = false;

    // Find the nearest aligned address to the end of the file. We can't
    // assume that the file-size is aligned.
    ssize_t offset = static_cast<ssize_t>(
        (fsize / kImageDescriptorAlignment) * kImageDescriptorAlignment);
    if (offset + sizeof(kDescriptorMagic) > fsize)
    {
        offset -= kImageDescriptorAlignment;
    }

    for (; offset >= 0; offset -= kImageDescriptorAlignment)
    {
        auto seek = sys->lseek(*fd, offset, SEEK_SET);
        if (seek < 0)
        {
            throw errnoException(std::format("Error seeking on file", path));
        }

        auto actualReadSize = sys->read(*fd, &read_data, sizeof(read_data));

        if (actualReadSize < 0)
        {
            throw errnoException(
                std::format("Failed to read from file {}", path));
        }

        if (read_data == kDescriptorMagic)
        {
            if (desc_offset)
            {
                *desc_offset = offset;
                desc_found = true;
                break;
            }
        }
    }

    return desc_found;
}

void PayloadUpdateImpl::eraseAndSendStaticWPRegions(const std::string& path,
                                                    uint32_t desc_offset) const
{
    Fd fd(sys->open(path.c_str(), O_RDONLY), sys);

    if (*fd < 0)
    {
        (void)fd.release();
        throw errnoException(std::format("Failed to open file {}", path));
    }

    struct image_descriptor descriptor;

    if (sys->lseek(*fd, desc_offset, SEEK_SET) < 0)
    {
        throw errnoException(std::format("Error seeking on file", path));
    }
    auto actualReadSize = sys->read(*fd, &descriptor, sizeof(descriptor));

    if (actualReadSize < 0)
    {
        throw errnoException(std::format("Failed to read from file {}", path));
    }

    if (descriptor.descriptor_magic != DESCRIPTOR_MAGIC ||
        descriptor.descriptor_offset != desc_offset ||
        descriptor.region_count == 0)
    {
        throw errnoException(
            std::format("Invalid descriptor at offset {}", path));
    }

    std::vector<struct image_region> image_regions(descriptor.region_count);

    actualReadSize =
        sys->read(*fd, image_regions.data(),
                  sizeof(struct image_region) * descriptor.region_count);
    if (actualReadSize < 0)
    {
        throw errnoException(std::format("Failed to read from file {}", path));
    }

    // Erase all the static and Write Protected regions of the payload
    for (uint32_t i = 0; i < descriptor.region_count; i++)
    {
        if ((image_regions[i].region_attributes & IMAGE_REGION_STATIC) ||
            (image_regions[i].region_attributes & IMAGE_REGION_WRITE_PROTECTED))
        {
            if (image_regions[i].region_size == 0 ||
                (image_regions[i].region_size % kSectorSizeBytes) != 0)
            {
                throw errnoException(std::format("invalid staging area size"));
            }
            uint32_t regionOffset = image_regions[i].region_offset;
            uint32_t toEraseSize = image_regions[i].region_size;
            while (toEraseSize >= kEraseChunkSizeBytes)
            {
                sendCommand(PAYLOAD_UPDATE_ERASE, regionOffset,
                            kEraseChunkSizeBytes);
                regionOffset += kEraseChunkSizeBytes;
                toEraseSize -= kEraseChunkSizeBytes;
            }
            if (toEraseSize > 0)
            {
                sendCommand(PAYLOAD_UPDATE_ERASE, regionOffset, toEraseSize);
            }
        }
    }

    // Read and send static and WP sections of the payload
    for (uint32_t i = 0; i < descriptor.region_count; i++)
    {
        if ((image_regions[i].region_attributes & IMAGE_REGION_STATIC) ||
            (image_regions[i].region_attributes & IMAGE_REGION_WRITE_PROTECTED))
        {
            uint32_t offset = image_regions[i].region_offset;
            auto regionSize = image_regions[i].region_size;
            size_t readSize = 0;
            std::vector<uint8_t> readBuffer(max_packet_size);

            if (sys->lseek(*fd, offset, SEEK_SET) != offset)
            {
                throw errnoException(
                    std::format("Failed to read file size {}", path));
            }
            do
            {
                if (regionSize <= max_packet_size)
                {
                    readSize = regionSize;
                }
                else
                {
                    readSize = max_packet_size;
                }

                if (!sys->read(*fd, readBuffer.data(), readSize))
                {
                    throw errnoException(
                        std::format("Failed to read from file {}", path));
                }

                // Decided not to use initializer list to create the span here
                // as actualReadSize is ssize_t and we'd need to static_cast
                trimAndSend(std::span<uint8_t>(readBuffer.data(), readSize),
                            offset);
                offset += readSize;
                regionSize -= readSize;

            } while (regionSize); // actualReadSize will be 0 when EOF is
                                  // reached, exit loop
        }
    }
}

void PayloadUpdateImpl::eraseAndSendStaticWP(const std::string& path) const
{
    uint32_t desc_offset = 0;

    if (!findDescriptor(path, &desc_offset))
    {
        throw errnoException(std::format("No valid descriptor found"));
    }

    eraseAndSendStaticWPRegions(path, desc_offset);
}

void PayloadUpdateImpl::read(uint32_t offset, std::span<uint8_t> data) const
{
    std::vector<uint8_t> buf;
    auto rsp = sendCommand(buf, PAYLOAD_UPDATE_READ, offset, data.size());
    if (rsp.size() != data.size())
    {
        stdplus::print(
            stderr,
            "Payload command received a short response from Hoth `{} < {}`\n",
            rsp.size(), data.size());
        throw ResponseFailure();
    }
    memcpy(data.data(), rsp.data(), data.size());
}

void PayloadUpdateImpl::verify() const
{
    payload_update_packet request = {};
    request.type = PAYLOAD_UPDATE_VERIFY_DESCRIPTOR;
    auto buf = hostCmd->sendCommand(
        EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
        &request, sizeof(request));
    std::span<uint8_t> rsp = buf;
    auto& hdr = stdplus::raw::extractRef<RspHeader>(rsp);

    // In case PAYLOAD_UPDATE_VERIFY is not supported (EC_RES_ERROR),
    // we fall back to PAYLOAD_UPDATE_VERIFY instead.
    if (hdr.result == EC_RES_INVALID_PARAM || hdr.result == EC_RES_ERROR)
    {
        sendCommand(PAYLOAD_UPDATE_VERIFY);
        return;
    }
    if (hdr.result != EC_RES_SUCCESS)
    {
        stdplus::print(stderr, "VERIFY_DESCRIPTOR error: {:#x}\n",
                       static_cast<uint16_t>(hdr.result));
        throw ResponseFailure();
    }
}

payload_update_status PayloadUpdateImpl::getStatus() const
{
    std::vector<uint8_t> buf;
    std::span<const uint8_t> output =
        sendCommand(buf, PAYLOAD_UPDATE_GET_STATUS);

    return stdplus::raw::copyFrom<payload_update_status>(output);
}

void PayloadUpdateImpl::activate(Side side, Persistence persistence) const
{
    ActivateRequest request;
    request.header.offset = 0;
    request.header.len = sizeof(request.activate);
    request.header.type = PAYLOAD_UPDATE_ACTIVATE;
    request.activate.half = static_cast<uint8_t>(side);
    request.activate.make_persistent = static_cast<uint8_t>(persistence);

    sendCommand(
        {reinterpret_cast<const uint8_t*>(&request), sizeof(ActivateRequest)});
}

std::optional<payload_update_confirm_response> PayloadUpdateImpl::confirm(
    enum payload_update_confirm_option option, uint32_t timeout,
    uint64_t confirmation_cookie) const
{
    ConfirmRequest request;
    request.header.offset = 0;
    request.header.len = sizeof(request.confirm);
    request.header.type = PAYLOAD_UPDATE_CONFIRM;
    request.confirm.option = option;
    request.confirm.timeout_value = boost::endian::native_to_little(timeout);
    request.confirm.confirmation_cookie =
        boost::endian::native_to_little(confirmation_cookie);

    std::vector<uint8_t> buf = hostCmd->sendCommand(
        EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
        &request, sizeof(request));
    // Extract the response header out when returning the span
    std::span<const uint8_t> output = buf;
    auto rsp = stdplus::raw::extract<RspHeader>(output);
    if (rsp.result == HOTH_PAYLOAD_UPDATE_CONFIRM_NO_PENDING_PAYLOAD)
    {
        return std::nullopt;
    }

    if (rsp.result != EC_RES_SUCCESS)
    {
        stdplus::print(
            stderr,
            "Payload confirm command received a bad response from Hoth {:#x}\n",
            static_cast<uint16_t>(rsp.result));
        throw ResponseFailure();
    }

    return stdplus::raw::copyFrom<payload_update_confirm_response>(output);
}

namespace
{
// Helper functions for PayloadUpdateImpl::send
size_t SizeToSkip(std::span<const uint8_t> data)
{
    size_t i;
    for (i = 0; i < data.size(); i++)
    {
        if (data[i] != 0xff)
        {
            break;
        }
    }
    return i;
}

size_t SizeToSend(std::span<const uint8_t> data)
{
    size_t i;
    for (i = data.size(); i > 0; i--)
    {
        if (data[i - 1] != 0xff)
        {
            break;
        }
    }
    return i;
}
} // namespace

void PayloadUpdateImpl::send(const std::string& path) const
{
    Fd fd(sys->open(path.c_str(), O_RDONLY), sys);

    if (*fd < 0)
    {
        (void)fd.release();
        throw errnoException(std::format("Failed to open file {}", path));
    }

    std::array<uint8_t, max_packet_size> readBuffer;
    uint32_t offset = 0;
    ssize_t actualReadSize = 0;
    // Read and send payload until we reach EOF of the given file
    do
    {
        actualReadSize = sys->read(*fd, readBuffer.data(), max_packet_size);

        if (actualReadSize < 0)
        {
            throw errnoException(
                std::format("Failed to read from file {}", path));
        }
        if (actualReadSize > 0)
        {
            // Decided not to use initializer list to create the span here as
            // actualReadSize is ssize_t and we'd need to static_cast
            trimAndSend(std::span<uint8_t>(readBuffer.data(), actualReadSize),
                        offset);
            offset += actualReadSize;
        }
        // actualReadSize will be 0 when EOF is reached, exit loop
    } while (actualReadSize);
}

/* Parse and send the given data after trimming 0xff from the front and back
 * - This works because PayloadUpdateImpl::Initiate erased the
 * EEPROM to 0xff.
 * - This is also more efficient than sending everything, as our
 * image binaries tend to have large sections of 0xff and we can
 * avoid sending those sections.
 */
void PayloadUpdateImpl::trimAndSend(std::span<const uint8_t> data,
                                    uint32_t globalOffset) const
{
    // Allocate the payload buffer at "buffer".
    // "request" will point to the payload_update_packet section of the buffer
    // "request_payload" will point to the beginning of the payload
    // (after the payload_update_packet header).
    std::array<uint8_t, sizeof(payload_update_packet) + max_packet_size> buffer;
    payload_update_packet* request =
        reinterpret_cast<payload_update_packet*>(buffer.data());
    uint8_t* request_payload = &buffer[sizeof(payload_update_packet)];

    const size_t dataSize = data.size();
    if (dataSize > max_packet_size)
    {
        throw errnoException(
            "data to send cannot be bigger than max_packet_size");
    }
    size_t localOffset = SizeToSkip(data);
    if (localOffset >= dataSize)
    {
        // No need to send any payload
        return;
    }
    size_t max_size_to_send = std::min(dataSize - localOffset, max_packet_size);
    size_t size_to_send =
        SizeToSend(data.subspan(localOffset, max_size_to_send));

    // Construct and send payload
    request->offset = globalOffset + localOffset;
    request->len = size_to_send;
    request->type = PAYLOAD_UPDATE_CONTINUE;
    memcpy(request_payload, &data[localOffset], size_to_send);
    sendCommand({buffer.data(), sizeof(*request) + size_to_send});
}

void PayloadUpdateImpl::sendCommand(uint8_t command, uint32_t offset,
                                    uint32_t len) const
{
    std::vector<uint8_t> buf;
    (void)sendCommand(buf, command, offset, len);
}

void PayloadUpdateImpl::sendCommand(std::span<const uint8_t> request) const
{
    std::vector<uint8_t> buf;
    (void)sendCommand(buf, request);
}

[[nodiscard]] std::span<const uint8_t> PayloadUpdateImpl::sendCommand(
    std::vector<uint8_t>& buf, uint8_t command, uint32_t offset,
    uint32_t len) const
{
    // For most basic commands, request offset and length are zero
    payload_update_packet request;
    request.offset = offset;
    request.len = len;
    request.type = command;
    return sendCommand(buf, {reinterpret_cast<const uint8_t*>(&request),
                             sizeof(payload_update_packet)});
}

[[nodiscard]] std::span<const uint8_t> PayloadUpdateImpl::sendCommand(
    std::vector<uint8_t>& buf, std::span<const uint8_t> request) const
{
    buf = hostCmd->sendCommand(
        EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
        request.data(), request.size());
    // Extract the response header out when returning the span
    std::span<const uint8_t> output = buf;
    auto rsp = stdplus::raw::extract<RspHeader>(output);
    if (rsp.result != EC_RES_SUCCESS)
    {
        stdplus::print(
            stderr, "Payload command received a bad response from Hoth {:#x}\n",
            static_cast<uint16_t>(rsp.result));
        throw ResponseFailure();
    }

    return output;
}

} // namespace internal

} // namespace hoth

} // namespace google
