// 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 "util.h"

#include <ctype.h>

#include <fbl/algorithm.h>
#include <fs/connection.h>
#include <safemath/checked_math.h>
#include <zircon/assert.h>
#include <zircon/boot/image.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>

namespace {

// Returns true for boot item types that should be stored.
bool StoreItem(uint32_t type) {
    switch (type) {
    case ZBI_TYPE_CRASHLOG:
    case ZBI_TYPE_KERNEL_DRIVER:
    case ZBI_TYPE_PLATFORM_ID:
    case ZBI_TYPE_STORAGE_BOOTFS_FACTORY:
    case ZBI_TYPE_STORAGE_RAMDISK:
        return true;
    default:
        return ZBI_TYPE_DRV_METADATA(type);
    }
}

// Discards the boot item from the boot image VMO.
void DiscardItem(zx::vmo* vmo, uint32_t begin_in, uint32_t end_in) {
    uint64_t begin = fbl::round_up(begin_in, static_cast<uint32_t>(PAGE_SIZE));
    uint64_t end = fbl::round_down(end_in, static_cast<uint32_t>(PAGE_SIZE));
    if (begin < end) {
        zx_status_t status = vmo->op_range(ZX_VMO_OP_DECOMMIT, begin, end - begin, nullptr, 0);
        ZX_ASSERT_MSG(status == ZX_OK, "Discarding boot item failed: %s\n",
                      zx_status_get_string(status));
        printf("bootsvc: Decommitted BOOTDATA VMO from %#lx to %#lx\n", begin, end);
    }
}

bootsvc::ItemKey CreateItemKey(uint32_t type, uint32_t extra) {
    switch (type) {
    case ZBI_TYPE_STORAGE_RAMDISK:
        // If this is for a ramdisk, set the extra value to zero.
        return bootsvc::ItemKey{.type = type, .extra = 0};
    default:
        // Otherwise, store the extra value.
        return bootsvc::ItemKey{.type = type, .extra = extra};
    }
}

bootsvc::ItemValue CreateItemValue(uint32_t type, uint32_t off, uint32_t len) {
    switch (type) {
    case ZBI_TYPE_STORAGE_RAMDISK:
        // If this is for a ramdisk, capture the ZBI header.
        len = safemath::CheckAdd(len, sizeof(zbi_header_t)).ValueOrDie<uint32_t>();
        break;
    default:
        // Otherwise, adjust the offset to skip the ZBI header.
        off = safemath::CheckAdd(off, sizeof(zbi_header_t)).ValueOrDie<uint32_t>();
    }
    return bootsvc::ItemValue{.offset = off, .length = len};
}

} // namespace

namespace bootsvc {

const char* const kLastPanicFilePath = "log/last-panic.txt";

zx_status_t RetrieveBootImage(zx::vmo* out_vmo, ItemMap* out_map) {
    // Validate boot image VMO provided by startup handle.
    zx::vmo vmo(zx_take_startup_handle(PA_HND(PA_VMO_BOOTDATA, 0)));
    zbi_header_t header;
    zx_status_t status = vmo.read(&header, 0, sizeof(header));
    if (status != ZX_OK) {
        printf("bootsvc: Failed to read ZBI image header: %s\n", zx_status_get_string(status));
        return status;
    } else if (header.type != ZBI_TYPE_CONTAINER || header.extra != ZBI_CONTAINER_MAGIC ||
               header.magic != ZBI_ITEM_MAGIC || !(header.flags & ZBI_FLAG_VERSION)) {
        printf("bootsvc: Invalid ZBI image header\n");
        return ZX_ERR_IO_DATA_INTEGRITY;
    }

    // Used to discard pages from the boot image VMO.
    uint32_t discard_begin = 0;
    uint32_t discard_end = 0;

    // Read boot items from the boot image VMO.
    ItemMap map;
    uint32_t off = sizeof(header);
    uint32_t len = header.length;
    while (len > sizeof(header)) {
        status = vmo.read(&header, off, sizeof(header));
        if (status != ZX_OK) {
            printf("bootsvc: Failed to read ZBI item header: %s\n", zx_status_get_string(status));
            return status;
        } else if (header.type == ZBI_CONTAINER_MAGIC || header.magic != ZBI_ITEM_MAGIC) {
            printf("bootsvc: Invalid ZBI item header\n");
            return ZX_ERR_IO_DATA_INTEGRITY;
        }
        uint32_t item_len = ZBI_ALIGN(header.length + static_cast<uint32_t>(sizeof(zbi_header_t)));
        uint32_t next_off = safemath::CheckAdd(off, item_len).ValueOrDie();
        if (item_len > len) {
            printf("bootsvc: ZBI item too large (%u > %u)\n", item_len, len);
            return ZX_ERR_IO_DATA_INTEGRITY;
        } else if (StoreItem(header.type)) {
            map.emplace(CreateItemKey(header.type, header.extra),
                        CreateItemValue(header.type, off, header.length));
            DiscardItem(&vmo, discard_begin, discard_end);
            discard_begin = next_off;
        } else {
            discard_end = next_off;
        }
        off = next_off;
        len = safemath::CheckSub(len, item_len).ValueOrDie();
    }

    DiscardItem(&vmo, discard_begin, discard_end);
    *out_vmo = std::move(vmo);
    *out_map = std::move(map);
    return ZX_OK;
}

zx_status_t ParseBootArgs(std::string_view str, fbl::Vector<char>* buf) {
    buf->reserve(buf->size() + str.size());
    for (auto it = str.begin(); it != str.end(); it++) {
        // Skip any leading whitespace.
        if (isspace(*it)) {
            continue;
        }
        // Is the line a comment or a zero-length name?
        bool is_comment = *it == '#' || *it == '=';
        // Append line, if it is not a comment.
        for (; it != str.end(); it++) {
            if (*it == '\n') {
                // We've reached the end of the line.
                break;
            } else if (is_comment) {
                // Skip this character, as it is part of a comment.
                continue;
            } else if (isspace(*it)) {
                // It is invalid to have a space within an argument.
                return ZX_ERR_INVALID_ARGS;
            } else {
                buf->push_back(*it);
            }
        }
        if (!is_comment) {
            buf->push_back(0);
        }
    }
    return ZX_OK;
}

zx_status_t CreateVnodeConnection(fs::Vfs* vfs, fbl::RefPtr<fs::Vnode> vnode, zx::channel* out) {
    zx::channel local, remote;
    zx_status_t status = zx::channel::create(0, &local, &remote);
    if (status != ZX_OK) {
        return status;
    }

    auto conn = std::make_unique<fs::Connection>(vfs, vnode, std::move(local),
                                                 ZX_FS_FLAG_DIRECTORY |
                                                     ZX_FS_RIGHT_READABLE |
                                                     ZX_FS_RIGHT_WRITABLE);
    status = vfs->ServeConnection(std::move(conn));
    if (status != ZX_OK) {
        return status;
    }
    *out = std::move(remote);
    return ZX_OK;
}

fbl::Vector<fbl::String> SplitString(fbl::String input, char delimiter) {
    fbl::Vector<fbl::String> result;

    // No fbl::String::find, do it ourselves.
    const char* start = input.begin();
    for (auto end = start; end != input.end(); start = end + 1) {
        end = start;
        while (end != input.end() && *end != delimiter) {
            ++end;
        }
        result.push_back(fbl::String(start, end - start));
    }
    return result;
}

} // namespace bootsvc
