// Copyright 2021 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.

// Main HPS class.

#include <algorithm>
#include <fstream>
#include <optional>
#include <vector>

#include <base/strings/string_number_conversions.h>
#include <base/files/file.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>
#include <base/timer/elapsed_timer.h>
#include <lzma.h>

#include "hps/hps_impl.h"
#include "hps/hps_reg.h"
#include "hps/utils.h"

namespace hps {
namespace {

// Observed times are
// MCU: ~4ms for a normal write, ~27ms for a erase write
// SPI: 3ms for a normal write, 250ms for a erase write
// 5000ms for the full erase
// Theoretical max time for SPI flash full erase is 120s
// Set the sleep to ~1/5 of the normal time, and the timeout to 2x the
// expected max time. TODO(evanbenn) only do the long timeout for the
// first spi write.
static constexpr base::TimeDelta kBankReadySleep = base::Microseconds(500);
static constexpr base::TimeDelta kBankReadyTimeout = base::Seconds(240);

// After reset, we poll the magic number register for this long.
// Observed time is 1000ms.
static constexpr base::TimeDelta kMagicSleep = base::Milliseconds(100);
static constexpr base::TimeDelta kMagicTimeout = base::Milliseconds(3000);

// After requesting application launch, we must wait for verification
// Observed time is 100 seconds.
static constexpr base::TimeDelta kApplTimeout = base::Milliseconds(200000);
static constexpr base::TimeDelta kApplSleep = base::Milliseconds(1000);

// Time from powering on the sensor to it becoming ready for communication.
static constexpr base::TimeDelta kPowerOnDelay = base::Milliseconds(1000);

// Time for letting the sensor settle after powering it off.
static constexpr base::TimeDelta kPowerOffDelay = base::Milliseconds(100);

// If the system is suspended for longer than this, we consider it a system
// suspend event.
static constexpr base::TimeDelta kSuspendThreshold = base::Milliseconds(1000);

// Special exit code to prevent upstart respawning us and crash
// service-failure-hpsd from being uploaded. See normal exit.
static constexpr int kNoRespawnExit = 5;

base::TimeDelta GetTime(clockid_t clk_id) {
  struct timespec ts = {};
  CHECK_EQ(clock_gettime(clk_id, &ts), 0);
  return base::TimeDelta::FromTimeSpec(ts);
}

}  // namespace

// Initialise the firmware parameters.
void HPS_impl::Init(uint32_t stage1_version,
                    const base::FilePath& mcu,
                    const base::FilePath& fpga_bitstream,
                    const base::FilePath& fpga_app_image) {
  this->required_stage1_version_ = stage1_version;
  this->mcu_blob_ = mcu;
  this->fpga_bitstream_ = fpga_bitstream;
  this->fpga_app_image_ = fpga_app_image;
}

// Attempt the boot sequence
void HPS_impl::Boot() {
  // Make sure blobs are set etc.
  if (this->mcu_blob_.empty() || this->fpga_bitstream_.empty() ||
      this->fpga_app_image_.empty()) {
    LOG(FATAL) << "No HPS firmware to download.";
  }

  this->boot_start_suspend_time_ = GetSystemSuspendTime();

  // If the boot process sent an update, reboot and try again
  // A full update takes 3 boots, so try 3 times.
  constexpr int kMaxBootAttempts = 3;
  for (int i = 0; i < kMaxBootAttempts; ++i) {
    if (!this->Reboot()) {
      LOG(INFO) << "Reboot failed, retrying";
      i = -1;
      continue;
    }
    if (!i)
      this->boot_start_time_ = base::TimeTicks::Now();

    switch (this->TryBoot()) {
      case BootResult::kOk:
        LOG(INFO) << "HPS device booted";
        return;
      case BootResult::kUpdate:
        LOG(INFO) << "Update sent, rebooting";
        continue;
      case BootResult::kRetry: {
        LOG(INFO) << "Transient boot failure, retrying";
        i = -1;
        continue;
      }
    }
  }
  OnFatalError(FROM_HERE, "Boot failure, too many updates.");
}

bool HPS_impl::Enable(uint8_t feature) {
  DCHECK(wake_lock_);
  // Only 2 features available at the moment.
  if (feature >= kFeatures) {
    LOG(ERROR) << "Enabling unknown feature (" << static_cast<int>(feature)
               << ")";
    return false;
  }
  // Check the application is enabled and running.
  std::optional<uint16_t> status = this->device_->ReadReg(HpsReg::kSysStatus);
  if (!status || !(status.value() & R2::kAppl)) {
    LOG(ERROR) << "Module not ready for feature control";
    return false;
  }
  this->feat_enabled_ |= 1 << feature;
  // Write the enable feature mask.
  return this->device_->WriteReg(HpsReg::kFeatEn, this->feat_enabled_);
}

bool HPS_impl::Disable(uint8_t feature) {
  DCHECK(wake_lock_);
  if (feature >= kFeatures) {
    LOG(ERROR) << "Disabling unknown feature (" << static_cast<int>(feature)
               << ")";
    return false;
  }
  // Check the application is enabled and running.
  std::optional<uint16_t> status = this->device_->ReadReg(HpsReg::kSysStatus);
  if (!status || !(status.value() & R2::kAppl)) {
    LOG(ERROR) << "Module not ready for feature control";
    return false;
  }
  this->feat_enabled_ &= ~(1 << feature);
  // Write the enable feature mask.
  return this->device_->WriteReg(HpsReg::kFeatEn, this->feat_enabled_);
}

FeatureResult HPS_impl::Result(int feature) {
  DCHECK(wake_lock_);
  // Check the application is enabled and running.
  std::optional<uint16_t> status = this->device_->ReadReg(HpsReg::kSysStatus);
  if (!status || !(status.value() & R2::kAppl)) {
    return {.valid = false};
  }
  // Check that feature is enabled.
  if (((1 << feature) & this->feat_enabled_) == 0) {
    return {.valid = false};
  }
  std::optional<uint16_t> hps_result = std::nullopt;
  switch (feature) {
    case 0:
      hps_result = this->device_->ReadReg(HpsReg::kFeature0);
      break;
    case 1:
      hps_result = this->device_->ReadReg(HpsReg::kFeature1);
      break;
  }
  if (!hps_result) {
    return {.valid = false};
  }
  // TODO(slangley): Clean this up when we introduce sequence numbers for
  // inference results.
  FeatureResult result;
  result.valid = (hps_result.value() & RFeat::kValid) == RFeat::kValid;
  hps_metrics_->SendImageValidity(result.valid);

  // The lower 8 bits are an int8_t.
  // We are extracting that byte here, not converting the uint16_t.
  result.inference_result = static_cast<int8_t>(hps_result.value() & 0xFF);
  return result;
}

// Attempt the boot sequence:
// Check stage0 flags, send a MCU update, fail or continue
// Check stage1 flags, fail or continue
// Check stage2 flags, send a SPI update or continue
// returns BootResult::kOk if booting completed
// returns BootResult::kUpdate if an update was sent
// returns BootResult::kRetry if we detect a transient error.
// else returns BootResult::kFail
hps::HPS_impl::BootResult HPS_impl::TryBoot() {
  // Inspect stage0 flags and either fail, update, or launch stage1 and continue
  switch (this->CheckStage0()) {
    case BootResult::kOk:
      VLOG(1) << "Launching stage 1";
      if (!this->device_->WriteReg(HpsReg::kSysCmd, R3::kLaunch1)) {
        OnFatalError(FROM_HERE, "Launch stage 1 failed");
      }
      break;
    // TODO(b/227977336): this will no longer be reachable when we drop support
    // for stage0 v3.
    case BootResult::kUpdate:
      if (mcu_update_sent_) {
        LOG(ERROR) << "Failed to boot after MCU update, giving up";
        hps_metrics_->SendHpsTurnOnResult(
            HpsTurnOnResult::kMcuUpdatedThenFailed,
            base::TimeTicks::Now() - this->boot_start_time_);
        exit(kNoRespawnExit);
      }
      mcu_update_sent_ = true;
      SendStage1Update();
      return BootResult::kUpdate;
    case BootResult::kRetry:
      return BootResult::kRetry;
  }

  // Inspect stage1 flags and either fail, update, or launch application and
  // continue
  switch (this->CheckStage1()) {
    case BootResult::kOk:
      VLOG(1) << "Launching Application";
      if (!this->device_->WriteReg(HpsReg::kSysCmd, R3::kLaunchAppl)) {
        OnFatalError(FROM_HERE, "Launch Application failed");
      }
      break;
    case BootResult::kUpdate:
      if (mcu_update_sent_) {
        LOG(ERROR) << "Failed to launch stage1 after MCU update, giving up";
        hps_metrics_->SendHpsTurnOnResult(
            HpsTurnOnResult::kMcuUpdatedThenFailed,
            base::TimeTicks::Now() - this->boot_start_time_);
        exit(kNoRespawnExit);
      }
      mcu_update_sent_ = true;
      VLOG(1) << "Rebooting back to stage0 before sending update";
      this->Reboot();
      if (!CheckMagic()) {
        hps_metrics_->SendHpsTurnOnResult(
            HpsTurnOnResult::kNoResponse,
            base::TimeTicks::Now() - this->boot_start_time_);
        OnFatalError(FROM_HERE, "Timeout waiting for stage0 magic number");
      }
      SendStage1Update();
      return BootResult::kUpdate;
    case BootResult::kRetry:
      return BootResult::kRetry;
  }

  // Inspect application flags and either fail, send an update, or succeed
  switch (this->CheckApplication()) {
    case BootResult::kOk:
      VLOG(1) << "Application Running";
      return BootResult::kOk;
    case BootResult::kUpdate:
      if (spi_update_sent_) {
        LOG(ERROR) << "Failed to boot after SPI update, giving up";
        hps_metrics_->SendHpsTurnOnResult(
            HpsTurnOnResult::kSpiUpdatedThenFailed,
            base::TimeTicks::Now() - this->boot_start_time_);
        exit(kNoRespawnExit);
      }
      spi_update_sent_ = true;
      SendApplicationUpdate();
      return BootResult::kUpdate;
    case BootResult::kRetry:
      return BootResult::kRetry;
  }
}

// Returns true if the device replies with the expected magic number in time.
// Attempts are made for kMagicTimeout time, with kMagicSleep delays between
// failures. Retries are only done for failed reads, not incorrect
// responses.
bool HPS_impl::CheckMagic() {
  base::ElapsedTimer timer;
  for (;;) {
    std::optional<uint16_t> magic = this->device_->ReadReg(HpsReg::kMagic);
    // Note that we don't treat a read failure here as a retryable transient
    // error, but rely on the caller to map a failure to an appropriate error.
    // In general failure to read the magic register is a fatal error, because
    // even a v3 stage0 should come online before this loop times out.
    if (!magic) {
      if (timer.Elapsed() < kMagicTimeout) {
        Sleep(kMagicSleep);
        continue;
      } else {
        return false;
      }
    } else if (magic == kHpsMagic) {
      VLOG(1) << "Good magic number after " << timer.Elapsed().InMilliseconds()
              << "ms";
      return true;
    } else {
      hps_metrics_->SendHpsTurnOnResult(
          HpsTurnOnResult::kBadMagic,
          base::TimeTicks::Now() - this->boot_start_time_);
      OnFatalError(FROM_HERE, base::StringPrintf("Bad magic number 0x%04x",
                                                 magic.value()));
    }
  }
}

// Check stage0 status:
// Check status flags.
// Read and store kHwRev.
// Check stage1 verification and version.
// Return BootResult::kOk if booting should continue.
// Return BootResult::kUpdate if an update should be sent.
// Return BootResult::kRetry if we detect a transient error.
hps::HPS_impl::BootResult HPS_impl::CheckStage0() {
  if (!CheckMagic()) {
    hps_metrics_->SendHpsTurnOnResult(
        HpsTurnOnResult::kNoResponse,
        base::TimeTicks::Now() - this->boot_start_time_);
    OnTransientBootFault(FROM_HERE, "Timeout waiting for stage0 magic number");
    return BootResult::kRetry;
  }

  std::optional<uint16_t> status = this->device_->ReadReg(HpsReg::kSysStatus);
  if (!status) {
    // TODO(evanbenn) log a metric
    OnTransientBootFault(FROM_HERE, "ReadReg failure");
    return BootResult::kRetry;
  }

  if (status.value() & R2::kFault || !(status.value() & R2::kOK)) {
    OnBootFault(FROM_HERE);
  }

  std::optional<uint16_t> hwrev = this->device_->ReadReg(HpsReg::kHwRev);
  if (!hwrev) {
    // TODO(evanbenn) log a metric
    OnTransientBootFault(FROM_HERE, "Failed to read hwrev");
    return BootResult::kRetry;
  }
  this->hw_rev_ = hwrev.value();

  if ((this->hw_rev_ & 0xff) >= 4) {
    // From version 4, stage0 does not validate stage1 after reset, nor does it
    // report the stage1 version. Instead it validates+launches stage1 when the
    // 'launch1' command is sent below.
    // It means we don't need to pay attention to the WP state, nor can we
    // determine whether a stage1 update is needed here. So there is nothing
    // more to do.
    return BootResult::kOk;
  }

  // Old logic for stage0 version 3 and earlier follows.
  // TODO(b/227977336): delete this when Taeko DVT is no longer in use.

  bool write_protect_off = status.value() & R2::kWpOff;
  VLOG_IF(1, write_protect_off) << "kWpOff, ignoring verified bits";

  // When write protect is off we ignore the verified signal.
  // When write protect is not off we update if there is no verified signal.
  if (!write_protect_off && !(status.value() & R2::kDeprecatedAVerify)) {
    // Stage1 not verified, so need to update it.
    LOG(INFO) << "Stage1 flash not verified";
    hps_metrics_->SendHpsTurnOnResult(
        HpsTurnOnResult::kMcuNotVerified,
        base::TimeTicks::Now() - this->boot_start_time_);
    return BootResult::kUpdate;
  }

  // Verified, so now check the version. If it is different, update it.
  return this->CheckStage1Version();
}

// Checks that stage1 version matches the version we expected.
// Returns BootResult::kOk if it does.
// Returns BootResult::kUpdate if it doesn't.
// Returns BootResult::kRetry if we detect a transient error.
//
// This is extracted to a helper function because it would normally be called
// during CheckStage1, but for the older boot flow (stage0 version 3 and older)
// it is done in CheckStage0 instead. We changed the behaviour so that stage1
// reports its own version after launch, stage0 doesn't report the stage1
// version anymore.
// TODO(b/227977336): This logic can be moved into CheckStage1 after we stop
// supporting stage0 v3.
hps::HPS_impl::BootResult HPS_impl::CheckStage1Version() {
  std::optional<uint16_t> version_low =
      this->device_->ReadReg(HpsReg::kFirmwareVersionLow);
  std::optional<uint16_t> version_high =
      this->device_->ReadReg(HpsReg::kFirmwareVersionHigh);
  if (!version_low || !version_high) {
    // TODO(evanbenn) log a metric
    OnTransientBootFault(FROM_HERE, "ReadReg failure");
    return BootResult::kRetry;
  }
  this->actual_stage1_version_ =
      static_cast<uint32_t>(version_high.value() << 16) | version_low.value();
  if (this->actual_stage1_version_ == this->required_stage1_version_) {
    // Stage 1 is verified
    VLOG(1) << "Stage1 version OK";
    return BootResult::kOk;
  } else {
    // Versions do not match, need to update.
    LOG(INFO) << "Stage1 version mismatch, module: "
              << this->actual_stage1_version_
              << " expected: " << this->required_stage1_version_;
    hps_metrics_->SendHpsTurnOnResult(
        HpsTurnOnResult::kMcuVersionMismatch,
        base::TimeTicks::Now() - this->boot_start_time_);
    return BootResult::kUpdate;
  }
}

// Check stage1 status:
// Check status flags.
// Check stage1 version.
// Check spi verification.
// Return BootResult::kOk if stage1 is running and up-to-date.
// Return BootResult::kUpdate if an update should be sent.
// Return BootResult::kRetry if we detect a transient error.
hps::HPS_impl::BootResult HPS_impl::CheckStage1() {
  if (!CheckMagic()) {
    hps_metrics_->SendHpsTurnOnResult(
        HpsTurnOnResult::kStage1NotStarted,
        base::TimeTicks::Now() - this->boot_start_time_);
    OnTransientBootFault(FROM_HERE, "Timeout waiting for stage1 magic number");
    return BootResult::kRetry;
  }

  std::optional<uint16_t> status = this->device_->ReadReg(HpsReg::kSysStatus);
  if (!status) {
    // TODO(evanbenn) log a metric
    OnTransientBootFault(FROM_HERE, "ReadReg failure");
    return BootResult::kRetry;
  }

  if (status.value() & R2::kFault || !(status.value() & R2::kOK)) {
    // If stage1 is blank/missing/out-of-date we will get one of the errors
    // related to stage1 validation after we tried to launch it.
    // Check for those first.
    std::optional<uint16_t> error = this->device_->ReadReg(HpsReg::kError);
    if (!error) {
      OnTransientBootFault(FROM_HERE, "ReadReg failure");
      return BootResult::kRetry;
    }
    if (error.value() == RError::kStage1NotFound ||
        error.value() == RError::kStage1TooOld ||
        error.value() == RError::kStage1InvalidSignature ||
        error.value() == RError::kMcuFlashEcc) {
      LOG(INFO) << "Stage1 flash not verified: "
                << HpsRegValToString(HpsReg::kError, error.value());
      hps_metrics_->SendHpsTurnOnResult(
          HpsTurnOnResult::kMcuNotVerified,
          base::TimeTicks::Now() - this->boot_start_time_);
      return BootResult::kUpdate;
    }
    // Any other error after launching stage1 is unexpected.
    OnBootFault(FROM_HERE);
  }

  if (!(status.value() & R2::kStage1)) {
    hps_metrics_->SendHpsTurnOnResult(
        HpsTurnOnResult::kStage1NotStarted,
        base::TimeTicks::Now() - this->boot_start_time_);
    if (status.value() & R2::kOneTimeInit) {
      // One-time-init is a special stage1 payload used by hps-factory.
      // If we see it, send an update to get back to the real stage1.
      return BootResult::kUpdate;
    }
    OnTransientBootFault(FROM_HERE, "Stage 1 did not start");
    return BootResult::kRetry;
  }
  VLOG(1) << "Stage 1 OK";

  return this->CheckStage1Version();
}

// Check stage2 status:
// Check status flags.
// Return BootResult::kOk if application is running.
// Return BootResult::kUpdate if an update should be sent.
// Return BootResult::kRetry if we detect a transient error.
hps::HPS_impl::BootResult HPS_impl::CheckApplication() {
  // Poll for kAppl (started) or kSpiNotVer (not started)
  base::ElapsedTimer timer;
  do {
    std::optional<uint16_t> status = this->device_->ReadReg(HpsReg::kSysStatus);
    if (!status) {
      // TODO(evanbenn) log a metric
      OnTransientBootFault(FROM_HERE, "ReadReg failure");
      return BootResult::kRetry;
    }
    if (status.value() & R2::kAppl) {
      VLOG(1) << "Application boot after " << timer.Elapsed().InMilliseconds()
              << "ms";
      hps_metrics_->SendHpsTurnOnResult(
          HpsTurnOnResult::kSuccess,
          base::TimeTicks::Now() - this->boot_start_time_);
      return BootResult::kOk;
    }

    std::optional<uint16_t> error = this->device_->ReadReg(HpsReg::kError);
    if (!error) {
      // TODO(evanbenn) log a metric
      OnTransientBootFault(FROM_HERE, "ReadReg failure");
      return BootResult::kRetry;
    }
    if (error.value() == RError::kSpiFlashNotVerified) {
      VLOG(1) << "SPI verification failed after "
              << timer.Elapsed().InMilliseconds() << "ms";
      hps_metrics_->SendHpsTurnOnResult(
          HpsTurnOnResult::kSpiNotVerified,
          base::TimeTicks::Now() - this->boot_start_time_);
      return BootResult::kUpdate;
    } else if (error.value()) {
      OnBootFault(FROM_HERE);
    }

    Sleep(kApplSleep);
  } while (timer.Elapsed() < kApplTimeout);

  hps_metrics_->SendHpsTurnOnResult(
      HpsTurnOnResult::kApplNotStarted,
      base::TimeTicks::Now() - this->boot_start_time_);
  OnTransientBootFault(FROM_HERE, "Application did not start");
  return BootResult::kRetry;
}

// Reboot the hardware module.
bool HPS_impl::Reboot() {
  if (wake_lock_)
    ShutDown();
  LOG(INFO) << "Starting HPS device";
  wake_lock_ = device_->CreateWakeLock();
  Sleep(kPowerOnDelay);

  // On some units, HPS fails to start reliably after powering on. Detect and
  // work around this by toggling the power gpio off and on again one extra
  // time. See b/228917921.
  if (!CheckMagic()) {
    LOG(ERROR) << "Unable to read magic number after powering on, retrying...";
    ShutDown();
    wake_lock_ = device_->CreateWakeLock();
    Sleep(kPowerOnDelay);
    if (!CheckMagic()) {
      hps_metrics_->SendHpsTurnOnResult(
          HpsTurnOnResult::kPowerOnRecoveryFailed,
          base::TimeTicks::Now() - this->boot_start_time_);
      OnFatalError(FROM_HERE, "HPS device recovery failed");
    } else {
      LOG(INFO) << "HPS device recovered";
      hps_metrics_->SendHpsTurnOnResult(
          HpsTurnOnResult::kPowerOnRecoverySucceeded, base::TimeDelta());
    }
  }

  // Also send a reset cmd in case the kernel driver isn't present.
  if (!this->device_->WriteReg(HpsReg::kSysCmd, R3::kReset)) {
    OnTransientBootFault(FROM_HERE, "Reboot failed");
    return false;
  }
  return true;
}

bool HPS_impl::ShutDown() {
  DCHECK(wake_lock_);
  LOG(INFO) << "Shutting down HPS device";
  wake_lock_.reset();
  feat_enabled_ = 0;
  Sleep(kPowerOffDelay);
  return true;
}

bool HPS_impl::IsRunning() {
  DCHECK(wake_lock_);
  // Check the application is enabled and running.
  std::optional<uint16_t> status = this->device_->ReadReg(HpsReg::kSysStatus);
  if (!status || !(status.value() & R2::kAppl)) {
    LOG(ERROR) << "Fault: application not running";
    return false;
  }

  // Check for errors.
  std::optional<uint16_t> errors = this->device_->ReadReg(HpsReg::kError);
  if (errors.has_value() && errors.value()) {
    std::string msg =
        "Error " + HpsRegValToString(HpsReg::kError, errors.value());
    OnFatalError(FROM_HERE, msg);
  }
  return true;
}

// Fault bit seen during boot, attempt to dump status information and abort.
// Only call this function in the boot process.
[[noreturn]] void HPS_impl::OnBootFault(const base::Location& location) {
  hps_metrics_->SendHpsTurnOnResult(
      HpsTurnOnResult::kFault, base::TimeTicks::Now() - this->boot_start_time_);
  OnFatalError(location, "Boot fault");
}

[[noreturn]] void HPS_impl::OnFatalError(const base::Location& location,
                                         const std::string& msg) {
  LOG(ERROR) << "Fatal error at " << location.ToString() << ": " << msg;
  LogStateOnError();
  LOG(FATAL) << "Terminating for fatal error at " << location.ToString() << ": "
             << msg;
  abort();
}

void HPS_impl::OnTransientBootFault(const base::Location& location,
                                    const std::string& msg) {
  LOG(WARNING) << "Boot attempt failed with transient error at "
               << location.ToString() << ": " << msg;
  base::TimeDelta suspend_time = GetSystemSuspendTime();
  // If the system got suspended during booting, HPS is now probably in an
  // indeterminate state. In this case, ignore transient errors and try booting
  // again from scratch, hoping we don't get interrupted again.
  if (suspend_time - boot_start_suspend_time_ > kSuspendThreshold) {
    boot_start_suspend_time_ = suspend_time;
    LOG(INFO) << "System suspend detected, retrying boot";
    return;
  }
  LogStateOnError();
  LOG(FATAL) << "Terminating for boot fault at " << location.ToString() << ": "
             << msg;
  abort();
}

void HPS_impl::LogStateOnError() {
  LOG(ERROR) << base::StringPrintf("- Requested feature status: 0x%04x",
                                   feat_enabled_);
  LOG(ERROR) << base::StringPrintf("- Stage1 rootfs version: 0x%08x",
                                   required_stage1_version_);
  LOG(ERROR) << base::StringPrintf("- Stage1 running version: 0x%08x",
                                   actual_stage1_version_);
  LOG(ERROR) << base::StringPrintf("- HW rev: 0x%04x", hw_rev_);
  LOG(ERROR) << base::StringPrintf("- Updates sent: mcu:%d spi:%d",
                                   mcu_update_sent_, spi_update_sent_);
  LOG(ERROR) << base::StringPrintf("- Wake lock: %d", !!wake_lock_);
  DumpHpsRegisters(*device_,
                   [](const std::string& s) { LOG(ERROR) << "- " << s; });
}

// Send the stage1 MCU flash update.
// Returns if update was sent
void HPS_impl::SendStage1Update() {
  LOG(INFO) << "Updating MCU flash";
  base::ElapsedTimer timer;
  if (this->Download(HpsBank::kMcuFlash, this->mcu_blob_)) {
    hps_metrics_->SendHpsUpdateDuration(HpsBank::kMcuFlash, timer.Elapsed());
  } else {
    hps_metrics_->SendHpsTurnOnResult(
        HpsTurnOnResult::kMcuUpdateFailure,
        base::TimeTicks::Now() - this->boot_start_time_);
    OnFatalError(FROM_HERE, "Failed sending stage1 update");
  }
}

// Send the Application SPI flash update.
// Returns kFail or kUpdate.
void HPS_impl::SendApplicationUpdate() {
  LOG(INFO) << "Updating SPI flash";
  base::ElapsedTimer timer;
  if (this->Download(HpsBank::kSpiFlash, this->fpga_bitstream_) &&
      this->Download(HpsBank::kSocRom, this->fpga_app_image_)) {
    hps_metrics_->SendHpsUpdateDuration(HpsBank::kSpiFlash, timer.Elapsed());
  } else {
    hps_metrics_->SendHpsTurnOnResult(
        HpsTurnOnResult::kSpiUpdateFailure,
        base::TimeTicks::Now() - this->boot_start_time_);
    OnFatalError(FROM_HERE, "Failed sending stage1 update");
  }
}

/*
 * Download data to the bank specified.
 * The HPS/Host I2C Interface Memory Write is used.
 */
bool HPS_impl::Download(hps::HpsBank bank, const base::FilePath& source) {
  DCHECK(wake_lock_);
  uint8_t ibank = static_cast<uint8_t>(bank);
  if (ibank >= kNumBanks) {
    LOG(ERROR) << "Download: Illegal bank: " << static_cast<int>(ibank) << ": "
               << source;
    return -1;
  }
  std::optional<std::vector<uint8_t>> contents = this->DecompressFile(source);
  if (!contents.has_value())
    return false;
  return this->WriteFile(ibank, source, contents.value());
}

std::optional<std::vector<uint8_t>> HPS_impl::DecompressFile(
    const base::FilePath& source) {
  std::string compressed_contents;
  if (!base::ReadFileToString(source, &compressed_contents)) {
    PLOG(ERROR) << "DecompressFile: \"" << source << "\": Reading failed";
    return std::nullopt;
  }

  if (source.FinalExtension() != ".xz") {
    // Assume it's not actually compressed and return its contents as is.
    std::vector<uint8_t> uncompressed(compressed_contents.begin(),
                                      compressed_contents.end());
    return std::make_optional(std::move(uncompressed));
  }

  std::vector<uint8_t> decompressed(2 * 1024 * 1024);  // max 2MB decompressed
  uint64_t memlimit = 20 * 1024 * 1024;  // limit decoder to allocating 20MB
  size_t in_pos = 0;
  size_t out_pos = 0;
  lzma_ret ret = lzma_stream_buffer_decode(
      &memlimit, /* flags */ 0, /* allocator */ nullptr,
      reinterpret_cast<const uint8_t*>(compressed_contents.data()), &in_pos,
      compressed_contents.size(), decompressed.data(), &out_pos,
      decompressed.size());
  if (ret != LZMA_OK) {
    LOG(ERROR) << "DecompressFile: \"" << source
               << "\": Decompressing failed with error " << ret;
    return std::nullopt;
  }
  decompressed.resize(out_pos);
  return std::make_optional(std::move(decompressed));
}

void HPS_impl::SetDownloadObserver(DownloadObserver observer) {
  this->download_observer_ = std::move(observer);
}

/*
 * Write the file to the bank indicated.
 */
bool HPS_impl::WriteFile(uint8_t bank,
                         const base::FilePath& source,
                         const std::vector<uint8_t>& contents) {
  switch (bank) {
    case static_cast<uint8_t>(HpsBank::kMcuFlash):
      if (!this->device_->WriteReg(HpsReg::kSysCmd, R3::kEraseStage1)) {
        LOG(ERROR) << "WriteFile: error erasing bank: "
                   << static_cast<int>(bank);
        return false;
      }
      break;
    case static_cast<uint8_t>(HpsBank::kSpiFlash):
      // Note that this also erases bank 2 (HpsBank::kSocRom)
      // because they are both on the same SPI flash!
      if (!this->device_->WriteReg(HpsReg::kSysCmd, R3::kEraseSpiFlash)) {
        LOG(ERROR) << "WriteFile: error erasing bank: "
                   << static_cast<int>(bank);
        return false;
      }
      break;
    case static_cast<uint8_t>(HpsBank::kSocRom):
      // Assume it was already erased by writing HpsBank::kSpiFlash before this.
      break;
  }
  if (!this->WaitForBankReady(bank)) {
    LOG(ERROR) << "WriteFile: bank " << static_cast<int>(bank)
               << " not ready after erase";
    return false;
  }
  base::ElapsedTimer timer;
  size_t block_size = this->device_->BlockSizeBytes();
  /*
   * Leave room for a 32 bit address at the start of the block to be written.
   * The address is updated for each block to indicate
   * where this block is to be written.
   * The format of the data block is:
   *    4 bytes of address in big endian format
   *    data
   */
  auto buf = std::make_unique<uint8_t[]>(block_size + sizeof(uint32_t));
  // Iterate over the firmware contents in blocks of *block_size* bytes.
  auto block_begin = contents.begin();
  while (block_begin != contents.end()) {
    // The current block ends after *block_size* bytes,
    // or at end of *contents* if there are fewer bytes remaining.
    auto block_end = std::distance(block_begin, contents.end()) >=
                             static_cast<std::ptrdiff_t>(block_size)
                         ? block_begin + block_size
                         : contents.end();
    // The address is just the offset of the current block from the beginning.
    uint32_t address =
        static_cast<uint32_t>(std::distance(contents.begin(), block_begin));
    buf[0] = address >> 24;
    buf[1] = (address >> 16) & 0xff;
    buf[2] = (address >> 8) & 0xff;
    buf[3] = address & 0xff;
    std::copy(block_begin, block_end, &buf[sizeof(uint32_t)]);
    size_t length = std::distance(block_begin, block_end) + sizeof(uint32_t);
    if (!this->device_->Write(I2cMemWrite(bank), &buf[0], length)) {
      LOG(ERROR) << "WriteFile: device write error. bank: "
                 << static_cast<int>(bank);
      return false;
    }
    // Wait for the bank to become ready, indicating that the previous write has
    // finished.
    if (!this->WaitForBankReady(bank)) {
      LOG(ERROR) << "WriteFile: bank " << static_cast<int>(bank)
                 << " not ready after write";
      return false;
    }
    if (download_observer_) {
      download_observer_.Run(source, static_cast<uint32_t>(contents.size()),
                             std::distance(contents.begin(), block_end),
                             timer.Elapsed());
    }
    block_begin = block_end;
  }
  VLOG(1) << "Wrote " << contents.size() << " bytes from " << source << " in "
          << timer.Elapsed().InMilliseconds() << "ms";
  return true;
}

bool HPS_impl::WaitForBankReady(uint8_t bank) {
  base::ElapsedTimer timer;
  do {
    std::optional<uint16_t> result = this->device_->ReadReg(HpsReg::kBankReady);
    if (result && (result.value() & (1 << bank))) {
      return true;
    }
    Sleep(kBankReadySleep);
  } while (timer.Elapsed() < kBankReadyTimeout);
  return false;
}

base::TimeDelta HPS_impl::GetSystemSuspendTime() {
  // Estimates how much time the system has spend in a suspended state since
  // boot. The boot time clock keeps running in suspend state while the
  // monotonic one pauses, so their difference gives an indication on the total
  // time spent suspended. Note that the returned absolute value is mostly
  // meaningless since the clocks likely have different epochs, but differences
  // in measurements taken at different points in time can estimate the time
  // spent suspended during that interval.
  return GetTime(CLOCK_BOOTTIME) - GetTime(CLOCK_MONOTONIC);
}

}  // namespace hps
