1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * PROM I/O backend 28 */ 29 30 #include <sys/param.h> 31 #include <sys/types.h> 32 #include <sys/obpdefs.h> 33 #include <string.h> 34 #include <errno.h> 35 #include <ctype.h> 36 37 #include <mdb/mdb_modapi.h> 38 #include <mdb/mdb_io_impl.h> 39 #include <kmdb/kmdb_promif.h> 40 #include <kmdb/kmdb_io.h> 41 #include <mdb/mdb_debug.h> 42 #include <mdb/mdb_err.h> 43 #include <mdb/mdb.h> 44 45 #define PIO_FL_TIO_READ 0x001 46 47 typedef struct pio_data { 48 char pio_name[MAXPATHLEN]; 49 ihandle_t pio_fd; 50 uint_t pio_flags; 51 struct termios pio_ti; 52 } pio_data_t; 53 54 static pid_t pio_pgrp; 55 56 static ssize_t 57 pio_read(mdb_io_t *io, void *buf, size_t nbytes) 58 { 59 pio_data_t *pdp = io->io_data; 60 61 if (io->io_next == NULL) 62 return (kmdb_prom_read(buf, nbytes, &pdp->pio_ti)); 63 64 return (IOP_READ(io->io_next, buf, nbytes)); 65 } 66 67 static ssize_t 68 pio_write(mdb_io_t *io, const void *buf, size_t nbytes) 69 { 70 pio_data_t *pdp = io->io_data; 71 72 if (io->io_next == NULL) 73 return (kmdb_prom_write(buf, nbytes, &pdp->pio_ti)); 74 75 return (IOP_WRITE(io->io_next, buf, nbytes)); 76 } 77 78 static off64_t 79 pio_seek(mdb_io_t *io, off64_t offset, int whence) 80 { 81 if (io->io_next == NULL) 82 return (set_errno(ENOTSUP)); 83 84 return (IOP_SEEK(io->io_next, offset, whence)); 85 } 86 87 static int 88 pio_ctl(mdb_io_t *io, int req, void *arg) 89 { 90 pio_data_t *pdp = io->io_data; 91 92 if (io->io_next != NULL) 93 return (IOP_CTL(io->io_next, req, arg)); 94 95 switch (req) { 96 case TIOCGWINSZ: 97 return (kmdb_prom_term_ctl(TIOCGWINSZ, arg)); 98 99 case TCGETS: { 100 struct termios *ti = arg; 101 102 if (!(pdp->pio_flags & PIO_FL_TIO_READ)) { 103 (void) kmdb_prom_term_ctl(TCGETS, &pdp->pio_ti); 104 pdp->pio_flags |= PIO_FL_TIO_READ; 105 } 106 107 bcopy(&pdp->pio_ti, ti, sizeof (struct termios)); 108 109 mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: gets: i: 0%o o: 0%o c: " 110 "0%o l: 0%o\n", ti->c_iflag, ti->c_oflag, ti->c_cflag, 111 ti->c_lflag); 112 return (0); 113 } 114 115 case TCSETSW: { 116 struct termios *ti = arg; 117 118 mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: setsw: i: 0%o o: 0%o c: " 119 "0%o l: 0%o\n", ti->c_iflag, ti->c_oflag, ti->c_cflag, 120 ti->c_lflag); 121 122 bcopy(ti, &pdp->pio_ti, sizeof (struct termios)); 123 124 return (0); 125 } 126 127 case TIOCSPGRP: 128 pio_pgrp = *(pid_t *)arg; 129 mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: spgrp: %ld\n", 130 (long)pio_pgrp); 131 return (0); 132 133 case TIOCGPGRP: 134 mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: gpgrp: %ld\n", 135 (long)pio_pgrp); 136 *(pid_t *)arg = pio_pgrp; 137 return (0); 138 139 case MDB_IOC_CTTY: 140 mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: ignoring MDB_IOC_CTTY\n"); 141 return (0); 142 143 case MDB_IOC_GETFD: 144 return (set_errno(ENOTSUP)); 145 146 default: 147 warn("Unknown ioctl %d\n", req); 148 return (set_errno(EINVAL)); 149 } 150 } 151 152 void 153 pio_close(mdb_io_t *io) 154 { 155 pio_data_t *pdp = io->io_data; 156 157 mdb_free(pdp, sizeof (pio_data_t)); 158 } 159 160 static const char * 161 pio_name(mdb_io_t *io) 162 { 163 pio_data_t *pdp = io->io_data; 164 165 if (io->io_next == NULL) 166 return (pdp->pio_name); 167 168 return (IOP_NAME(io->io_next)); 169 } 170 171 static const mdb_io_ops_t promio_ops = { 172 .io_read = pio_read, 173 .io_write = pio_write, 174 .io_seek = pio_seek, 175 .io_ctl = pio_ctl, 176 .io_close = pio_close, 177 .io_name = pio_name, 178 .io_link = no_io_link, 179 .io_unlink = no_io_unlink, 180 .io_setattr = no_io_setattr, 181 .io_suspend = no_io_suspend, 182 .io_resume = no_io_resume, 183 }; 184 185 mdb_io_t * 186 kmdb_promio_create(char *name) 187 { 188 mdb_io_t *io; 189 pio_data_t *pdp; 190 ihandle_t hdl = kmdb_prom_get_handle(name); 191 192 if (hdl == -1) 193 return (NULL); 194 195 io = mdb_zalloc(sizeof (mdb_io_t), UM_SLEEP); 196 pdp = mdb_zalloc(sizeof (pio_data_t), UM_SLEEP); 197 198 (void) strlcpy(pdp->pio_name, name, MAXPATHLEN); 199 pdp->pio_fd = hdl; 200 201 #ifdef __sparc 202 pdp->pio_ti.c_oflag |= ONLCR; 203 pdp->pio_ti.c_iflag |= ICRNL; 204 #endif 205 pdp->pio_ti.c_lflag |= ECHO; 206 207 io->io_data = pdp; 208 io->io_ops = &promio_ops; 209 210 return (io); 211 } 212 213 char 214 kmdb_getchar(void) 215 { 216 char c; 217 218 while (IOP_READ(mdb.m_term, &c, 1) != 1) 219 continue; 220 if (isprint(c) && c != '\n') 221 mdb_iob_printf(mdb.m_out, "%c", c); 222 mdb_iob_printf(mdb.m_out, "\n"); 223 224 return (c); 225 } 226