// Copyright 2016 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/console.h>
#include <lib/debuglog.h>
#include <lib/io.h>
#include <lib/ktrace.h>
#include <lib/mtrace.h>
#include <lib/persistent-debuglog.h>
#include <lib/syscalls/forward.h>
#include <lib/user_copy/user_ptr.h>
#include <platform.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <trace.h>
#include <zircon/errors.h>
#include <zircon/syscalls/debug.h>
#include <zircon/types.h>

#include <object/handle.h>
#include <object/process_dispatcher.h>
#include <object/resource.h>
#include <platform/debug.h>

#define LOCAL_TRACE 0

constexpr uint32_t kMaxDebugWriteSize = 256u;

// zx_status_t zx_debug_read
zx_status_t sys_debug_read(zx_handle_t handle, user_out_ptr<char> ptr, size_t max_len,
                           user_out_ptr<size_t> len) {
  LTRACEF("ptr %p\n", ptr.get());

  if (BootOptions::Get()->enable_serial_syscalls != SerialDebugSyscalls::kEnabled) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  zx_status_t status;
  if ((status = validate_ranged_resource(handle, ZX_RSRC_KIND_SYSTEM, ZX_RSRC_SYSTEM_DEBUG_BASE,
                                         1)) != ZX_OK) {
    return status;
  }

  size_t idx = 0;
  for (; idx < max_len; ++idx) {
    char c;
    // Wait only on the first character.
    // The API for this function can return any number of characters up to the supplied buffer
    // length, however there is no notification mechanism for when there are bytes to read.
    // Hence, we need to read at least one character or applications will be forced to spin poll.
    // We avoid reading all the characters so that interactive applications can stay responsive
    // without losing efficiency by being forced to read one character at a time.
    bool wait = (idx == 0);
    int err = platform_dgetc(&c, wait);
    if (err < 0) {
      return err;
    } else if (err == 0) {
      break;
    }

    if (c == '\r') {
      c = '\n';
    }

    status = ptr.copy_array_to_user(&c, 1, idx);
    if (status != ZX_OK) {
      return status;
    }
  }
  return len.copy_to_user(idx);
}

// zx_status_t zx_debug_write
zx_status_t sys_debug_write(user_in_ptr<const char> ptr, size_t len) {
  LTRACEF("ptr %p, len %zu\n", ptr.get(), len);

  if (BootOptions::Get()->enable_serial_syscalls != SerialDebugSyscalls::kEnabled &&
      BootOptions::Get()->enable_serial_syscalls != SerialDebugSyscalls::kOutputOnly) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  if (len > kMaxDebugWriteSize)
    len = kMaxDebugWriteSize;

  char buf[kMaxDebugWriteSize];
  if (ptr.copy_array_from_user(buf, len) != ZX_OK)
    return ZX_ERR_INVALID_ARGS;

  // Dump what we can into the persistent dlog, if we have one.
  persistent_dlog_write({buf, len});

  // This path to serial out arbitrates with the debug log
  // drainer and/or kernel ll debug path to minimize interleaving
  // of serial output between various sources
  dlog_serial_write({buf, len});

  return ZX_OK;
}

// zx_status_t zx_debug_send_command
zx_status_t sys_debug_send_command(zx_handle_t handle, user_in_ptr<const char> ptr, size_t len) {
  LTRACEF("ptr %p, len %zu\n", ptr.get(), len);

  if (!BootOptions::Get()->enable_debugging_syscalls) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  zx_status_t status;
  if ((status = validate_ranged_resource(handle, ZX_RSRC_KIND_SYSTEM, ZX_RSRC_SYSTEM_DEBUG_BASE,
                                         1)) != ZX_OK) {
    return status;
  }

  if (len > kMaxDebugWriteSize)
    return ZX_ERR_INVALID_ARGS;

  char buf[kMaxDebugWriteSize + 2];
  if (ptr.copy_array_from_user(buf, len) != ZX_OK)
    return ZX_ERR_INVALID_ARGS;

  buf[len] = '\n';
  buf[len + 1] = 0;
  return console_run_script(buf);
}

// zx_status_t zx_ktrace_read
zx_status_t sys_ktrace_read(zx_handle_t handle, user_out_ptr<void> _data, uint32_t offset,
                            size_t len, user_out_ptr<size_t> _actual) {
  zx_status_t status;
  if ((status = validate_ranged_resource(handle, ZX_RSRC_KIND_SYSTEM, ZX_RSRC_SYSTEM_TRACING_BASE,
                                         1)) != ZX_OK) {
    return status;
  }

  zx::result<size_t> result = KTrace::GetInstance().ReadUser(_data, offset, len);
  if (result.is_error())
    return result.status_value();

  return _actual.copy_to_user(result.value());
}

// zx_status_t zx_ktrace_control
zx_status_t sys_ktrace_control(zx_handle_t handle, uint32_t action, uint32_t options,
                               user_inout_ptr<void> _ptr) {
  zx_status_t status;
  if ((status = validate_ranged_resource(handle, ZX_RSRC_KIND_SYSTEM, ZX_RSRC_SYSTEM_TRACING_BASE,
                                         1)) != ZX_OK) {
    return status;
  }

  return KTrace::GetInstance().Control(action, options);
}

// zx_status_t zx_mtrace_control
zx_status_t sys_mtrace_control(zx_handle_t handle, uint32_t kind, uint32_t action, uint32_t options,
                               user_inout_ptr<void> ptr, size_t size) {
  if (!BootOptions::Get()->enable_debugging_syscalls) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  zx_status_t status;
  if ((status = validate_ranged_resource(handle, ZX_RSRC_KIND_SYSTEM, ZX_RSRC_SYSTEM_DEBUG_BASE,
                                         1)) != ZX_OK) {
    return status;
  }

  return mtrace_control(kind, action, options, ptr, size);
}
