/*
 * 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,
};
