/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <string>

#include <android-base/macros.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <libavb/libavb.h>
#include <utils/Compat.h>

#include "fs_mgr.h"
#include "fs_mgr_avb_ops.h"
#include "fs_mgr_priv.h"

static struct fstab *fs_mgr_fstab = nullptr;

static AvbIOResult read_from_partition(AvbOps *ops ATTRIBUTE_UNUSED,
                                       const char *partition,
                                       int64_t offset,
                                       size_t num_bytes,
                                       void *buffer,
                                       size_t *out_num_read)
{
    // The input |partition| name is with ab_suffix, e.g. system_a.
    // Slot suffix (e.g. _a) will be appended to the device file path
    // for partitions having 'slotselect' optin in fstab file, but it
    // won't be appended to the mount point.
    //
    // In AVB, we can assume that there's an entry for the /misc mount
    // point and use that to get the device file for the misc partition.
    // From there we'll assume that a by-name scheme is used
    // so we can just replace the trailing "misc" by the given
    // |partition|, e.g.
    //
    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a

    struct fstab_rec *fstab_entry =
        fs_mgr_get_entry_for_mount_point(fs_mgr_fstab, "/misc");

    if (fstab_entry == nullptr) {
        LERROR << "/misc mount point not found in fstab";
        return AVB_IO_RESULT_ERROR_IO;
    }

    std::string partition_name(partition);
    std::string path(fstab_entry->blk_device);
    // Replaces the last field of device file if it's not misc.
    if (!android::base::StartsWith(partition_name, "misc")) {
        size_t end_slash = path.find_last_of("/");
        std::string by_name_prefix(path.substr(0, end_slash + 1));
        path = by_name_prefix + partition_name;
    }

    // Ensures the device path (a symlink created by init) is ready to
    // access. fs_mgr_test_access() will test a few iterations if the
    // path doesn't exist yet.
    if (fs_mgr_test_access(path.c_str()) < 0) {
        return AVB_IO_RESULT_ERROR_IO;
    }

    android::base::unique_fd fd(
        TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));

    if (fd < 0) {
        PERROR << "Failed to open " << path.c_str();
        return AVB_IO_RESULT_ERROR_IO;
    }

    // If offset is negative, interprets its absolute value as the
    //  number of bytes from the end of the partition.
    if (offset < 0) {
        off64_t total_size = lseek64(fd, 0, SEEK_END);
        if (total_size == -1) {
            LERROR << "Failed to lseek64 to end of the partition";
            return AVB_IO_RESULT_ERROR_IO;
        }
        offset = total_size + offset;
        // Repositions the offset to the beginning.
        if (lseek64(fd, 0, SEEK_SET) == -1) {
            LERROR << "Failed to lseek64 to the beginning of the partition";
            return AVB_IO_RESULT_ERROR_IO;
        }
    }

    // On Linux, we never get partial reads from block devices (except
    // for EOF).
    ssize_t num_read =
        TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset));

    if (num_read < 0 || (size_t)num_read != num_bytes) {
        PERROR << "Failed to read " << num_bytes << " bytes from "
               << path.c_str() << " offset " << offset;
        return AVB_IO_RESULT_ERROR_IO;
    }

    if (out_num_read != nullptr) {
        *out_num_read = num_read;
    }

    return AVB_IO_RESULT_OK;
}

static AvbIOResult dummy_read_rollback_index(AvbOps *ops ATTRIBUTE_UNUSED,
                                             size_t rollback_index_location
                                                 ATTRIBUTE_UNUSED,
                                             uint64_t *out_rollback_index)
{
    // rollback_index has been checked in bootloader phase.
    // In user-space, returns the smallest value 0 to pass the check.
    *out_rollback_index = 0;
    return AVB_IO_RESULT_OK;
}

static AvbIOResult dummy_validate_vbmeta_public_key(
    AvbOps *ops ATTRIBUTE_UNUSED,
    const uint8_t *public_key_data ATTRIBUTE_UNUSED,
    size_t public_key_length ATTRIBUTE_UNUSED,
    const uint8_t *public_key_metadata ATTRIBUTE_UNUSED,
    size_t public_key_metadata_length ATTRIBUTE_UNUSED,
    bool *out_is_trusted)
{
    // vbmeta public key has been checked in bootloader phase.
    // In user-space, returns true to pass the check.
    //
    // Addtionally, user-space should check
    // androidboot.vbmeta.{hash_alg, size, digest} against the digest
    // of all vbmeta images after invoking avb_slot_verify().

    *out_is_trusted = true;
    return AVB_IO_RESULT_OK;
}

static AvbIOResult dummy_read_is_device_unlocked(AvbOps *ops ATTRIBUTE_UNUSED,
                                                 bool *out_is_unlocked)
{
    // The function is for bootloader to update the value into
    // androidboot.vbmeta.device_state in kernel cmdline.
    // In user-space, returns true as we don't need to update it anymore.
    *out_is_unlocked = true;
    return AVB_IO_RESULT_OK;
}

static AvbIOResult dummy_get_unique_guid_for_partition(
    AvbOps *ops ATTRIBUTE_UNUSED,
    const char *partition ATTRIBUTE_UNUSED,
    char *guid_buf,
    size_t guid_buf_size)
{
    // The function is for bootloader to set the correct UUID
    // for a given partition in kernel cmdline.
    // In user-space, returns a faking one as we don't need to update
    // it anymore.
    snprintf(guid_buf, guid_buf_size, "1234-fake-guid-for:%s", partition);
    return AVB_IO_RESULT_OK;
}

AvbOps *fs_mgr_dummy_avb_ops_new(struct fstab *fstab)
{
    AvbOps *ops;

    // Assigns the fstab to the static variable for later use.
    fs_mgr_fstab = fstab;

    ops = (AvbOps *)calloc(1, sizeof(AvbOps));
    if (ops == nullptr) {
        LERROR << "Error allocating memory for AvbOps";
        return nullptr;
    }

    // We only need these operations since that's all what is being used
    // by the avb_slot_verify(); Most of them are dummy operations because
    // they're only required in bootloader but not required in user-space.
    ops->read_from_partition = read_from_partition;
    ops->read_rollback_index = dummy_read_rollback_index;
    ops->validate_vbmeta_public_key = dummy_validate_vbmeta_public_key;
    ops->read_is_device_unlocked = dummy_read_is_device_unlocked;
    ops->get_unique_guid_for_partition = dummy_get_unique_guid_for_partition;

    return ops;
}

void fs_mgr_dummy_avb_ops_free(AvbOps *ops)
{
    free(ops);
}
