// Copyright 2019 The Chromium OS 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 <stdint.h>
#include <stdlib.h>

#include <string>

#include <base/command_line.h>
#include <base/logging.h>
#include <base/time/time.h>
#include <base/timer/elapsed_timer.h>
#include <brillo/daemons/daemon.h>
#include <brillo/flag_helper.h>
#include <brillo/syslog_logging.h>
#include <base/strings/stringprintf.h>
#include <cros_config/cros_config.h>

#include "biod/biod_metrics.h"
#include "biod/biod_version.h"
#include "biod/cros_fp_device.h"
#include "biod/cros_fp_updater.h"
#include "biod/update_reason.h"

using UpdateStatus = biod::updater::UpdateStatus;
using UpdateReason = biod::updater::UpdateReason;
using FwUpdaterStatus = biod::BiodMetrics::FwUpdaterStatus;
using FindFirmwareFileStatus = biod::updater::FindFirmwareFileStatus;

namespace {

constexpr char kHelpText[] =
    "bio_fw_updater ensures the fingerprint mcu has the latest firmware\n";

void LogFWFileVersion(const biod::CrosFpFirmware& fw) {
  biod::CrosFpFirmware::ImageVersion ver = fw.GetVersion();
  LOG(INFO) << "FWFile RO Version: '" << ver.ro_version << "'";
  LOG(INFO) << "FWFile RW Version: '" << ver.rw_version << "'";
}

void LogFPMCUVersion(const biod::CrosFpDevice::EcVersion& ver) {
  LOG(INFO) << "FPMCU RO Version: '" << ver.ro_version << "'";
  LOG(INFO) << "FPMCU RW Version: '" << ver.rw_version << "'";
  LOG(INFO) << "FPMCU Active Image: "
            << biod::CrosFpDeviceUpdate::EcCurrentImageToString(
                   ver.current_image);
}

void LogSetupDirectory(const base::FilePath& log_dir_path) {
  const auto log_file_path = log_dir_path.Append(base::StringPrintf(
      "bio_fw_updater.%s",
      brillo::GetTimeAsLogString(base::Time::Now()).c_str()));

  brillo::UpdateLogSymlinks(log_dir_path.Append("bio_fw_updater.LATEST"),
                            log_dir_path.Append("bio_fw_updater.PREVIOUS"),
                            log_file_path);

  logging::LoggingSettings logging_settings;
  logging_settings.logging_dest = logging::LOG_TO_FILE;
  logging_settings.log_file = log_file_path.value().c_str();
  logging_settings.lock_log = logging::DONT_LOCK_LOG_FILE;
  logging::InitLogging(logging_settings);
  logging::SetLogItems(true,    // process ID
                       true,    // thread ID
                       true,    // timestamp
                       false);  // tickcount
}

class UpdaterMetrics {
 public:
  void SetUpdateReason(UpdateReason reason) { update_reason_ = reason; }
  void Finished(FwUpdaterStatus status) {
    uint64_t overall = runtime_.Elapsed().InMilliseconds();
    DLOG(INFO) << "Runtime took " << overall << "ms.";
    metrics_.SendFwUpdaterStatus(status, update_reason_,
                                 static_cast<int>(overall));
  }

 private:
  biod::BiodMetrics metrics_;
  UpdateReason update_reason_ = UpdateReason::kNone;
  base::ElapsedTimer runtime_;
};

}  // namespace

int main(int argc, char* argv[]) {
  UpdaterMetrics metrics;

  DEFINE_string(log_dir, "/var/log/biod", "Directory where logs are written.");
  brillo::FlagHelper::Init(argc, argv, kHelpText);

  const auto log_dir_path = base::FilePath(FLAGS_log_dir);
  if (base::DirectoryExists(log_dir_path)) {
    LogSetupDirectory(log_dir_path);
  } else {
    LOG(ERROR) << "Log directory '" << log_dir_path.value()
               << "' does not exist, using syslog and stderr logging.";
    brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderrIfTty |
                    brillo::kLogHeader);
  }

  biod::LogVersion();

  // Check for firmware disable mechanism
  if (biod::updater::UpdateDisallowed()) {
    LOG(INFO) << "FPMCU update disabled, exiting.";
    return EXIT_SUCCESS;
  }

  // Check if model supports fingerprint
  brillo::CrosConfig cros_config;
  if (!cros_config.Init()) {
    LOG(WARNING) << "Cros config is not supported on this model, continuing "
                    "with legacy update.";
  }
  if (biod::updater::FingerprintUnsupported(&cros_config)) {
    LOG(INFO) << "Fingerprint is not supported on this model, exiting.";
    return EXIT_SUCCESS;
  }

  // Find a firmware file that matches the firmware file pattern
  base::FilePath file;
  auto status = biod::updater::FindFirmwareFile(
      base::FilePath(biod::updater::kFirmwareDir), &cros_config, &file);

  if (status == FindFirmwareFileStatus::kNoDirectory ||
      status == FindFirmwareFileStatus::kFileNotFound) {
    LOG(INFO) << "No firmware "
              << ((status == FindFirmwareFileStatus::kNoDirectory) ? "directory"
                                                                   : "file")
              << " on rootfs, exiting.";

    return EXIT_SUCCESS;
  }
  if (status == FindFirmwareFileStatus::kMultipleFiles) {
    LOG(ERROR) << "Found more than one firmware file, aborting.";
    metrics.Finished(FwUpdaterStatus::kFailureFirmwareFileMultiple);
    return EXIT_FAILURE;
  }

  biod::CrosFpFirmware fw(file);
  if (!fw.IsValid()) {
    LOG(ERROR) << "Failed to load firmware file '" << fw.GetPath().value()
               << "': " << fw.GetStatusString();
    LOG(ERROR) << "We are aborting update.";
  }
  switch (fw.GetStatus()) {
    case biod::CrosFpFirmware::Status::kUninitialized:
      NOTREACHED();
      return EXIT_FAILURE;
    case biod::CrosFpFirmware::Status::kOk:
      break;
    case biod::CrosFpFirmware::Status::kNotFound:
      metrics.Finished(FwUpdaterStatus::kFailureFirmwareFileNotFound);
      return EXIT_FAILURE;
    case biod::CrosFpFirmware::Status::kOpenError:
      metrics.Finished(FwUpdaterStatus::kFailureFirmwareFileOpen);
      return EXIT_FAILURE;
    case biod::CrosFpFirmware::Status::kBadFmap:
      metrics.Finished(FwUpdaterStatus::kFailureFirmwareFileFmap);
      return EXIT_FAILURE;
  }
  LogFWFileVersion(fw);

  biod::CrosFpDeviceUpdate ec_device;
  biod::CrosFpBootUpdateCtrl boot_ctrl;

  biod::CrosFpDevice::EcVersion ecver;
  if (!ec_device.GetVersion(&ecver)) {
    LOG(INFO) << "Failed to fetch EC version, aborting.";
    metrics.Finished(FwUpdaterStatus::kFailurePreUpdateVersionCheck);
    return EXIT_FAILURE;
  }
  LogFPMCUVersion(ecver);

  auto result = biod::updater::DoUpdate(ec_device, boot_ctrl, fw);
  metrics.SetUpdateReason(result.reason);
  switch (result.status) {
    case UpdateStatus::kUpdateFailedGetVersion:
      LOG(INFO) << "Failed to fetch EC version, aborting.";
      metrics.Finished(FwUpdaterStatus::kFailureUpdateVersionCheck);
      return EXIT_FAILURE;
    case UpdateStatus::kUpdateFailedFlashProtect:
      LOG(ERROR) << "Failed to fetch flash protect status, aborting.";
      metrics.Finished(FwUpdaterStatus::kFailureUpdateFlashProtect);
      return EXIT_FAILURE;
    case UpdateStatus::kUpdateFailedRO:
      LOG(ERROR) << "Failed to update RO image, aborting.";
      metrics.Finished(FwUpdaterStatus::kFailureUpdateRO);
      return EXIT_FAILURE;
    case UpdateStatus::kUpdateFailedRW:
      LOG(ERROR) << "Failed to update RW image, aborting.";
      metrics.Finished(FwUpdaterStatus::kFailureUpdateRW);
      return EXIT_FAILURE;
    case UpdateStatus::kUpdateSucceeded:
      if (!ec_device.GetVersion(&ecver)) {
        LOG(ERROR) << "Failed to fetch final EC version, update failed.";
        metrics.Finished(FwUpdaterStatus::kFailurePostUpdateVersionCheck);
        return EXIT_FAILURE;
      }
      LogFPMCUVersion(ecver);
      LOG(INFO) << "The update was successful.";
      metrics.Finished(FwUpdaterStatus::kSuccessful);
      return EXIT_SUCCESS;
    case UpdateStatus::kUpdateNotNecessary:
      LOG(INFO) << "Update was not necessary.";
      metrics.Finished(FwUpdaterStatus::kUnnecessary);
      return EXIT_SUCCESS;
  }

  NOTREACHED();
  return EXIT_SUCCESS;
}
