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 /* 23 * Copyright (c) 2012 Gary Mills 24 * 25 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #include <kmdb/kmdb_auxv.h> 30 #include <kmdb/kctl/kctl.h> 31 32 #include <sys/bootconf.h> 33 #include <sys/kobj.h> 34 #include <sys/kobj_impl.h> 35 #include <sys/cpuvar.h> 36 #include <sys/kdi_impl.h> 37 #include <sys/controlregs.h> 38 #include <sys/archsystm.h> 39 40 static int 41 kctl_boot_prop_read(char *pname, char *prop_buf, int buf_len) 42 { 43 struct bootops *ops = kctl.kctl_boot_ops; 44 int len; 45 46 len = BOP_GETPROPLEN(ops, pname); 47 if (len > 0 && len <= buf_len) { 48 (void) BOP_GETPROP(ops, pname, (void *)prop_buf); 49 return (1); 50 } 51 52 return (0); 53 } 54 55 static int 56 kctl_ddi_prop_read(char *pname, char *prop_buf, int buf_len) 57 { 58 dev_info_t *dip = ddi_root_node(); 59 char *val; 60 int ret = 0; 61 62 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 63 DDI_PROP_DONTPASS, pname, &val) != DDI_SUCCESS) 64 return (0); 65 66 if (strlen(val) < buf_len) { 67 (void) strcpy(prop_buf, val); 68 ret = 1; 69 } 70 71 ddi_prop_free(val); 72 return (ret); 73 } 74 75 /* 76 * We don't have any property-walking routines, so we have to specifically 77 * query and thus have guilty knowledge of the properties that the 78 * debugger wants to see. 79 * 80 * Here actually we only support eight console properties: 81 * input-device, output-device, tty[a-d]-mode, screen-#rows, screen-#cols. 82 */ 83 #define KCTL_PROPNV_NIODEV 2 84 #define KCTL_PROPNV_NTTYMD 4 85 #define KCTL_PROPNV_NSCREEN 2 86 #define KCTL_PROPNV_NENT (KCTL_PROPNV_NIODEV + KCTL_PROPNV_NTTYMD + \ 87 KCTL_PROPNV_NSCREEN) 88 89 static kmdb_auxv_nv_t * 90 kctl_pcache_create(int *nprops) 91 { 92 int (*preader)(char *, char *, int); 93 kmdb_auxv_nv_t *pnv; 94 size_t psz = sizeof (kmdb_auxv_nv_t) * KCTL_PROPNV_NENT; 95 char *inputdev, *outputdev; 96 int i, j; 97 char ttymode[] = "ttyX-mode"; 98 99 if (kctl.kctl_boot_loaded) { 100 preader = kctl_boot_prop_read; 101 } else { 102 preader = kctl_ddi_prop_read; 103 } 104 105 pnv = kobj_alloc(psz, KM_WAIT); 106 inputdev = (&pnv[0])->kanv_val; 107 outputdev = (&pnv[1])->kanv_val; 108 109 /* Set the property names. */ 110 (void) strcpy((&pnv[0])->kanv_name, "input-device"); 111 (void) strcpy((&pnv[1])->kanv_name, "output-device"); 112 for (i = 0; i < KCTL_PROPNV_NTTYMD; i++) { 113 ttymode[3] = 'a' + i; 114 (void) strcpy((&pnv[i + KCTL_PROPNV_NIODEV])->kanv_name, 115 ttymode); 116 } 117 118 (void) strcpy(inputdev, "text"); /* default to screen */ 119 if (!preader("diag-device", inputdev, sizeof ((&pnv[0])->kanv_val)) && 120 !preader("console", inputdev, sizeof ((&pnv[0])->kanv_val))) { 121 (void) preader("input-device", inputdev, 122 sizeof ((&pnv[0])->kanv_val)); 123 } 124 125 if (strncmp(inputdev, "tty", 3) == 0 && 126 inputdev[4] == '\0' && 127 inputdev[3] >= 'a' && 128 inputdev[3] < 'a' + KCTL_PROPNV_NTTYMD) { 129 (void) strcpy(outputdev, inputdev); 130 } else { 131 (void) strcpy(inputdev, "keyboard"); 132 (void) strcpy(outputdev, "screen"); 133 } 134 135 /* Set tty modes or defaults. */ 136 j = KCTL_PROPNV_NIODEV + KCTL_PROPNV_NTTYMD; 137 for (i = KCTL_PROPNV_NIODEV; i < j; i++) { 138 if (!preader((&pnv[i])->kanv_name, (&pnv[i])->kanv_val, 139 sizeof ((&pnv[0])->kanv_val))) 140 (void) strcpy((&pnv[i])->kanv_val, "9600,8,n,1,-"); 141 } 142 143 (void) strcpy((&pnv[j])->kanv_name, "screen-#rows"); 144 (void) strcpy((&pnv[j + 1])->kanv_name, "screen-#cols"); 145 (void) strcpy((&pnv[j])->kanv_val, "0"); 146 (void) strcpy((&pnv[j + 1])->kanv_val, "0"); 147 (void) preader((&pnv[j])->kanv_name, (&pnv[j])->kanv_val, 148 sizeof ((&pnv[j])->kanv_val)); 149 (void) preader((&pnv[j + 1])->kanv_name, (&pnv[j + 1])->kanv_val, 150 sizeof ((&pnv[j + 1])->kanv_val)); 151 152 *nprops = KCTL_PROPNV_NENT; 153 return (pnv); 154 } 155 156 static void 157 kctl_pcache_destroy(kmdb_auxv_nv_t *pnv) 158 { 159 kobj_free(pnv, sizeof (kmdb_auxv_nv_t) * KCTL_PROPNV_NENT); 160 } 161 162 void 163 kctl_auxv_init_isadep(kmdb_auxv_t *kav, void *romp) 164 { 165 kav->kav_pcache = kctl_pcache_create(&kav->kav_nprops); 166 kav->kav_romp = romp; 167 } 168 169 void 170 kctl_auxv_fini_isadep(kmdb_auxv_t *kav) 171 { 172 if (kav->kav_pcache != NULL) 173 kctl_pcache_destroy(kav->kav_pcache); 174 } 175 176 int 177 kctl_preactivate_isadep(void) 178 { 179 return (0); 180 } 181 182 /*ARGSUSED*/ 183 void 184 kctl_activate_isadep(kdi_debugvec_t *dvec) 185 { 186 dvec->dv_kctl_vmready = hat_kdi_init; 187 188 if (!kctl.kctl_boot_loaded) 189 hat_kdi_init(); 190 } 191 192 void 193 kctl_depreactivate_isadep(void) 194 { 195 } 196 197 /* 198 * Many common kernel functions assume that %gs can be deferenced, and 199 * fail horribly if it cannot. Ask the kernel to set up a temporary 200 * mapping to a fake cpu_t so that we can call such functions during 201 * initialization. 202 */ 203 void * 204 kctl_boot_tmpinit(void) 205 { 206 return (boot_kdi_tmpinit()); 207 } 208 209 void 210 kctl_boot_tmpfini(void *old) 211 { 212 boot_kdi_tmpfini(old); 213 } 214