1// Copyright 2016 The Fuchsia Authors 2// 3// Use of this source code is governed by a MIT-style 4// license that can be found in the LICENSE file or at 5// https://opensource.org/licenses/MIT 6 7#include <err.h> 8#include <platform.h> 9#include <stdint.h> 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13#include <trace.h> 14 15#include <lib/console.h> 16#include <lib/debuglog.h> 17#include <lib/user_copy/user_ptr.h> 18#include <lib/ktrace.h> 19#include <lib/mtrace.h> 20#include <lib/io.h> 21#include <object/handle.h> 22#include <object/process_dispatcher.h> 23#include <object/resource.h> 24 25#include <platform/debug.h> 26 27#include <zircon/syscalls/debug.h> 28 29#include "priv.h" 30 31#define LOCAL_TRACE 0 32 33constexpr uint32_t kMaxDebugWriteSize = 256u; 34 35zx_status_t sys_debug_read(zx_handle_t handle, user_out_ptr<char> ptr, user_inout_ptr<size_t> len) { 36 LTRACEF("ptr %p\n", ptr.get()); 37 38 // TODO(ZX-971): finer grained validation 39 zx_status_t status; 40 if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) { 41 return status; 42 } 43 44 // get the number of bytes the user wants us to read 45 size_t readlen; 46 status = len.copy_from_user(&readlen); 47 if (status != ZX_OK) { 48 return status; 49 } 50 51 size_t idx = 0; 52 for (; idx < readlen; ++idx) { 53 int intc = getchar(); 54 if (intc < 0) { 55 return intc; 56 } 57 58 if (intc == '\r') { 59 intc = '\n'; 60 } 61 62 char c = static_cast<char>(intc); 63 64 status = ptr.copy_array_to_user(&c, 1, idx); 65 if (status != ZX_OK) { 66 return status; 67 } 68 } 69 return len.copy_to_user(idx); 70} 71 72zx_status_t sys_debug_write(user_in_ptr<const char> ptr, size_t len) { 73 LTRACEF("ptr %p, len %zu\n", ptr.get(), len); 74 75 if (len > kMaxDebugWriteSize) 76 len = kMaxDebugWriteSize; 77 78 char buf[kMaxDebugWriteSize]; 79 if (ptr.copy_array_from_user(buf, len) != ZX_OK) 80 return ZX_ERR_INVALID_ARGS; 81 82 // This path to serial out arbitrates with the debug log 83 // drainer and/or kernel ll debug path to minimize interleaving 84 // of serial output between various sources 85 dlog_serial_write(buf, len); 86 87 return ZX_OK; 88} 89 90zx_status_t sys_debug_send_command(zx_handle_t handle, user_in_ptr<const char> ptr, size_t len) { 91 LTRACEF("ptr %p, len %zu\n", ptr.get(), len); 92 93 // TODO(ZX-971): finer grained validation 94 zx_status_t status; 95 if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) { 96 return status; 97 } 98 99 if (len > kMaxDebugWriteSize) 100 return ZX_ERR_INVALID_ARGS; 101 102 char buf[kMaxDebugWriteSize + 2]; 103 if (ptr.copy_array_from_user(buf, len) != ZX_OK) 104 return ZX_ERR_INVALID_ARGS; 105 106 buf[len] = '\n'; 107 buf[len + 1] = 0; 108 return console_run_script(buf); 109} 110 111zx_status_t sys_ktrace_read(zx_handle_t handle, user_out_ptr<void> _data, 112 uint32_t offset, size_t len, 113 user_out_ptr<size_t> _actual) { 114 // TODO(ZX-971): finer grained validation 115 zx_status_t status; 116 if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) { 117 return status; 118 } 119 120 ssize_t result = ktrace_read_user(_data.get(), offset, len); 121 if (result < 0) 122 return static_cast<zx_status_t>(result); 123 124 return _actual.copy_to_user(static_cast<size_t>(result)); 125} 126 127zx_status_t sys_ktrace_control( 128 zx_handle_t handle, uint32_t action, uint32_t options, user_inout_ptr<void> _ptr) { 129 // TODO(ZX-971): finer grained validation 130 zx_status_t status; 131 if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) { 132 return status; 133 } 134 135 switch (action) { 136 case KTRACE_ACTION_NEW_PROBE: { 137 char name[ZX_MAX_NAME_LEN]; 138 if (_ptr.copy_array_from_user(name, sizeof(name) - 1) != ZX_OK) 139 return ZX_ERR_INVALID_ARGS; 140 name[sizeof(name) - 1] = 0; 141 return ktrace_control(action, options, name); 142 } 143 default: 144 return ktrace_control(action, options, nullptr); 145 } 146} 147 148zx_status_t sys_ktrace_write(zx_handle_t handle, uint32_t event_id, uint32_t arg0, uint32_t arg1) { 149 // TODO(ZX-971): finer grained validation 150 zx_status_t status; 151 if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) { 152 return status; 153 } 154 155 if (event_id > 0x7FF) { 156 return ZX_ERR_INVALID_ARGS; 157 } 158 159 uint32_t* args = static_cast<uint32_t*>(ktrace_open(TAG_PROBE_24(event_id))); 160 if (!args) { 161 // There is not a single reason for failure. Assume it reached the end. 162 return ZX_ERR_UNAVAILABLE; 163 } 164 165 args[0] = arg0; 166 args[1] = arg1; 167 return ZX_OK; 168} 169 170zx_status_t sys_mtrace_control(zx_handle_t handle, 171 uint32_t kind, uint32_t action, uint32_t options, 172 user_inout_ptr<void> ptr, size_t size) { 173 // TODO(ZX-971): finer grained validation 174 zx_status_t status; 175 if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) { 176 return status; 177 } 178 179 return mtrace_control(kind, action, options, ptr, size); 180} 181