/*
 * Copyright (C) 2015 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 <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>

#include <fs_mgr.h>
#include <hardware/hardware.h>
#include <hardware/boot_control.h>

#include "bootinfo.h"

void module_init(boot_control_module_t *module)
{
}

unsigned module_getNumberSlots(boot_control_module_t *module)
{
  return 2;
}

static bool get_dev_t_for_partition(const char *name, dev_t *out_device)
{
  int fd;
  struct stat statbuf;

  fd = boot_info_open_partition(name, NULL, O_RDONLY);
  if (fd == -1)
    return false;
  if (fstat(fd, &statbuf) != 0) {
    fprintf(stderr, "WARNING: Error getting information about part %s: %s\n",
            name, strerror(errno));
    close(fd);
    return false;
  }
  close(fd);
  *out_device = statbuf.st_rdev;
  return true;
}

unsigned module_getCurrentSlot(boot_control_module_t *module)
{
  struct stat statbuf;
  dev_t system_a_dev, system_b_dev;

  if (stat("/system", &statbuf) != 0) {
    fprintf(stderr, "WARNING: Error getting information about /system: %s\n",
            strerror(errno));
    return 0;
  }

  if (!get_dev_t_for_partition("system_a", &system_a_dev) ||
      !get_dev_t_for_partition("system_b", &system_b_dev))
    return 0;

  if (statbuf.st_dev == system_a_dev) {
    return 0;
  } else if (statbuf.st_dev == system_b_dev) {
    return 1;
  } else {
    fprintf(stderr, "WARNING: Error determining current slot "
            "(/system dev_t of %d:%d does not match a=%d:%d or b=%d:%d)\n",
            major(statbuf.st_dev), minor(statbuf.st_dev),
            major(system_a_dev), minor(system_a_dev),
            major(system_b_dev), minor(system_b_dev));
    return 0;
  }
}

int module_markBootSuccessful(boot_control_module_t *module)
{
  return 0;
}

#define COPY_BUF_SIZE (1024*1024)

static bool copy_data(int src_fd, int dst_fd, size_t num_bytes)
{
  char copy_buf[COPY_BUF_SIZE];
  size_t remaining;

  remaining = num_bytes;
  while (remaining > 0) {
    size_t num_to_read = remaining > COPY_BUF_SIZE ? COPY_BUF_SIZE : remaining;
    ssize_t num_read;
    do {
      num_read = read(src_fd, copy_buf, num_to_read);
    } while (num_read == -1 && errno == EINTR);
    if (num_read <= 0) {
      fprintf(stderr, "Error reading %zd bytes from source: %s\n",
              num_to_read, strerror(errno));
      return false;
    }
    size_t num_to_write = num_read;
    while (num_to_write > 0) {
      size_t offset = num_read - num_to_write;
      ssize_t num_written;
      do {
        num_written = write(dst_fd, copy_buf + offset, num_to_write);
      } while (num_written == -1 && errno == EINTR);
      if (num_written <= 0) {
        fprintf(stderr, "Error writing %zd bytes to destination: %s\n",
                num_to_write, strerror(errno));
        return false;
      }
      num_to_write -= num_written;
    }
    remaining -= num_read;
  }

  return true;
}

int module_setActiveBootSlot(boot_control_module_t *module, unsigned slot)
{
  BrilloBootInfo info;
  int src_fd, dst_fd;
  uint64_t src_size, dst_size;
  char src_name[32];

  if (slot >= 2)
    return -EINVAL;

  if (!boot_info_load(&info)) {
    fprintf(stderr, "WARNING: Error loading boot-info. Resetting.\n");
    boot_info_reset(&info);
  } else {
    if (!boot_info_validate(&info)) {
      fprintf(stderr, "WARNING: boot-info is invalid. Resetting.\n");
      boot_info_reset(&info);
    }
  }

  info.active_slot = slot;
  info.slot_info[slot].bootable = true;
  snprintf(info.bootctrl_suffix,
           sizeof(info.bootctrl_suffix),
           "_%c", slot + 'a');

  if (!boot_info_save(&info)) {
    fprintf(stderr, "Error saving boot-info.\n");
    return -errno;
  }

  // Finally copy the contents of boot_X into boot.
  snprintf(src_name, sizeof(src_name), "boot_%c", slot + 'a');
  src_fd = boot_info_open_partition(src_name, &src_size, O_RDONLY);
  if (src_fd == -1) {
    fprintf(stderr, "Error opening \"%s\" partition.\n", src_name);
    return -errno;
  }

  dst_fd = boot_info_open_partition("boot", &dst_size, O_RDWR);
  if (dst_fd == -1) {
    fprintf(stderr, "Error opening \"boot\" partition.\n");
    close(src_fd);
    return -errno;
  }

  if (src_size != dst_size) {
    fprintf(stderr,
            "src (%" PRIu64 " bytes) and dst (%" PRIu64 " bytes) "
            "have different sizes.\n",
            src_size, dst_size);
    close(src_fd);
    close(dst_fd);
    return -EINVAL;
  }

  if (!copy_data(src_fd, dst_fd, src_size)) {
    close(src_fd);
    close(dst_fd);
    return -errno;
  }

  if (fsync(dst_fd) != 0) {
    fprintf(stderr, "Error calling fsync on destination: %s\n",
            strerror(errno));
    return -errno;
  }

  close(src_fd);
  close(dst_fd);
  return 0;
}

int module_setSlotAsUnbootable(struct boot_control_module *module, unsigned slot)
{
  BrilloBootInfo info;

  if (slot >= 2)
    return -EINVAL;

  if (!boot_info_load(&info)) {
    fprintf(stderr, "WARNING: Error loading boot-info. Resetting.\n");
    boot_info_reset(&info);
  } else {
    if (!boot_info_validate(&info)) {
      fprintf(stderr, "WARNING: boot-info is invalid. Resetting.\n");
      boot_info_reset(&info);
    }
  }

  info.slot_info[slot].bootable = false;

  if (!boot_info_save(&info)) {
    fprintf(stderr, "Error saving boot-info.\n");
    return -errno;
  }

  return 0;
}

int module_isSlotBootable(struct boot_control_module *module, unsigned slot)
{
  BrilloBootInfo info;

  if (slot >= 2)
    return -EINVAL;

  if (!boot_info_load(&info)) {
    fprintf(stderr, "WARNING: Error loading boot-info. Resetting.\n");
    boot_info_reset(&info);
  } else {
    if (!boot_info_validate(&info)) {
      fprintf(stderr, "WARNING: boot-info is invalid. Resetting.\n");
      boot_info_reset(&info);
    }
  }

  return info.slot_info[slot].bootable;
}

const char* module_getSuffix(boot_control_module_t *module, unsigned slot)
{
  static const char* suffix[2] = {"_a", "_b"};
  if (slot >= 2)
    return NULL;
  return suffix[slot];
}

static struct hw_module_methods_t module_methods = {
  .open  = NULL,
};


/* This boot_control HAL implementation emulates A/B by copying the
 * contents of the boot partition of the requested slot to the boot
 * partition. It hence works with bootloaders that are not yet aware
 * of A/B. This code is only intended to be used for development.
 */

boot_control_module_t HAL_MODULE_INFO_SYM = {
  .common = {
    .tag                 = HARDWARE_MODULE_TAG,
    .module_api_version  = BOOT_CONTROL_MODULE_API_VERSION_0_1,
    .hal_api_version     = HARDWARE_HAL_API_VERSION,
    .id                  = BOOT_CONTROL_HARDWARE_MODULE_ID,
    .name                = "Copy Implementation of boot_control HAL",
    .author              = "The Android Open Source Project",
    .methods             = &module_methods,
  },
  .init                 = module_init,
  .getNumberSlots       = module_getNumberSlots,
  .getCurrentSlot       = module_getCurrentSlot,
  .markBootSuccessful   = module_markBootSuccessful,
  .setActiveBootSlot    = module_setActiveBootSlot,
  .setSlotAsUnbootable  = module_setSlotAsUnbootable,
  .isSlotBootable       = module_isSlotBootable,
  .getSuffix            = module_getSuffix,
};
