// Copyright 2023 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 "sparse.h"

#include <sparse_format.h>
#include <stdbool.h>
#include <string.h>

// Can't reliably depend on endian macros, so just define them ourselves
#ifndef __BYTE_ORDER__
#error Compiler does not provide __BYTE_ORDER__
#endif

// The compiler provides it, use what it says
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
#endif

#ifndef BIG_ENDIAN
#define BIG_ENDIAN __ORDER_BIG_ENDIAN__
#endif

#ifndef BYTE_ORDER
#define BYTE_ORDER __BYTE_ORDER__
#endif

// We only want macros to convert from little-endian
// because that's what the fields in a sparse header are defined as.
#if BYTE_ORDER == BIG_ENDIAN
static inline uint64_t SWAP_64(uint64_t x) { return __builtin_bswap64(x); }
static inline uint32_t SWAP_32(uint32_t x) { return __builtin_bswap32(x); }
static inline uint16_t SWAP_16(uint16_t x) { return __builtin_bswap16(x); }

#define LE64(val) SWAP_64(val)
#define LE32(val) SWAP_32(val)
#define LE16(val) SWAP_16(val)
#else
#define LE64(val) (val)
#define LE32(val) (val)
#define LE16(val) (val)
#endif

static void DumpStruct(SparseLogFn log, const void* s, size_t size) {
#ifdef ENABLE_VERBOSE_SPARSE_LOG
  for (size_t i = 0; i < size; i++) {
    log("0x%02X ", ((uint8_t*)s)[i]);
  }
#endif
  log("\n");
}

// Check the values of the fields in header to make sure they conform to
// the expected semantics of a valid sparse file header.
//
// @header: The sparse header to be checked.
//
// Return true if it is valid, false otherwise.
static bool IsValidFileHeader(const sparse_header_t* header) {
  return header && LE64(header->magic) == SPARSE_HEADER_MAGIC &&
         LE16(header->major_version) <= 0x1 && sizeof(*header) <= LE16(header->file_hdr_sz) &&
         sizeof(chunk_header_t) <= LE16(header->chunk_hdr_sz) && LE32(header->blk_sz) % 4 == 0;
}

// Check that a sparse image header is valid, i.e. fields are set to reasonable values,
// and if it is valid copy the header to an aligned header struct.
//
// Returns true if the header is valid, false otherwise.
// The header output parameter is only valid if the function returns true.
static bool ValidateHeader(SparseIoBufferOps* handle_ops, SparseIoBufferHandle handle,
                           sparse_header_t* header) {
  return handle_ops->read(handle, 0, (uint8_t*)header, sizeof(*header)) &&
         IsValidFileHeader(header);
}

static bool ValidateChunkSize(const sparse_header_t* header, const chunk_header_t* chunk,
                              size_t payload_size) {
  return LE32(chunk->total_sz) == header->chunk_hdr_sz + payload_size;
}

int sparse_nop_logger(const char* msg, ...) { return 0; }

bool sparse_is_sparse_image(SparseIoBufferOps* handle_ops, SparseIoBufferHandle src) {
  if (handle_ops == NULL) {
    return false;
  }
  sparse_header_t header;
  return ValidateHeader(handle_ops, src, &header);
}

static bool sparse_write_fill(SparseIoInterface* io, SparseLogFn log, SparseIoBufferHandle src,
                              uint32_t fill, size_t out_offset, size_t write_bytes) {
  static bool fill_cache_valid = false;
  uint32_t tmp;
  if (!io->handle_ops.read(io->fill_handle, 0, (uint8_t*)&tmp, sizeof(tmp))) {
    log("Failed to read fill buffer\n");
    return false;
  }

  // Setup: populate the fill buffer with the fill data.
  if (!fill_cache_valid || tmp != fill) {
    // Minor optimization for repeated fill chunks with the same payload.
    fill_cache_valid = true;
    if (!io->handle_ops.fill(io->fill_handle, fill)) {
      log("Failed to populate fill buffer\n");
      return false;
    }
  }

  // Phase 1: write the entire fill buffer, possibly multiple times.
  // Remember that the fill buffer size must be a multiple of both the block size
  // and the storage buffer alignment.
  size_t fill_size = io->handle_ops.size(io->fill_handle);
  for (size_t i = 0; i < write_bytes / fill_size; i++, out_offset += fill_size) {
    if (!io->write(io->ctx, out_offset, io->fill_handle, 0, fill_size)) {
      log("Failed to write sparse fill block of size %z\n", fill_size);
      return false;
    }
  }

  // Phase 2: write the smaller-than-fill-buffer-sized remainder.
  size_t trailing_bytes = write_bytes % fill_size;
  if (trailing_bytes) {
    if (!io->write(io->ctx, out_offset, io->fill_handle, 0, trailing_bytes)) {
      log("Failed to write sparse fill chunk of size %z\n", trailing_bytes);
      return false;
    }
  }

  return true;
}

bool sparse_unpack_image(SparseIoInterface* io, SparseLogFn log, SparseIoBufferHandle src) {
  if (io == NULL || log == NULL) {
    return false;
  }
  const size_t size = io->handle_ops.size(src);

  sparse_header_t file_header;
  if (!io->handle_ops.read(src, 0, (uint8_t*)(&file_header), sizeof(sparse_header_t))) {
    log("Failed to read image header\n");
    return false;
  }
  if (!IsValidFileHeader(&file_header)) {
    log("invalid sparse image header: ");
    DumpStruct(log, &file_header, sizeof(file_header));
    return false;
  }

  uint64_t in_offset = file_header.file_hdr_sz;
  uint64_t out_offset = 0;
  for (size_t i = 0; i < LE32(file_header.total_chunks); i++) {
    if (in_offset + sizeof(chunk_header_t) > size) {
      log("Chunk header exceeds handle length\n");
      return false;
    }
    chunk_header_t chunk;
    if (!io->handle_ops.read(src, in_offset, (uint8_t*)(&chunk), sizeof(chunk_header_t))) {
      log("Failed to read chunk header\n");
      return false;
    }

    in_offset += LE16(file_header.chunk_hdr_sz);

    switch (LE16(chunk.chunk_type)) {
      case CHUNK_TYPE_RAW:
        if (!ValidateChunkSize(&file_header, &chunk,
                               (size_t)LE32(file_header.blk_sz) * LE32(chunk.chunk_sz))) {
          log("inconsistent chunk size for chunk: ");
          DumpStruct(log, &chunk, sizeof(chunk));
          return false;
        }

        size_t data_len = (size_t)LE32(chunk.chunk_sz) * LE32(file_header.blk_sz);
        if (in_offset + data_len > size) {
          log("chunk exceeds handle length\n");
          return false;
        }
        if (!io->write(io->ctx, out_offset, src, in_offset, data_len)) {
          log("Failed to write %lu @ %lu from %lu\n", data_len, out_offset, in_offset);
          return false;
        }
        in_offset += data_len;
        out_offset += data_len;
        break;
      case CHUNK_TYPE_DONT_CARE:
        if (!ValidateChunkSize(&file_header, &chunk, 0)) {
          log("inconsistent chunk size for chunk: ");
          DumpStruct(log, &chunk, sizeof(chunk));
          return false;
        }
        out_offset += (size_t)LE32(chunk.chunk_sz) * LE32(file_header.blk_sz);
        break;
      case CHUNK_TYPE_FILL:
        if (!ValidateChunkSize(&file_header, &chunk, sizeof(uint32_t))) {
          log("inconsistent chunk size for chunk: ");
          DumpStruct(log, &chunk, sizeof(chunk));
          return false;
        }

        uint32_t fill;
        if (in_offset + sizeof(fill) > size) {
          log("chunk exceeds handle length\n");
          return false;
        }
        if (!io->handle_ops.read(src, in_offset, (uint8_t*)&fill, sizeof(fill))) {
          log("Failed to read fill word\n");
          return false;
        }
        fill = LE32(fill);
        in_offset += sizeof(fill);

        size_t write_size = LE32(file_header.blk_sz) * LE32(chunk.chunk_sz);
        if (!sparse_write_fill(io, log, src, fill, out_offset, write_size)) {
          return false;
        }
        out_offset += write_size;
        break;
      case CHUNK_TYPE_CRC32:
        if (!ValidateChunkSize(&file_header, &chunk, sizeof(uint32_t))) {
          log("inconsistent chunk size for chunk: ");
          DumpStruct(log, &chunk, sizeof(chunk));
          return false;
        }
        // Ignore CRC32 chunks for the time being
        in_offset += sizeof(uint32_t);
        break;
      default:
        log("unexpected chunk type: 0x%08X\n", LE16(chunk.chunk_type));
        return false;
    }
  }

  return true;
}
