// Copyright 2016 The Fuchsia 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 <fidl/fuchsia.driver.index/cpp/wire.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <fuchsia/boot/cpp/fidl.h>
#include <fuchsia/kernel/cpp/fidl.h>
#include <getopt.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/io.h>
#include <lib/service/llcpp/service.h>
#include <lib/zx/event.h>
#include <lib/zx/port.h>
#include <lib/zx/resource.h>
#include <lib/zx/vmo.h>
#include <threads.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/object.h>
#include <zircon/syscalls/policy.h>
#include <zircon/types.h>

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <memory>

#include <fbl/string_printf.h>

#include "component_lifecycle.h"
#include "coordinator.h"
#include "devfs.h"
#include "driver_host_loader_service.h"
#include "fdio.h"
#include "lib/async/cpp/task.h"
#include "src/devices/bin/driver_manager/devfs_exporter.h"
#include "src/devices/bin/driver_manager/device_watcher.h"
#include "src/devices/bin/driver_manager/v2/driver_development_service.h"
#include "src/devices/lib/log/log.h"
#include "src/lib/storage/vfs/cpp/managed_vfs.h"
#include "src/lib/storage/vfs/cpp/pseudo_dir.h"
#include "src/lib/storage/vfs/cpp/remote_dir.h"
#include "src/lib/storage/vfs/cpp/vfs.h"
#include "src/lib/storage/vfs/cpp/vmo_file.h"
#include "src/sys/lib/stdout-to-debuglog/cpp/stdout-to-debuglog.h"
#include "system_instance.h"
#include "v2/driver_runner.h"

namespace {

#define DEVMGR_LAUNCHER_DEVFS_ROOT_HND PA_HND(PA_USER1, 0)
#define DEVMGR_LAUNCHER_OUTGOING_SERVICES_HND PA_HND(PA_USER1, 1)

// These are helpers for getting sets of parameters over FIDL
struct DriverManagerParams {
  bool enable_ephemeral;
  bool log_to_debuglog;
  bool require_system;
  bool suspend_timeout_fallback;
  bool verbose;
  DriverHostCrashPolicy crash_policy;
  std::string root_driver;
  bool use_dfv2;
};

DriverManagerParams GetDriverManagerParams(fidl::WireSyncClient<fuchsia_boot::Arguments>& client) {
  fuchsia_boot::wire::BoolPair bool_req[]{
      {"devmgr.enable-ephemeral", false}, {"devmgr.log-to-debuglog", false},
      {"devmgr.require-system", false},   {"devmgr.suspend-timeout-fallback", true},
      {"devmgr.verbose", false},          {"driver_manager.use_driver_framework_v2", false},
  };
  auto bool_resp =
      client->GetBools(fidl::VectorView<fuchsia_boot::wire::BoolPair>::FromExternal(bool_req));
  if (!bool_resp.ok()) {
    return {};
  }

  auto crash_policy = DriverHostCrashPolicy::kRestartDriverHost;
  auto response = client->GetString("driver-manager.driver-host-crash-policy");
  if (response.ok() && !response.value().value.is_null() && !response.value().value.empty()) {
    std::string crash_policy_str(response.value().value.get());
    if (crash_policy_str == "reboot-system") {
      crash_policy = DriverHostCrashPolicy::kRebootSystem;
    } else if (crash_policy_str == "restart-driver-host") {
      crash_policy = DriverHostCrashPolicy::kRestartDriverHost;
    } else if (crash_policy_str == "do-nothing") {
      crash_policy = DriverHostCrashPolicy::kDoNothing;
    } else {
      LOGF(ERROR, "Unexpected option for driver-manager.driver-host-crash-policy: %s",
           crash_policy_str.c_str());
    }
  }

  std::string root_driver = "";
  {
    auto response = client->GetString("driver_manager.root-driver");
    if (response.ok() && !response.value().value.is_null() && !response.value().value.empty()) {
      root_driver = std::string(response.value().value.data(), response.value().value.size());
    }
  }

  return {
      .enable_ephemeral = bool_resp.value().values[0],
      .log_to_debuglog = bool_resp.value().values[1],
      .require_system = bool_resp.value().values[2],
      .suspend_timeout_fallback = bool_resp.value().values[3],
      .verbose = bool_resp.value().values[4],
      .crash_policy = crash_policy,
      .root_driver = std::move(root_driver),
      .use_dfv2 = bool_resp.value().values[5],
  };
}

static const std::string kRootJobPath = "/svc/" + std::string(fuchsia::kernel::RootJob::Name_);
static const std::string kRootResourcePath =
    "/svc/" + std::string(fuchsia::boot::RootResource::Name_);

// Get the root job from the root job service.
zx_status_t get_root_job(zx::job* root_job) {
  fuchsia::kernel::RootJobSyncPtr root_job_ptr;
  zx_status_t status =
      fdio_service_connect(kRootJobPath.c_str(), root_job_ptr.NewRequest().TakeChannel().release());
  if (status != ZX_OK) {
    return status;
  }
  return root_job_ptr->Get(root_job);
}

// Get the root resource from the root resource service. Not receiving the
// startup handle is logged, but not fatal.  In test environments, it would not
// be present.
zx_status_t get_root_resource(zx::resource* root_resource) {
  fuchsia::boot::RootResourceSyncPtr root_resource_ptr;
  zx_status_t status = fdio_service_connect(kRootResourcePath.c_str(),
                                            root_resource_ptr.NewRequest().TakeChannel().release());
  if (status != ZX_OK) {
    return status;
  }
  return root_resource_ptr->Get(root_resource);
}

// Values parsed out of argv.  All paths described below are absolute paths.
struct DriverManagerArgs {
  // Load drivers from these directories.  If this is empty, the default will
  // be used (unless load_drivers is set).
  fbl::Vector<std::string> driver_search_paths;
  // Load the drivers with these paths. The specified drivers do not need to
  // be in directories in |driver_search_paths|.
  // If any of these drivers are set, then driver_search_paths default will not
  // be used.
  fbl::Vector<const char*> load_drivers;
  // Connect the stdout and stderr file descriptors for this program to a
  // debuglog handle acquired with fuchsia.boot.WriteOnlyLog.
  bool log_to_debuglog = false;
  // Do not exit driver manager after suspending the system.
  bool no_exit_after_suspend = false;
  // Path prefix for binaries/drivers/libraries etc.
  std::string path_prefix = "/boot/";
  // Use this driver as the sys_device driver.  If nullptr, the default will
  // be used.
  std::string sys_device_driver;
  // If true then DriverManager uses DriverIndex for binding rather than
  // looking in /boot/drivers/. If this is false DriverManager will not
  // be able to load base packages.
  bool use_driver_index = false;
};

DriverManagerArgs ParseDriverManagerArgs(int argc, char** argv) {
  enum {
    kLoadDriver,
    kLogToDebuglog,
    kNoExitAfterSuspend,
    kSysDeviceDriver,
    kUseDriverIndex,
  };
  option options[] = {
      {"load-driver", required_argument, nullptr, kLoadDriver},
      {"log-to-debuglog", no_argument, nullptr, kLogToDebuglog},
      {"no-exit-after-suspend", no_argument, nullptr, kNoExitAfterSuspend},
      {"sys-device-driver", required_argument, nullptr, kSysDeviceDriver},
      {"use-driver-index", no_argument, nullptr, kUseDriverIndex},
      {0, 0, 0, 0},
  };

  auto print_usage_and_exit = [options]() {
    printf("driver_manager: supported arguments:\n");
    for (const auto& option : options) {
      printf("  --%s\n", option.name);
    }
    abort();
  };

  auto check_not_duplicated = [print_usage_and_exit](const std::string& arg) {
    if (!arg.empty()) {
      printf("driver_manager: duplicated argument\n");
      print_usage_and_exit();
    }
  };

  DriverManagerArgs args{};
  for (int opt; (opt = getopt_long(argc, argv, "", options, nullptr)) != -1;) {
    switch (opt) {
      case kLoadDriver:
        args.load_drivers.push_back(optarg);
        break;
      case kLogToDebuglog:
        args.log_to_debuglog = true;
        break;
      case kNoExitAfterSuspend:
        args.no_exit_after_suspend = true;
        break;
      case kSysDeviceDriver:
        check_not_duplicated(args.sys_device_driver);
        args.sys_device_driver = optarg;
        break;
      case kUseDriverIndex:
        args.use_driver_index = true;
        break;
      default:
        print_usage_and_exit();
    }
  }
  return args;
}

}  // namespace

int main(int argc, char** argv) {
  zx_status_t status = StdoutToDebuglog::Init();
  if (status != ZX_OK) {
    LOGF(INFO, "Failed to redirect stdout to debuglog, assuming test environment and continuing");
  }

  auto args_result = service::Connect<fuchsia_boot::Arguments>();
  if (args_result.is_error()) {
    LOGF(ERROR, "Failed to get boot arguments service handle: %s", args_result.status_string());
    return args_result.error_value();
  }

  auto boot_args = fidl::WireSyncClient<fuchsia_boot::Arguments>{std::move(*args_result)};
  auto driver_manager_params = GetDriverManagerParams(boot_args);
  auto driver_manager_args = ParseDriverManagerArgs(argc, argv);

  if (driver_manager_params.verbose) {
    fx_logger_t* logger = fx_log_get_logger();
    if (logger) {
      fx_logger_set_min_severity(logger, std::numeric_limits<fx_log_severity_t>::min());
    }
  }
  if (driver_manager_params.log_to_debuglog || driver_manager_args.log_to_debuglog) {
    status = log_to_debuglog();
    if (status != ZX_OK) {
      LOGF(ERROR, "Failed to reconfigure logger to use debuglog: %s", zx_status_get_string(status));
      return status;
    }
  }
  if (!driver_manager_params.root_driver.empty()) {
    driver_manager_args.sys_device_driver = driver_manager_params.root_driver;
  }
  // Set up the default values for our arguments if they weren't given.
  if (driver_manager_args.driver_search_paths.size() == 0 &&
      driver_manager_args.load_drivers.size() == 0 && !driver_manager_args.use_driver_index) {
    driver_manager_args.driver_search_paths.push_back(driver_manager_args.path_prefix + "driver");
  }
  if (driver_manager_args.sys_device_driver.empty()) {
    driver_manager_args.sys_device_driver =
        driver_manager_args.path_prefix + "driver/platform-bus.so";
  }

  SuspendCallback suspend_callback = [&driver_manager_args](zx_status_t status) {
    if (status != ZX_OK) {
      // TODO(https://fxbug.dev/56208): Change this log back to error once isolated devmgr is fixed.
      LOGF(WARNING, "Error suspending devices while stopping the component:%s",
           zx_status_get_string(status));
    }
    if (!driver_manager_args.no_exit_after_suspend) {
      LOGF(INFO, "Exiting driver manager gracefully");
      // TODO(fxb:52627) This event handler should teardown devices and driver hosts
      // properly for system state transitions where driver manager needs to go down.
      // Exiting like so, will not run all the destructors and clean things up properly.
      // Instead the main devcoordinator loop should be quit.
      exit(0);
    }
  };

  async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
  svc::Outgoing outgoing(loop.dispatcher());
  InspectManager inspect_manager(loop.dispatcher());

  CoordinatorConfig config;
  SystemInstance system_instance;
  config.boot_args = &boot_args;
  config.require_system = driver_manager_params.require_system;
  config.log_to_debuglog =
      driver_manager_params.log_to_debuglog || driver_manager_args.log_to_debuglog;
  config.verbose = driver_manager_params.verbose;
  config.fs_provider = &system_instance;
  config.path_prefix = driver_manager_args.path_prefix;
  config.enable_ephemeral = driver_manager_params.enable_ephemeral;
  config.crash_policy = driver_manager_params.crash_policy;

  // Waiting an infinite amount of time before falling back is effectively not
  // falling back at all.
  if (!driver_manager_params.suspend_timeout_fallback) {
    config.suspend_timeout = zx::duration::infinite();
  }

  if (driver_manager_args.use_driver_index) {
    auto driver_index_client = service::Connect<fuchsia_driver_index::DriverIndex>();
    if (driver_index_client.is_error()) {
      LOGF(ERROR, "Failed to connect to driver_index: %d", driver_index_client.error_value());
      return driver_index_client.error_value();
    }
    config.driver_index = fidl::WireSharedClient<fuchsia_driver_index::DriverIndex>(
        std::move(driver_index_client.value()), loop.dispatcher());
  }

  // TODO(fxbug.dev/33958): Remove all uses of the root resource.
  status = get_root_resource(&config.root_resource);
  if (status != ZX_OK) {
    LOGF(INFO, "Failed to get root resource, assuming test environment and continuing");
  }
  // TODO(fxbug.dev/33957): Remove all uses of the root job.
  zx::job root_job;
  status = get_root_job(&root_job);
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to get root job: %s", zx_status_get_string(status));
    return status;
  }

  zx_handle_t oom_event;
  status = zx_system_get_event(root_job.get(), ZX_SYSTEM_EVENT_OUT_OF_MEMORY, &oom_event);
  if (status != ZX_OK) {
    LOGF(INFO, "Failed to get OOM event, assuming test environment and continuing");
  } else {
    config.oom_event = zx::event(oom_event);
  }

  async::Loop firmware_loop(&kAsyncLoopConfigNeverAttachToThread);
  firmware_loop.StartThread("firmware-loop");

  Coordinator coordinator(std::move(config), &inspect_manager, loop.dispatcher(),
                          firmware_loop.dispatcher());

  // Services offered to the rest of the system.
  status = coordinator.InitOutgoingServices(outgoing.svc_dir());
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to initialize outgoing services: %s", zx_status_get_string(status));
    return status;
  }

  // Check if whatever launched devcoordinator gave a channel to be connected to the
  // outgoing services directory. This is for use in tests to let the test environment see
  // outgoing services.
  fidl::ServerEnd<fuchsia_io::Directory> outgoing_svc_dir_client(
      zx::channel(zx_take_startup_handle(DEVMGR_LAUNCHER_OUTGOING_SERVICES_HND)));
  if (outgoing_svc_dir_client.is_valid()) {
    status = outgoing.Serve(std::move(outgoing_svc_dir_client));
    if (status != ZX_OK) {
      LOGF(ERROR, "Failed to bind outgoing services: %s", zx_status_get_string(status));
      return status;
    }
  }

  devfs_init(coordinator.root_device(), loop.dispatcher());

  std::optional<dfv2::DriverRunner> driver_runner;
  std::optional<driver_manager::DriverDevelopmentService> driver_development_service;
  std::optional<driver_manager::DevfsExporter> devfs_exporter;

  // Find and load v1 or v2 Drivers.
  if (!driver_manager_params.use_dfv2) {
    auto publish = coordinator.PublishDriverDevelopmentService(outgoing.svc_dir());
    if (publish.is_error()) {
      LOGF(ERROR, "Failed to publish Driver Development service in DFv1: %s",
           publish.status_string());
      return publish.error_value();
    }

    if (config.enable_ephemeral) {
      auto publish = coordinator.PublishDriverRegistrarService(outgoing.svc_dir());
      if (publish.is_error()) {
        LOGF(ERROR, "Failed to publish Driver Registrar service in DFv1: %s",
             publish.status_string());
        return publish.error_value();
      }
    }

    // V1 Drivers.
    status = system_instance.CreateDriverHostJob(root_job, &config.driver_host_job);
    if (status != ZX_OK) {
      LOGF(ERROR, "Failed to create driver_host job: %s", zx_status_get_string(status));
      return status;
    }

    coordinator.LoadV1Drivers(driver_manager_args.sys_device_driver.c_str(),
                              driver_manager_args.driver_search_paths,
                              driver_manager_args.load_drivers);
  } else {
    // V2 Drivers.
    LOGF(INFO, "Starting DriverRunner with root driver URL: %s",
         driver_manager_args.sys_device_driver.data());

    auto realm_result = service::Connect<fuchsia_component::Realm>();
    if (realm_result.is_error()) {
      return realm_result.error_value();
    }

    auto driver_index_result = service::Connect<fuchsia_driver_index::DriverIndex>();
    if (driver_index_result.is_error()) {
      LOGF(ERROR, "Failed to connect to driver_index: %d", driver_index_result.error_value());
      return driver_index_result.error_value();
    }

    driver_runner.emplace(std::move(realm_result.value()), std::move(driver_index_result.value()),
                          inspect_manager.inspector(), loop.dispatcher());
    auto publish_component_runner = driver_runner->PublishComponentRunner(outgoing.svc_dir());
    if (publish_component_runner.is_error()) {
      return publish_component_runner.error_value();
    }
    auto start = driver_runner->StartRootDriver(driver_manager_args.sys_device_driver);
    if (start.is_error()) {
      return start.error_value();
    }
    driver_development_service.emplace(driver_runner.value(), loop.dispatcher());
    auto publish_driver_development_service =
        driver_development_service->Publish(outgoing.svc_dir());
    if (publish_driver_development_service.is_error()) {
      return publish_driver_development_service.error_value();
    }

    devfs_exporter.emplace(coordinator.root_device()->devnode(), loop.dispatcher());
    auto devfs_publish = devfs_exporter->PublishExporter(outgoing.svc_dir());
    if (devfs_publish.is_error()) {
      return devfs_publish.error_value();
    }

    driver_runner->ScheduleBaseDriversBinding();
  }

  devfs_connect_diagnostics(coordinator.inspect_manager().diagnostics_client());

  // Check if whatever launched devmgr gave a channel to be connected to /dev.
  // This is for use in tests to let the test environment see devfs.
  zx::channel devfs_client(zx_take_startup_handle(DEVMGR_LAUNCHER_DEVFS_ROOT_HND));
  if (devfs_client.is_valid()) {
    fdio_service_clone_to(devfs_root_borrow()->get(), devfs_client.release());
  }

  // Check if whatever launched devmgr gave a channel for component lifecycle events
  fidl::ServerEnd<fuchsia_process_lifecycle::Lifecycle> component_lifecycle_request(
      zx::channel(zx_take_startup_handle(PA_LIFECYCLE)));
  if (component_lifecycle_request.is_valid()) {
    status = devmgr::ComponentLifecycleServer::Create(loop.dispatcher(), &coordinator,
                                                      std::move(component_lifecycle_request),
                                                      std::move(suspend_callback));
    if (status != ZX_OK) {
      LOGF(ERROR, "driver_manager: Cannot create componentlifecycleserver: %s",
           zx_status_get_string(status));
      return status;
    }
  } else {
    LOGF(INFO,
         "No valid handle found for lifecycle events, assuming test environment and "
         "continuing");
  }

  system_instance.InstallDevFsIntoNamespace();
  system_instance.ServiceStarter(&coordinator);

  fbl::unique_fd lib_fd;
  {
    std::string library_path = driver_manager_args.path_prefix + "lib";
    status = fdio_open_fd(library_path.c_str(),
                          static_cast<uint32_t>(fio::wire::OpenFlags::kDirectory |
                                                fio::wire::OpenFlags::kRightReadable |
                                                fio::wire::OpenFlags::kRightExecutable),
                          lib_fd.reset_and_get_address());
    if (status != ZX_OK) {
      LOGF(ERROR, "Failed to open %s: %s", library_path.c_str(), zx_status_get_string(status));
      return status;
    }
  }

  // The loader needs its own thread because DriverManager makes synchronous calls to the
  // DriverHosts, which make synchronous calls to load their shared libraries.
  async::Loop loader_loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  auto loader_service =
      DriverHostLoaderService::Create(loader_loop.dispatcher(), std::move(lib_fd));
  coordinator.set_loader_service_connector([ls = std::move(loader_service)](zx::channel* c) {
    auto conn = ls->Connect();
    if (conn.is_error()) {
      LOGF(ERROR, "Failed to add driver_host loader connection: %s", conn.status_string());
    } else {
      *c = conn->TakeChannel();
    }
    return conn.status_value();
  });
  loader_loop.StartThread();

  // TODO(https://fxbug.dev/99076) Remove this when this issue is fixed.
  LOGF(INFO, "driver_manager loader loop started");

  outgoing.svc_dir()->AddEntry(
      "fuchsia.hardware.pci.DeviceWatcher",
      fbl::MakeRefCounted<fs::Service>(
          [&loader_loop](fidl::ServerEnd<fuchsia_device_manager::DeviceWatcher> request) {
            auto watcher =
                std::make_unique<DeviceWatcher>("/dev/class/pciroot", loader_loop.dispatcher());
            fidl::BindServer(loader_loop.dispatcher(), std::move(request), std::move(watcher));
            return ZX_OK;
          }));
  outgoing.svc_dir()->AddEntry(
      "fuchsia.hardware.usb.DeviceWatcher",
      fbl::MakeRefCounted<fs::Service>(
          [&loader_loop](fidl::ServerEnd<fuchsia_device_manager::DeviceWatcher> request) {
            auto watcher =
                std::make_unique<DeviceWatcher>("/dev/class/usb-device", loader_loop.dispatcher());
            fidl::BindServer(loader_loop.dispatcher(), std::move(request), std::move(watcher));
            return ZX_OK;
          }));

  outgoing.root_dir()->AddEntry("dev",
                                fbl::MakeRefCounted<fs::RemoteDir>(system_instance.CloneFs("dev")));
  outgoing.root_dir()->AddEntry("diagnostics", fbl::MakeRefCounted<fs::RemoteDir>(
                                                   system_instance.CloneFs("dev/diagnostics")));
  outgoing.ServeFromStartupInfo();

  // TODO(https://fxbug.dev/99076) Remove this when this issue is fixed.
  auto log_loop_start = std::make_unique<async::TaskClosure>(
      [] { LOGF(INFO, "driver_manager main loop is running"); });
  log_loop_start->Post(loop.dispatcher());

  coordinator.set_running(true);
  status = loop.Run();
  LOGF(ERROR, "Coordinator exited unexpectedly: %s", zx_status_get_string(status));
  return status;
}
