/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * 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 "writer.h"

#include <inttypes.h>
#include <unistd.h>

#include <string>

#include <android-base/file.h>
#include <android-base/unique_fd.h>

#include "reader.h"
#include "utility.h"

namespace android {
namespace fs_mgr {

std::string SerializeGeometry(const LpMetadataGeometry& input) {
    LpMetadataGeometry geometry = input;
    memset(geometry.checksum, 0, sizeof(geometry.checksum));
    SHA256(&geometry, sizeof(geometry), geometry.checksum);

    std::string blob(reinterpret_cast<const char*>(&geometry), sizeof(geometry));
    blob.resize(LP_METADATA_GEOMETRY_SIZE);
    return blob;
}

static bool CompareGeometry(const LpMetadataGeometry& g1, const LpMetadataGeometry& g2) {
    return g1.metadata_max_size == g2.metadata_max_size &&
           g1.metadata_slot_count == g2.metadata_slot_count &&
           g1.logical_block_size == g2.logical_block_size;
}

std::string SerializeMetadata(const LpMetadata& input) {
    LpMetadata metadata = input;
    LpMetadataHeader& header = metadata.header;

    // Serialize individual tables.
    std::string partitions(reinterpret_cast<const char*>(metadata.partitions.data()),
                           metadata.partitions.size() * sizeof(LpMetadataPartition));
    std::string extents(reinterpret_cast<const char*>(metadata.extents.data()),
                        metadata.extents.size() * sizeof(LpMetadataExtent));
    std::string groups(reinterpret_cast<const char*>(metadata.groups.data()),
                       metadata.groups.size() * sizeof(LpMetadataPartitionGroup));
    std::string block_devices(reinterpret_cast<const char*>(metadata.block_devices.data()),
                              metadata.block_devices.size() * sizeof(LpMetadataBlockDevice));

    // Compute positions of tables.
    header.partitions.offset = 0;
    header.extents.offset = header.partitions.offset + partitions.size();
    header.groups.offset = header.extents.offset + extents.size();
    header.block_devices.offset = header.groups.offset + groups.size();
    header.tables_size = header.block_devices.offset + block_devices.size();

    // Compute payload checksum.
    std::string tables = partitions + extents + groups + block_devices;
    SHA256(tables.data(), tables.size(), header.tables_checksum);

    // Compute header checksum.
    memset(header.header_checksum, 0, sizeof(header.header_checksum));
    SHA256(&header, sizeof(header), header.header_checksum);

    std::string header_blob =
            std::string(reinterpret_cast<const char*>(&metadata.header), sizeof(metadata.header));
    return header_blob + tables;
}

// Perform sanity checks so we don't accidentally overwrite valid metadata
// with potentially invalid metadata, or random partition data with metadata.
static bool ValidateAndSerializeMetadata(const IPartitionOpener& opener, const LpMetadata& metadata,
                                         std::string* blob) {
    const LpMetadataHeader& header = metadata.header;
    const LpMetadataGeometry& geometry = metadata.geometry;

    *blob = SerializeMetadata(metadata);

    // Make sure we're writing within the space reserved.
    if (blob->size() > geometry.metadata_max_size) {
        LERROR << "Logical partition metadata is too large. " << blob->size() << " > "
               << geometry.metadata_max_size;
        return false;
    }

    // Make sure the device has enough space to store two backup copies of the
    // metadata.
    uint64_t reserved_size = LP_METADATA_GEOMETRY_SIZE +
                             uint64_t(geometry.metadata_max_size) * geometry.metadata_slot_count;
    uint64_t total_reserved = LP_PARTITION_RESERVED_BYTES + reserved_size * 2;

    const LpMetadataBlockDevice* super_device = GetMetadataSuperBlockDevice(metadata);
    if (!super_device) {
        LERROR << "Logical partition metadata does not have a super block device.";
        return false;
    }

    if (total_reserved > super_device->first_logical_sector * LP_SECTOR_SIZE) {
        LERROR << "Not enough space to store all logical partition metadata slots.";
        return false;
    }
    for (const auto& block_device : metadata.block_devices) {
        std::string partition_name = GetBlockDevicePartitionName(block_device);
        if ((block_device.first_logical_sector + 1) * LP_SECTOR_SIZE > block_device.size) {
            LERROR << "Block device " << partition_name << " has invalid first sector "
                   << block_device.first_logical_sector << " for size " << block_device.size;
            return false;
        }
        BlockDeviceInfo info;
        if (!opener.GetInfo(partition_name, &info)) {
            PERROR << partition_name << ": ioctl";
            return false;
        }
        if (info.size != block_device.size) {
            LERROR << "Block device " << partition_name << " size mismatch (expected"
                   << block_device.size << ", got " << info.size << ")";
            return false;
        }
    }

    // Make sure all partition entries reference valid extents.
    for (const auto& partition : metadata.partitions) {
        if (partition.first_extent_index + partition.num_extents > metadata.extents.size()) {
            LERROR << "Partition references invalid extent.";
            return false;
        }
    }

    // Make sure all linear extents have a valid range.
    uint64_t last_sector = super_device->size / LP_SECTOR_SIZE;
    for (const auto& extent : metadata.extents) {
        if (extent.target_type == LP_TARGET_TYPE_LINEAR) {
            uint64_t physical_sector = extent.target_data;
            if (physical_sector < super_device->first_logical_sector ||
                physical_sector + extent.num_sectors > last_sector) {
                LERROR << "Extent table entry is out of bounds.";
                return false;
            }
        }
    }
    return true;
}

// Check that the given region is within metadata bounds.
static bool ValidateMetadataRegion(const LpMetadata& metadata, uint64_t start, size_t size) {
    const LpMetadataBlockDevice* super_device = GetMetadataSuperBlockDevice(metadata);
    if (!super_device) {
        LERROR << __PRETTY_FUNCTION__ << " could not locate super block device in metadata";
        return false;
    }
    if (start + size >= super_device->first_logical_sector * LP_SECTOR_SIZE) {
        LERROR << __PRETTY_FUNCTION__ << " write of " << size << " bytes at " << start
               << " overlaps with logical partition contents";
        return false;
    }
    return true;
}

static bool WritePrimaryMetadata(int fd, const LpMetadata& metadata, uint32_t slot_number,
                                 const std::string& blob,
                                 const std::function<bool(int, const std::string&)>& writer) {
    int64_t primary_offset = GetPrimaryMetadataOffset(metadata.geometry, slot_number);
    if (!ValidateMetadataRegion(metadata, primary_offset, blob.size())) {
        return false;
    }
    if (SeekFile64(fd, primary_offset, SEEK_SET) < 0) {
        PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << primary_offset;
        return false;
    }
    if (!writer(fd, blob)) {
        PERROR << __PRETTY_FUNCTION__ << " write " << blob.size() << " bytes failed";
        return false;
    }
    return true;
}

static bool WriteBackupMetadata(int fd, const LpMetadata& metadata, uint32_t slot_number,
                                const std::string& blob,
                                const std::function<bool(int, const std::string&)>& writer) {
    int64_t backup_offset = GetBackupMetadataOffset(metadata.geometry, slot_number);
    if (!ValidateMetadataRegion(metadata, backup_offset, blob.size())) {
        return false;
    }
    if (SeekFile64(fd, backup_offset, SEEK_SET) < 0) {
        PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << backup_offset;
        return false;
    }
    if (!writer(fd, blob)) {
        PERROR << __PRETTY_FUNCTION__ << " backup write " << blob.size() << " bytes failed";
        return false;
    }
    return true;
}

static bool WriteMetadata(int fd, const LpMetadata& metadata, uint32_t slot_number,
                          const std::string& blob,
                          const std::function<bool(int, const std::string&)>& writer) {
    // Make sure we're writing to a valid metadata slot.
    if (slot_number >= metadata.geometry.metadata_slot_count) {
        LERROR << "Invalid logical partition metadata slot number.";
        return false;
    }
    if (!WritePrimaryMetadata(fd, metadata, slot_number, blob, writer)) {
        return false;
    }
    if (!WriteBackupMetadata(fd, metadata, slot_number, blob, writer)) {
        return false;
    }
    return true;
}

static bool DefaultWriter(int fd, const std::string& blob) {
    return android::base::WriteFully(fd, blob.data(), blob.size());
}

bool FlashPartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
                         const LpMetadata& metadata) {
    android::base::unique_fd fd = opener.Open(super_partition, O_RDWR | O_SYNC);
    if (fd < 0) {
        PERROR << __PRETTY_FUNCTION__ << " open failed: " << super_partition;
        return false;
    }

    // Before writing geometry and/or logical partition tables, perform some
    // basic checks that the geometry and tables are coherent, and will fit
    // on the given block device.
    std::string metadata_blob;
    if (!ValidateAndSerializeMetadata(opener, metadata, &metadata_blob)) {
        return false;
    }

    // Write zeroes to the first block.
    std::string zeroes(LP_PARTITION_RESERVED_BYTES, 0);
    if (SeekFile64(fd, 0, SEEK_SET) < 0) {
        PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset 0";
        return false;
    }
    if (!android::base::WriteFully(fd, zeroes.data(), zeroes.size())) {
        PERROR << __PRETTY_FUNCTION__ << " write " << zeroes.size() << " bytes failed";
        return false;
    }

    LWARN << "Flashing new logical partition geometry to " << super_partition;

    // Write geometry to the primary and backup locations.
    std::string blob = SerializeGeometry(metadata.geometry);
    if (SeekFile64(fd, GetPrimaryGeometryOffset(), SEEK_SET) < 0) {
        PERROR << __PRETTY_FUNCTION__ << " lseek failed: primary geometry";
        return false;
    }
    if (!android::base::WriteFully(fd, blob.data(), blob.size())) {
        PERROR << __PRETTY_FUNCTION__ << " write " << blob.size() << " bytes failed";
        return false;
    }
    if (SeekFile64(fd, GetBackupGeometryOffset(), SEEK_SET) < 0) {
        PERROR << __PRETTY_FUNCTION__ << " lseek failed: backup geometry";
        return false;
    }
    if (!android::base::WriteFully(fd, blob.data(), blob.size())) {
        PERROR << __PRETTY_FUNCTION__ << " backup write " << blob.size() << " bytes failed";
        return false;
    }

    bool ok = true;
    for (size_t i = 0; i < metadata.geometry.metadata_slot_count; i++) {
        ok &= WriteMetadata(fd, metadata, i, metadata_blob, DefaultWriter);
    }
    return ok;
}

bool FlashPartitionTable(const std::string& super_partition, const LpMetadata& metadata) {
    return FlashPartitionTable(PartitionOpener(), super_partition, metadata);
}

static bool CompareMetadata(const LpMetadata& a, const LpMetadata& b) {
    return !memcmp(a.header.header_checksum, b.header.header_checksum,
                   sizeof(a.header.header_checksum));
}

bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
                          const LpMetadata& metadata, uint32_t slot_number,
                          const std::function<bool(int, const std::string&)>& writer) {
    android::base::unique_fd fd = opener.Open(super_partition, O_RDWR | O_SYNC);
    if (fd < 0) {
        PERROR << __PRETTY_FUNCTION__ << " open failed: " << super_partition;
        return false;
    }

    // Before writing geometry and/or logical partition tables, perform some
    // basic checks that the geometry and tables are coherent, and will fit
    // on the given block device.
    std::string blob;
    if (!ValidateAndSerializeMetadata(opener, metadata, &blob)) {
        return false;
    }

    // Verify that the old geometry is identical. If it's not, then we might be
    // writing a table that was built for a different device, so we must reject
    // it.
    const LpMetadataGeometry& geometry = metadata.geometry;
    LpMetadataGeometry old_geometry;
    if (!ReadLogicalPartitionGeometry(fd, &old_geometry)) {
        return false;
    }
    if (!CompareGeometry(geometry, old_geometry)) {
        LERROR << "Incompatible geometry in new logical partition metadata";
        return false;
    }

    // Validate the slot number now, before we call Read*Metadata.
    if (slot_number >= geometry.metadata_slot_count) {
        LERROR << "Invalid logical partition metadata slot number.";
        return false;
    }

    // Try to read both existing copies of the metadata, if any.
    std::unique_ptr<LpMetadata> primary = ReadPrimaryMetadata(fd, geometry, slot_number);
    std::unique_ptr<LpMetadata> backup = ReadBackupMetadata(fd, geometry, slot_number);

    if (primary && (!backup || !CompareMetadata(*primary.get(), *backup.get()))) {
        // If the backup copy does not match the primary copy, we first
        // synchronize the backup copy. This guarantees that a partial write
        // still leaves one copy intact.
        std::string old_blob;
        if (!ValidateAndSerializeMetadata(opener, *primary.get(), &old_blob)) {
            LERROR << "Error serializing primary metadata to repair corrupted backup";
            return false;
        }
        if (!WriteBackupMetadata(fd, metadata, slot_number, old_blob, writer)) {
            LERROR << "Error writing primary metadata to repair corrupted backup";
            return false;
        }
    } else if (backup && !primary) {
        // The backup copy is coherent, and the primary is not. Sync it for
        // safety.
        std::string old_blob;
        if (!ValidateAndSerializeMetadata(opener, *backup.get(), &old_blob)) {
            LERROR << "Error serializing primary metadata to repair corrupted backup";
            return false;
        }
        if (!WritePrimaryMetadata(fd, metadata, slot_number, old_blob, writer)) {
            LERROR << "Error writing primary metadata to repair corrupted backup";
            return false;
        }
    }

    // Both copies should now be in sync, so we can continue the update.
    if (!WriteMetadata(fd, metadata, slot_number, blob, writer)) {
        return false;
    }

    LINFO << "Updated logical partition table at slot " << slot_number << " on device "
          << super_partition;
    return true;
}

bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
                          const LpMetadata& metadata, uint32_t slot_number) {
    return UpdatePartitionTable(opener, super_partition, metadata, slot_number, DefaultWriter);
}

bool UpdatePartitionTable(const std::string& super_partition, const LpMetadata& metadata,
                          uint32_t slot_number) {
    PartitionOpener opener;
    return UpdatePartitionTable(opener, super_partition, metadata, slot_number, DefaultWriter);
}

}  // namespace fs_mgr
}  // namespace android
