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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * This module supports callbacks from the firmware 29 * such that address and name lookups can work and use kernel symbol names. 30 * For example "ctrace" will provide symbolic names, if they are available. 31 * Also, normal firmware name to address lookups should work, though be 32 * careful with clashing kernel names, such as "startup" and "reset" which 33 * may be the firmware names and *not* the kernel names. 34 * 35 * The module locks the symbol tables in memory, when it's installed, 36 * and unlocks them when it is removed. The module is loaded automatically 37 * on cobp systems and is replaced by forthdebug on all other systems. 38 * 39 * This file contains the actual code the does the lookups, and interfaces 40 * with the kernel kobj stuff. The transfer of data and control to/from 41 * the firmware is handled in prom-dependent code. 42 */ 43 44 #include <sys/types.h> 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/debug.h> 48 #include <sys/errno.h> 49 #include <sys/modctl.h> 50 #include <sys/kobj.h> 51 #include <sys/promif.h> 52 #include <sys/ddi.h> 53 #include <sys/sunddi.h> 54 #include <sys/reboot.h> 55 #include <sys/callb.h> 56 57 int obpsym_debug = 0; 58 #define DPRINTF(str) if (obpsym_debug) prom_printf(str) 59 #define DPRINTF1(str, a) if (obpsym_debug) prom_printf(str, a); 60 #define DPRINTF2(str, a, b) if (obpsym_debug) prom_printf(str, a, b); 61 #define DXPRINTF if (obpsym_debug > 1) prom_printf 62 63 int obpheld = 1; /* Prevents unloading when set */ 64 65 /* 66 * name_to_value - translate a string into an address 67 * 68 * The string may be one of two forms - 'symname' or 'modname:symname'. 69 * (We also accept 'unix:symname' as a synonymn for 'symname'.) 70 * The latter form causes a kobj_lookup() to occur only in the given module, 71 * the former causes a kobj_getsymvalue() on the entire kernel symbol table. 72 * 73 * mod_lock locking is not needed for the &modules list because 74 * modctl structures are never unlinked from the &modules list. 75 */ 76 int 77 name_to_value(char *name, uintptr_t *value) 78 { 79 register char *symname = name; 80 register char *modname = ""; 81 char *p; 82 int retval = 0; 83 uintptr_t symvalue = 0; 84 char c = (char)0; 85 86 /* 87 * we take names of the form: "modname:symbol", "unix:symbol", "symbol" 88 */ 89 if ((p = strchr(name, ':')) != NULL && p[1] != (char)0) { 90 symname = p + 1; 91 modname = name; 92 c = *p; 93 *p = (char)0; 94 } 95 96 if (*modname == (char)0) { 97 symvalue = kobj_getsymvalue(symname, 0); 98 } else { 99 struct modctl *mp = &modules; 100 101 do { 102 if (strcmp(modname, mp->mod_modname) == 0) { 103 symvalue = kobj_lookup(mp->mod_mp, symname); 104 break; 105 } 106 } while ((mp = mp->mod_next) != &modules); 107 } 108 109 if (symvalue == 0) 110 retval = -1; 111 if (c != (char)0) /* Restore incoming cstr */ 112 *p = c; 113 114 *value = symvalue; 115 return (retval); 116 } 117 118 /* 119 * value_to_name - translate an address into a string + offset 120 * 121 * mod_lock locking is not needed fro the modules list because 122 * modctl structures are never unlinked from the &modules list. 123 */ 124 ulong_t 125 value_to_name(uintptr_t value, char *symbol) 126 { 127 struct modctl *modp = &modules; 128 ulong_t offset; 129 char *name; 130 131 DPRINTF1("value_to_name: Looking for %p\n", (void *)value); 132 133 do { 134 if (modp->mod_mp && 135 (name = kobj_searchsym(modp->mod_mp, value, &offset))) { 136 (void) strcpy(symbol, modp->mod_modname); 137 (void) strcat(symbol, ":"); 138 (void) strcat(symbol, name); 139 return (offset); 140 } 141 } while ((modp = modp->mod_next) != &modules); 142 143 *symbol = (char)0; 144 return ((ulong_t)-1l); 145 } 146 147 /* 148 * loadable module wrapper 149 */ 150 static struct modlmisc modlmisc = { 151 &mod_miscops, "OBP symbol callbacks" 152 }; 153 154 static struct modlinkage modlinkage = { 155 MODREV_1, (void *)&modlmisc, NULL 156 }; 157 158 /*ARGSUSED*/ 159 static boolean_t 160 reset_callbacks(void *arg, int code) 161 { 162 extern void set_sym_callbacks(); 163 164 if (code == CB_CODE_CPR_RESUME) 165 set_sym_callbacks(); 166 return (B_TRUE); 167 } 168 169 int 170 _init(void) 171 { 172 int retval; 173 extern int install_callbacks(void); 174 extern void remove_callbacks(void); 175 176 if (install_callbacks() != 0) 177 return (ENXIO); 178 179 if (boothowto & RB_HALT) 180 debug_enter("obpsym: halt flag (-h) is set.\n"); 181 182 retval = mod_install(&modlinkage); 183 184 /* 185 * if load fails remove callback and unlock symbols 186 */ 187 if (retval) { 188 printf("obpsym: Error %d installing OBP syms module\n", retval); 189 remove_callbacks(); 190 } 191 else 192 (void) callb_add(reset_callbacks, 0, CB_CL_CPR_OBP, "obpsym"); 193 194 return (retval); 195 } 196 197 int 198 _fini(void) 199 { 200 int retval; 201 extern void remove_callbacks(void); 202 203 if (obpheld != 0) 204 return (EBUSY); 205 206 retval = mod_remove(&modlinkage); 207 208 /* 209 * if unload succeeds remove callback and unlock symbols 210 */ 211 if (retval == 0) { 212 remove_callbacks(); 213 } 214 return (retval); 215 } 216 217 int 218 _info(struct modinfo *modinfop) 219 { 220 return (mod_info(&modlinkage, modinfop)); 221 } 222