// 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 <err.h>
#include <platform.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <trace.h>

#include <lib/console.h>
#include <lib/user_copy/user_ptr.h>
#include <lib/ktrace.h>
#include <lib/mtrace.h>
#include <lib/io.h>
#include <object/handle_owner.h>
#include <object/process_dispatcher.h>
#include <object/resources.h>

#include <platform/debug.h>

#include <zircon/syscalls/debug.h>

#include "syscalls_priv.h"

#define LOCAL_TRACE 0

constexpr uint32_t kMaxDebugWriteSize = 256u;

zx_status_t sys_debug_read(zx_handle_t handle, user_ptr<void> ptr, uint32_t len) {
    LTRACEF("ptr %p\n", ptr.get());

    // TODO(MG-971): finer grained validation
    zx_status_t status;
    if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) {
        return status;
    }

    // TODO: remove this cast.
    auto uptr = ptr.reinterpret<uint8_t>();

    uint32_t idx = 0;
    for (; idx < len; ++idx) {
        int c = getchar();
        if (c < 0)
            break;

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

        auto cur = uptr.byte_offset(idx);
        if (cur.copy_to_user(static_cast<uint8_t>(c)) != ZX_OK)
            break;
    }
    // TODO: fix this cast, which can overflow.
    return static_cast<zx_status_t>(idx);
}

zx_status_t sys_debug_write(user_ptr<const void> ptr, uint32_t len) {
    LTRACEF("ptr %p, len %u\n", ptr.get(), len);

    if (len > kMaxDebugWriteSize)
        len = kMaxDebugWriteSize;

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

    __kernel_serial_write(buf, len);

    return len;
}

zx_status_t sys_debug_send_command(zx_handle_t handle, user_ptr<const void> ptr, uint32_t len) {
    LTRACEF("ptr %p, len %u\n", ptr.get(), len);

    // TODO(MG-971): finer grained validation
    zx_status_t status;
    if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) {
        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 sys_ktrace_read(zx_handle_t handle, user_ptr<void> _data,
                            uint32_t offset, uint32_t len,
                            user_ptr<uint32_t> _actual) {
    // TODO(MG-971): finer grained validation
    zx_status_t status;
    if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) {
        return status;
    }

    int result = ktrace_read_user(_data.get(), offset, len);
    if (result < 0)
        return result;

    return _actual.copy_to_user(static_cast<uint32_t>(result));
}

zx_status_t sys_ktrace_control(
        zx_handle_t handle, uint32_t action, uint32_t options, user_ptr<void> _ptr) {
    // TODO(MG-971): finer grained validation
    zx_status_t status;
    if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) {
        return status;
    }

    switch (action) {
    case KTRACE_ACTION_NEW_PROBE: {
        char name[ZX_MAX_NAME_LEN];
        if (_ptr.copy_array_from_user(name, sizeof(name) - 1) != ZX_OK)
            return ZX_ERR_INVALID_ARGS;
        name[sizeof(name) - 1] = 0;
        return ktrace_control(action, options, name);
    }
    default:
        return ktrace_control(action, options, nullptr);
    }
}

zx_status_t sys_ktrace_write(zx_handle_t handle, uint32_t event_id, uint32_t arg0, uint32_t arg1) {
    // TODO(MG-971): finer grained validation
    zx_status_t status;
    if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) {
        return status;
    }

    if (event_id > 0x7FF) {
        return ZX_ERR_INVALID_ARGS;
    }

    uint32_t* args = static_cast<uint32_t*>(ktrace_open(TAG_PROBE_24(event_id)));
    if (!args) {
        //  There is not a single reason for failure. Assume it reached the end.
        return ZX_ERR_UNAVAILABLE;
    }

    args[0] = arg0;
    args[1] = arg1;
    return ZX_OK;
}

zx_status_t sys_mtrace_control(zx_handle_t handle,
                               uint32_t kind, uint32_t action, uint32_t options,
                               user_ptr<void> ptr, uint32_t size) {
    // TODO(MG-971): finer grained validation
    zx_status_t status;
    if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) {
        return status;
    }

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