// Copyright 2020 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <lib/boot-options/boot-options.h>
#include <lib/boot-options/types.h>
#include <lib/debuglog.h>
#include <platform.h>
#include <string.h>
#include <zircon/boot/crash-reason.h>
#include <zircon/compiler.h>

#include <kernel/mutex.h>
#include <ktl/array.h>
#include <object/root_job_observer.h>
#include <platform/halt_helper.h>
#include <platform/halt_token.h>

#include <ktl/enforce.h>

namespace {

DECLARE_SINGLETON_MUTEX(CriticalProcessNameLock);
char gCriticalProcessName[ZX_MAX_NAME_LEN] __TA_GUARDED(CriticalProcessNameLock::Get());
zx_koid_t gCriticalProcessKoid __TA_GUARDED(CriticalProcessNameLock::Get()) = ZX_KOID_INVALID;

// May or may not return.
void Halt() {
  const char* notice = gBootOptions->root_job_notice.data();
  if (!HaltToken::Get().Take()) {
    printf("root-job: halt/reboot already in progress; returning\n");
    return;
  }
  // We now have the halt token so we're committed.  There is no return from this point.

  if (strlen(notice) != 0) {
    printf("root-job: notice: %s\n", notice);
  }

  ktl::string_view action_name;
  platform_halt_action action;
  switch (gBootOptions->root_job_behavior) {
    case RootJobBehavior::kHalt:
      action = HALT_ACTION_HALT;
      action_name = kRootJobBehaviorHaltName;
      break;
    case RootJobBehavior::kBootloader:
      action = HALT_ACTION_REBOOT_BOOTLOADER;
      action_name = kRootJobBehaviorBootloaderName;
      break;
    case RootJobBehavior::kRecovery:
      action = HALT_ACTION_REBOOT_RECOVERY;
      action_name = kRootJobBehaviorRecoveryName;
      break;
    case RootJobBehavior::kShutdown:
      action = HALT_ACTION_SHUTDOWN;
      action_name = kRootJobBehaviorShutdownName;
      break;
    case RootJobBehavior::kReboot:
    default:
      action = HALT_ACTION_REBOOT;
      action_name = kRootJobBehaviorRebootName;
      break;
  }

  printf("root-job: taking %s action\n", action_name.data());
  const zx_time_t dlog_deadline = current_time() + ZX_SEC(5);
  dlog_shutdown(dlog_deadline);
  // Does not return.
  platform_halt(action, ZirconCrashReason::UserspaceRootJobTermination);
}

}  // anonymous namespace

RootJobObserver::RootJobObserver(fbl::RefPtr<JobDispatcher> root_job, Handle* root_job_handle_)
    : RootJobObserver(ktl::move(root_job), root_job_handle_, Halt) {}

RootJobObserver::RootJobObserver(fbl::RefPtr<JobDispatcher> root_job, Handle* root_job_handle,
                                 RootJobObserver::Callback callback)
    : root_job_(ktl::move(root_job)), callback_(ktl::move(callback)) {
  root_job_->AddObserver(this, root_job_handle, ZX_JOB_NO_CHILDREN);
}

RootJobObserver::~RootJobObserver() { root_job_->RemoveObserver(this); }

void RootJobObserver::OnMatch(zx_signals_t signals) {
  // Remember, the |root_job_|'s Dispatcher lock is held for the duration of
  // this method.  Take care to avoid calling anything that might attempt to
  // acquire that lock.
  callback_();
}

void RootJobObserver::OnCancel(zx_signals_t signals) {}

void RootJobObserver::CriticalProcessKill(fbl::RefPtr<ProcessDispatcher> dead_process) {
  Guard<Mutex> guard(CriticalProcessNameLock::Get());
  if (gCriticalProcessKoid == ZX_KOID_INVALID) {
    dead_process->get_name(gCriticalProcessName);
    gCriticalProcessKoid = dead_process->get_koid();
  }
}

ktl::array<char, ZX_MAX_NAME_LEN> RootJobObserver::GetCriticalProcessName() {
  Guard<Mutex> guard(CriticalProcessNameLock::Get());
  return ktl::to_array(gCriticalProcessName);
}

zx_koid_t RootJobObserver::GetCriticalProcessKoid() {
  Guard<Mutex> guard(CriticalProcessNameLock::Get());
  return gCriticalProcessKoid;
}
