1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/inttypes.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/disp.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/sysconf.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/esunddi.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/vmem.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/hwconf.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/kobj_lex.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/callb.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/dacf.h> 55*7c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate struct hwc_class *hcl_head; /* head of list of classes */ 58*7c478bd9Sstevel@tonic-gate static kmutex_t hcl_lock; /* for accessing list of classes */ 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate #define DAFILE "/etc/driver_aliases" 61*7c478bd9Sstevel@tonic-gate #define CLASSFILE "/etc/driver_classes" 62*7c478bd9Sstevel@tonic-gate #define DACFFILE "/etc/dacf.conf" 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate static char class_file[] = CLASSFILE; 65*7c478bd9Sstevel@tonic-gate static char dafile[] = DAFILE; 66*7c478bd9Sstevel@tonic-gate static char dacffile[] = DACFFILE; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate char *systemfile = "etc/system"; /* name of ascii system file */ 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate static struct sysparam *sysparam_hd; /* head of parameters list */ 71*7c478bd9Sstevel@tonic-gate static struct sysparam *sysparam_tl; /* tail of parameters list */ 72*7c478bd9Sstevel@tonic-gate static vmem_t *mod_sysfile_arena; /* parser memory */ 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate char obp_bootpath[BO_MAXOBJNAME]; /* bootpath from obp */ 75*7c478bd9Sstevel@tonic-gate char svm_bootpath[BO_MAXOBJNAME]; /* bootpath redirected via rootdev */ 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate #if defined(_PSM_MODULES) 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate struct psm_mach { 80*7c478bd9Sstevel@tonic-gate struct psm_mach *m_next; 81*7c478bd9Sstevel@tonic-gate char *m_machname; 82*7c478bd9Sstevel@tonic-gate }; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate static struct psm_mach *pmach_head; /* head of list of classes */ 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate #define MACHFILE "/etc/mach" 87*7c478bd9Sstevel@tonic-gate static char mach_file[] = MACHFILE; 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate #endif /* _PSM_MODULES */ 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate #if defined(_RTC_CONFIG) 92*7c478bd9Sstevel@tonic-gate static char rtc_config_file[] = "/etc/rtc_config"; 93*7c478bd9Sstevel@tonic-gate #endif 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate static void sys_set_var(int, struct sysparam *, void *); 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate static void setparams(void); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* 100*7c478bd9Sstevel@tonic-gate * driver.conf parse thread control structure 101*7c478bd9Sstevel@tonic-gate */ 102*7c478bd9Sstevel@tonic-gate struct hwc_parse_mt { 103*7c478bd9Sstevel@tonic-gate ksema_t sema; 104*7c478bd9Sstevel@tonic-gate char *name; /* name of .conf files */ 105*7c478bd9Sstevel@tonic-gate struct par_list **pl; /* parsed parent list */ 106*7c478bd9Sstevel@tonic-gate ddi_prop_t **props; /* parsed properties */ 107*7c478bd9Sstevel@tonic-gate int rv; /* return value */ 108*7c478bd9Sstevel@tonic-gate }; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate static int hwc_parse_now(char *, struct par_list **, ddi_prop_t **); 111*7c478bd9Sstevel@tonic-gate static void hwc_parse_thread(struct hwc_parse_mt *); 112*7c478bd9Sstevel@tonic-gate static struct hwc_parse_mt *hwc_parse_mtalloc(char *, struct par_list **, 113*7c478bd9Sstevel@tonic-gate ddi_prop_t **); 114*7c478bd9Sstevel@tonic-gate static void hwc_parse_mtfree(struct hwc_parse_mt *); 115*7c478bd9Sstevel@tonic-gate static void add_spec(struct hwc_spec *, struct par_list **); 116*7c478bd9Sstevel@tonic-gate static void add_props(struct hwc_spec *, ddi_prop_t **); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate static void check_system_file(void); 119*7c478bd9Sstevel@tonic-gate static int sysparam_compare_entry(struct sysparam *, struct sysparam *); 120*7c478bd9Sstevel@tonic-gate static char *sysparam_type_to_str(int); 121*7c478bd9Sstevel@tonic-gate static void sysparam_count_entry(struct sysparam *, int *, u_longlong_t *); 122*7c478bd9Sstevel@tonic-gate static void sysparam_print_warning(struct sysparam *, u_longlong_t); 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 125*7c478bd9Sstevel@tonic-gate static int parse_debug_on = 0; 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /*VARARGS1*/ 128*7c478bd9Sstevel@tonic-gate static void 129*7c478bd9Sstevel@tonic-gate parse_debug(struct _buf *file, char *fmt, ...) 130*7c478bd9Sstevel@tonic-gate { 131*7c478bd9Sstevel@tonic-gate va_list adx; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate if (parse_debug_on) { 134*7c478bd9Sstevel@tonic-gate va_start(adx, fmt); 135*7c478bd9Sstevel@tonic-gate vprintf(fmt, adx); 136*7c478bd9Sstevel@tonic-gate if (file) 137*7c478bd9Sstevel@tonic-gate printf(" on line %d of %s\n", kobj_linenum(file), 138*7c478bd9Sstevel@tonic-gate kobj_filename(file)); 139*7c478bd9Sstevel@tonic-gate va_end(adx); 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate #define FE_BUFLEN 256 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE3*/ 147*7c478bd9Sstevel@tonic-gate void 148*7c478bd9Sstevel@tonic-gate kobj_file_err(int type, struct _buf *file, char *fmt, ...) 149*7c478bd9Sstevel@tonic-gate { 150*7c478bd9Sstevel@tonic-gate va_list ap; 151*7c478bd9Sstevel@tonic-gate /* 152*7c478bd9Sstevel@tonic-gate * If we're in trouble, we might be short on stack... be paranoid 153*7c478bd9Sstevel@tonic-gate */ 154*7c478bd9Sstevel@tonic-gate char *buf = kmem_alloc(FE_BUFLEN, KM_SLEEP); 155*7c478bd9Sstevel@tonic-gate char *trailer = kmem_alloc(FE_BUFLEN, KM_SLEEP); 156*7c478bd9Sstevel@tonic-gate char *fmt_str = kmem_alloc(FE_BUFLEN, KM_SLEEP); 157*7c478bd9Sstevel@tonic-gate char prefix = '\0'; 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 160*7c478bd9Sstevel@tonic-gate if (strchr("^!?", fmt[0]) != NULL) { 161*7c478bd9Sstevel@tonic-gate prefix = fmt[0]; 162*7c478bd9Sstevel@tonic-gate fmt++; 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate (void) vsnprintf(buf, FE_BUFLEN, fmt, ap); 165*7c478bd9Sstevel@tonic-gate va_end(ap); 166*7c478bd9Sstevel@tonic-gate (void) snprintf(trailer, FE_BUFLEN, " on line %d of %s", 167*7c478bd9Sstevel@tonic-gate kobj_linenum(file), kobj_filename(file)); 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate /* 170*7c478bd9Sstevel@tonic-gate * If prefixed with !^?, prepend that character 171*7c478bd9Sstevel@tonic-gate */ 172*7c478bd9Sstevel@tonic-gate if (prefix != '\0') { 173*7c478bd9Sstevel@tonic-gate (void) snprintf(fmt_str, FE_BUFLEN, "%c%%s%%s", prefix); 174*7c478bd9Sstevel@tonic-gate } else { 175*7c478bd9Sstevel@tonic-gate (void) strncpy(fmt_str, "%s%s", FE_BUFLEN); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate cmn_err(type, fmt_str, buf, trailer); 179*7c478bd9Sstevel@tonic-gate kmem_free(buf, FE_BUFLEN); 180*7c478bd9Sstevel@tonic-gate kmem_free(trailer, FE_BUFLEN); 181*7c478bd9Sstevel@tonic-gate kmem_free(fmt_str, FE_BUFLEN); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 185*7c478bd9Sstevel@tonic-gate char *tokennames[] = { 186*7c478bd9Sstevel@tonic-gate "EQUALS", 187*7c478bd9Sstevel@tonic-gate "AMPERSAND", 188*7c478bd9Sstevel@tonic-gate "BIT_OR", 189*7c478bd9Sstevel@tonic-gate "STAR", 190*7c478bd9Sstevel@tonic-gate "POUND", 191*7c478bd9Sstevel@tonic-gate "COLON", 192*7c478bd9Sstevel@tonic-gate "SEMICOLON", 193*7c478bd9Sstevel@tonic-gate "COMMA", 194*7c478bd9Sstevel@tonic-gate "SLASH", 195*7c478bd9Sstevel@tonic-gate "WHITE_SPACE", 196*7c478bd9Sstevel@tonic-gate "NEWLINE", 197*7c478bd9Sstevel@tonic-gate "EOF", 198*7c478bd9Sstevel@tonic-gate "STRING", 199*7c478bd9Sstevel@tonic-gate "HEXVAL", 200*7c478bd9Sstevel@tonic-gate "DECVAL", 201*7c478bd9Sstevel@tonic-gate "NAME" 202*7c478bd9Sstevel@tonic-gate }; 203*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate token_t 206*7c478bd9Sstevel@tonic-gate kobj_lex(struct _buf *file, char *val, size_t size) 207*7c478bd9Sstevel@tonic-gate { 208*7c478bd9Sstevel@tonic-gate char *cp; 209*7c478bd9Sstevel@tonic-gate int ch, oval, badquote; 210*7c478bd9Sstevel@tonic-gate size_t remain; 211*7c478bd9Sstevel@tonic-gate token_t token; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if (size < 2) 214*7c478bd9Sstevel@tonic-gate return (-1); 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate cp = val; 217*7c478bd9Sstevel@tonic-gate while ((ch = kobj_getc(file)) == ' ' || ch == '\t') 218*7c478bd9Sstevel@tonic-gate ; 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate remain = size - 1; 221*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 222*7c478bd9Sstevel@tonic-gate switch (ch) { 223*7c478bd9Sstevel@tonic-gate case '=': 224*7c478bd9Sstevel@tonic-gate token = EQUALS; 225*7c478bd9Sstevel@tonic-gate break; 226*7c478bd9Sstevel@tonic-gate case '&': 227*7c478bd9Sstevel@tonic-gate token = AMPERSAND; 228*7c478bd9Sstevel@tonic-gate break; 229*7c478bd9Sstevel@tonic-gate case '|': 230*7c478bd9Sstevel@tonic-gate token = BIT_OR; 231*7c478bd9Sstevel@tonic-gate break; 232*7c478bd9Sstevel@tonic-gate case '*': 233*7c478bd9Sstevel@tonic-gate token = STAR; 234*7c478bd9Sstevel@tonic-gate break; 235*7c478bd9Sstevel@tonic-gate case '#': 236*7c478bd9Sstevel@tonic-gate token = POUND; 237*7c478bd9Sstevel@tonic-gate break; 238*7c478bd9Sstevel@tonic-gate case ':': 239*7c478bd9Sstevel@tonic-gate token = COLON; 240*7c478bd9Sstevel@tonic-gate break; 241*7c478bd9Sstevel@tonic-gate case ';': 242*7c478bd9Sstevel@tonic-gate token = SEMICOLON; 243*7c478bd9Sstevel@tonic-gate break; 244*7c478bd9Sstevel@tonic-gate case ',': 245*7c478bd9Sstevel@tonic-gate token = COMMA; 246*7c478bd9Sstevel@tonic-gate break; 247*7c478bd9Sstevel@tonic-gate case '/': 248*7c478bd9Sstevel@tonic-gate token = SLASH; 249*7c478bd9Sstevel@tonic-gate break; 250*7c478bd9Sstevel@tonic-gate case ' ': 251*7c478bd9Sstevel@tonic-gate case '\t': 252*7c478bd9Sstevel@tonic-gate case '\f': 253*7c478bd9Sstevel@tonic-gate while ((ch = kobj_getc(file)) == ' ' || 254*7c478bd9Sstevel@tonic-gate ch == '\t' || ch == '\f') { 255*7c478bd9Sstevel@tonic-gate if (--remain == 0) { 256*7c478bd9Sstevel@tonic-gate *cp = '\0'; 257*7c478bd9Sstevel@tonic-gate return (-1); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 262*7c478bd9Sstevel@tonic-gate token = WHITE_SPACE; 263*7c478bd9Sstevel@tonic-gate break; 264*7c478bd9Sstevel@tonic-gate case '\n': 265*7c478bd9Sstevel@tonic-gate case '\r': 266*7c478bd9Sstevel@tonic-gate token = NEWLINE; 267*7c478bd9Sstevel@tonic-gate break; 268*7c478bd9Sstevel@tonic-gate case '"': 269*7c478bd9Sstevel@tonic-gate remain++; 270*7c478bd9Sstevel@tonic-gate cp--; 271*7c478bd9Sstevel@tonic-gate badquote = 0; 272*7c478bd9Sstevel@tonic-gate while (!badquote && (ch = kobj_getc(file)) != '"') { 273*7c478bd9Sstevel@tonic-gate switch (ch) { 274*7c478bd9Sstevel@tonic-gate case '\n': 275*7c478bd9Sstevel@tonic-gate case -1: 276*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "Missing \""); 277*7c478bd9Sstevel@tonic-gate remain = size - 1; 278*7c478bd9Sstevel@tonic-gate cp = val; 279*7c478bd9Sstevel@tonic-gate *cp++ = '\n'; 280*7c478bd9Sstevel@tonic-gate badquote = 1; 281*7c478bd9Sstevel@tonic-gate /* since we consumed the newline/EOF */ 282*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 283*7c478bd9Sstevel@tonic-gate break; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate case '\\': 286*7c478bd9Sstevel@tonic-gate if (--remain == 0) { 287*7c478bd9Sstevel@tonic-gate *cp = '\0'; 288*7c478bd9Sstevel@tonic-gate return (-1); 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate ch = (char)kobj_getc(file); 291*7c478bd9Sstevel@tonic-gate if (!isdigit(ch)) { 292*7c478bd9Sstevel@tonic-gate /* escape the character */ 293*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 294*7c478bd9Sstevel@tonic-gate break; 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate oval = 0; 297*7c478bd9Sstevel@tonic-gate while (ch >= '0' && ch <= '7') { 298*7c478bd9Sstevel@tonic-gate ch -= '0'; 299*7c478bd9Sstevel@tonic-gate oval = (oval << 3) + ch; 300*7c478bd9Sstevel@tonic-gate ch = (char)kobj_getc(file); 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 303*7c478bd9Sstevel@tonic-gate /* check for character overflow? */ 304*7c478bd9Sstevel@tonic-gate if (oval > 127) { 305*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 306*7c478bd9Sstevel@tonic-gate "Character " 307*7c478bd9Sstevel@tonic-gate "overflow detected."); 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate *cp++ = (char)oval; 310*7c478bd9Sstevel@tonic-gate break; 311*7c478bd9Sstevel@tonic-gate default: 312*7c478bd9Sstevel@tonic-gate if (--remain == 0) { 313*7c478bd9Sstevel@tonic-gate *cp = '\0'; 314*7c478bd9Sstevel@tonic-gate return (-1); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 317*7c478bd9Sstevel@tonic-gate break; 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate token = STRING; 321*7c478bd9Sstevel@tonic-gate break; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate case -1: 324*7c478bd9Sstevel@tonic-gate token = EOF; 325*7c478bd9Sstevel@tonic-gate break; 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate default: 328*7c478bd9Sstevel@tonic-gate /* 329*7c478bd9Sstevel@tonic-gate * detect a lone '-' (including at the end of a line), and 330*7c478bd9Sstevel@tonic-gate * identify it as a 'name' 331*7c478bd9Sstevel@tonic-gate */ 332*7c478bd9Sstevel@tonic-gate if (ch == '-') { 333*7c478bd9Sstevel@tonic-gate if (--remain == 0) { 334*7c478bd9Sstevel@tonic-gate *cp = '\0'; 335*7c478bd9Sstevel@tonic-gate return (-1); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate *cp++ = (char)(ch = kobj_getc(file)); 338*7c478bd9Sstevel@tonic-gate if (iswhite(ch) || (ch == '\n')) { 339*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 340*7c478bd9Sstevel@tonic-gate remain++; 341*7c478bd9Sstevel@tonic-gate cp--; 342*7c478bd9Sstevel@tonic-gate token = NAME; 343*7c478bd9Sstevel@tonic-gate break; 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate } else if (isunary(ch)) { 346*7c478bd9Sstevel@tonic-gate if (--remain == 0) { 347*7c478bd9Sstevel@tonic-gate *cp = '\0'; 348*7c478bd9Sstevel@tonic-gate return (-1); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate *cp++ = (char)(ch = kobj_getc(file)); 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate if (isdigit(ch)) { 355*7c478bd9Sstevel@tonic-gate if (ch == '0') { 356*7c478bd9Sstevel@tonic-gate if ((ch = kobj_getc(file)) == 'x') { 357*7c478bd9Sstevel@tonic-gate if (--remain == 0) { 358*7c478bd9Sstevel@tonic-gate *cp = '\0'; 359*7c478bd9Sstevel@tonic-gate return (-1); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 362*7c478bd9Sstevel@tonic-gate ch = kobj_getc(file); 363*7c478bd9Sstevel@tonic-gate while (isxdigit(ch)) { 364*7c478bd9Sstevel@tonic-gate if (--remain == 0) { 365*7c478bd9Sstevel@tonic-gate *cp = '\0'; 366*7c478bd9Sstevel@tonic-gate return (-1); 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 369*7c478bd9Sstevel@tonic-gate ch = kobj_getc(file); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 372*7c478bd9Sstevel@tonic-gate token = HEXVAL; 373*7c478bd9Sstevel@tonic-gate } else { 374*7c478bd9Sstevel@tonic-gate goto digit; 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate } else { 377*7c478bd9Sstevel@tonic-gate ch = kobj_getc(file); 378*7c478bd9Sstevel@tonic-gate digit: 379*7c478bd9Sstevel@tonic-gate while (isdigit(ch)) { 380*7c478bd9Sstevel@tonic-gate if (--remain == 0) { 381*7c478bd9Sstevel@tonic-gate *cp = '\0'; 382*7c478bd9Sstevel@tonic-gate return (-1); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 385*7c478bd9Sstevel@tonic-gate ch = kobj_getc(file); 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 388*7c478bd9Sstevel@tonic-gate token = DECVAL; 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate } else if (isalpha(ch) || ch == '\\' || ch == '_') { 391*7c478bd9Sstevel@tonic-gate if (ch != '\\') { 392*7c478bd9Sstevel@tonic-gate ch = kobj_getc(file); 393*7c478bd9Sstevel@tonic-gate } else { 394*7c478bd9Sstevel@tonic-gate /* 395*7c478bd9Sstevel@tonic-gate * if the character was a backslash, 396*7c478bd9Sstevel@tonic-gate * back up so we can overwrite it with 397*7c478bd9Sstevel@tonic-gate * the next (i.e. escaped) character. 398*7c478bd9Sstevel@tonic-gate */ 399*7c478bd9Sstevel@tonic-gate remain++; 400*7c478bd9Sstevel@tonic-gate cp--; 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate while (isnamechar(ch) || ch == '\\') { 403*7c478bd9Sstevel@tonic-gate if (ch == '\\') 404*7c478bd9Sstevel@tonic-gate ch = kobj_getc(file); 405*7c478bd9Sstevel@tonic-gate if (--remain == 0) { 406*7c478bd9Sstevel@tonic-gate *cp = '\0'; 407*7c478bd9Sstevel@tonic-gate return (-1); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 410*7c478bd9Sstevel@tonic-gate ch = kobj_getc(file); 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 413*7c478bd9Sstevel@tonic-gate token = NAME; 414*7c478bd9Sstevel@tonic-gate } else { 415*7c478bd9Sstevel@tonic-gate return (-1); 416*7c478bd9Sstevel@tonic-gate } 417*7c478bd9Sstevel@tonic-gate break; 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate *cp = '\0'; 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 423*7c478bd9Sstevel@tonic-gate parse_debug(NULL, "kobj_lex: token %s value '%s'\n", tokennames[token], 424*7c478bd9Sstevel@tonic-gate val); 425*7c478bd9Sstevel@tonic-gate #endif 426*7c478bd9Sstevel@tonic-gate return (token); 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate /* 430*7c478bd9Sstevel@tonic-gate * Leave NEWLINE as the next character. 431*7c478bd9Sstevel@tonic-gate */ 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate void 434*7c478bd9Sstevel@tonic-gate kobj_find_eol(struct _buf *file) 435*7c478bd9Sstevel@tonic-gate { 436*7c478bd9Sstevel@tonic-gate int ch; 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate while ((ch = kobj_getc(file)) != -1) { 439*7c478bd9Sstevel@tonic-gate if (isnewline(ch)) { 440*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 441*7c478bd9Sstevel@tonic-gate break; 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate /* 447*7c478bd9Sstevel@tonic-gate * The ascii system file is read and processed. 448*7c478bd9Sstevel@tonic-gate * 449*7c478bd9Sstevel@tonic-gate * The syntax of commands is as follows: 450*7c478bd9Sstevel@tonic-gate * 451*7c478bd9Sstevel@tonic-gate * '*' in column 1 is a comment line. 452*7c478bd9Sstevel@tonic-gate * <command> : <value> 453*7c478bd9Sstevel@tonic-gate * 454*7c478bd9Sstevel@tonic-gate * command is EXCLUDE, INCLUDE, FORCELOAD, ROOTDEV, ROOTFS, 455*7c478bd9Sstevel@tonic-gate * SWAPDEV, SWAPFS, MODDIR, SET 456*7c478bd9Sstevel@tonic-gate * 457*7c478bd9Sstevel@tonic-gate * value is an ascii string meaningful for the command. 458*7c478bd9Sstevel@tonic-gate */ 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate /* 461*7c478bd9Sstevel@tonic-gate * Table of commands 462*7c478bd9Sstevel@tonic-gate */ 463*7c478bd9Sstevel@tonic-gate static struct modcmd modcmd[] = { 464*7c478bd9Sstevel@tonic-gate { "EXCLUDE", MOD_EXCLUDE }, 465*7c478bd9Sstevel@tonic-gate { "exclude", MOD_EXCLUDE }, 466*7c478bd9Sstevel@tonic-gate { "INCLUDE", MOD_INCLUDE }, 467*7c478bd9Sstevel@tonic-gate { "include", MOD_INCLUDE }, 468*7c478bd9Sstevel@tonic-gate { "FORCELOAD", MOD_FORCELOAD }, 469*7c478bd9Sstevel@tonic-gate { "forceload", MOD_FORCELOAD }, 470*7c478bd9Sstevel@tonic-gate { "ROOTDEV", MOD_ROOTDEV }, 471*7c478bd9Sstevel@tonic-gate { "rootdev", MOD_ROOTDEV }, 472*7c478bd9Sstevel@tonic-gate { "ROOTFS", MOD_ROOTFS }, 473*7c478bd9Sstevel@tonic-gate { "rootfs", MOD_ROOTFS }, 474*7c478bd9Sstevel@tonic-gate { "SWAPDEV", MOD_SWAPDEV }, 475*7c478bd9Sstevel@tonic-gate { "swapdev", MOD_SWAPDEV }, 476*7c478bd9Sstevel@tonic-gate { "SWAPFS", MOD_SWAPFS }, 477*7c478bd9Sstevel@tonic-gate { "swapfs", MOD_SWAPFS }, 478*7c478bd9Sstevel@tonic-gate { "MODDIR", MOD_MODDIR }, 479*7c478bd9Sstevel@tonic-gate { "moddir", MOD_MODDIR }, 480*7c478bd9Sstevel@tonic-gate { "SET", MOD_SET }, 481*7c478bd9Sstevel@tonic-gate { "set", MOD_SET }, 482*7c478bd9Sstevel@tonic-gate { "SET32", MOD_SET32 }, 483*7c478bd9Sstevel@tonic-gate { "set32", MOD_SET32 }, 484*7c478bd9Sstevel@tonic-gate { "SET64", MOD_SET64 }, 485*7c478bd9Sstevel@tonic-gate { "set64", MOD_SET64 }, 486*7c478bd9Sstevel@tonic-gate { NULL, MOD_UNKNOWN } 487*7c478bd9Sstevel@tonic-gate }; 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate static char bad_op[] = "illegal operator '%s' used on a string"; 491*7c478bd9Sstevel@tonic-gate static char colon_err[] = "A colon (:) must follow the '%s' command"; 492*7c478bd9Sstevel@tonic-gate static char tok_err[] = "Unexpected token '%s'"; 493*7c478bd9Sstevel@tonic-gate static char extra_err[] = "extraneous input ignored starting at '%s'"; 494*7c478bd9Sstevel@tonic-gate static char oversize_err[] = "value too long"; 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate static struct sysparam * 497*7c478bd9Sstevel@tonic-gate do_sysfile_cmd(struct _buf *file, const char *cmd) 498*7c478bd9Sstevel@tonic-gate { 499*7c478bd9Sstevel@tonic-gate struct sysparam *sysp; 500*7c478bd9Sstevel@tonic-gate struct modcmd *mcp; 501*7c478bd9Sstevel@tonic-gate token_t token, op; 502*7c478bd9Sstevel@tonic-gate char *cp; 503*7c478bd9Sstevel@tonic-gate int ch; 504*7c478bd9Sstevel@tonic-gate char tok1[MOD_MAXPATH + 1]; /* used to read the path set by 'moddir' */ 505*7c478bd9Sstevel@tonic-gate char tok2[64]; 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate for (mcp = modcmd; mcp->mc_cmdname != NULL; mcp++) { 508*7c478bd9Sstevel@tonic-gate if (strcmp(mcp->mc_cmdname, cmd) == 0) 509*7c478bd9Sstevel@tonic-gate break; 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate sysp = vmem_alloc(mod_sysfile_arena, sizeof (struct sysparam), 512*7c478bd9Sstevel@tonic-gate VM_SLEEP); 513*7c478bd9Sstevel@tonic-gate bzero(sysp, sizeof (struct sysparam)); 514*7c478bd9Sstevel@tonic-gate sysp->sys_op = SETOP_NONE; /* set op to noop initially */ 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate switch (sysp->sys_type = mcp->mc_type) { 517*7c478bd9Sstevel@tonic-gate case MOD_INCLUDE: 518*7c478bd9Sstevel@tonic-gate case MOD_EXCLUDE: 519*7c478bd9Sstevel@tonic-gate case MOD_FORCELOAD: 520*7c478bd9Sstevel@tonic-gate /* 521*7c478bd9Sstevel@tonic-gate * Are followed by colon. 522*7c478bd9Sstevel@tonic-gate */ 523*7c478bd9Sstevel@tonic-gate case MOD_ROOTFS: 524*7c478bd9Sstevel@tonic-gate case MOD_SWAPFS: 525*7c478bd9Sstevel@tonic-gate if ((token = kobj_lex(file, tok1, sizeof (tok1))) == COLON) { 526*7c478bd9Sstevel@tonic-gate token = kobj_lex(file, tok1, sizeof (tok1)); 527*7c478bd9Sstevel@tonic-gate } else { 528*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, colon_err, cmd); 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate if (token != NAME) { 531*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "value expected"); 532*7c478bd9Sstevel@tonic-gate goto bad; 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate cp = tok1 + strlen(tok1); 536*7c478bd9Sstevel@tonic-gate while ((ch = kobj_getc(file)) != -1 && !iswhite(ch) && 537*7c478bd9Sstevel@tonic-gate !isnewline(ch)) { 538*7c478bd9Sstevel@tonic-gate if (cp - tok1 >= sizeof (tok1) - 1) { 539*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, oversize_err); 540*7c478bd9Sstevel@tonic-gate goto bad; 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate *cp = '\0'; 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate if (ch != -1) 547*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 548*7c478bd9Sstevel@tonic-gate if (sysp->sys_type == MOD_INCLUDE) 549*7c478bd9Sstevel@tonic-gate return (NULL); 550*7c478bd9Sstevel@tonic-gate sysp->sys_ptr = vmem_alloc(mod_sysfile_arena, strlen(tok1) + 1, 551*7c478bd9Sstevel@tonic-gate VM_SLEEP); 552*7c478bd9Sstevel@tonic-gate (void) strcpy(sysp->sys_ptr, tok1); 553*7c478bd9Sstevel@tonic-gate break; 554*7c478bd9Sstevel@tonic-gate case MOD_SET: 555*7c478bd9Sstevel@tonic-gate case MOD_SET64: 556*7c478bd9Sstevel@tonic-gate case MOD_SET32: 557*7c478bd9Sstevel@tonic-gate { 558*7c478bd9Sstevel@tonic-gate char *var; 559*7c478bd9Sstevel@tonic-gate token_t tok3; 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate if (kobj_lex(file, tok1, sizeof (tok1)) != NAME) { 562*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "value expected"); 563*7c478bd9Sstevel@tonic-gate goto bad; 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate /* 567*7c478bd9Sstevel@tonic-gate * If the next token is a colon (:), 568*7c478bd9Sstevel@tonic-gate * we have the <modname>:<variable> construct. 569*7c478bd9Sstevel@tonic-gate */ 570*7c478bd9Sstevel@tonic-gate if ((token = kobj_lex(file, tok2, sizeof (tok2))) == COLON) { 571*7c478bd9Sstevel@tonic-gate if ((token = kobj_lex(file, tok2, 572*7c478bd9Sstevel@tonic-gate sizeof (tok2))) == NAME) { 573*7c478bd9Sstevel@tonic-gate var = tok2; 574*7c478bd9Sstevel@tonic-gate /* 575*7c478bd9Sstevel@tonic-gate * Save the module name. 576*7c478bd9Sstevel@tonic-gate */ 577*7c478bd9Sstevel@tonic-gate sysp->sys_modnam = vmem_alloc(mod_sysfile_arena, 578*7c478bd9Sstevel@tonic-gate strlen(tok1) + 1, VM_SLEEP); 579*7c478bd9Sstevel@tonic-gate (void) strcpy(sysp->sys_modnam, tok1); 580*7c478bd9Sstevel@tonic-gate op = kobj_lex(file, tok1, sizeof (tok1)); 581*7c478bd9Sstevel@tonic-gate } else { 582*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "value expected"); 583*7c478bd9Sstevel@tonic-gate goto bad; 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate } else { 586*7c478bd9Sstevel@tonic-gate /* otherwise, it was the op */ 587*7c478bd9Sstevel@tonic-gate var = tok1; 588*7c478bd9Sstevel@tonic-gate op = token; 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate /* 591*7c478bd9Sstevel@tonic-gate * kernel param - place variable name in sys_ptr. 592*7c478bd9Sstevel@tonic-gate */ 593*7c478bd9Sstevel@tonic-gate sysp->sys_ptr = vmem_alloc(mod_sysfile_arena, strlen(var) + 1, 594*7c478bd9Sstevel@tonic-gate VM_SLEEP); 595*7c478bd9Sstevel@tonic-gate (void) strcpy(sysp->sys_ptr, var); 596*7c478bd9Sstevel@tonic-gate /* set operation */ 597*7c478bd9Sstevel@tonic-gate switch (op) { 598*7c478bd9Sstevel@tonic-gate case EQUALS: 599*7c478bd9Sstevel@tonic-gate /* simple assignment */ 600*7c478bd9Sstevel@tonic-gate sysp->sys_op = SETOP_ASSIGN; 601*7c478bd9Sstevel@tonic-gate break; 602*7c478bd9Sstevel@tonic-gate case AMPERSAND: 603*7c478bd9Sstevel@tonic-gate /* bitwise AND */ 604*7c478bd9Sstevel@tonic-gate sysp->sys_op = SETOP_AND; 605*7c478bd9Sstevel@tonic-gate break; 606*7c478bd9Sstevel@tonic-gate case BIT_OR: 607*7c478bd9Sstevel@tonic-gate /* bitwise OR */ 608*7c478bd9Sstevel@tonic-gate sysp->sys_op = SETOP_OR; 609*7c478bd9Sstevel@tonic-gate break; 610*7c478bd9Sstevel@tonic-gate default: 611*7c478bd9Sstevel@tonic-gate /* unsupported operation */ 612*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 613*7c478bd9Sstevel@tonic-gate "unsupported operator %s", tok2); 614*7c478bd9Sstevel@tonic-gate goto bad; 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate switch ((tok3 = kobj_lex(file, tok1, sizeof (tok1)))) { 618*7c478bd9Sstevel@tonic-gate case STRING: 619*7c478bd9Sstevel@tonic-gate /* string variable */ 620*7c478bd9Sstevel@tonic-gate if (sysp->sys_op != SETOP_ASSIGN) { 621*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, bad_op, tok1); 622*7c478bd9Sstevel@tonic-gate goto bad; 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate if (kobj_get_string(&sysp->sys_info, tok1) == 0) { 625*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "string garbled"); 626*7c478bd9Sstevel@tonic-gate goto bad; 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate /* 629*7c478bd9Sstevel@tonic-gate * Set SYSPARAM_STR_TOKEN in sys_flags to notify 630*7c478bd9Sstevel@tonic-gate * sysparam_print_warning() that this is a string 631*7c478bd9Sstevel@tonic-gate * token. 632*7c478bd9Sstevel@tonic-gate */ 633*7c478bd9Sstevel@tonic-gate sysp->sys_flags |= SYSPARAM_STR_TOKEN; 634*7c478bd9Sstevel@tonic-gate break; 635*7c478bd9Sstevel@tonic-gate case HEXVAL: 636*7c478bd9Sstevel@tonic-gate case DECVAL: 637*7c478bd9Sstevel@tonic-gate if (kobj_getvalue(tok1, &sysp->sys_info) == -1) { 638*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 639*7c478bd9Sstevel@tonic-gate "invalid number '%s'", tok1); 640*7c478bd9Sstevel@tonic-gate goto bad; 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate /* 644*7c478bd9Sstevel@tonic-gate * Set the appropriate flag (hexadecimal or decimal) 645*7c478bd9Sstevel@tonic-gate * in sys_flags for sysparam_print_warning() to be 646*7c478bd9Sstevel@tonic-gate * able to print the number with the correct format. 647*7c478bd9Sstevel@tonic-gate */ 648*7c478bd9Sstevel@tonic-gate if (tok3 == HEXVAL) { 649*7c478bd9Sstevel@tonic-gate sysp->sys_flags |= SYSPARAM_HEX_TOKEN; 650*7c478bd9Sstevel@tonic-gate } else { 651*7c478bd9Sstevel@tonic-gate sysp->sys_flags |= SYSPARAM_DEC_TOKEN; 652*7c478bd9Sstevel@tonic-gate } 653*7c478bd9Sstevel@tonic-gate break; 654*7c478bd9Sstevel@tonic-gate default: 655*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "bad rvalue '%s'", tok1); 656*7c478bd9Sstevel@tonic-gate goto bad; 657*7c478bd9Sstevel@tonic-gate } /* end switch */ 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate /* 660*7c478bd9Sstevel@tonic-gate * Now that we've parsed it to check the syntax, consider 661*7c478bd9Sstevel@tonic-gate * discarding it (because it -doesn't- apply to this flavor 662*7c478bd9Sstevel@tonic-gate * of the kernel) 663*7c478bd9Sstevel@tonic-gate */ 664*7c478bd9Sstevel@tonic-gate #ifdef _LP64 665*7c478bd9Sstevel@tonic-gate if (sysp->sys_type == MOD_SET32) 666*7c478bd9Sstevel@tonic-gate return (NULL); 667*7c478bd9Sstevel@tonic-gate #else 668*7c478bd9Sstevel@tonic-gate if (sysp->sys_type == MOD_SET64) 669*7c478bd9Sstevel@tonic-gate return (NULL); 670*7c478bd9Sstevel@tonic-gate #endif 671*7c478bd9Sstevel@tonic-gate sysp->sys_type = MOD_SET; 672*7c478bd9Sstevel@tonic-gate break; 673*7c478bd9Sstevel@tonic-gate } 674*7c478bd9Sstevel@tonic-gate case MOD_MODDIR: 675*7c478bd9Sstevel@tonic-gate if ((token = kobj_lex(file, tok1, sizeof (tok1))) != COLON) { 676*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, colon_err, cmd); 677*7c478bd9Sstevel@tonic-gate goto bad; 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate cp = tok1; 681*7c478bd9Sstevel@tonic-gate while ((token = kobj_lex(file, cp, 682*7c478bd9Sstevel@tonic-gate sizeof (tok1) - (cp - tok1))) != NEWLINE && token != EOF) { 683*7c478bd9Sstevel@tonic-gate if (token == -1) { 684*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, oversize_err); 685*7c478bd9Sstevel@tonic-gate goto bad; 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate cp += strlen(cp); 688*7c478bd9Sstevel@tonic-gate while ((ch = kobj_getc(file)) != -1 && !iswhite(ch) && 689*7c478bd9Sstevel@tonic-gate !isnewline(ch) && ch != ':') { 690*7c478bd9Sstevel@tonic-gate if (cp - tok1 >= sizeof (tok1) - 1) { 691*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 692*7c478bd9Sstevel@tonic-gate oversize_err); 693*7c478bd9Sstevel@tonic-gate goto bad; 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate *cp = ':'; 698*7c478bd9Sstevel@tonic-gate if (isnewline(ch)) 699*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 702*7c478bd9Sstevel@tonic-gate *cp = '\0'; 703*7c478bd9Sstevel@tonic-gate sysp->sys_ptr = vmem_alloc(mod_sysfile_arena, strlen(tok1) + 1, 704*7c478bd9Sstevel@tonic-gate VM_SLEEP); 705*7c478bd9Sstevel@tonic-gate (void) strcpy(sysp->sys_ptr, tok1); 706*7c478bd9Sstevel@tonic-gate break; 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate case MOD_SWAPDEV: 709*7c478bd9Sstevel@tonic-gate case MOD_ROOTDEV: 710*7c478bd9Sstevel@tonic-gate if ((token = kobj_lex(file, tok1, sizeof (tok1))) != COLON) { 711*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, colon_err, cmd); 712*7c478bd9Sstevel@tonic-gate goto bad; 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate while ((ch = kobj_getc(file)) == ' ' || ch == '\t') 715*7c478bd9Sstevel@tonic-gate ; 716*7c478bd9Sstevel@tonic-gate cp = tok1; 717*7c478bd9Sstevel@tonic-gate while (!iswhite(ch) && !isnewline(ch) && ch != -1) { 718*7c478bd9Sstevel@tonic-gate if (cp - tok1 >= sizeof (tok1) - 1) { 719*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, oversize_err); 720*7c478bd9Sstevel@tonic-gate goto bad; 721*7c478bd9Sstevel@tonic-gate } 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 724*7c478bd9Sstevel@tonic-gate ch = kobj_getc(file); 725*7c478bd9Sstevel@tonic-gate } 726*7c478bd9Sstevel@tonic-gate if (ch != -1) 727*7c478bd9Sstevel@tonic-gate (void) kobj_ungetc(file); 728*7c478bd9Sstevel@tonic-gate *cp = '\0'; 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate sysp->sys_ptr = vmem_alloc(mod_sysfile_arena, strlen(tok1) + 1, 731*7c478bd9Sstevel@tonic-gate VM_SLEEP); 732*7c478bd9Sstevel@tonic-gate (void) strcpy(sysp->sys_ptr, tok1); 733*7c478bd9Sstevel@tonic-gate break; 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate case MOD_UNKNOWN: 736*7c478bd9Sstevel@tonic-gate default: 737*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "unknown command '%s'", cmd); 738*7c478bd9Sstevel@tonic-gate goto bad; 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate return (sysp); 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate bad: 744*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 745*7c478bd9Sstevel@tonic-gate return (NULL); 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate void 749*7c478bd9Sstevel@tonic-gate mod_read_system_file(int ask) 750*7c478bd9Sstevel@tonic-gate { 751*7c478bd9Sstevel@tonic-gate register struct sysparam *sp; 752*7c478bd9Sstevel@tonic-gate register struct _buf *file; 753*7c478bd9Sstevel@tonic-gate register token_t token, last_tok; 754*7c478bd9Sstevel@tonic-gate char tokval[MAXLINESIZE]; 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate mod_sysfile_arena = vmem_create("mod_sysfile", NULL, 0, 8, 757*7c478bd9Sstevel@tonic-gate segkmem_alloc, segkmem_free, heap_arena, 0, VM_SLEEP); 758*7c478bd9Sstevel@tonic-gate 759*7c478bd9Sstevel@tonic-gate if (ask) 760*7c478bd9Sstevel@tonic-gate mod_askparams(); 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate if (systemfile != NULL) { 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate if ((file = kobj_open_file(systemfile)) == 765*7c478bd9Sstevel@tonic-gate (struct _buf *)-1) { 766*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "cannot open system file: %s", 767*7c478bd9Sstevel@tonic-gate systemfile); 768*7c478bd9Sstevel@tonic-gate } else { 769*7c478bd9Sstevel@tonic-gate sysparam_tl = (struct sysparam *)&sysparam_hd; 770*7c478bd9Sstevel@tonic-gate 771*7c478bd9Sstevel@tonic-gate last_tok = NEWLINE; 772*7c478bd9Sstevel@tonic-gate while ((token = kobj_lex(file, tokval, 773*7c478bd9Sstevel@tonic-gate sizeof (tokval))) != EOF) { 774*7c478bd9Sstevel@tonic-gate switch (token) { 775*7c478bd9Sstevel@tonic-gate case STAR: 776*7c478bd9Sstevel@tonic-gate case POUND: 777*7c478bd9Sstevel@tonic-gate /* 778*7c478bd9Sstevel@tonic-gate * Skip comments. 779*7c478bd9Sstevel@tonic-gate */ 780*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 781*7c478bd9Sstevel@tonic-gate break; 782*7c478bd9Sstevel@tonic-gate case NEWLINE: 783*7c478bd9Sstevel@tonic-gate kobj_newline(file); 784*7c478bd9Sstevel@tonic-gate last_tok = NEWLINE; 785*7c478bd9Sstevel@tonic-gate break; 786*7c478bd9Sstevel@tonic-gate case NAME: 787*7c478bd9Sstevel@tonic-gate if (last_tok != NEWLINE) { 788*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 789*7c478bd9Sstevel@tonic-gate extra_err, tokval); 790*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 791*7c478bd9Sstevel@tonic-gate } else if ((sp = do_sysfile_cmd(file, 792*7c478bd9Sstevel@tonic-gate tokval)) != NULL) { 793*7c478bd9Sstevel@tonic-gate sp->sys_next = NULL; 794*7c478bd9Sstevel@tonic-gate sysparam_tl->sys_next = sp; 795*7c478bd9Sstevel@tonic-gate sysparam_tl = sp; 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate last_tok = NAME; 798*7c478bd9Sstevel@tonic-gate break; 799*7c478bd9Sstevel@tonic-gate default: 800*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, 801*7c478bd9Sstevel@tonic-gate file, tok_err, tokval); 802*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 803*7c478bd9Sstevel@tonic-gate break; 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate kobj_close_file(file); 807*7c478bd9Sstevel@tonic-gate } 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate /* 811*7c478bd9Sstevel@tonic-gate * Sanity check of /etc/system. 812*7c478bd9Sstevel@tonic-gate */ 813*7c478bd9Sstevel@tonic-gate check_system_file(); 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate param_preset(); 816*7c478bd9Sstevel@tonic-gate (void) mod_sysctl(SYS_SET_KVAR, NULL); 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate if (ask == 0) 819*7c478bd9Sstevel@tonic-gate setparams(); 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate 822*7c478bd9Sstevel@tonic-gate /* 823*7c478bd9Sstevel@tonic-gate * Search for a specific module variable assignment in /etc/system. If 824*7c478bd9Sstevel@tonic-gate * successful, 1 is returned and the value is stored in '*value'. 825*7c478bd9Sstevel@tonic-gate * Otherwise 0 is returned and '*value' isn't modified. If 'module' is 826*7c478bd9Sstevel@tonic-gate * NULL we look for global definitions. 827*7c478bd9Sstevel@tonic-gate * 828*7c478bd9Sstevel@tonic-gate * This is useful if the value of an assignment is needed before a 829*7c478bd9Sstevel@tonic-gate * module is loaded (e.g. to obtain a default privileged rctl limit). 830*7c478bd9Sstevel@tonic-gate */ 831*7c478bd9Sstevel@tonic-gate int 832*7c478bd9Sstevel@tonic-gate mod_sysvar(const char *module, const char *name, u_longlong_t *value) 833*7c478bd9Sstevel@tonic-gate { 834*7c478bd9Sstevel@tonic-gate struct sysparam *sysp; 835*7c478bd9Sstevel@tonic-gate int cnt = 0; /* dummy */ 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate ASSERT(name != NULL); 838*7c478bd9Sstevel@tonic-gate ASSERT(value != NULL); 839*7c478bd9Sstevel@tonic-gate for (sysp = sysparam_hd; sysp != NULL; sysp = sysp->sys_next) { 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate if ((sysp->sys_type == MOD_SET) && 842*7c478bd9Sstevel@tonic-gate (((module == NULL) && (sysp->sys_modnam == NULL)) || 843*7c478bd9Sstevel@tonic-gate ((module != NULL) && (sysp->sys_modnam != NULL) && 844*7c478bd9Sstevel@tonic-gate (strcmp(module, sysp->sys_modnam) == 0)))) { 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate ASSERT(sysp->sys_ptr != NULL); 847*7c478bd9Sstevel@tonic-gate 848*7c478bd9Sstevel@tonic-gate if (strcmp(name, sysp->sys_ptr) == 0) { 849*7c478bd9Sstevel@tonic-gate sysparam_count_entry(sysp, &cnt, value); 850*7c478bd9Sstevel@tonic-gate if ((sysp->sys_flags & SYSPARAM_TERM) != 0) 851*7c478bd9Sstevel@tonic-gate return (1); 852*7c478bd9Sstevel@tonic-gate continue; 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate } 856*7c478bd9Sstevel@tonic-gate ASSERT(cnt == 0); 857*7c478bd9Sstevel@tonic-gate return (0); 858*7c478bd9Sstevel@tonic-gate } 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate /* 861*7c478bd9Sstevel@tonic-gate * This function scans sysparam records, which are created from the 862*7c478bd9Sstevel@tonic-gate * contents of /etc/system, for entries which are logical duplicates, 863*7c478bd9Sstevel@tonic-gate * and prints warning messages as appropriate. When multiple "set" 864*7c478bd9Sstevel@tonic-gate * commands are encountered, the pileup of values with "&", "|" 865*7c478bd9Sstevel@tonic-gate * and "=" operators results in the final value. 866*7c478bd9Sstevel@tonic-gate */ 867*7c478bd9Sstevel@tonic-gate static void 868*7c478bd9Sstevel@tonic-gate check_system_file(void) 869*7c478bd9Sstevel@tonic-gate { 870*7c478bd9Sstevel@tonic-gate struct sysparam *sysp; 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate for (sysp = sysparam_hd; sysp != NULL; sysp = sysp->sys_next) { 873*7c478bd9Sstevel@tonic-gate struct sysparam *entry, *final; 874*7c478bd9Sstevel@tonic-gate u_longlong_t value = 0; 875*7c478bd9Sstevel@tonic-gate int cnt = 1; 876*7c478bd9Sstevel@tonic-gate /* 877*7c478bd9Sstevel@tonic-gate * If the entry is already checked, skip it. 878*7c478bd9Sstevel@tonic-gate */ 879*7c478bd9Sstevel@tonic-gate if ((sysp->sys_flags & SYSPARAM_DUP) != 0) 880*7c478bd9Sstevel@tonic-gate continue; 881*7c478bd9Sstevel@tonic-gate /* 882*7c478bd9Sstevel@tonic-gate * Check if there is a duplicate entry by doing a linear 883*7c478bd9Sstevel@tonic-gate * search. 884*7c478bd9Sstevel@tonic-gate */ 885*7c478bd9Sstevel@tonic-gate final = sysp; 886*7c478bd9Sstevel@tonic-gate for (entry = sysp->sys_next; entry != NULL; 887*7c478bd9Sstevel@tonic-gate entry = entry->sys_next) { 888*7c478bd9Sstevel@tonic-gate /* 889*7c478bd9Sstevel@tonic-gate * Check the entry. if it's different, skip this. 890*7c478bd9Sstevel@tonic-gate */ 891*7c478bd9Sstevel@tonic-gate if (sysparam_compare_entry(sysp, entry) != 0) 892*7c478bd9Sstevel@tonic-gate continue; 893*7c478bd9Sstevel@tonic-gate /* 894*7c478bd9Sstevel@tonic-gate * Count the entry and put the mark. 895*7c478bd9Sstevel@tonic-gate */ 896*7c478bd9Sstevel@tonic-gate sysparam_count_entry(entry, &cnt, &value); 897*7c478bd9Sstevel@tonic-gate entry->sys_flags |= SYSPARAM_DUP; 898*7c478bd9Sstevel@tonic-gate final = entry; 899*7c478bd9Sstevel@tonic-gate } 900*7c478bd9Sstevel@tonic-gate final->sys_flags |= SYSPARAM_TERM; 901*7c478bd9Sstevel@tonic-gate /* 902*7c478bd9Sstevel@tonic-gate * Print the warning if it's duplicated. 903*7c478bd9Sstevel@tonic-gate */ 904*7c478bd9Sstevel@tonic-gate if (cnt >= 2) 905*7c478bd9Sstevel@tonic-gate sysparam_print_warning(final, value); 906*7c478bd9Sstevel@tonic-gate } 907*7c478bd9Sstevel@tonic-gate } 908*7c478bd9Sstevel@tonic-gate 909*7c478bd9Sstevel@tonic-gate /* 910*7c478bd9Sstevel@tonic-gate * Compare the sysparam records. 911*7c478bd9Sstevel@tonic-gate * Return 0 if they are the same, return 1 if not. 912*7c478bd9Sstevel@tonic-gate */ 913*7c478bd9Sstevel@tonic-gate static int 914*7c478bd9Sstevel@tonic-gate sysparam_compare_entry(struct sysparam *sysp, struct sysparam *entry) 915*7c478bd9Sstevel@tonic-gate { 916*7c478bd9Sstevel@tonic-gate ASSERT(sysp->sys_ptr != NULL && entry->sys_ptr != NULL); 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate /* 919*7c478bd9Sstevel@tonic-gate * If the command is rootdev, rootfs, swapdev, swapfs or moddir, 920*7c478bd9Sstevel@tonic-gate * the record with the same type is treated as a duplicate record. 921*7c478bd9Sstevel@tonic-gate * In other cases, the record is treated as a duplicate record when 922*7c478bd9Sstevel@tonic-gate * its type, its module name (if it exists), and its variable name 923*7c478bd9Sstevel@tonic-gate * are the same. 924*7c478bd9Sstevel@tonic-gate */ 925*7c478bd9Sstevel@tonic-gate switch (sysp->sys_type) { 926*7c478bd9Sstevel@tonic-gate case MOD_ROOTDEV: 927*7c478bd9Sstevel@tonic-gate case MOD_ROOTFS: 928*7c478bd9Sstevel@tonic-gate case MOD_SWAPDEV: 929*7c478bd9Sstevel@tonic-gate case MOD_SWAPFS: 930*7c478bd9Sstevel@tonic-gate case MOD_MODDIR: 931*7c478bd9Sstevel@tonic-gate return (sysp->sys_type == entry->sys_type ? 0 : 1); 932*7c478bd9Sstevel@tonic-gate default: /* In other cases, just go through it. */ 933*7c478bd9Sstevel@tonic-gate break; 934*7c478bd9Sstevel@tonic-gate } 935*7c478bd9Sstevel@tonic-gate 936*7c478bd9Sstevel@tonic-gate if (sysp->sys_type != entry->sys_type) 937*7c478bd9Sstevel@tonic-gate return (1); 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate if (sysp->sys_modnam != NULL && entry->sys_modnam == NULL) 940*7c478bd9Sstevel@tonic-gate return (1); 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate if (sysp->sys_modnam == NULL && entry->sys_modnam != NULL) 943*7c478bd9Sstevel@tonic-gate return (1); 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate if (sysp->sys_modnam != NULL && entry->sys_modnam != NULL && 946*7c478bd9Sstevel@tonic-gate strcmp(sysp->sys_modnam, entry->sys_modnam) != 0) 947*7c478bd9Sstevel@tonic-gate return (1); 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate return (strcmp(sysp->sys_ptr, entry->sys_ptr)); 950*7c478bd9Sstevel@tonic-gate } 951*7c478bd9Sstevel@tonic-gate 952*7c478bd9Sstevel@tonic-gate /* 953*7c478bd9Sstevel@tonic-gate * Translate a sysparam type value to a string. 954*7c478bd9Sstevel@tonic-gate */ 955*7c478bd9Sstevel@tonic-gate static char * 956*7c478bd9Sstevel@tonic-gate sysparam_type_to_str(int type) 957*7c478bd9Sstevel@tonic-gate { 958*7c478bd9Sstevel@tonic-gate struct modcmd *mcp; 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate for (mcp = modcmd; mcp->mc_cmdname != NULL; mcp++) { 961*7c478bd9Sstevel@tonic-gate if (mcp->mc_type == type) 962*7c478bd9Sstevel@tonic-gate break; 963*7c478bd9Sstevel@tonic-gate } 964*7c478bd9Sstevel@tonic-gate ASSERT(mcp->mc_type == type); 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate if (type != MOD_UNKNOWN) 967*7c478bd9Sstevel@tonic-gate return ((++mcp)->mc_cmdname); /* lower case */ 968*7c478bd9Sstevel@tonic-gate else 969*7c478bd9Sstevel@tonic-gate return (""); /* MOD_UNKNOWN */ 970*7c478bd9Sstevel@tonic-gate } 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate /* 973*7c478bd9Sstevel@tonic-gate * Check the entry and accumulate the number of entries. 974*7c478bd9Sstevel@tonic-gate */ 975*7c478bd9Sstevel@tonic-gate static void 976*7c478bd9Sstevel@tonic-gate sysparam_count_entry(struct sysparam *sysp, int *cnt, u_longlong_t *value) 977*7c478bd9Sstevel@tonic-gate { 978*7c478bd9Sstevel@tonic-gate u_longlong_t ul = sysp->sys_info; 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate switch (sysp->sys_op) { 981*7c478bd9Sstevel@tonic-gate case SETOP_ASSIGN: 982*7c478bd9Sstevel@tonic-gate *value = ul; 983*7c478bd9Sstevel@tonic-gate (*cnt)++; 984*7c478bd9Sstevel@tonic-gate return; 985*7c478bd9Sstevel@tonic-gate case SETOP_AND: 986*7c478bd9Sstevel@tonic-gate *value &= ul; 987*7c478bd9Sstevel@tonic-gate return; 988*7c478bd9Sstevel@tonic-gate case SETOP_OR: 989*7c478bd9Sstevel@tonic-gate *value |= ul; 990*7c478bd9Sstevel@tonic-gate return; 991*7c478bd9Sstevel@tonic-gate default: /* Not MOD_SET */ 992*7c478bd9Sstevel@tonic-gate (*cnt)++; 993*7c478bd9Sstevel@tonic-gate return; 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate } 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate /* 998*7c478bd9Sstevel@tonic-gate * Print out the warning if multiple entries are found in the system file. 999*7c478bd9Sstevel@tonic-gate */ 1000*7c478bd9Sstevel@tonic-gate static void 1001*7c478bd9Sstevel@tonic-gate sysparam_print_warning(struct sysparam *sysp, u_longlong_t value) 1002*7c478bd9Sstevel@tonic-gate { 1003*7c478bd9Sstevel@tonic-gate char *modnam = sysp->sys_modnam; 1004*7c478bd9Sstevel@tonic-gate char *varnam = sysp->sys_ptr; 1005*7c478bd9Sstevel@tonic-gate int type = sysp->sys_type; 1006*7c478bd9Sstevel@tonic-gate char *typenam = sysparam_type_to_str(type); 1007*7c478bd9Sstevel@tonic-gate boolean_t str_token = ((sysp->sys_flags & SYSPARAM_STR_TOKEN) != 0); 1008*7c478bd9Sstevel@tonic-gate boolean_t hex_number = ((sysp->sys_flags & SYSPARAM_HEX_TOKEN) != 0); 1009*7c478bd9Sstevel@tonic-gate #define warn_format1 " is set more than once in /%s. " 1010*7c478bd9Sstevel@tonic-gate #define warn_format2 " applied as the current setting.\n" 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate ASSERT(varnam != NULL); 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate if (type == MOD_SET) { 1015*7c478bd9Sstevel@tonic-gate /* 1016*7c478bd9Sstevel@tonic-gate * If a string token is set, print out the string 1017*7c478bd9Sstevel@tonic-gate * instead of its pointer value. In other cases, 1018*7c478bd9Sstevel@tonic-gate * print out the value with the appropriate format 1019*7c478bd9Sstevel@tonic-gate * for a hexadecimal number or a decimal number. 1020*7c478bd9Sstevel@tonic-gate */ 1021*7c478bd9Sstevel@tonic-gate if (modnam == NULL) { 1022*7c478bd9Sstevel@tonic-gate if (str_token == B_TRUE) { 1023*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s" warn_format1 1024*7c478bd9Sstevel@tonic-gate "\"%s %s = %s\"" warn_format2, 1025*7c478bd9Sstevel@tonic-gate varnam, systemfile, typenam, 1026*7c478bd9Sstevel@tonic-gate varnam, (char *)(uintptr_t)value); 1027*7c478bd9Sstevel@tonic-gate } else if (hex_number == B_TRUE) { 1028*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s" warn_format1 1029*7c478bd9Sstevel@tonic-gate "\"%s %s = 0x%llx\"" warn_format2, 1030*7c478bd9Sstevel@tonic-gate varnam, systemfile, typenam, 1031*7c478bd9Sstevel@tonic-gate varnam, value); 1032*7c478bd9Sstevel@tonic-gate } else { 1033*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s" warn_format1 1034*7c478bd9Sstevel@tonic-gate "\"%s %s = %lld\"" warn_format2, 1035*7c478bd9Sstevel@tonic-gate varnam, systemfile, typenam, 1036*7c478bd9Sstevel@tonic-gate varnam, value); 1037*7c478bd9Sstevel@tonic-gate } 1038*7c478bd9Sstevel@tonic-gate } else { 1039*7c478bd9Sstevel@tonic-gate if (str_token == B_TRUE) { 1040*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s:%s" warn_format1 1041*7c478bd9Sstevel@tonic-gate "\"%s %s:%s = %s\"" warn_format2, 1042*7c478bd9Sstevel@tonic-gate modnam, varnam, systemfile, 1043*7c478bd9Sstevel@tonic-gate typenam, modnam, varnam, 1044*7c478bd9Sstevel@tonic-gate (char *)(uintptr_t)value); 1045*7c478bd9Sstevel@tonic-gate } else if (hex_number == B_TRUE) { 1046*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s:%s" warn_format1 1047*7c478bd9Sstevel@tonic-gate "\"%s %s:%s = 0x%llx\"" warn_format2, 1048*7c478bd9Sstevel@tonic-gate modnam, varnam, systemfile, 1049*7c478bd9Sstevel@tonic-gate typenam, modnam, varnam, value); 1050*7c478bd9Sstevel@tonic-gate } else { 1051*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s:%s" warn_format1 1052*7c478bd9Sstevel@tonic-gate "\"%s %s:%s = %lld\"" warn_format2, 1053*7c478bd9Sstevel@tonic-gate modnam, varnam, systemfile, 1054*7c478bd9Sstevel@tonic-gate typenam, modnam, varnam, value); 1055*7c478bd9Sstevel@tonic-gate } 1056*7c478bd9Sstevel@tonic-gate } 1057*7c478bd9Sstevel@tonic-gate } else { 1058*7c478bd9Sstevel@tonic-gate /* 1059*7c478bd9Sstevel@tonic-gate * If the type is MOD_ROOTDEV, MOD_ROOTFS, MOD_SWAPDEV, 1060*7c478bd9Sstevel@tonic-gate * MOD_SWAPFS or MOD_MODDIR, the entry is treated as 1061*7c478bd9Sstevel@tonic-gate * a duplicate one if it has the same type regardless 1062*7c478bd9Sstevel@tonic-gate * of its variable name. 1063*7c478bd9Sstevel@tonic-gate */ 1064*7c478bd9Sstevel@tonic-gate switch (type) { 1065*7c478bd9Sstevel@tonic-gate case MOD_ROOTDEV: 1066*7c478bd9Sstevel@tonic-gate case MOD_ROOTFS: 1067*7c478bd9Sstevel@tonic-gate case MOD_SWAPDEV: 1068*7c478bd9Sstevel@tonic-gate case MOD_SWAPFS: 1069*7c478bd9Sstevel@tonic-gate case MOD_MODDIR: 1070*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "\"%s\" appears more than once " 1071*7c478bd9Sstevel@tonic-gate "in /%s.", typenam, systemfile); 1072*7c478bd9Sstevel@tonic-gate break; 1073*7c478bd9Sstevel@tonic-gate default: 1074*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "\"%s: %s\" appears more than once " 1075*7c478bd9Sstevel@tonic-gate "in /%s.", typenam, varnam, systemfile); 1076*7c478bd9Sstevel@tonic-gate break; 1077*7c478bd9Sstevel@tonic-gate } 1078*7c478bd9Sstevel@tonic-gate } 1079*7c478bd9Sstevel@tonic-gate } 1080*7c478bd9Sstevel@tonic-gate 1081*7c478bd9Sstevel@tonic-gate /* 1082*7c478bd9Sstevel@tonic-gate * Process the system file commands. 1083*7c478bd9Sstevel@tonic-gate */ 1084*7c478bd9Sstevel@tonic-gate int 1085*7c478bd9Sstevel@tonic-gate mod_sysctl(int fcn, void *p) 1086*7c478bd9Sstevel@tonic-gate { 1087*7c478bd9Sstevel@tonic-gate static char wmesg[] = "forceload of %s failed"; 1088*7c478bd9Sstevel@tonic-gate struct sysparam *sysp; 1089*7c478bd9Sstevel@tonic-gate char *name; 1090*7c478bd9Sstevel@tonic-gate struct modctl *modp; 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate if (sysparam_hd == NULL) 1093*7c478bd9Sstevel@tonic-gate return (0); 1094*7c478bd9Sstevel@tonic-gate 1095*7c478bd9Sstevel@tonic-gate for (sysp = sysparam_hd; sysp != NULL; sysp = sysp->sys_next) { 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate switch (fcn) { 1098*7c478bd9Sstevel@tonic-gate 1099*7c478bd9Sstevel@tonic-gate case SYS_FORCELOAD: 1100*7c478bd9Sstevel@tonic-gate if (sysp->sys_type == MOD_FORCELOAD) { 1101*7c478bd9Sstevel@tonic-gate name = sysp->sys_ptr; 1102*7c478bd9Sstevel@tonic-gate if (modload(NULL, name) == -1) 1103*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, wmesg, name); 1104*7c478bd9Sstevel@tonic-gate /* 1105*7c478bd9Sstevel@tonic-gate * The following works because it 1106*7c478bd9Sstevel@tonic-gate * runs before autounloading is started!! 1107*7c478bd9Sstevel@tonic-gate */ 1108*7c478bd9Sstevel@tonic-gate modp = mod_find_by_filename(NULL, name); 1109*7c478bd9Sstevel@tonic-gate if (modp != NULL) 1110*7c478bd9Sstevel@tonic-gate modp->mod_loadflags |= MOD_NOAUTOUNLOAD; 1111*7c478bd9Sstevel@tonic-gate /* 1112*7c478bd9Sstevel@tonic-gate * For drivers, attempt to install it. 1113*7c478bd9Sstevel@tonic-gate */ 1114*7c478bd9Sstevel@tonic-gate if (strncmp(sysp->sys_ptr, "drv", 3) == 0) { 1115*7c478bd9Sstevel@tonic-gate (void) ddi_install_driver(name + 4); 1116*7c478bd9Sstevel@tonic-gate } 1117*7c478bd9Sstevel@tonic-gate } 1118*7c478bd9Sstevel@tonic-gate break; 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate case SYS_SET_KVAR: 1121*7c478bd9Sstevel@tonic-gate case SYS_SET_MVAR: 1122*7c478bd9Sstevel@tonic-gate if (sysp->sys_type == MOD_SET) 1123*7c478bd9Sstevel@tonic-gate sys_set_var(fcn, sysp, p); 1124*7c478bd9Sstevel@tonic-gate break; 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate case SYS_CHECK_EXCLUDE: 1127*7c478bd9Sstevel@tonic-gate if (sysp->sys_type == MOD_EXCLUDE) { 1128*7c478bd9Sstevel@tonic-gate if (p == NULL || sysp->sys_ptr == NULL) 1129*7c478bd9Sstevel@tonic-gate return (0); 1130*7c478bd9Sstevel@tonic-gate if (strcmp((char *)p, sysp->sys_ptr) == 0) 1131*7c478bd9Sstevel@tonic-gate return (1); 1132*7c478bd9Sstevel@tonic-gate } 1133*7c478bd9Sstevel@tonic-gate } 1134*7c478bd9Sstevel@tonic-gate } 1135*7c478bd9Sstevel@tonic-gate param_check(); 1136*7c478bd9Sstevel@tonic-gate 1137*7c478bd9Sstevel@tonic-gate return (0); 1138*7c478bd9Sstevel@tonic-gate } 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate /* 1141*7c478bd9Sstevel@tonic-gate * Process the system file commands, by type. 1142*7c478bd9Sstevel@tonic-gate */ 1143*7c478bd9Sstevel@tonic-gate int 1144*7c478bd9Sstevel@tonic-gate mod_sysctl_type(int type, int (*func)(struct sysparam *, void *), void *p) 1145*7c478bd9Sstevel@tonic-gate { 1146*7c478bd9Sstevel@tonic-gate struct sysparam *sysp; 1147*7c478bd9Sstevel@tonic-gate int err; 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate for (sysp = sysparam_hd; sysp != NULL; sysp = sysp->sys_next) 1150*7c478bd9Sstevel@tonic-gate if (sysp->sys_type == type) 1151*7c478bd9Sstevel@tonic-gate if (err = (*(func))(sysp, p)) 1152*7c478bd9Sstevel@tonic-gate return (err); 1153*7c478bd9Sstevel@tonic-gate return (0); 1154*7c478bd9Sstevel@tonic-gate } 1155*7c478bd9Sstevel@tonic-gate 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate static char seterr[] = "Symbol %s has size of 0 in symbol table. %s"; 1158*7c478bd9Sstevel@tonic-gate static char assumption[] = "Assuming it is an 'int'"; 1159*7c478bd9Sstevel@tonic-gate static char defmsg[] = "Trying to set a variable that is of size %d"; 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate static void set_int8_var(uintptr_t, struct sysparam *); 1162*7c478bd9Sstevel@tonic-gate static void set_int16_var(uintptr_t, struct sysparam *); 1163*7c478bd9Sstevel@tonic-gate static void set_int32_var(uintptr_t, struct sysparam *); 1164*7c478bd9Sstevel@tonic-gate static void set_int64_var(uintptr_t, struct sysparam *); 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate static void 1167*7c478bd9Sstevel@tonic-gate sys_set_var(int fcn, struct sysparam *sysp, void *p) 1168*7c478bd9Sstevel@tonic-gate { 1169*7c478bd9Sstevel@tonic-gate uintptr_t symaddr; 1170*7c478bd9Sstevel@tonic-gate int size; 1171*7c478bd9Sstevel@tonic-gate 1172*7c478bd9Sstevel@tonic-gate if (fcn == SYS_SET_KVAR && sysp->sys_modnam == NULL) { 1173*7c478bd9Sstevel@tonic-gate symaddr = kobj_getelfsym(sysp->sys_ptr, NULL, &size); 1174*7c478bd9Sstevel@tonic-gate } else if (fcn == SYS_SET_MVAR) { 1175*7c478bd9Sstevel@tonic-gate if (sysp->sys_modnam == (char *)NULL || 1176*7c478bd9Sstevel@tonic-gate strcmp(((struct modctl *)p)->mod_modname, 1177*7c478bd9Sstevel@tonic-gate sysp->sys_modnam) != 0) 1178*7c478bd9Sstevel@tonic-gate return; 1179*7c478bd9Sstevel@tonic-gate symaddr = kobj_getelfsym(sysp->sys_ptr, 1180*7c478bd9Sstevel@tonic-gate ((struct modctl *)p)->mod_mp, &size); 1181*7c478bd9Sstevel@tonic-gate } else 1182*7c478bd9Sstevel@tonic-gate return; 1183*7c478bd9Sstevel@tonic-gate 1184*7c478bd9Sstevel@tonic-gate if (symaddr != NULL) { 1185*7c478bd9Sstevel@tonic-gate switch (size) { 1186*7c478bd9Sstevel@tonic-gate case 1: 1187*7c478bd9Sstevel@tonic-gate set_int8_var(symaddr, sysp); 1188*7c478bd9Sstevel@tonic-gate break; 1189*7c478bd9Sstevel@tonic-gate case 2: 1190*7c478bd9Sstevel@tonic-gate set_int16_var(symaddr, sysp); 1191*7c478bd9Sstevel@tonic-gate break; 1192*7c478bd9Sstevel@tonic-gate case 0: 1193*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, seterr, sysp->sys_ptr, assumption); 1194*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 1195*7c478bd9Sstevel@tonic-gate case 4: 1196*7c478bd9Sstevel@tonic-gate set_int32_var(symaddr, sysp); 1197*7c478bd9Sstevel@tonic-gate break; 1198*7c478bd9Sstevel@tonic-gate case 8: 1199*7c478bd9Sstevel@tonic-gate set_int64_var(symaddr, sysp); 1200*7c478bd9Sstevel@tonic-gate break; 1201*7c478bd9Sstevel@tonic-gate default: 1202*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, defmsg, size); 1203*7c478bd9Sstevel@tonic-gate break; 1204*7c478bd9Sstevel@tonic-gate } 1205*7c478bd9Sstevel@tonic-gate } else { 1206*7c478bd9Sstevel@tonic-gate printf("sorry, variable '%s' is not defined in the '%s' ", 1207*7c478bd9Sstevel@tonic-gate sysp->sys_ptr, 1208*7c478bd9Sstevel@tonic-gate sysp->sys_modnam ? sysp->sys_modnam : "kernel"); 1209*7c478bd9Sstevel@tonic-gate if (sysp->sys_modnam) 1210*7c478bd9Sstevel@tonic-gate printf("module"); 1211*7c478bd9Sstevel@tonic-gate printf("\n"); 1212*7c478bd9Sstevel@tonic-gate } 1213*7c478bd9Sstevel@tonic-gate } 1214*7c478bd9Sstevel@tonic-gate 1215*7c478bd9Sstevel@tonic-gate static void 1216*7c478bd9Sstevel@tonic-gate set_int8_var(uintptr_t symaddr, struct sysparam *sysp) 1217*7c478bd9Sstevel@tonic-gate { 1218*7c478bd9Sstevel@tonic-gate uint8_t uc = (uint8_t)sysp->sys_info; 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate if (moddebug & MODDEBUG_LOADMSG) 1221*7c478bd9Sstevel@tonic-gate printf("OP: %x: param '%s' was '0x%" PRIx8 1222*7c478bd9Sstevel@tonic-gate "' in module: '%s'.\n", sysp->sys_op, sysp->sys_ptr, 1223*7c478bd9Sstevel@tonic-gate *(uint8_t *)symaddr, sysp->sys_modnam); 1224*7c478bd9Sstevel@tonic-gate 1225*7c478bd9Sstevel@tonic-gate switch (sysp->sys_op) { 1226*7c478bd9Sstevel@tonic-gate case SETOP_ASSIGN: 1227*7c478bd9Sstevel@tonic-gate *(uint8_t *)symaddr = uc; 1228*7c478bd9Sstevel@tonic-gate break; 1229*7c478bd9Sstevel@tonic-gate case SETOP_AND: 1230*7c478bd9Sstevel@tonic-gate *(uint8_t *)symaddr &= uc; 1231*7c478bd9Sstevel@tonic-gate break; 1232*7c478bd9Sstevel@tonic-gate case SETOP_OR: 1233*7c478bd9Sstevel@tonic-gate *(uint8_t *)symaddr |= uc; 1234*7c478bd9Sstevel@tonic-gate break; 1235*7c478bd9Sstevel@tonic-gate } 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate if (moddebug & MODDEBUG_LOADMSG) 1238*7c478bd9Sstevel@tonic-gate printf("now it is set to '0x%" PRIx8 "'.\n", 1239*7c478bd9Sstevel@tonic-gate *(uint8_t *)symaddr); 1240*7c478bd9Sstevel@tonic-gate } 1241*7c478bd9Sstevel@tonic-gate 1242*7c478bd9Sstevel@tonic-gate static void 1243*7c478bd9Sstevel@tonic-gate set_int16_var(uintptr_t symaddr, struct sysparam *sysp) 1244*7c478bd9Sstevel@tonic-gate { 1245*7c478bd9Sstevel@tonic-gate uint16_t us = (uint16_t)sysp->sys_info; 1246*7c478bd9Sstevel@tonic-gate 1247*7c478bd9Sstevel@tonic-gate if (moddebug & MODDEBUG_LOADMSG) 1248*7c478bd9Sstevel@tonic-gate printf("OP: %x: param '%s' was '0x%" PRIx16 1249*7c478bd9Sstevel@tonic-gate "' in module: '%s'.\n", sysp->sys_op, sysp->sys_ptr, 1250*7c478bd9Sstevel@tonic-gate *(uint16_t *)symaddr, sysp->sys_modnam); 1251*7c478bd9Sstevel@tonic-gate 1252*7c478bd9Sstevel@tonic-gate switch (sysp->sys_op) { 1253*7c478bd9Sstevel@tonic-gate case SETOP_ASSIGN: 1254*7c478bd9Sstevel@tonic-gate *(uint16_t *)symaddr = us; 1255*7c478bd9Sstevel@tonic-gate break; 1256*7c478bd9Sstevel@tonic-gate case SETOP_AND: 1257*7c478bd9Sstevel@tonic-gate *(uint16_t *)symaddr &= us; 1258*7c478bd9Sstevel@tonic-gate break; 1259*7c478bd9Sstevel@tonic-gate case SETOP_OR: 1260*7c478bd9Sstevel@tonic-gate *(uint16_t *)symaddr |= us; 1261*7c478bd9Sstevel@tonic-gate break; 1262*7c478bd9Sstevel@tonic-gate } 1263*7c478bd9Sstevel@tonic-gate 1264*7c478bd9Sstevel@tonic-gate if (moddebug & MODDEBUG_LOADMSG) 1265*7c478bd9Sstevel@tonic-gate printf("now it is set to '0x%" PRIx16 "'.\n", 1266*7c478bd9Sstevel@tonic-gate *(uint16_t *)symaddr); 1267*7c478bd9Sstevel@tonic-gate } 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate static void 1270*7c478bd9Sstevel@tonic-gate set_int32_var(uintptr_t symaddr, struct sysparam *sysp) 1271*7c478bd9Sstevel@tonic-gate { 1272*7c478bd9Sstevel@tonic-gate uint32_t ui = (uint32_t)sysp->sys_info; 1273*7c478bd9Sstevel@tonic-gate 1274*7c478bd9Sstevel@tonic-gate if (moddebug & MODDEBUG_LOADMSG) 1275*7c478bd9Sstevel@tonic-gate printf("OP: %x: param '%s' was '0x%" PRIx32 1276*7c478bd9Sstevel@tonic-gate "' in module: '%s'.\n", sysp->sys_op, sysp->sys_ptr, 1277*7c478bd9Sstevel@tonic-gate *(uint32_t *)symaddr, sysp->sys_modnam); 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate switch (sysp->sys_op) { 1280*7c478bd9Sstevel@tonic-gate case SETOP_ASSIGN: 1281*7c478bd9Sstevel@tonic-gate *(uint32_t *)symaddr = ui; 1282*7c478bd9Sstevel@tonic-gate break; 1283*7c478bd9Sstevel@tonic-gate case SETOP_AND: 1284*7c478bd9Sstevel@tonic-gate *(uint32_t *)symaddr &= ui; 1285*7c478bd9Sstevel@tonic-gate break; 1286*7c478bd9Sstevel@tonic-gate case SETOP_OR: 1287*7c478bd9Sstevel@tonic-gate *(uint32_t *)symaddr |= ui; 1288*7c478bd9Sstevel@tonic-gate break; 1289*7c478bd9Sstevel@tonic-gate } 1290*7c478bd9Sstevel@tonic-gate 1291*7c478bd9Sstevel@tonic-gate if (moddebug & MODDEBUG_LOADMSG) 1292*7c478bd9Sstevel@tonic-gate printf("now it is set to '0x%" PRIx32 "'.\n", 1293*7c478bd9Sstevel@tonic-gate *(uint32_t *)symaddr); 1294*7c478bd9Sstevel@tonic-gate } 1295*7c478bd9Sstevel@tonic-gate 1296*7c478bd9Sstevel@tonic-gate static void 1297*7c478bd9Sstevel@tonic-gate set_int64_var(uintptr_t symaddr, struct sysparam *sysp) 1298*7c478bd9Sstevel@tonic-gate { 1299*7c478bd9Sstevel@tonic-gate uint64_t ul = sysp->sys_info; 1300*7c478bd9Sstevel@tonic-gate 1301*7c478bd9Sstevel@tonic-gate if (moddebug & MODDEBUG_LOADMSG) 1302*7c478bd9Sstevel@tonic-gate printf("OP: %x: param '%s' was '0x%" PRIx64 1303*7c478bd9Sstevel@tonic-gate "' in module: '%s'.\n", sysp->sys_op, sysp->sys_ptr, 1304*7c478bd9Sstevel@tonic-gate *(uint64_t *)symaddr, sysp->sys_modnam); 1305*7c478bd9Sstevel@tonic-gate 1306*7c478bd9Sstevel@tonic-gate switch (sysp->sys_op) { 1307*7c478bd9Sstevel@tonic-gate case SETOP_ASSIGN: 1308*7c478bd9Sstevel@tonic-gate *(uint64_t *)symaddr = ul; 1309*7c478bd9Sstevel@tonic-gate break; 1310*7c478bd9Sstevel@tonic-gate case SETOP_AND: 1311*7c478bd9Sstevel@tonic-gate *(uint64_t *)symaddr &= ul; 1312*7c478bd9Sstevel@tonic-gate break; 1313*7c478bd9Sstevel@tonic-gate case SETOP_OR: 1314*7c478bd9Sstevel@tonic-gate *(uint64_t *)symaddr |= ul; 1315*7c478bd9Sstevel@tonic-gate break; 1316*7c478bd9Sstevel@tonic-gate } 1317*7c478bd9Sstevel@tonic-gate 1318*7c478bd9Sstevel@tonic-gate if (moddebug & MODDEBUG_LOADMSG) 1319*7c478bd9Sstevel@tonic-gate printf("now it is set to '0x%" PRIx64 "'.\n", 1320*7c478bd9Sstevel@tonic-gate *(uint64_t *)symaddr); 1321*7c478bd9Sstevel@tonic-gate } 1322*7c478bd9Sstevel@tonic-gate 1323*7c478bd9Sstevel@tonic-gate /* 1324*7c478bd9Sstevel@tonic-gate * The next item on the line is a string value. Allocate memory for 1325*7c478bd9Sstevel@tonic-gate * it and copy the string. Return 1, and set arg ptr to newly allocated 1326*7c478bd9Sstevel@tonic-gate * and initialized buffer, or NULL if an error occurs. 1327*7c478bd9Sstevel@tonic-gate */ 1328*7c478bd9Sstevel@tonic-gate int 1329*7c478bd9Sstevel@tonic-gate kobj_get_string(u_longlong_t *llptr, char *tchar) 1330*7c478bd9Sstevel@tonic-gate { 1331*7c478bd9Sstevel@tonic-gate char *cp; 1332*7c478bd9Sstevel@tonic-gate char *start = (char *)0; 1333*7c478bd9Sstevel@tonic-gate int len = 0; 1334*7c478bd9Sstevel@tonic-gate 1335*7c478bd9Sstevel@tonic-gate len = strlen(tchar); 1336*7c478bd9Sstevel@tonic-gate start = tchar; 1337*7c478bd9Sstevel@tonic-gate /* copy string */ 1338*7c478bd9Sstevel@tonic-gate cp = vmem_alloc(mod_sysfile_arena, len + 1, VM_SLEEP); 1339*7c478bd9Sstevel@tonic-gate bzero(cp, len + 1); 1340*7c478bd9Sstevel@tonic-gate *llptr = (u_longlong_t)(uintptr_t)cp; 1341*7c478bd9Sstevel@tonic-gate for (; len > 0; len--) { 1342*7c478bd9Sstevel@tonic-gate /* convert some common escape sequences */ 1343*7c478bd9Sstevel@tonic-gate if (*start == '\\') { 1344*7c478bd9Sstevel@tonic-gate switch (*(start + 1)) { 1345*7c478bd9Sstevel@tonic-gate case 't': 1346*7c478bd9Sstevel@tonic-gate /* tab */ 1347*7c478bd9Sstevel@tonic-gate *cp++ = '\t'; 1348*7c478bd9Sstevel@tonic-gate len--; 1349*7c478bd9Sstevel@tonic-gate start += 2; 1350*7c478bd9Sstevel@tonic-gate break; 1351*7c478bd9Sstevel@tonic-gate case 'n': 1352*7c478bd9Sstevel@tonic-gate /* new line */ 1353*7c478bd9Sstevel@tonic-gate *cp++ = '\n'; 1354*7c478bd9Sstevel@tonic-gate len--; 1355*7c478bd9Sstevel@tonic-gate start += 2; 1356*7c478bd9Sstevel@tonic-gate break; 1357*7c478bd9Sstevel@tonic-gate case 'b': 1358*7c478bd9Sstevel@tonic-gate /* back space */ 1359*7c478bd9Sstevel@tonic-gate *cp++ = '\b'; 1360*7c478bd9Sstevel@tonic-gate len--; 1361*7c478bd9Sstevel@tonic-gate start += 2; 1362*7c478bd9Sstevel@tonic-gate break; 1363*7c478bd9Sstevel@tonic-gate default: 1364*7c478bd9Sstevel@tonic-gate /* simply copy it */ 1365*7c478bd9Sstevel@tonic-gate *cp++ = *start++; 1366*7c478bd9Sstevel@tonic-gate break; 1367*7c478bd9Sstevel@tonic-gate } 1368*7c478bd9Sstevel@tonic-gate } else 1369*7c478bd9Sstevel@tonic-gate *cp++ = *start++; 1370*7c478bd9Sstevel@tonic-gate } 1371*7c478bd9Sstevel@tonic-gate *cp = '\0'; 1372*7c478bd9Sstevel@tonic-gate return (1); 1373*7c478bd9Sstevel@tonic-gate } 1374*7c478bd9Sstevel@tonic-gate 1375*7c478bd9Sstevel@tonic-gate 1376*7c478bd9Sstevel@tonic-gate /* 1377*7c478bd9Sstevel@tonic-gate * this function frees the memory allocated by kobj_get_string 1378*7c478bd9Sstevel@tonic-gate */ 1379*7c478bd9Sstevel@tonic-gate void 1380*7c478bd9Sstevel@tonic-gate kobj_free_string(void *ptr, int len) 1381*7c478bd9Sstevel@tonic-gate { 1382*7c478bd9Sstevel@tonic-gate vmem_free(mod_sysfile_arena, ptr, len); 1383*7c478bd9Sstevel@tonic-gate } 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate 1386*7c478bd9Sstevel@tonic-gate /* 1387*7c478bd9Sstevel@tonic-gate * get a decimal octal or hex number. Handle '~' for one's complement. 1388*7c478bd9Sstevel@tonic-gate */ 1389*7c478bd9Sstevel@tonic-gate int 1390*7c478bd9Sstevel@tonic-gate kobj_getvalue(const char *token, u_longlong_t *valuep) 1391*7c478bd9Sstevel@tonic-gate { 1392*7c478bd9Sstevel@tonic-gate int radix; 1393*7c478bd9Sstevel@tonic-gate u_longlong_t retval = 0; 1394*7c478bd9Sstevel@tonic-gate int onescompl = 0; 1395*7c478bd9Sstevel@tonic-gate int negate = 0; 1396*7c478bd9Sstevel@tonic-gate char c; 1397*7c478bd9Sstevel@tonic-gate 1398*7c478bd9Sstevel@tonic-gate if (*token == '~') { 1399*7c478bd9Sstevel@tonic-gate onescompl++; /* perform one's complement on result */ 1400*7c478bd9Sstevel@tonic-gate token++; 1401*7c478bd9Sstevel@tonic-gate } else if (*token == '-') { 1402*7c478bd9Sstevel@tonic-gate negate++; 1403*7c478bd9Sstevel@tonic-gate token++; 1404*7c478bd9Sstevel@tonic-gate } 1405*7c478bd9Sstevel@tonic-gate if (*token == '0') { 1406*7c478bd9Sstevel@tonic-gate token++; 1407*7c478bd9Sstevel@tonic-gate c = *token; 1408*7c478bd9Sstevel@tonic-gate 1409*7c478bd9Sstevel@tonic-gate if (c == '\0') { 1410*7c478bd9Sstevel@tonic-gate *valuep = 0; /* value is 0 */ 1411*7c478bd9Sstevel@tonic-gate return (0); 1412*7c478bd9Sstevel@tonic-gate } 1413*7c478bd9Sstevel@tonic-gate 1414*7c478bd9Sstevel@tonic-gate if (c == 'x' || c == 'X') { 1415*7c478bd9Sstevel@tonic-gate radix = 16; 1416*7c478bd9Sstevel@tonic-gate token++; 1417*7c478bd9Sstevel@tonic-gate } else 1418*7c478bd9Sstevel@tonic-gate radix = 8; 1419*7c478bd9Sstevel@tonic-gate } else 1420*7c478bd9Sstevel@tonic-gate radix = 10; 1421*7c478bd9Sstevel@tonic-gate 1422*7c478bd9Sstevel@tonic-gate while ((c = *token++)) { 1423*7c478bd9Sstevel@tonic-gate switch (radix) { 1424*7c478bd9Sstevel@tonic-gate case 8: 1425*7c478bd9Sstevel@tonic-gate if (c >= '0' && c <= '7') 1426*7c478bd9Sstevel@tonic-gate c -= '0'; 1427*7c478bd9Sstevel@tonic-gate else 1428*7c478bd9Sstevel@tonic-gate return (-1); /* invalid number */ 1429*7c478bd9Sstevel@tonic-gate retval = (retval << 3) + c; 1430*7c478bd9Sstevel@tonic-gate break; 1431*7c478bd9Sstevel@tonic-gate case 10: 1432*7c478bd9Sstevel@tonic-gate if (c >= '0' && c <= '9') 1433*7c478bd9Sstevel@tonic-gate c -= '0'; 1434*7c478bd9Sstevel@tonic-gate else 1435*7c478bd9Sstevel@tonic-gate return (-1); /* invalid number */ 1436*7c478bd9Sstevel@tonic-gate retval = (retval * 10) + c; 1437*7c478bd9Sstevel@tonic-gate break; 1438*7c478bd9Sstevel@tonic-gate case 16: 1439*7c478bd9Sstevel@tonic-gate if (c >= 'a' && c <= 'f') 1440*7c478bd9Sstevel@tonic-gate c = c - 'a' + 10; 1441*7c478bd9Sstevel@tonic-gate else if (c >= 'A' && c <= 'F') 1442*7c478bd9Sstevel@tonic-gate c = c - 'A' + 10; 1443*7c478bd9Sstevel@tonic-gate else if (c >= '0' && c <= '9') 1444*7c478bd9Sstevel@tonic-gate c -= '0'; 1445*7c478bd9Sstevel@tonic-gate else 1446*7c478bd9Sstevel@tonic-gate return (-1); /* invalid number */ 1447*7c478bd9Sstevel@tonic-gate retval = (retval << 4) + c; 1448*7c478bd9Sstevel@tonic-gate break; 1449*7c478bd9Sstevel@tonic-gate } 1450*7c478bd9Sstevel@tonic-gate } 1451*7c478bd9Sstevel@tonic-gate if (onescompl) 1452*7c478bd9Sstevel@tonic-gate retval = ~retval; 1453*7c478bd9Sstevel@tonic-gate if (negate) 1454*7c478bd9Sstevel@tonic-gate retval = -retval; 1455*7c478bd9Sstevel@tonic-gate *valuep = retval; 1456*7c478bd9Sstevel@tonic-gate return (0); 1457*7c478bd9Sstevel@tonic-gate } 1458*7c478bd9Sstevel@tonic-gate 1459*7c478bd9Sstevel@tonic-gate /* 1460*7c478bd9Sstevel@tonic-gate * Path to the root device and root filesystem type from 1461*7c478bd9Sstevel@tonic-gate * property information derived from the boot subsystem 1462*7c478bd9Sstevel@tonic-gate */ 1463*7c478bd9Sstevel@tonic-gate void 1464*7c478bd9Sstevel@tonic-gate setbootpath(char *path) 1465*7c478bd9Sstevel@tonic-gate { 1466*7c478bd9Sstevel@tonic-gate rootfs.bo_flags |= BO_VALID; 1467*7c478bd9Sstevel@tonic-gate (void) copystr(path, rootfs.bo_name, BO_MAXOBJNAME, NULL); 1468*7c478bd9Sstevel@tonic-gate BMDPRINTF(("rootfs bootpath: %s\n", rootfs.bo_name)); 1469*7c478bd9Sstevel@tonic-gate } 1470*7c478bd9Sstevel@tonic-gate 1471*7c478bd9Sstevel@tonic-gate void 1472*7c478bd9Sstevel@tonic-gate setbootfstype(char *fstype) 1473*7c478bd9Sstevel@tonic-gate { 1474*7c478bd9Sstevel@tonic-gate (void) copystr(fstype, rootfs.bo_fstype, BO_MAXFSNAME, NULL); 1475*7c478bd9Sstevel@tonic-gate BMDPRINTF(("rootfs fstype: %s\n", rootfs.bo_fstype)); 1476*7c478bd9Sstevel@tonic-gate } 1477*7c478bd9Sstevel@tonic-gate 1478*7c478bd9Sstevel@tonic-gate /* 1479*7c478bd9Sstevel@tonic-gate * set parameters that can be set early during initialization. 1480*7c478bd9Sstevel@tonic-gate */ 1481*7c478bd9Sstevel@tonic-gate static void 1482*7c478bd9Sstevel@tonic-gate setparams() 1483*7c478bd9Sstevel@tonic-gate { 1484*7c478bd9Sstevel@tonic-gate struct sysparam *sysp; 1485*7c478bd9Sstevel@tonic-gate struct bootobj *bootobjp; 1486*7c478bd9Sstevel@tonic-gate 1487*7c478bd9Sstevel@tonic-gate for (sysp = sysparam_hd; sysp != NULL; sysp = sysp->sys_next) { 1488*7c478bd9Sstevel@tonic-gate 1489*7c478bd9Sstevel@tonic-gate if (sysp->sys_type == MOD_MODDIR) { 1490*7c478bd9Sstevel@tonic-gate default_path = sysp->sys_ptr; 1491*7c478bd9Sstevel@tonic-gate continue; 1492*7c478bd9Sstevel@tonic-gate } 1493*7c478bd9Sstevel@tonic-gate 1494*7c478bd9Sstevel@tonic-gate if (sysp->sys_type == MOD_SWAPDEV || 1495*7c478bd9Sstevel@tonic-gate sysp->sys_type == MOD_SWAPFS) 1496*7c478bd9Sstevel@tonic-gate bootobjp = &swapfile; 1497*7c478bd9Sstevel@tonic-gate else if (sysp->sys_type == MOD_ROOTFS) 1498*7c478bd9Sstevel@tonic-gate bootobjp = &rootfs; 1499*7c478bd9Sstevel@tonic-gate 1500*7c478bd9Sstevel@tonic-gate switch (sysp->sys_type) { 1501*7c478bd9Sstevel@tonic-gate case MOD_ROOTDEV: 1502*7c478bd9Sstevel@tonic-gate root_is_svm = 1; 1503*7c478bd9Sstevel@tonic-gate (void) copystr(sysp->sys_ptr, svm_bootpath, 1504*7c478bd9Sstevel@tonic-gate BO_MAXOBJNAME, NULL); 1505*7c478bd9Sstevel@tonic-gate break; 1506*7c478bd9Sstevel@tonic-gate case MOD_SWAPDEV: 1507*7c478bd9Sstevel@tonic-gate bootobjp->bo_flags |= BO_VALID; 1508*7c478bd9Sstevel@tonic-gate (void) copystr(sysp->sys_ptr, bootobjp->bo_name, 1509*7c478bd9Sstevel@tonic-gate BO_MAXOBJNAME, NULL); 1510*7c478bd9Sstevel@tonic-gate break; 1511*7c478bd9Sstevel@tonic-gate case MOD_ROOTFS: 1512*7c478bd9Sstevel@tonic-gate case MOD_SWAPFS: 1513*7c478bd9Sstevel@tonic-gate bootobjp->bo_flags |= BO_VALID; 1514*7c478bd9Sstevel@tonic-gate (void) copystr(sysp->sys_ptr, bootobjp->bo_fstype, 1515*7c478bd9Sstevel@tonic-gate BO_MAXOBJNAME, NULL); 1516*7c478bd9Sstevel@tonic-gate break; 1517*7c478bd9Sstevel@tonic-gate 1518*7c478bd9Sstevel@tonic-gate default: 1519*7c478bd9Sstevel@tonic-gate break; 1520*7c478bd9Sstevel@tonic-gate } 1521*7c478bd9Sstevel@tonic-gate } 1522*7c478bd9Sstevel@tonic-gate } 1523*7c478bd9Sstevel@tonic-gate 1524*7c478bd9Sstevel@tonic-gate /* 1525*7c478bd9Sstevel@tonic-gate * clean up after an error. 1526*7c478bd9Sstevel@tonic-gate */ 1527*7c478bd9Sstevel@tonic-gate static void 1528*7c478bd9Sstevel@tonic-gate hwc_free(struct hwc_spec *hwcp) 1529*7c478bd9Sstevel@tonic-gate { 1530*7c478bd9Sstevel@tonic-gate char *name; 1531*7c478bd9Sstevel@tonic-gate 1532*7c478bd9Sstevel@tonic-gate if ((name = hwcp->hwc_parent_name) != NULL) 1533*7c478bd9Sstevel@tonic-gate kmem_free(name, strlen(name) + 1); 1534*7c478bd9Sstevel@tonic-gate if ((name = hwcp->hwc_class_name) != NULL) 1535*7c478bd9Sstevel@tonic-gate kmem_free(name, strlen(name) + 1); 1536*7c478bd9Sstevel@tonic-gate if ((name = hwcp->hwc_devi_name) != NULL) 1537*7c478bd9Sstevel@tonic-gate kmem_free(name, strlen(name) + 1); 1538*7c478bd9Sstevel@tonic-gate i_ddi_prop_list_delete(hwcp->hwc_devi_sys_prop_ptr); 1539*7c478bd9Sstevel@tonic-gate kmem_free(hwcp, sizeof (struct hwc_spec)); 1540*7c478bd9Sstevel@tonic-gate } 1541*7c478bd9Sstevel@tonic-gate 1542*7c478bd9Sstevel@tonic-gate /* 1543*7c478bd9Sstevel@tonic-gate * Free a list of specs 1544*7c478bd9Sstevel@tonic-gate */ 1545*7c478bd9Sstevel@tonic-gate void 1546*7c478bd9Sstevel@tonic-gate hwc_free_spec_list(struct hwc_spec *list) 1547*7c478bd9Sstevel@tonic-gate { 1548*7c478bd9Sstevel@tonic-gate while (list) { 1549*7c478bd9Sstevel@tonic-gate struct hwc_spec *tmp = list; 1550*7c478bd9Sstevel@tonic-gate list = tmp->hwc_next; 1551*7c478bd9Sstevel@tonic-gate hwc_free(tmp); 1552*7c478bd9Sstevel@tonic-gate } 1553*7c478bd9Sstevel@tonic-gate } 1554*7c478bd9Sstevel@tonic-gate 1555*7c478bd9Sstevel@tonic-gate struct val_list { 1556*7c478bd9Sstevel@tonic-gate struct val_list *val_next; 1557*7c478bd9Sstevel@tonic-gate int val_type; 1558*7c478bd9Sstevel@tonic-gate int val_size; 1559*7c478bd9Sstevel@tonic-gate union { 1560*7c478bd9Sstevel@tonic-gate char *string; 1561*7c478bd9Sstevel@tonic-gate int integer; 1562*7c478bd9Sstevel@tonic-gate } val; 1563*7c478bd9Sstevel@tonic-gate }; 1564*7c478bd9Sstevel@tonic-gate 1565*7c478bd9Sstevel@tonic-gate static void 1566*7c478bd9Sstevel@tonic-gate add_val(struct val_list **val_listp, int val_type, caddr_t val) 1567*7c478bd9Sstevel@tonic-gate { 1568*7c478bd9Sstevel@tonic-gate struct val_list *new_val, *listp = *val_listp; 1569*7c478bd9Sstevel@tonic-gate 1570*7c478bd9Sstevel@tonic-gate new_val = kmem_alloc(sizeof (struct val_list), KM_SLEEP); 1571*7c478bd9Sstevel@tonic-gate new_val->val_next = NULL; 1572*7c478bd9Sstevel@tonic-gate if ((new_val->val_type = val_type) == 0) { 1573*7c478bd9Sstevel@tonic-gate new_val->val_size = strlen((char *)val) + 1; 1574*7c478bd9Sstevel@tonic-gate new_val->val.string = (char *)val; 1575*7c478bd9Sstevel@tonic-gate } else { 1576*7c478bd9Sstevel@tonic-gate new_val->val_size = sizeof (int); 1577*7c478bd9Sstevel@tonic-gate new_val->val.integer = (int)(uintptr_t)val; 1578*7c478bd9Sstevel@tonic-gate } 1579*7c478bd9Sstevel@tonic-gate 1580*7c478bd9Sstevel@tonic-gate if (listp) { 1581*7c478bd9Sstevel@tonic-gate while (listp->val_next) { 1582*7c478bd9Sstevel@tonic-gate listp = listp->val_next; 1583*7c478bd9Sstevel@tonic-gate } 1584*7c478bd9Sstevel@tonic-gate listp->val_next = new_val; 1585*7c478bd9Sstevel@tonic-gate } else { 1586*7c478bd9Sstevel@tonic-gate *val_listp = new_val; 1587*7c478bd9Sstevel@tonic-gate } 1588*7c478bd9Sstevel@tonic-gate } 1589*7c478bd9Sstevel@tonic-gate 1590*7c478bd9Sstevel@tonic-gate /* 1591*7c478bd9Sstevel@tonic-gate * make sure there are no reserved IEEE 1275 characters (except 1592*7c478bd9Sstevel@tonic-gate * for uppercase characters). 1593*7c478bd9Sstevel@tonic-gate */ 1594*7c478bd9Sstevel@tonic-gate static int 1595*7c478bd9Sstevel@tonic-gate valid_prop_name(char *name) 1596*7c478bd9Sstevel@tonic-gate { 1597*7c478bd9Sstevel@tonic-gate int i; 1598*7c478bd9Sstevel@tonic-gate int len = strlen(name); 1599*7c478bd9Sstevel@tonic-gate 1600*7c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) { 1601*7c478bd9Sstevel@tonic-gate if (name[i] < 0x21 || 1602*7c478bd9Sstevel@tonic-gate name[i] == '/' || 1603*7c478bd9Sstevel@tonic-gate name[i] == '\\' || 1604*7c478bd9Sstevel@tonic-gate name[i] == ':' || 1605*7c478bd9Sstevel@tonic-gate name[i] == '[' || 1606*7c478bd9Sstevel@tonic-gate name[i] == ']' || 1607*7c478bd9Sstevel@tonic-gate name[i] == '@') 1608*7c478bd9Sstevel@tonic-gate return (0); 1609*7c478bd9Sstevel@tonic-gate } 1610*7c478bd9Sstevel@tonic-gate return (1); 1611*7c478bd9Sstevel@tonic-gate } 1612*7c478bd9Sstevel@tonic-gate 1613*7c478bd9Sstevel@tonic-gate static void 1614*7c478bd9Sstevel@tonic-gate make_prop(struct _buf *file, dev_info_t *devi, char *name, struct val_list *val) 1615*7c478bd9Sstevel@tonic-gate { 1616*7c478bd9Sstevel@tonic-gate int propcnt = 0, val_type; 1617*7c478bd9Sstevel@tonic-gate struct val_list *vl, *tvl; 1618*7c478bd9Sstevel@tonic-gate caddr_t valbuf = NULL; 1619*7c478bd9Sstevel@tonic-gate char **valsp; 1620*7c478bd9Sstevel@tonic-gate int *valip; 1621*7c478bd9Sstevel@tonic-gate 1622*7c478bd9Sstevel@tonic-gate if (name == NULL) 1623*7c478bd9Sstevel@tonic-gate return; 1624*7c478bd9Sstevel@tonic-gate 1625*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1626*7c478bd9Sstevel@tonic-gate parse_debug(NULL, "%s", name); 1627*7c478bd9Sstevel@tonic-gate #endif 1628*7c478bd9Sstevel@tonic-gate if (!valid_prop_name(name)) { 1629*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "invalid property name '%s'", name); 1630*7c478bd9Sstevel@tonic-gate kmem_free(name, strlen(name) + 1); 1631*7c478bd9Sstevel@tonic-gate return; 1632*7c478bd9Sstevel@tonic-gate } 1633*7c478bd9Sstevel@tonic-gate if (val) { 1634*7c478bd9Sstevel@tonic-gate for (vl = val, val_type = vl->val_type; vl; vl = vl->val_next) { 1635*7c478bd9Sstevel@tonic-gate if (val_type != vl->val_type) { 1636*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Mixed types in value list"); 1637*7c478bd9Sstevel@tonic-gate return; 1638*7c478bd9Sstevel@tonic-gate } 1639*7c478bd9Sstevel@tonic-gate propcnt++; 1640*7c478bd9Sstevel@tonic-gate } 1641*7c478bd9Sstevel@tonic-gate 1642*7c478bd9Sstevel@tonic-gate vl = val; 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate if (val_type == 1) { 1645*7c478bd9Sstevel@tonic-gate valip = (int *)kmem_alloc( 1646*7c478bd9Sstevel@tonic-gate (propcnt * sizeof (int)), KM_SLEEP); 1647*7c478bd9Sstevel@tonic-gate valbuf = (caddr_t)valip; 1648*7c478bd9Sstevel@tonic-gate while (vl) { 1649*7c478bd9Sstevel@tonic-gate tvl = vl; 1650*7c478bd9Sstevel@tonic-gate vl = vl->val_next; 1651*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1652*7c478bd9Sstevel@tonic-gate parse_debug(NULL, " %x", tvl->val.integer); 1653*7c478bd9Sstevel@tonic-gate #endif 1654*7c478bd9Sstevel@tonic-gate *valip = tvl->val.integer; 1655*7c478bd9Sstevel@tonic-gate valip++; 1656*7c478bd9Sstevel@tonic-gate kmem_free(tvl, sizeof (struct val_list)); 1657*7c478bd9Sstevel@tonic-gate } 1658*7c478bd9Sstevel@tonic-gate /* restore valip */ 1659*7c478bd9Sstevel@tonic-gate valip = (int *)valbuf; 1660*7c478bd9Sstevel@tonic-gate 1661*7c478bd9Sstevel@tonic-gate /* create the property */ 1662*7c478bd9Sstevel@tonic-gate if (e_ddi_prop_update_int_array(DDI_DEV_T_NONE, devi, 1663*7c478bd9Sstevel@tonic-gate name, valip, propcnt) != DDI_PROP_SUCCESS) { 1664*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 1665*7c478bd9Sstevel@tonic-gate "cannot create property %s", name); 1666*7c478bd9Sstevel@tonic-gate } 1667*7c478bd9Sstevel@tonic-gate /* cleanup */ 1668*7c478bd9Sstevel@tonic-gate kmem_free(valip, (propcnt * sizeof (int))); 1669*7c478bd9Sstevel@tonic-gate } else if (val_type == 0) { 1670*7c478bd9Sstevel@tonic-gate valsp = (char **)kmem_alloc( 1671*7c478bd9Sstevel@tonic-gate ((propcnt + 1) * sizeof (char *)), KM_SLEEP); 1672*7c478bd9Sstevel@tonic-gate valbuf = (caddr_t)valsp; 1673*7c478bd9Sstevel@tonic-gate while (vl) { 1674*7c478bd9Sstevel@tonic-gate tvl = vl; 1675*7c478bd9Sstevel@tonic-gate vl = vl->val_next; 1676*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1677*7c478bd9Sstevel@tonic-gate parse_debug(NULL, " %s", tvl->val.string); 1678*7c478bd9Sstevel@tonic-gate #endif 1679*7c478bd9Sstevel@tonic-gate *valsp = tvl->val.string; 1680*7c478bd9Sstevel@tonic-gate valsp++; 1681*7c478bd9Sstevel@tonic-gate } 1682*7c478bd9Sstevel@tonic-gate /* terminate array with NULL */ 1683*7c478bd9Sstevel@tonic-gate *valsp = NULL; 1684*7c478bd9Sstevel@tonic-gate 1685*7c478bd9Sstevel@tonic-gate /* restore valsp */ 1686*7c478bd9Sstevel@tonic-gate valsp = (char **)valbuf; 1687*7c478bd9Sstevel@tonic-gate 1688*7c478bd9Sstevel@tonic-gate /* create the property */ 1689*7c478bd9Sstevel@tonic-gate if (e_ddi_prop_update_string_array(DDI_DEV_T_NONE, 1690*7c478bd9Sstevel@tonic-gate devi, name, valsp, propcnt) 1691*7c478bd9Sstevel@tonic-gate != DDI_PROP_SUCCESS) { 1692*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 1693*7c478bd9Sstevel@tonic-gate "cannot create property %s", name); 1694*7c478bd9Sstevel@tonic-gate } 1695*7c478bd9Sstevel@tonic-gate /* Clean up */ 1696*7c478bd9Sstevel@tonic-gate vl = val; 1697*7c478bd9Sstevel@tonic-gate while (vl) { 1698*7c478bd9Sstevel@tonic-gate tvl = vl; 1699*7c478bd9Sstevel@tonic-gate vl = vl->val_next; 1700*7c478bd9Sstevel@tonic-gate kmem_free(tvl->val.string, tvl->val_size); 1701*7c478bd9Sstevel@tonic-gate kmem_free(tvl, sizeof (struct val_list)); 1702*7c478bd9Sstevel@tonic-gate } 1703*7c478bd9Sstevel@tonic-gate kmem_free(valsp, ((propcnt + 1) * sizeof (char *))); 1704*7c478bd9Sstevel@tonic-gate } else { 1705*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Invalid property type"); 1706*7c478bd9Sstevel@tonic-gate return; 1707*7c478bd9Sstevel@tonic-gate } 1708*7c478bd9Sstevel@tonic-gate } else { 1709*7c478bd9Sstevel@tonic-gate /* 1710*7c478bd9Sstevel@tonic-gate * No value was passed in with property so we will assume 1711*7c478bd9Sstevel@tonic-gate * it is a "boolean" property and create an integer 1712*7c478bd9Sstevel@tonic-gate * property with 0 value. 1713*7c478bd9Sstevel@tonic-gate */ 1714*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1715*7c478bd9Sstevel@tonic-gate parse_debug(NULL, "\n"); 1716*7c478bd9Sstevel@tonic-gate #endif 1717*7c478bd9Sstevel@tonic-gate if (e_ddi_prop_update_int(DDI_DEV_T_NONE, devi, name, 0) 1718*7c478bd9Sstevel@tonic-gate != DDI_PROP_SUCCESS) { 1719*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 1720*7c478bd9Sstevel@tonic-gate "cannot create property %s", name); 1721*7c478bd9Sstevel@tonic-gate } 1722*7c478bd9Sstevel@tonic-gate } 1723*7c478bd9Sstevel@tonic-gate kmem_free(name, strlen(name) + 1); 1724*7c478bd9Sstevel@tonic-gate } 1725*7c478bd9Sstevel@tonic-gate 1726*7c478bd9Sstevel@tonic-gate static char omit_err[] = "(the ';' may have been omitted on previous spec!)"; 1727*7c478bd9Sstevel@tonic-gate static char prnt_err[] = "'parent' property already specified"; 1728*7c478bd9Sstevel@tonic-gate static char nm_err[] = "'name' property already specified"; 1729*7c478bd9Sstevel@tonic-gate static char class_err[] = "'class' property already specified"; 1730*7c478bd9Sstevel@tonic-gate 1731*7c478bd9Sstevel@tonic-gate typedef enum { 1732*7c478bd9Sstevel@tonic-gate hwc_begin, parent, drvname, drvclass, prop, 1733*7c478bd9Sstevel@tonic-gate parent_equals, name_equals, drvclass_equals, 1734*7c478bd9Sstevel@tonic-gate parent_equals_string, name_equals_string, 1735*7c478bd9Sstevel@tonic-gate drvclass_equals_string, 1736*7c478bd9Sstevel@tonic-gate prop_equals, prop_equals_string, prop_equals_integer, 1737*7c478bd9Sstevel@tonic-gate prop_equals_string_comma, prop_equals_integer_comma 1738*7c478bd9Sstevel@tonic-gate } hwc_state_t; 1739*7c478bd9Sstevel@tonic-gate 1740*7c478bd9Sstevel@tonic-gate static struct hwc_spec * 1741*7c478bd9Sstevel@tonic-gate get_hwc_spec(struct _buf *file, char *tokbuf, size_t linesize) 1742*7c478bd9Sstevel@tonic-gate { 1743*7c478bd9Sstevel@tonic-gate char *prop_name, *string, *class_string; 1744*7c478bd9Sstevel@tonic-gate token_t token; 1745*7c478bd9Sstevel@tonic-gate struct hwc_spec *hwcp; 1746*7c478bd9Sstevel@tonic-gate struct dev_info *devi; 1747*7c478bd9Sstevel@tonic-gate struct val_list *val_list; 1748*7c478bd9Sstevel@tonic-gate hwc_state_t state; 1749*7c478bd9Sstevel@tonic-gate u_longlong_t ival; 1750*7c478bd9Sstevel@tonic-gate 1751*7c478bd9Sstevel@tonic-gate hwcp = kmem_zalloc(sizeof (*hwcp), KM_SLEEP); 1752*7c478bd9Sstevel@tonic-gate devi = kmem_zalloc(sizeof (*devi), KM_SLEEP); 1753*7c478bd9Sstevel@tonic-gate 1754*7c478bd9Sstevel@tonic-gate state = hwc_begin; 1755*7c478bd9Sstevel@tonic-gate token = NAME; 1756*7c478bd9Sstevel@tonic-gate prop_name = NULL; 1757*7c478bd9Sstevel@tonic-gate val_list = NULL; 1758*7c478bd9Sstevel@tonic-gate string = NULL; 1759*7c478bd9Sstevel@tonic-gate do { 1760*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1761*7c478bd9Sstevel@tonic-gate parse_debug(NULL, "state 0x%x\n", state); 1762*7c478bd9Sstevel@tonic-gate #endif 1763*7c478bd9Sstevel@tonic-gate switch (token) { 1764*7c478bd9Sstevel@tonic-gate case NAME: 1765*7c478bd9Sstevel@tonic-gate switch (state) { 1766*7c478bd9Sstevel@tonic-gate case prop: 1767*7c478bd9Sstevel@tonic-gate case prop_equals_string: 1768*7c478bd9Sstevel@tonic-gate case prop_equals_integer: 1769*7c478bd9Sstevel@tonic-gate make_prop(file, (dev_info_t *)devi, 1770*7c478bd9Sstevel@tonic-gate prop_name, val_list); 1771*7c478bd9Sstevel@tonic-gate prop_name = NULL; 1772*7c478bd9Sstevel@tonic-gate val_list = NULL; 1773*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 1774*7c478bd9Sstevel@tonic-gate case hwc_begin: 1775*7c478bd9Sstevel@tonic-gate if (strcmp(tokbuf, "PARENT") == 0 || 1776*7c478bd9Sstevel@tonic-gate strcmp(tokbuf, "parent") == 0) { 1777*7c478bd9Sstevel@tonic-gate state = parent; 1778*7c478bd9Sstevel@tonic-gate } else if (strcmp(tokbuf, "NAME") == 0 || 1779*7c478bd9Sstevel@tonic-gate strcmp(tokbuf, "name") == 0) { 1780*7c478bd9Sstevel@tonic-gate state = drvname; 1781*7c478bd9Sstevel@tonic-gate } else if (strcmp(tokbuf, "CLASS") == 0 || 1782*7c478bd9Sstevel@tonic-gate strcmp(tokbuf, "class") == 0) { 1783*7c478bd9Sstevel@tonic-gate state = drvclass; 1784*7c478bd9Sstevel@tonic-gate prop_name = kmem_alloc(strlen(tokbuf) + 1785*7c478bd9Sstevel@tonic-gate 1, KM_SLEEP); 1786*7c478bd9Sstevel@tonic-gate (void) strcpy(prop_name, tokbuf); 1787*7c478bd9Sstevel@tonic-gate } else { 1788*7c478bd9Sstevel@tonic-gate state = prop; 1789*7c478bd9Sstevel@tonic-gate prop_name = kmem_alloc(strlen(tokbuf) + 1790*7c478bd9Sstevel@tonic-gate 1, KM_SLEEP); 1791*7c478bd9Sstevel@tonic-gate (void) strcpy(prop_name, tokbuf); 1792*7c478bd9Sstevel@tonic-gate } 1793*7c478bd9Sstevel@tonic-gate break; 1794*7c478bd9Sstevel@tonic-gate default: 1795*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 1796*7c478bd9Sstevel@tonic-gate } 1797*7c478bd9Sstevel@tonic-gate break; 1798*7c478bd9Sstevel@tonic-gate case EQUALS: 1799*7c478bd9Sstevel@tonic-gate switch (state) { 1800*7c478bd9Sstevel@tonic-gate case drvname: 1801*7c478bd9Sstevel@tonic-gate state = name_equals; 1802*7c478bd9Sstevel@tonic-gate break; 1803*7c478bd9Sstevel@tonic-gate case parent: 1804*7c478bd9Sstevel@tonic-gate state = parent_equals; 1805*7c478bd9Sstevel@tonic-gate break; 1806*7c478bd9Sstevel@tonic-gate case drvclass: 1807*7c478bd9Sstevel@tonic-gate state = drvclass_equals; 1808*7c478bd9Sstevel@tonic-gate break; 1809*7c478bd9Sstevel@tonic-gate case prop: 1810*7c478bd9Sstevel@tonic-gate state = prop_equals; 1811*7c478bd9Sstevel@tonic-gate break; 1812*7c478bd9Sstevel@tonic-gate default: 1813*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 1814*7c478bd9Sstevel@tonic-gate } 1815*7c478bd9Sstevel@tonic-gate break; 1816*7c478bd9Sstevel@tonic-gate case STRING: 1817*7c478bd9Sstevel@tonic-gate string = kmem_alloc(strlen(tokbuf) + 1, KM_SLEEP); 1818*7c478bd9Sstevel@tonic-gate (void) strcpy(string, tokbuf); 1819*7c478bd9Sstevel@tonic-gate switch (state) { 1820*7c478bd9Sstevel@tonic-gate case name_equals: 1821*7c478bd9Sstevel@tonic-gate if (ddi_get_name((dev_info_t *)devi)) { 1822*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "%s %s", 1823*7c478bd9Sstevel@tonic-gate nm_err, omit_err); 1824*7c478bd9Sstevel@tonic-gate goto bad; 1825*7c478bd9Sstevel@tonic-gate } 1826*7c478bd9Sstevel@tonic-gate devi->devi_name = string; 1827*7c478bd9Sstevel@tonic-gate string = NULL; 1828*7c478bd9Sstevel@tonic-gate state = hwc_begin; 1829*7c478bd9Sstevel@tonic-gate break; 1830*7c478bd9Sstevel@tonic-gate case parent_equals: 1831*7c478bd9Sstevel@tonic-gate if (hwcp->hwc_parent_name) { 1832*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "%s %s", 1833*7c478bd9Sstevel@tonic-gate prnt_err, omit_err); 1834*7c478bd9Sstevel@tonic-gate goto bad; 1835*7c478bd9Sstevel@tonic-gate } 1836*7c478bd9Sstevel@tonic-gate hwcp->hwc_parent_name = string; 1837*7c478bd9Sstevel@tonic-gate string = NULL; 1838*7c478bd9Sstevel@tonic-gate state = hwc_begin; 1839*7c478bd9Sstevel@tonic-gate break; 1840*7c478bd9Sstevel@tonic-gate case drvclass_equals: 1841*7c478bd9Sstevel@tonic-gate if (hwcp->hwc_class_name) { 1842*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, class_err); 1843*7c478bd9Sstevel@tonic-gate goto bad; 1844*7c478bd9Sstevel@tonic-gate } 1845*7c478bd9Sstevel@tonic-gate class_string = kmem_alloc(strlen(string) + 1, 1846*7c478bd9Sstevel@tonic-gate KM_SLEEP); 1847*7c478bd9Sstevel@tonic-gate (void) strcpy(class_string, string); 1848*7c478bd9Sstevel@tonic-gate hwcp->hwc_class_name = class_string; 1849*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 1850*7c478bd9Sstevel@tonic-gate case prop_equals: 1851*7c478bd9Sstevel@tonic-gate case prop_equals_string_comma: 1852*7c478bd9Sstevel@tonic-gate add_val(&val_list, 0, string); 1853*7c478bd9Sstevel@tonic-gate string = NULL; 1854*7c478bd9Sstevel@tonic-gate state = prop_equals_string; 1855*7c478bd9Sstevel@tonic-gate break; 1856*7c478bd9Sstevel@tonic-gate default: 1857*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 1858*7c478bd9Sstevel@tonic-gate } 1859*7c478bd9Sstevel@tonic-gate break; 1860*7c478bd9Sstevel@tonic-gate case HEXVAL: 1861*7c478bd9Sstevel@tonic-gate case DECVAL: 1862*7c478bd9Sstevel@tonic-gate switch (state) { 1863*7c478bd9Sstevel@tonic-gate case prop_equals: 1864*7c478bd9Sstevel@tonic-gate case prop_equals_integer_comma: 1865*7c478bd9Sstevel@tonic-gate (void) kobj_getvalue(tokbuf, &ival); 1866*7c478bd9Sstevel@tonic-gate add_val(&val_list, 1, (caddr_t)(uintptr_t)ival); 1867*7c478bd9Sstevel@tonic-gate state = prop_equals_integer; 1868*7c478bd9Sstevel@tonic-gate break; 1869*7c478bd9Sstevel@tonic-gate default: 1870*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 1871*7c478bd9Sstevel@tonic-gate } 1872*7c478bd9Sstevel@tonic-gate break; 1873*7c478bd9Sstevel@tonic-gate case COMMA: 1874*7c478bd9Sstevel@tonic-gate switch (state) { 1875*7c478bd9Sstevel@tonic-gate case prop_equals_string: 1876*7c478bd9Sstevel@tonic-gate state = prop_equals_string_comma; 1877*7c478bd9Sstevel@tonic-gate break; 1878*7c478bd9Sstevel@tonic-gate case prop_equals_integer: 1879*7c478bd9Sstevel@tonic-gate state = prop_equals_integer_comma; 1880*7c478bd9Sstevel@tonic-gate break; 1881*7c478bd9Sstevel@tonic-gate default: 1882*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 1883*7c478bd9Sstevel@tonic-gate } 1884*7c478bd9Sstevel@tonic-gate break; 1885*7c478bd9Sstevel@tonic-gate case NEWLINE: 1886*7c478bd9Sstevel@tonic-gate kobj_newline(file); 1887*7c478bd9Sstevel@tonic-gate break; 1888*7c478bd9Sstevel@tonic-gate case POUND: 1889*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 1890*7c478bd9Sstevel@tonic-gate break; 1891*7c478bd9Sstevel@tonic-gate case EOF: 1892*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "Unexpected EOF"); 1893*7c478bd9Sstevel@tonic-gate goto bad; 1894*7c478bd9Sstevel@tonic-gate default: 1895*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 1896*7c478bd9Sstevel@tonic-gate goto bad; 1897*7c478bd9Sstevel@tonic-gate } 1898*7c478bd9Sstevel@tonic-gate } while ((token = kobj_lex(file, tokbuf, linesize)) != SEMICOLON); 1899*7c478bd9Sstevel@tonic-gate 1900*7c478bd9Sstevel@tonic-gate switch (state) { 1901*7c478bd9Sstevel@tonic-gate case prop: 1902*7c478bd9Sstevel@tonic-gate case prop_equals_string: 1903*7c478bd9Sstevel@tonic-gate case prop_equals_integer: 1904*7c478bd9Sstevel@tonic-gate make_prop(file, (dev_info_t *)devi, 1905*7c478bd9Sstevel@tonic-gate prop_name, val_list); 1906*7c478bd9Sstevel@tonic-gate break; 1907*7c478bd9Sstevel@tonic-gate 1908*7c478bd9Sstevel@tonic-gate case hwc_begin: 1909*7c478bd9Sstevel@tonic-gate break; 1910*7c478bd9Sstevel@tonic-gate default: 1911*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "Unexpected end of line"); 1912*7c478bd9Sstevel@tonic-gate break; 1913*7c478bd9Sstevel@tonic-gate } 1914*7c478bd9Sstevel@tonic-gate 1915*7c478bd9Sstevel@tonic-gate /* copy 2 relevant members of devi to hwcp */ 1916*7c478bd9Sstevel@tonic-gate hwcp->hwc_devi_sys_prop_ptr = devi->devi_sys_prop_ptr; 1917*7c478bd9Sstevel@tonic-gate hwcp->hwc_devi_name = devi->devi_name; 1918*7c478bd9Sstevel@tonic-gate 1919*7c478bd9Sstevel@tonic-gate kmem_free(devi, sizeof (struct dev_info)); 1920*7c478bd9Sstevel@tonic-gate 1921*7c478bd9Sstevel@tonic-gate return (hwcp); 1922*7c478bd9Sstevel@tonic-gate 1923*7c478bd9Sstevel@tonic-gate bad: 1924*7c478bd9Sstevel@tonic-gate if (string) { 1925*7c478bd9Sstevel@tonic-gate kmem_free(string, strlen(string) + 1); 1926*7c478bd9Sstevel@tonic-gate } 1927*7c478bd9Sstevel@tonic-gate if (hwcp) { 1928*7c478bd9Sstevel@tonic-gate hwc_free(hwcp); 1929*7c478bd9Sstevel@tonic-gate } 1930*7c478bd9Sstevel@tonic-gate if (devi) { 1931*7c478bd9Sstevel@tonic-gate if (devi->devi_name) 1932*7c478bd9Sstevel@tonic-gate kmem_free(devi->devi_name, 1933*7c478bd9Sstevel@tonic-gate strlen(devi->devi_name) + 1); 1934*7c478bd9Sstevel@tonic-gate kmem_free(devi, sizeof (struct dev_info)); 1935*7c478bd9Sstevel@tonic-gate } 1936*7c478bd9Sstevel@tonic-gate return (NULL); 1937*7c478bd9Sstevel@tonic-gate } 1938*7c478bd9Sstevel@tonic-gate 1939*7c478bd9Sstevel@tonic-gate /* 1940*7c478bd9Sstevel@tonic-gate * This is the primary kernel interface to parse driver.conf files. 1941*7c478bd9Sstevel@tonic-gate * 1942*7c478bd9Sstevel@tonic-gate * Yet another bigstk thread handoff due to deep kernel stacks when booting 1943*7c478bd9Sstevel@tonic-gate * cache-only-clients. 1944*7c478bd9Sstevel@tonic-gate */ 1945*7c478bd9Sstevel@tonic-gate int 1946*7c478bd9Sstevel@tonic-gate hwc_parse(char *fname, struct par_list **pl, ddi_prop_t **props) 1947*7c478bd9Sstevel@tonic-gate { 1948*7c478bd9Sstevel@tonic-gate int ret; 1949*7c478bd9Sstevel@tonic-gate struct hwc_parse_mt *pltp = hwc_parse_mtalloc(fname, pl, props); 1950*7c478bd9Sstevel@tonic-gate 1951*7c478bd9Sstevel@tonic-gate if (curthread != &t0) { 1952*7c478bd9Sstevel@tonic-gate (void) thread_create(NULL, DEFAULTSTKSZ * 2, 1953*7c478bd9Sstevel@tonic-gate hwc_parse_thread, pltp, 0, &p0, TS_RUN, maxclsyspri); 1954*7c478bd9Sstevel@tonic-gate sema_p(&pltp->sema); 1955*7c478bd9Sstevel@tonic-gate } else { 1956*7c478bd9Sstevel@tonic-gate pltp->rv = hwc_parse_now(fname, pl, props); 1957*7c478bd9Sstevel@tonic-gate } 1958*7c478bd9Sstevel@tonic-gate ret = pltp->rv; 1959*7c478bd9Sstevel@tonic-gate hwc_parse_mtfree(pltp); 1960*7c478bd9Sstevel@tonic-gate return (ret); 1961*7c478bd9Sstevel@tonic-gate } 1962*7c478bd9Sstevel@tonic-gate 1963*7c478bd9Sstevel@tonic-gate /* 1964*7c478bd9Sstevel@tonic-gate * Calls to hwc_parse() are handled off to this routine in a separate 1965*7c478bd9Sstevel@tonic-gate * thread. 1966*7c478bd9Sstevel@tonic-gate */ 1967*7c478bd9Sstevel@tonic-gate static void 1968*7c478bd9Sstevel@tonic-gate hwc_parse_thread(struct hwc_parse_mt *pltp) 1969*7c478bd9Sstevel@tonic-gate { 1970*7c478bd9Sstevel@tonic-gate kmutex_t cpr_lk; 1971*7c478bd9Sstevel@tonic-gate callb_cpr_t cpr_i; 1972*7c478bd9Sstevel@tonic-gate 1973*7c478bd9Sstevel@tonic-gate mutex_init(&cpr_lk, NULL, MUTEX_DEFAULT, NULL); 1974*7c478bd9Sstevel@tonic-gate CALLB_CPR_INIT(&cpr_i, &cpr_lk, callb_generic_cpr, "hwc_parse"); 1975*7c478bd9Sstevel@tonic-gate 1976*7c478bd9Sstevel@tonic-gate /* 1977*7c478bd9Sstevel@tonic-gate * load and parse the .conf file 1978*7c478bd9Sstevel@tonic-gate * return the hwc_spec list (if any) to the creator of this thread 1979*7c478bd9Sstevel@tonic-gate */ 1980*7c478bd9Sstevel@tonic-gate pltp->rv = hwc_parse_now(pltp->name, pltp->pl, pltp->props); 1981*7c478bd9Sstevel@tonic-gate sema_v(&pltp->sema); 1982*7c478bd9Sstevel@tonic-gate mutex_enter(&cpr_lk); 1983*7c478bd9Sstevel@tonic-gate CALLB_CPR_EXIT(&cpr_i); 1984*7c478bd9Sstevel@tonic-gate mutex_destroy(&cpr_lk); 1985*7c478bd9Sstevel@tonic-gate thread_exit(); 1986*7c478bd9Sstevel@tonic-gate } 1987*7c478bd9Sstevel@tonic-gate 1988*7c478bd9Sstevel@tonic-gate /* 1989*7c478bd9Sstevel@tonic-gate * allocate and initialize a hwc_parse thread control structure 1990*7c478bd9Sstevel@tonic-gate */ 1991*7c478bd9Sstevel@tonic-gate static struct hwc_parse_mt * 1992*7c478bd9Sstevel@tonic-gate hwc_parse_mtalloc(char *name, struct par_list **pl, ddi_prop_t **props) 1993*7c478bd9Sstevel@tonic-gate { 1994*7c478bd9Sstevel@tonic-gate struct hwc_parse_mt *pltp = kmem_zalloc(sizeof (*pltp), KM_SLEEP); 1995*7c478bd9Sstevel@tonic-gate 1996*7c478bd9Sstevel@tonic-gate ASSERT(name != NULL); 1997*7c478bd9Sstevel@tonic-gate 1998*7c478bd9Sstevel@tonic-gate pltp->name = kmem_alloc(strlen(name) + 1, KM_SLEEP); 1999*7c478bd9Sstevel@tonic-gate bcopy(name, pltp->name, strlen(name) + 1); 2000*7c478bd9Sstevel@tonic-gate pltp->pl = pl; 2001*7c478bd9Sstevel@tonic-gate pltp->props = props; 2002*7c478bd9Sstevel@tonic-gate 2003*7c478bd9Sstevel@tonic-gate sema_init(&pltp->sema, 0, NULL, SEMA_DEFAULT, NULL); 2004*7c478bd9Sstevel@tonic-gate return (pltp); 2005*7c478bd9Sstevel@tonic-gate } 2006*7c478bd9Sstevel@tonic-gate 2007*7c478bd9Sstevel@tonic-gate /* 2008*7c478bd9Sstevel@tonic-gate * free a hwc_parse thread control structure 2009*7c478bd9Sstevel@tonic-gate */ 2010*7c478bd9Sstevel@tonic-gate static void 2011*7c478bd9Sstevel@tonic-gate hwc_parse_mtfree(struct hwc_parse_mt *pltp) 2012*7c478bd9Sstevel@tonic-gate { 2013*7c478bd9Sstevel@tonic-gate sema_destroy(&pltp->sema); 2014*7c478bd9Sstevel@tonic-gate 2015*7c478bd9Sstevel@tonic-gate kmem_free(pltp->name, strlen(pltp->name) + 1); 2016*7c478bd9Sstevel@tonic-gate kmem_free(pltp, sizeof (*pltp)); 2017*7c478bd9Sstevel@tonic-gate } 2018*7c478bd9Sstevel@tonic-gate 2019*7c478bd9Sstevel@tonic-gate /* 2020*7c478bd9Sstevel@tonic-gate * hwc_parse -- parse an hwconf file. Ignore error lines and parse 2021*7c478bd9Sstevel@tonic-gate * as much as possible. 2022*7c478bd9Sstevel@tonic-gate */ 2023*7c478bd9Sstevel@tonic-gate static int 2024*7c478bd9Sstevel@tonic-gate hwc_parse_now(char *fname, struct par_list **pl, ddi_prop_t **props) 2025*7c478bd9Sstevel@tonic-gate { 2026*7c478bd9Sstevel@tonic-gate struct _buf *file; 2027*7c478bd9Sstevel@tonic-gate struct hwc_spec *hwcp; 2028*7c478bd9Sstevel@tonic-gate char *tokval; 2029*7c478bd9Sstevel@tonic-gate token_t token; 2030*7c478bd9Sstevel@tonic-gate 2031*7c478bd9Sstevel@tonic-gate /* 2032*7c478bd9Sstevel@tonic-gate * Don't use kobj_open_path's use_moddir_suffix option, we only 2033*7c478bd9Sstevel@tonic-gate * expect to find conf files in the base module directory, not 2034*7c478bd9Sstevel@tonic-gate * an ISA-specific subdirectory. 2035*7c478bd9Sstevel@tonic-gate */ 2036*7c478bd9Sstevel@tonic-gate if ((file = kobj_open_path(fname, 1, 0)) == (struct _buf *)-1) { 2037*7c478bd9Sstevel@tonic-gate if (moddebug & MODDEBUG_ERRMSG) 2038*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Cannot open %s", fname); 2039*7c478bd9Sstevel@tonic-gate return (-1); 2040*7c478bd9Sstevel@tonic-gate } 2041*7c478bd9Sstevel@tonic-gate 2042*7c478bd9Sstevel@tonic-gate /* 2043*7c478bd9Sstevel@tonic-gate * Initialize variables 2044*7c478bd9Sstevel@tonic-gate */ 2045*7c478bd9Sstevel@tonic-gate tokval = kmem_alloc(MAX_HWC_LINESIZE, KM_SLEEP); 2046*7c478bd9Sstevel@tonic-gate 2047*7c478bd9Sstevel@tonic-gate while ((token = kobj_lex(file, tokval, MAX_HWC_LINESIZE)) != EOF) { 2048*7c478bd9Sstevel@tonic-gate switch (token) { 2049*7c478bd9Sstevel@tonic-gate case POUND: 2050*7c478bd9Sstevel@tonic-gate /* 2051*7c478bd9Sstevel@tonic-gate * Skip comments. 2052*7c478bd9Sstevel@tonic-gate */ 2053*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 2054*7c478bd9Sstevel@tonic-gate break; 2055*7c478bd9Sstevel@tonic-gate case NAME: 2056*7c478bd9Sstevel@tonic-gate hwcp = get_hwc_spec(file, tokval, MAX_HWC_LINESIZE); 2057*7c478bd9Sstevel@tonic-gate if (hwcp == NULL) 2058*7c478bd9Sstevel@tonic-gate break; 2059*7c478bd9Sstevel@tonic-gate /* 2060*7c478bd9Sstevel@tonic-gate * No devi_name indicates global property. 2061*7c478bd9Sstevel@tonic-gate * Make sure parent and class not NULL. 2062*7c478bd9Sstevel@tonic-gate */ 2063*7c478bd9Sstevel@tonic-gate if (hwcp->hwc_devi_name == NULL) { 2064*7c478bd9Sstevel@tonic-gate if (hwcp->hwc_parent_name || 2065*7c478bd9Sstevel@tonic-gate hwcp->hwc_class_name) { 2066*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 2067*7c478bd9Sstevel@tonic-gate "missing name attribute"); 2068*7c478bd9Sstevel@tonic-gate hwc_free(hwcp); 2069*7c478bd9Sstevel@tonic-gate continue; 2070*7c478bd9Sstevel@tonic-gate } 2071*7c478bd9Sstevel@tonic-gate /* Add to global property list */ 2072*7c478bd9Sstevel@tonic-gate add_props(hwcp, props); 2073*7c478bd9Sstevel@tonic-gate break; 2074*7c478bd9Sstevel@tonic-gate } 2075*7c478bd9Sstevel@tonic-gate 2076*7c478bd9Sstevel@tonic-gate /* 2077*7c478bd9Sstevel@tonic-gate * This is a node spec, either parent or class 2078*7c478bd9Sstevel@tonic-gate * must be specified. 2079*7c478bd9Sstevel@tonic-gate */ 2080*7c478bd9Sstevel@tonic-gate if ((hwcp->hwc_parent_name == NULL) && 2081*7c478bd9Sstevel@tonic-gate (hwcp->hwc_class_name == NULL)) { 2082*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 2083*7c478bd9Sstevel@tonic-gate "missing parent or class attribute"); 2084*7c478bd9Sstevel@tonic-gate hwc_free(hwcp); 2085*7c478bd9Sstevel@tonic-gate continue; 2086*7c478bd9Sstevel@tonic-gate } 2087*7c478bd9Sstevel@tonic-gate 2088*7c478bd9Sstevel@tonic-gate /* add to node spec list */ 2089*7c478bd9Sstevel@tonic-gate add_spec(hwcp, pl); 2090*7c478bd9Sstevel@tonic-gate break; 2091*7c478bd9Sstevel@tonic-gate case NEWLINE: 2092*7c478bd9Sstevel@tonic-gate kobj_newline(file); 2093*7c478bd9Sstevel@tonic-gate break; 2094*7c478bd9Sstevel@tonic-gate default: 2095*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokval); 2096*7c478bd9Sstevel@tonic-gate break; 2097*7c478bd9Sstevel@tonic-gate } 2098*7c478bd9Sstevel@tonic-gate } 2099*7c478bd9Sstevel@tonic-gate /* 2100*7c478bd9Sstevel@tonic-gate * XXX - Check for clean termination. 2101*7c478bd9Sstevel@tonic-gate */ 2102*7c478bd9Sstevel@tonic-gate kmem_free(tokval, MAX_HWC_LINESIZE); 2103*7c478bd9Sstevel@tonic-gate kobj_close_file(file); 2104*7c478bd9Sstevel@tonic-gate return (0); /* always return success */ 2105*7c478bd9Sstevel@tonic-gate } 2106*7c478bd9Sstevel@tonic-gate 2107*7c478bd9Sstevel@tonic-gate void 2108*7c478bd9Sstevel@tonic-gate make_aliases(struct bind **bhash) 2109*7c478bd9Sstevel@tonic-gate { 2110*7c478bd9Sstevel@tonic-gate enum { 2111*7c478bd9Sstevel@tonic-gate AL_NEW, AL_DRVNAME, AL_DRVNAME_COMMA, AL_ALIAS, AL_ALIAS_COMMA 2112*7c478bd9Sstevel@tonic-gate } state; 2113*7c478bd9Sstevel@tonic-gate 2114*7c478bd9Sstevel@tonic-gate struct _buf *file; 2115*7c478bd9Sstevel@tonic-gate char tokbuf[MAXNAMELEN]; 2116*7c478bd9Sstevel@tonic-gate char drvbuf[MAXNAMELEN]; 2117*7c478bd9Sstevel@tonic-gate token_t token; 2118*7c478bd9Sstevel@tonic-gate major_t major; 2119*7c478bd9Sstevel@tonic-gate int done = 0; 2120*7c478bd9Sstevel@tonic-gate static char dupwarn[] = "!Driver alias \"%s\" conflicts with " 2121*7c478bd9Sstevel@tonic-gate "an existing driver name or alias."; 2122*7c478bd9Sstevel@tonic-gate 2123*7c478bd9Sstevel@tonic-gate if ((file = kobj_open_file(dafile)) == (struct _buf *)-1) 2124*7c478bd9Sstevel@tonic-gate return; 2125*7c478bd9Sstevel@tonic-gate 2126*7c478bd9Sstevel@tonic-gate state = AL_NEW; 2127*7c478bd9Sstevel@tonic-gate major = (major_t)-1; 2128*7c478bd9Sstevel@tonic-gate while (!done) { 2129*7c478bd9Sstevel@tonic-gate token = kobj_lex(file, tokbuf, sizeof (tokbuf)); 2130*7c478bd9Sstevel@tonic-gate switch (token) { 2131*7c478bd9Sstevel@tonic-gate case POUND: 2132*7c478bd9Sstevel@tonic-gate state = AL_NEW; 2133*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 2134*7c478bd9Sstevel@tonic-gate break; 2135*7c478bd9Sstevel@tonic-gate case NAME: 2136*7c478bd9Sstevel@tonic-gate case STRING: 2137*7c478bd9Sstevel@tonic-gate switch (state) { 2138*7c478bd9Sstevel@tonic-gate case AL_NEW: 2139*7c478bd9Sstevel@tonic-gate (void) strcpy(drvbuf, tokbuf); 2140*7c478bd9Sstevel@tonic-gate state = AL_DRVNAME; 2141*7c478bd9Sstevel@tonic-gate break; 2142*7c478bd9Sstevel@tonic-gate case AL_DRVNAME_COMMA: 2143*7c478bd9Sstevel@tonic-gate (void) strcat(drvbuf, tokbuf); 2144*7c478bd9Sstevel@tonic-gate state = AL_DRVNAME; 2145*7c478bd9Sstevel@tonic-gate break; 2146*7c478bd9Sstevel@tonic-gate case AL_ALIAS_COMMA: 2147*7c478bd9Sstevel@tonic-gate (void) strcat(drvbuf, tokbuf); 2148*7c478bd9Sstevel@tonic-gate state = AL_ALIAS; 2149*7c478bd9Sstevel@tonic-gate break; 2150*7c478bd9Sstevel@tonic-gate case AL_DRVNAME: 2151*7c478bd9Sstevel@tonic-gate major = mod_name_to_major(drvbuf); 2152*7c478bd9Sstevel@tonic-gate if (major == (major_t)-1) { 2153*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 2154*7c478bd9Sstevel@tonic-gate state = AL_NEW; 2155*7c478bd9Sstevel@tonic-gate } else { 2156*7c478bd9Sstevel@tonic-gate (void) strcpy(drvbuf, tokbuf); 2157*7c478bd9Sstevel@tonic-gate state = AL_ALIAS; 2158*7c478bd9Sstevel@tonic-gate } 2159*7c478bd9Sstevel@tonic-gate break; 2160*7c478bd9Sstevel@tonic-gate case AL_ALIAS: 2161*7c478bd9Sstevel@tonic-gate if (make_mbind(drvbuf, major, NULL, bhash) 2162*7c478bd9Sstevel@tonic-gate != 0) { 2163*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, dupwarn, drvbuf); 2164*7c478bd9Sstevel@tonic-gate } 2165*7c478bd9Sstevel@tonic-gate break; 2166*7c478bd9Sstevel@tonic-gate } 2167*7c478bd9Sstevel@tonic-gate break; 2168*7c478bd9Sstevel@tonic-gate case COMMA: 2169*7c478bd9Sstevel@tonic-gate (void) strcat(drvbuf, tokbuf); 2170*7c478bd9Sstevel@tonic-gate switch (state) { 2171*7c478bd9Sstevel@tonic-gate case AL_DRVNAME: 2172*7c478bd9Sstevel@tonic-gate state = AL_DRVNAME_COMMA; 2173*7c478bd9Sstevel@tonic-gate break; 2174*7c478bd9Sstevel@tonic-gate case AL_ALIAS: 2175*7c478bd9Sstevel@tonic-gate state = AL_ALIAS_COMMA; 2176*7c478bd9Sstevel@tonic-gate break; 2177*7c478bd9Sstevel@tonic-gate default: 2178*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 2179*7c478bd9Sstevel@tonic-gate } 2180*7c478bd9Sstevel@tonic-gate break; 2181*7c478bd9Sstevel@tonic-gate case EOF: 2182*7c478bd9Sstevel@tonic-gate done = 1; 2183*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 2184*7c478bd9Sstevel@tonic-gate case NEWLINE: 2185*7c478bd9Sstevel@tonic-gate if (state == AL_ALIAS) { 2186*7c478bd9Sstevel@tonic-gate if (make_mbind(drvbuf, major, NULL, bhash) 2187*7c478bd9Sstevel@tonic-gate != 0) { 2188*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, dupwarn, drvbuf); 2189*7c478bd9Sstevel@tonic-gate } 2190*7c478bd9Sstevel@tonic-gate } else if (state != AL_NEW) { 2191*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 2192*7c478bd9Sstevel@tonic-gate "Missing alias for %s", drvbuf); 2193*7c478bd9Sstevel@tonic-gate } 2194*7c478bd9Sstevel@tonic-gate 2195*7c478bd9Sstevel@tonic-gate kobj_newline(file); 2196*7c478bd9Sstevel@tonic-gate state = AL_NEW; 2197*7c478bd9Sstevel@tonic-gate major = (major_t)-1; 2198*7c478bd9Sstevel@tonic-gate break; 2199*7c478bd9Sstevel@tonic-gate default: 2200*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 2201*7c478bd9Sstevel@tonic-gate } 2202*7c478bd9Sstevel@tonic-gate } 2203*7c478bd9Sstevel@tonic-gate 2204*7c478bd9Sstevel@tonic-gate kobj_close_file(file); 2205*7c478bd9Sstevel@tonic-gate } 2206*7c478bd9Sstevel@tonic-gate 2207*7c478bd9Sstevel@tonic-gate 2208*7c478bd9Sstevel@tonic-gate /* 2209*7c478bd9Sstevel@tonic-gate * It is called for parsing these files: 2210*7c478bd9Sstevel@tonic-gate * - /etc/path_to_inst 2211*7c478bd9Sstevel@tonic-gate * - /etc/name_to_major 2212*7c478bd9Sstevel@tonic-gate * - /etc/name_to_sysnum 2213*7c478bd9Sstevel@tonic-gate * A callback "int (*line_parser)(char *, int, char *, struct bind **)" 2214*7c478bd9Sstevel@tonic-gate * is invoked for each line of the file. 2215*7c478bd9Sstevel@tonic-gate * The callback can inhash the entry into a hashtable by supplying 2216*7c478bd9Sstevel@tonic-gate * a pre-allocated hashtable in "struct bind **hashtab". 2217*7c478bd9Sstevel@tonic-gate */ 2218*7c478bd9Sstevel@tonic-gate int 2219*7c478bd9Sstevel@tonic-gate read_binding_file(char *bindfile, struct bind **hashtab, 2220*7c478bd9Sstevel@tonic-gate int (*line_parser)(char *, int, char *, struct bind **)) 2221*7c478bd9Sstevel@tonic-gate { 2222*7c478bd9Sstevel@tonic-gate enum { 2223*7c478bd9Sstevel@tonic-gate B_NEW, B_NAME, B_VAL, B_BIND_NAME 2224*7c478bd9Sstevel@tonic-gate } state; 2225*7c478bd9Sstevel@tonic-gate struct _buf *file; 2226*7c478bd9Sstevel@tonic-gate char tokbuf[MAXNAMELEN]; 2227*7c478bd9Sstevel@tonic-gate token_t token; 2228*7c478bd9Sstevel@tonic-gate int maxnum = 0; 2229*7c478bd9Sstevel@tonic-gate char *bind_name = NULL, *name = NULL, *bn = NULL; 2230*7c478bd9Sstevel@tonic-gate u_longlong_t val; 2231*7c478bd9Sstevel@tonic-gate int done = 0; 2232*7c478bd9Sstevel@tonic-gate 2233*7c478bd9Sstevel@tonic-gate static char num_err[] = "Missing number on preceding line?"; 2234*7c478bd9Sstevel@tonic-gate static char dupwarn[] = "!The binding file entry \"%s %u\" conflicts " 2235*7c478bd9Sstevel@tonic-gate "with a previous entry"; 2236*7c478bd9Sstevel@tonic-gate 2237*7c478bd9Sstevel@tonic-gate if (hashtab != NULL) { 2238*7c478bd9Sstevel@tonic-gate clear_binding_hash(hashtab); 2239*7c478bd9Sstevel@tonic-gate } 2240*7c478bd9Sstevel@tonic-gate 2241*7c478bd9Sstevel@tonic-gate if ((file = kobj_open_file(bindfile)) == (struct _buf *)-1) 2242*7c478bd9Sstevel@tonic-gate panic("read_binding_file: %s file not found", bindfile); 2243*7c478bd9Sstevel@tonic-gate 2244*7c478bd9Sstevel@tonic-gate state = B_NEW; 2245*7c478bd9Sstevel@tonic-gate 2246*7c478bd9Sstevel@tonic-gate while (!done) { 2247*7c478bd9Sstevel@tonic-gate token = kobj_lex(file, tokbuf, sizeof (tokbuf)); 2248*7c478bd9Sstevel@tonic-gate 2249*7c478bd9Sstevel@tonic-gate switch (token) { 2250*7c478bd9Sstevel@tonic-gate case POUND: 2251*7c478bd9Sstevel@tonic-gate state = B_NEW; 2252*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 2253*7c478bd9Sstevel@tonic-gate break; 2254*7c478bd9Sstevel@tonic-gate case NAME: 2255*7c478bd9Sstevel@tonic-gate case STRING: 2256*7c478bd9Sstevel@tonic-gate switch (state) { 2257*7c478bd9Sstevel@tonic-gate case B_NEW: 2258*7c478bd9Sstevel@tonic-gate /* 2259*7c478bd9Sstevel@tonic-gate * This case is for the first name and 2260*7c478bd9Sstevel@tonic-gate * possibly only name in an entry. 2261*7c478bd9Sstevel@tonic-gate */ 2262*7c478bd9Sstevel@tonic-gate ASSERT(name == NULL); 2263*7c478bd9Sstevel@tonic-gate name = kmem_alloc(strlen(tokbuf) + 1, KM_SLEEP); 2264*7c478bd9Sstevel@tonic-gate (void) strcpy(name, tokbuf); 2265*7c478bd9Sstevel@tonic-gate state = B_NAME; 2266*7c478bd9Sstevel@tonic-gate break; 2267*7c478bd9Sstevel@tonic-gate case B_VAL: 2268*7c478bd9Sstevel@tonic-gate /* 2269*7c478bd9Sstevel@tonic-gate * This case is for a second name, which 2270*7c478bd9Sstevel@tonic-gate * would be the binding name if the first 2271*7c478bd9Sstevel@tonic-gate * name was actually a generic name. 2272*7c478bd9Sstevel@tonic-gate */ 2273*7c478bd9Sstevel@tonic-gate ASSERT(bind_name == NULL); 2274*7c478bd9Sstevel@tonic-gate bind_name = kmem_alloc(strlen(tokbuf) + 1, 2275*7c478bd9Sstevel@tonic-gate KM_SLEEP); 2276*7c478bd9Sstevel@tonic-gate (void) strcpy(bind_name, tokbuf); 2277*7c478bd9Sstevel@tonic-gate state = B_BIND_NAME; 2278*7c478bd9Sstevel@tonic-gate break; 2279*7c478bd9Sstevel@tonic-gate default: 2280*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, num_err); 2281*7c478bd9Sstevel@tonic-gate } 2282*7c478bd9Sstevel@tonic-gate break; 2283*7c478bd9Sstevel@tonic-gate case HEXVAL: 2284*7c478bd9Sstevel@tonic-gate case DECVAL: 2285*7c478bd9Sstevel@tonic-gate if (state != B_NAME) { 2286*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "Missing name?"); 2287*7c478bd9Sstevel@tonic-gate state = B_NEW; 2288*7c478bd9Sstevel@tonic-gate continue; 2289*7c478bd9Sstevel@tonic-gate } 2290*7c478bd9Sstevel@tonic-gate (void) kobj_getvalue(tokbuf, &val); 2291*7c478bd9Sstevel@tonic-gate if (val > (u_longlong_t)INT_MAX) { 2292*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 2293*7c478bd9Sstevel@tonic-gate "value %llu too large", val); 2294*7c478bd9Sstevel@tonic-gate state = B_NEW; 2295*7c478bd9Sstevel@tonic-gate continue; 2296*7c478bd9Sstevel@tonic-gate } 2297*7c478bd9Sstevel@tonic-gate state = B_VAL; 2298*7c478bd9Sstevel@tonic-gate break; 2299*7c478bd9Sstevel@tonic-gate case EOF: 2300*7c478bd9Sstevel@tonic-gate done = 1; 2301*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 2302*7c478bd9Sstevel@tonic-gate case NEWLINE: 2303*7c478bd9Sstevel@tonic-gate if ((state == B_BIND_NAME) || (state == B_VAL)) { 2304*7c478bd9Sstevel@tonic-gate if (state == B_BIND_NAME) 2305*7c478bd9Sstevel@tonic-gate bn = bind_name; 2306*7c478bd9Sstevel@tonic-gate else 2307*7c478bd9Sstevel@tonic-gate bn = NULL; 2308*7c478bd9Sstevel@tonic-gate 2309*7c478bd9Sstevel@tonic-gate if (line_parser != NULL) { 2310*7c478bd9Sstevel@tonic-gate if ((*line_parser)(name, (int)val, bn, 2311*7c478bd9Sstevel@tonic-gate hashtab) == 0) 2312*7c478bd9Sstevel@tonic-gate maxnum = MAX((int)val, maxnum); 2313*7c478bd9Sstevel@tonic-gate else 2314*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 2315*7c478bd9Sstevel@tonic-gate dupwarn, name, (uint_t)val); 2316*7c478bd9Sstevel@tonic-gate } 2317*7c478bd9Sstevel@tonic-gate } else if (state != B_NEW) 2318*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "Syntax error?"); 2319*7c478bd9Sstevel@tonic-gate 2320*7c478bd9Sstevel@tonic-gate if (name) { 2321*7c478bd9Sstevel@tonic-gate kmem_free(name, strlen(name) + 1); 2322*7c478bd9Sstevel@tonic-gate name = NULL; 2323*7c478bd9Sstevel@tonic-gate } 2324*7c478bd9Sstevel@tonic-gate if (bind_name) { 2325*7c478bd9Sstevel@tonic-gate kmem_free(bind_name, strlen(bind_name) + 1); 2326*7c478bd9Sstevel@tonic-gate bind_name = NULL; 2327*7c478bd9Sstevel@tonic-gate } 2328*7c478bd9Sstevel@tonic-gate state = B_NEW; 2329*7c478bd9Sstevel@tonic-gate kobj_newline(file); 2330*7c478bd9Sstevel@tonic-gate break; 2331*7c478bd9Sstevel@tonic-gate default: 2332*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, "Missing name/number?"); 2333*7c478bd9Sstevel@tonic-gate break; 2334*7c478bd9Sstevel@tonic-gate } 2335*7c478bd9Sstevel@tonic-gate } 2336*7c478bd9Sstevel@tonic-gate 2337*7c478bd9Sstevel@tonic-gate ASSERT(name == NULL); /* any leaks? */ 2338*7c478bd9Sstevel@tonic-gate ASSERT(bind_name == NULL); 2339*7c478bd9Sstevel@tonic-gate 2340*7c478bd9Sstevel@tonic-gate kobj_close_file(file); 2341*7c478bd9Sstevel@tonic-gate return (maxnum); 2342*7c478bd9Sstevel@tonic-gate } 2343*7c478bd9Sstevel@tonic-gate 2344*7c478bd9Sstevel@tonic-gate /* 2345*7c478bd9Sstevel@tonic-gate * read_dacf_binding_file() 2346*7c478bd9Sstevel@tonic-gate * Read the /etc/dacf.conf file and build the dacf_rule_t database from it. 2347*7c478bd9Sstevel@tonic-gate * 2348*7c478bd9Sstevel@tonic-gate * The syntax of a line in the dacf.conf file is: 2349*7c478bd9Sstevel@tonic-gate * dev-spec [module:]op-set operation options [config-args]; 2350*7c478bd9Sstevel@tonic-gate * 2351*7c478bd9Sstevel@tonic-gate * Where: 2352*7c478bd9Sstevel@tonic-gate * 1. dev-spec is of the format: name="data" 2353*7c478bd9Sstevel@tonic-gate * 2. operation is the operation that this rule matches. (i.e. pre-detach) 2354*7c478bd9Sstevel@tonic-gate * 3. options is a comma delimited list of options (i.e. debug,foobar) 2355*7c478bd9Sstevel@tonic-gate * 4. config-data is a whitespace delimited list of the format: name="data" 2356*7c478bd9Sstevel@tonic-gate */ 2357*7c478bd9Sstevel@tonic-gate int 2358*7c478bd9Sstevel@tonic-gate read_dacf_binding_file(char *filename) 2359*7c478bd9Sstevel@tonic-gate { 2360*7c478bd9Sstevel@tonic-gate enum { 2361*7c478bd9Sstevel@tonic-gate DACF_BEGIN, 2362*7c478bd9Sstevel@tonic-gate /* minor_nodetype="ddi_mouse:serial" */ 2363*7c478bd9Sstevel@tonic-gate DACF_NT_SPEC, DACF_NT_EQUALS, DACF_NT_DATA, 2364*7c478bd9Sstevel@tonic-gate /* consconfig:mouseconfig */ 2365*7c478bd9Sstevel@tonic-gate DACF_MN_MODNAME, DACF_MN_COLON, DACF_MN_OPSET, 2366*7c478bd9Sstevel@tonic-gate /* op */ 2367*7c478bd9Sstevel@tonic-gate DACF_OP_NAME, 2368*7c478bd9Sstevel@tonic-gate /* [ option1, option2, option3... | - ] */ 2369*7c478bd9Sstevel@tonic-gate DACF_OPT_OPTION, DACF_OPT_COMMA, DACF_OPT_END, 2370*7c478bd9Sstevel@tonic-gate /* argname1="argval1" argname2="argval2" ... */ 2371*7c478bd9Sstevel@tonic-gate DACF_OPARG_SPEC, DACF_OPARG_EQUALS, DACF_OPARG_DATA, 2372*7c478bd9Sstevel@tonic-gate DACF_ERR, DACF_ERR_NEWLINE, DACF_COMMENT 2373*7c478bd9Sstevel@tonic-gate } state = DACF_BEGIN; 2374*7c478bd9Sstevel@tonic-gate 2375*7c478bd9Sstevel@tonic-gate struct _buf *file; 2376*7c478bd9Sstevel@tonic-gate char *fname; 2377*7c478bd9Sstevel@tonic-gate token_t token; 2378*7c478bd9Sstevel@tonic-gate 2379*7c478bd9Sstevel@tonic-gate char tokbuf[MAXNAMELEN]; 2380*7c478bd9Sstevel@tonic-gate char mn_modname_buf[MAXNAMELEN], *mn_modnamep = NULL; 2381*7c478bd9Sstevel@tonic-gate char mn_opset_buf[MAXNAMELEN], *mn_opsetp = NULL; 2382*7c478bd9Sstevel@tonic-gate char nt_data_buf[MAXNAMELEN], *nt_datap = NULL; 2383*7c478bd9Sstevel@tonic-gate char arg_spec_buf[MAXNAMELEN]; 2384*7c478bd9Sstevel@tonic-gate 2385*7c478bd9Sstevel@tonic-gate uint_t opts = 0; 2386*7c478bd9Sstevel@tonic-gate dacf_devspec_t nt_spec_type = DACF_DS_ERROR; 2387*7c478bd9Sstevel@tonic-gate 2388*7c478bd9Sstevel@tonic-gate dacf_arg_t *arg_list = NULL; 2389*7c478bd9Sstevel@tonic-gate dacf_opid_t opid = DACF_OPID_ERROR; 2390*7c478bd9Sstevel@tonic-gate int done = 0; 2391*7c478bd9Sstevel@tonic-gate 2392*7c478bd9Sstevel@tonic-gate static char w_syntax[] = "'%s' unexpected"; 2393*7c478bd9Sstevel@tonic-gate static char w_equals[] = "'=' is illegal in the current context"; 2394*7c478bd9Sstevel@tonic-gate static char w_baddevspec[] = "device specification '%s' unrecognized"; 2395*7c478bd9Sstevel@tonic-gate static char w_badop[] = "operation '%s' unrecognized"; 2396*7c478bd9Sstevel@tonic-gate static char w_badopt[] = "option '%s' unrecognized, ignoring"; 2397*7c478bd9Sstevel@tonic-gate static char w_newline[] = "rule is incomplete"; 2398*7c478bd9Sstevel@tonic-gate static char w_insert[] = "failed to register rule"; 2399*7c478bd9Sstevel@tonic-gate static char w_comment[] = "'#' not allowed except at start of line"; 2400*7c478bd9Sstevel@tonic-gate static char w_dupargs[] = 2401*7c478bd9Sstevel@tonic-gate "argument '%s' duplicates a previous argument, skipping"; 2402*7c478bd9Sstevel@tonic-gate static char w_nt_empty[] = "empty device specification not allowed"; 2403*7c478bd9Sstevel@tonic-gate 2404*7c478bd9Sstevel@tonic-gate if (filename == NULL) { 2405*7c478bd9Sstevel@tonic-gate fname = dacffile; /* default binding file */ 2406*7c478bd9Sstevel@tonic-gate } else { 2407*7c478bd9Sstevel@tonic-gate fname = filename; /* user specified */ 2408*7c478bd9Sstevel@tonic-gate } 2409*7c478bd9Sstevel@tonic-gate 2410*7c478bd9Sstevel@tonic-gate if ((file = kobj_open_file(fname)) == (struct _buf *)-1) { 2411*7c478bd9Sstevel@tonic-gate return (ENOENT); 2412*7c478bd9Sstevel@tonic-gate } 2413*7c478bd9Sstevel@tonic-gate 2414*7c478bd9Sstevel@tonic-gate if (dacfdebug & DACF_DBG_MSGS) { 2415*7c478bd9Sstevel@tonic-gate printf("dacf debug: clearing rules database\n"); 2416*7c478bd9Sstevel@tonic-gate } 2417*7c478bd9Sstevel@tonic-gate 2418*7c478bd9Sstevel@tonic-gate mutex_enter(&dacf_lock); 2419*7c478bd9Sstevel@tonic-gate dacf_clear_rules(); 2420*7c478bd9Sstevel@tonic-gate 2421*7c478bd9Sstevel@tonic-gate if (dacfdebug & DACF_DBG_MSGS) { 2422*7c478bd9Sstevel@tonic-gate printf("dacf debug: parsing %s\n", fname); 2423*7c478bd9Sstevel@tonic-gate } 2424*7c478bd9Sstevel@tonic-gate 2425*7c478bd9Sstevel@tonic-gate while (!done) { 2426*7c478bd9Sstevel@tonic-gate token = kobj_lex(file, tokbuf, sizeof (tokbuf)); 2427*7c478bd9Sstevel@tonic-gate 2428*7c478bd9Sstevel@tonic-gate switch (token) { 2429*7c478bd9Sstevel@tonic-gate case POUND: /* comment line */ 2430*7c478bd9Sstevel@tonic-gate if (state != DACF_BEGIN) { 2431*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_comment); 2432*7c478bd9Sstevel@tonic-gate state = DACF_ERR; 2433*7c478bd9Sstevel@tonic-gate break; 2434*7c478bd9Sstevel@tonic-gate } 2435*7c478bd9Sstevel@tonic-gate state = DACF_COMMENT; 2436*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 2437*7c478bd9Sstevel@tonic-gate break; 2438*7c478bd9Sstevel@tonic-gate 2439*7c478bd9Sstevel@tonic-gate case EQUALS: 2440*7c478bd9Sstevel@tonic-gate switch (state) { 2441*7c478bd9Sstevel@tonic-gate case DACF_NT_SPEC: 2442*7c478bd9Sstevel@tonic-gate state = DACF_NT_EQUALS; 2443*7c478bd9Sstevel@tonic-gate break; 2444*7c478bd9Sstevel@tonic-gate case DACF_OPARG_SPEC: 2445*7c478bd9Sstevel@tonic-gate state = DACF_OPARG_EQUALS; 2446*7c478bd9Sstevel@tonic-gate break; 2447*7c478bd9Sstevel@tonic-gate default: 2448*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_equals); 2449*7c478bd9Sstevel@tonic-gate state = DACF_ERR; 2450*7c478bd9Sstevel@tonic-gate } 2451*7c478bd9Sstevel@tonic-gate break; 2452*7c478bd9Sstevel@tonic-gate 2453*7c478bd9Sstevel@tonic-gate case NAME: 2454*7c478bd9Sstevel@tonic-gate switch (state) { 2455*7c478bd9Sstevel@tonic-gate case DACF_BEGIN: 2456*7c478bd9Sstevel@tonic-gate nt_spec_type = dacf_get_devspec(tokbuf); 2457*7c478bd9Sstevel@tonic-gate if (nt_spec_type == DACF_DS_ERROR) { 2458*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 2459*7c478bd9Sstevel@tonic-gate w_baddevspec, tokbuf); 2460*7c478bd9Sstevel@tonic-gate state = DACF_ERR; 2461*7c478bd9Sstevel@tonic-gate break; 2462*7c478bd9Sstevel@tonic-gate } 2463*7c478bd9Sstevel@tonic-gate state = DACF_NT_SPEC; 2464*7c478bd9Sstevel@tonic-gate break; 2465*7c478bd9Sstevel@tonic-gate case DACF_NT_DATA: 2466*7c478bd9Sstevel@tonic-gate (void) strncpy(mn_modname_buf, tokbuf, 2467*7c478bd9Sstevel@tonic-gate sizeof (mn_modname_buf)); 2468*7c478bd9Sstevel@tonic-gate mn_modnamep = mn_modname_buf; 2469*7c478bd9Sstevel@tonic-gate state = DACF_MN_MODNAME; 2470*7c478bd9Sstevel@tonic-gate break; 2471*7c478bd9Sstevel@tonic-gate case DACF_MN_MODNAME: 2472*7c478bd9Sstevel@tonic-gate /* 2473*7c478bd9Sstevel@tonic-gate * This handles the 'optional' modname. 2474*7c478bd9Sstevel@tonic-gate * What we thought was the modname is really 2475*7c478bd9Sstevel@tonic-gate * the op-set. So it is copied over. 2476*7c478bd9Sstevel@tonic-gate */ 2477*7c478bd9Sstevel@tonic-gate ASSERT(mn_modnamep); 2478*7c478bd9Sstevel@tonic-gate (void) strncpy(mn_opset_buf, mn_modnamep, 2479*7c478bd9Sstevel@tonic-gate sizeof (mn_opset_buf)); 2480*7c478bd9Sstevel@tonic-gate mn_opsetp = mn_opset_buf; 2481*7c478bd9Sstevel@tonic-gate mn_modnamep = NULL; 2482*7c478bd9Sstevel@tonic-gate /* 2483*7c478bd9Sstevel@tonic-gate * Now, the token we just read is the opset, 2484*7c478bd9Sstevel@tonic-gate * so look that up and fill in opid 2485*7c478bd9Sstevel@tonic-gate */ 2486*7c478bd9Sstevel@tonic-gate if ((opid = dacf_get_op(tokbuf)) == 2487*7c478bd9Sstevel@tonic-gate DACF_OPID_ERROR) { 2488*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_badop, 2489*7c478bd9Sstevel@tonic-gate tokbuf); 2490*7c478bd9Sstevel@tonic-gate state = DACF_ERR; 2491*7c478bd9Sstevel@tonic-gate break; 2492*7c478bd9Sstevel@tonic-gate } 2493*7c478bd9Sstevel@tonic-gate state = DACF_OP_NAME; 2494*7c478bd9Sstevel@tonic-gate break; 2495*7c478bd9Sstevel@tonic-gate case DACF_MN_COLON: 2496*7c478bd9Sstevel@tonic-gate (void) strncpy(mn_opset_buf, tokbuf, 2497*7c478bd9Sstevel@tonic-gate sizeof (mn_opset_buf)); 2498*7c478bd9Sstevel@tonic-gate mn_opsetp = mn_opset_buf; 2499*7c478bd9Sstevel@tonic-gate state = DACF_MN_OPSET; 2500*7c478bd9Sstevel@tonic-gate break; 2501*7c478bd9Sstevel@tonic-gate case DACF_MN_OPSET: 2502*7c478bd9Sstevel@tonic-gate if ((opid = dacf_get_op(tokbuf)) == 2503*7c478bd9Sstevel@tonic-gate DACF_OPID_ERROR) { 2504*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_badop, 2505*7c478bd9Sstevel@tonic-gate tokbuf); 2506*7c478bd9Sstevel@tonic-gate state = DACF_ERR; 2507*7c478bd9Sstevel@tonic-gate break; 2508*7c478bd9Sstevel@tonic-gate } 2509*7c478bd9Sstevel@tonic-gate state = DACF_OP_NAME; 2510*7c478bd9Sstevel@tonic-gate break; 2511*7c478bd9Sstevel@tonic-gate case DACF_OP_NAME: 2512*7c478bd9Sstevel@tonic-gate /* 2513*7c478bd9Sstevel@tonic-gate * This case is just like DACF_OPT_COMMA below, 2514*7c478bd9Sstevel@tonic-gate * but we check for the sole '-' argument 2515*7c478bd9Sstevel@tonic-gate */ 2516*7c478bd9Sstevel@tonic-gate if (strcmp(tokbuf, "-") == 0) { 2517*7c478bd9Sstevel@tonic-gate state = DACF_OPT_END; 2518*7c478bd9Sstevel@tonic-gate break; 2519*7c478bd9Sstevel@tonic-gate } 2520*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 2521*7c478bd9Sstevel@tonic-gate case DACF_OPT_COMMA: 2522*7c478bd9Sstevel@tonic-gate /* 2523*7c478bd9Sstevel@tonic-gate * figure out what option was given, but don't 2524*7c478bd9Sstevel@tonic-gate * make a federal case if invalid, just skip it 2525*7c478bd9Sstevel@tonic-gate */ 2526*7c478bd9Sstevel@tonic-gate if (dacf_getopt(tokbuf, &opts) != 0) { 2527*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_badopt, 2528*7c478bd9Sstevel@tonic-gate tokbuf); 2529*7c478bd9Sstevel@tonic-gate } 2530*7c478bd9Sstevel@tonic-gate state = DACF_OPT_OPTION; 2531*7c478bd9Sstevel@tonic-gate break; 2532*7c478bd9Sstevel@tonic-gate case DACF_OPT_END: 2533*7c478bd9Sstevel@tonic-gate case DACF_OPT_OPTION: 2534*7c478bd9Sstevel@tonic-gate case DACF_OPARG_DATA: 2535*7c478bd9Sstevel@tonic-gate (void) strncpy(arg_spec_buf, tokbuf, 2536*7c478bd9Sstevel@tonic-gate sizeof (arg_spec_buf)); 2537*7c478bd9Sstevel@tonic-gate state = DACF_OPARG_SPEC; 2538*7c478bd9Sstevel@tonic-gate break; 2539*7c478bd9Sstevel@tonic-gate case DACF_OPARG_EQUALS: 2540*7c478bd9Sstevel@tonic-gate /* 2541*7c478bd9Sstevel@tonic-gate * Add the arg. Warn if it's a duplicate 2542*7c478bd9Sstevel@tonic-gate */ 2543*7c478bd9Sstevel@tonic-gate if (dacf_arg_insert(&arg_list, arg_spec_buf, 2544*7c478bd9Sstevel@tonic-gate tokbuf) != 0) { 2545*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_dupargs, 2546*7c478bd9Sstevel@tonic-gate arg_spec_buf); 2547*7c478bd9Sstevel@tonic-gate } 2548*7c478bd9Sstevel@tonic-gate state = DACF_OPARG_DATA; 2549*7c478bd9Sstevel@tonic-gate break; 2550*7c478bd9Sstevel@tonic-gate default: 2551*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_syntax, tokbuf); 2552*7c478bd9Sstevel@tonic-gate state = DACF_ERR; 2553*7c478bd9Sstevel@tonic-gate break; 2554*7c478bd9Sstevel@tonic-gate } 2555*7c478bd9Sstevel@tonic-gate break; 2556*7c478bd9Sstevel@tonic-gate 2557*7c478bd9Sstevel@tonic-gate case STRING: 2558*7c478bd9Sstevel@tonic-gate /* 2559*7c478bd9Sstevel@tonic-gate * We need to check to see if the string has a \n in it. 2560*7c478bd9Sstevel@tonic-gate * If so, we had an unmatched " mark error, and lex has 2561*7c478bd9Sstevel@tonic-gate * already emitted an error for us, so we need to enter 2562*7c478bd9Sstevel@tonic-gate * the error state. Stupid lex. 2563*7c478bd9Sstevel@tonic-gate */ 2564*7c478bd9Sstevel@tonic-gate if (strchr(tokbuf, '\n')) { 2565*7c478bd9Sstevel@tonic-gate state = DACF_ERR; 2566*7c478bd9Sstevel@tonic-gate break; 2567*7c478bd9Sstevel@tonic-gate } 2568*7c478bd9Sstevel@tonic-gate switch (state) { 2569*7c478bd9Sstevel@tonic-gate case DACF_NT_EQUALS: 2570*7c478bd9Sstevel@tonic-gate if (strlen(tokbuf) == 0) { 2571*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 2572*7c478bd9Sstevel@tonic-gate w_nt_empty); 2573*7c478bd9Sstevel@tonic-gate state = DACF_ERR; 2574*7c478bd9Sstevel@tonic-gate break; 2575*7c478bd9Sstevel@tonic-gate } 2576*7c478bd9Sstevel@tonic-gate state = DACF_NT_DATA; 2577*7c478bd9Sstevel@tonic-gate nt_datap = nt_data_buf; 2578*7c478bd9Sstevel@tonic-gate (void) strncpy(nt_datap, tokbuf, 2579*7c478bd9Sstevel@tonic-gate sizeof (nt_data_buf)); 2580*7c478bd9Sstevel@tonic-gate break; 2581*7c478bd9Sstevel@tonic-gate case DACF_OPARG_EQUALS: 2582*7c478bd9Sstevel@tonic-gate /* 2583*7c478bd9Sstevel@tonic-gate * Add the arg. Warn if it's a duplicate 2584*7c478bd9Sstevel@tonic-gate */ 2585*7c478bd9Sstevel@tonic-gate if (dacf_arg_insert(&arg_list, arg_spec_buf, 2586*7c478bd9Sstevel@tonic-gate tokbuf) != 0) { 2587*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_dupargs, 2588*7c478bd9Sstevel@tonic-gate arg_spec_buf); 2589*7c478bd9Sstevel@tonic-gate } 2590*7c478bd9Sstevel@tonic-gate state = DACF_OPARG_DATA; 2591*7c478bd9Sstevel@tonic-gate break; 2592*7c478bd9Sstevel@tonic-gate default: 2593*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_syntax, tokbuf); 2594*7c478bd9Sstevel@tonic-gate state = DACF_ERR; 2595*7c478bd9Sstevel@tonic-gate break; 2596*7c478bd9Sstevel@tonic-gate } 2597*7c478bd9Sstevel@tonic-gate break; 2598*7c478bd9Sstevel@tonic-gate 2599*7c478bd9Sstevel@tonic-gate case COMMA: 2600*7c478bd9Sstevel@tonic-gate switch (state) { 2601*7c478bd9Sstevel@tonic-gate case DACF_OPT_OPTION: 2602*7c478bd9Sstevel@tonic-gate state = DACF_OPT_COMMA; 2603*7c478bd9Sstevel@tonic-gate break; 2604*7c478bd9Sstevel@tonic-gate default: 2605*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_syntax, ","); 2606*7c478bd9Sstevel@tonic-gate state = DACF_ERR; 2607*7c478bd9Sstevel@tonic-gate break; 2608*7c478bd9Sstevel@tonic-gate } 2609*7c478bd9Sstevel@tonic-gate break; 2610*7c478bd9Sstevel@tonic-gate 2611*7c478bd9Sstevel@tonic-gate case COLON: 2612*7c478bd9Sstevel@tonic-gate if (state == DACF_MN_MODNAME) 2613*7c478bd9Sstevel@tonic-gate state = DACF_MN_COLON; 2614*7c478bd9Sstevel@tonic-gate else { 2615*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_syntax, ":"); 2616*7c478bd9Sstevel@tonic-gate state = DACF_ERR; 2617*7c478bd9Sstevel@tonic-gate } 2618*7c478bd9Sstevel@tonic-gate break; 2619*7c478bd9Sstevel@tonic-gate 2620*7c478bd9Sstevel@tonic-gate case EOF: 2621*7c478bd9Sstevel@tonic-gate done = 1; 2622*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 2623*7c478bd9Sstevel@tonic-gate case NEWLINE: 2624*7c478bd9Sstevel@tonic-gate if (state == DACF_COMMENT || state == DACF_BEGIN) { 2625*7c478bd9Sstevel@tonic-gate state = DACF_BEGIN; 2626*7c478bd9Sstevel@tonic-gate kobj_newline(file); 2627*7c478bd9Sstevel@tonic-gate break; 2628*7c478bd9Sstevel@tonic-gate } 2629*7c478bd9Sstevel@tonic-gate if ((state != DACF_OPT_OPTION) && 2630*7c478bd9Sstevel@tonic-gate (state != DACF_OPARG_DATA) && 2631*7c478bd9Sstevel@tonic-gate (state != DACF_OPT_END)) { 2632*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_newline); 2633*7c478bd9Sstevel@tonic-gate /* 2634*7c478bd9Sstevel@tonic-gate * We can't just do DACF_ERR here, since we'll 2635*7c478bd9Sstevel@tonic-gate * wind up eating the _next_ newline if so. 2636*7c478bd9Sstevel@tonic-gate */ 2637*7c478bd9Sstevel@tonic-gate state = DACF_ERR_NEWLINE; 2638*7c478bd9Sstevel@tonic-gate kobj_newline(file); 2639*7c478bd9Sstevel@tonic-gate break; 2640*7c478bd9Sstevel@tonic-gate } 2641*7c478bd9Sstevel@tonic-gate 2642*7c478bd9Sstevel@tonic-gate /* 2643*7c478bd9Sstevel@tonic-gate * insert the rule. 2644*7c478bd9Sstevel@tonic-gate */ 2645*7c478bd9Sstevel@tonic-gate if (dacf_rule_insert(nt_spec_type, nt_datap, 2646*7c478bd9Sstevel@tonic-gate mn_modnamep, mn_opsetp, opid, opts, arg_list) < 0) { 2647*7c478bd9Sstevel@tonic-gate /* 2648*7c478bd9Sstevel@tonic-gate * We can't just do DACF_ERR here, since we'll 2649*7c478bd9Sstevel@tonic-gate * wind up eating the _next_ newline if so. 2650*7c478bd9Sstevel@tonic-gate */ 2651*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_insert); 2652*7c478bd9Sstevel@tonic-gate state = DACF_ERR_NEWLINE; 2653*7c478bd9Sstevel@tonic-gate kobj_newline(file); 2654*7c478bd9Sstevel@tonic-gate break; 2655*7c478bd9Sstevel@tonic-gate } 2656*7c478bd9Sstevel@tonic-gate 2657*7c478bd9Sstevel@tonic-gate state = DACF_BEGIN; 2658*7c478bd9Sstevel@tonic-gate kobj_newline(file); 2659*7c478bd9Sstevel@tonic-gate break; 2660*7c478bd9Sstevel@tonic-gate 2661*7c478bd9Sstevel@tonic-gate default: 2662*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, w_syntax, tokbuf); 2663*7c478bd9Sstevel@tonic-gate break; 2664*7c478bd9Sstevel@tonic-gate } /* switch */ 2665*7c478bd9Sstevel@tonic-gate 2666*7c478bd9Sstevel@tonic-gate /* 2667*7c478bd9Sstevel@tonic-gate * Clean up after ourselves, either after a line has terminated 2668*7c478bd9Sstevel@tonic-gate * successfully or because of a syntax error; or when we reach 2669*7c478bd9Sstevel@tonic-gate * EOF (remember, we may reach EOF without being 'done' with 2670*7c478bd9Sstevel@tonic-gate * handling a particular line). 2671*7c478bd9Sstevel@tonic-gate */ 2672*7c478bd9Sstevel@tonic-gate if (state == DACF_ERR) { 2673*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 2674*7c478bd9Sstevel@tonic-gate } 2675*7c478bd9Sstevel@tonic-gate if ((state == DACF_BEGIN) || (state == DACF_ERR) || 2676*7c478bd9Sstevel@tonic-gate (state == DACF_ERR_NEWLINE) || done) { 2677*7c478bd9Sstevel@tonic-gate nt_datap = NULL; 2678*7c478bd9Sstevel@tonic-gate mn_modnamep = mn_opsetp = NULL; 2679*7c478bd9Sstevel@tonic-gate opts = 0; 2680*7c478bd9Sstevel@tonic-gate opid = DACF_OPID_ERROR; 2681*7c478bd9Sstevel@tonic-gate nt_spec_type = DACF_DS_ERROR; 2682*7c478bd9Sstevel@tonic-gate dacf_arglist_delete(&arg_list); 2683*7c478bd9Sstevel@tonic-gate state = DACF_BEGIN; 2684*7c478bd9Sstevel@tonic-gate } 2685*7c478bd9Sstevel@tonic-gate } /* while */ 2686*7c478bd9Sstevel@tonic-gate 2687*7c478bd9Sstevel@tonic-gate if (dacfdebug & DACF_DBG_MSGS) { 2688*7c478bd9Sstevel@tonic-gate printf("\ndacf debug: done!\n"); 2689*7c478bd9Sstevel@tonic-gate } 2690*7c478bd9Sstevel@tonic-gate 2691*7c478bd9Sstevel@tonic-gate mutex_exit(&dacf_lock); 2692*7c478bd9Sstevel@tonic-gate 2693*7c478bd9Sstevel@tonic-gate kobj_close_file(file); 2694*7c478bd9Sstevel@tonic-gate return (0); 2695*7c478bd9Sstevel@tonic-gate } 2696*7c478bd9Sstevel@tonic-gate 2697*7c478bd9Sstevel@tonic-gate void 2698*7c478bd9Sstevel@tonic-gate lock_hw_class_list() 2699*7c478bd9Sstevel@tonic-gate { 2700*7c478bd9Sstevel@tonic-gate mutex_enter(&hcl_lock); 2701*7c478bd9Sstevel@tonic-gate } 2702*7c478bd9Sstevel@tonic-gate 2703*7c478bd9Sstevel@tonic-gate void 2704*7c478bd9Sstevel@tonic-gate unlock_hw_class_list() 2705*7c478bd9Sstevel@tonic-gate { 2706*7c478bd9Sstevel@tonic-gate mutex_exit(&hcl_lock); 2707*7c478bd9Sstevel@tonic-gate } 2708*7c478bd9Sstevel@tonic-gate 2709*7c478bd9Sstevel@tonic-gate void 2710*7c478bd9Sstevel@tonic-gate add_class(char *exporter, char *class) 2711*7c478bd9Sstevel@tonic-gate { 2712*7c478bd9Sstevel@tonic-gate struct hwc_class *hcl; 2713*7c478bd9Sstevel@tonic-gate 2714*7c478bd9Sstevel@tonic-gate /* 2715*7c478bd9Sstevel@tonic-gate * If exporter's major is not registered in /etc/name_to_major, 2716*7c478bd9Sstevel@tonic-gate * don't update hwc_class, but just return here. 2717*7c478bd9Sstevel@tonic-gate */ 2718*7c478bd9Sstevel@tonic-gate if (ddi_name_to_major(exporter) >= devcnt) { 2719*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "No major number for driver %s" 2720*7c478bd9Sstevel@tonic-gate " in class %s", exporter, class); 2721*7c478bd9Sstevel@tonic-gate return; 2722*7c478bd9Sstevel@tonic-gate } 2723*7c478bd9Sstevel@tonic-gate hcl = kmem_zalloc(sizeof (struct hwc_class), KM_SLEEP); 2724*7c478bd9Sstevel@tonic-gate hcl->class_exporter = kmem_alloc(strlen(exporter) + 1, KM_SLEEP); 2725*7c478bd9Sstevel@tonic-gate hcl->class_name = kmem_alloc(strlen(class) + 1, KM_SLEEP); 2726*7c478bd9Sstevel@tonic-gate (void) strcpy(hcl->class_exporter, exporter); 2727*7c478bd9Sstevel@tonic-gate (void) strcpy(hcl->class_name, class); 2728*7c478bd9Sstevel@tonic-gate lock_hw_class_list(); 2729*7c478bd9Sstevel@tonic-gate hcl->class_next = hcl_head; 2730*7c478bd9Sstevel@tonic-gate hcl_head = hcl; 2731*7c478bd9Sstevel@tonic-gate unlock_hw_class_list(); 2732*7c478bd9Sstevel@tonic-gate } 2733*7c478bd9Sstevel@tonic-gate 2734*7c478bd9Sstevel@tonic-gate /* 2735*7c478bd9Sstevel@tonic-gate * Return the number of classes exported. If buf is not NULL, fill in 2736*7c478bd9Sstevel@tonic-gate * the array of the class names as well. 2737*7c478bd9Sstevel@tonic-gate * 2738*7c478bd9Sstevel@tonic-gate * Caller must hold hcl_lock to ensure the class list unmodified while 2739*7c478bd9Sstevel@tonic-gate * it is accessed. A typical caller will get a count first and then 2740*7c478bd9Sstevel@tonic-gate * allocate buf. The lock should be held by the caller. 2741*7c478bd9Sstevel@tonic-gate */ 2742*7c478bd9Sstevel@tonic-gate int 2743*7c478bd9Sstevel@tonic-gate get_class(const char *exporter, char **buf) 2744*7c478bd9Sstevel@tonic-gate { 2745*7c478bd9Sstevel@tonic-gate int n = 0; 2746*7c478bd9Sstevel@tonic-gate struct hwc_class *hcl; 2747*7c478bd9Sstevel@tonic-gate 2748*7c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&hcl_lock)); 2749*7c478bd9Sstevel@tonic-gate for (hcl = hcl_head; hcl != NULL; hcl = hcl->class_next) { 2750*7c478bd9Sstevel@tonic-gate if (strcmp(exporter, hcl->class_exporter) == 0) { 2751*7c478bd9Sstevel@tonic-gate if (buf) 2752*7c478bd9Sstevel@tonic-gate buf[n] = hcl->class_name; 2753*7c478bd9Sstevel@tonic-gate ++n; 2754*7c478bd9Sstevel@tonic-gate } 2755*7c478bd9Sstevel@tonic-gate } 2756*7c478bd9Sstevel@tonic-gate 2757*7c478bd9Sstevel@tonic-gate return (n); 2758*7c478bd9Sstevel@tonic-gate } 2759*7c478bd9Sstevel@tonic-gate 2760*7c478bd9Sstevel@tonic-gate void 2761*7c478bd9Sstevel@tonic-gate read_class_file(void) 2762*7c478bd9Sstevel@tonic-gate { 2763*7c478bd9Sstevel@tonic-gate struct _buf *file; 2764*7c478bd9Sstevel@tonic-gate struct hwc_class *hcl, *hcl1; 2765*7c478bd9Sstevel@tonic-gate char tokbuf[MAXNAMELEN]; 2766*7c478bd9Sstevel@tonic-gate enum { 2767*7c478bd9Sstevel@tonic-gate C_BEGIN, C_EXPORTER, C_END 2768*7c478bd9Sstevel@tonic-gate } state; 2769*7c478bd9Sstevel@tonic-gate token_t token; 2770*7c478bd9Sstevel@tonic-gate int done = 0; 2771*7c478bd9Sstevel@tonic-gate char *exporter = NULL, *class = NULL, *name = NULL; 2772*7c478bd9Sstevel@tonic-gate 2773*7c478bd9Sstevel@tonic-gate if (hcl_head != NULL) { 2774*7c478bd9Sstevel@tonic-gate hcl = hcl_head; 2775*7c478bd9Sstevel@tonic-gate while (hcl != NULL) { 2776*7c478bd9Sstevel@tonic-gate kmem_free(hcl->class_exporter, 2777*7c478bd9Sstevel@tonic-gate strlen(hcl->class_exporter) + 1); 2778*7c478bd9Sstevel@tonic-gate hcl1 = hcl; 2779*7c478bd9Sstevel@tonic-gate hcl = hcl->class_next; 2780*7c478bd9Sstevel@tonic-gate kmem_free(hcl1, sizeof (struct hwc_class)); 2781*7c478bd9Sstevel@tonic-gate } 2782*7c478bd9Sstevel@tonic-gate hcl_head = NULL; 2783*7c478bd9Sstevel@tonic-gate } 2784*7c478bd9Sstevel@tonic-gate 2785*7c478bd9Sstevel@tonic-gate if ((file = kobj_open_file(class_file)) == (struct _buf *)-1) 2786*7c478bd9Sstevel@tonic-gate return; 2787*7c478bd9Sstevel@tonic-gate 2788*7c478bd9Sstevel@tonic-gate state = C_BEGIN; 2789*7c478bd9Sstevel@tonic-gate while (!done) { 2790*7c478bd9Sstevel@tonic-gate token = kobj_lex(file, tokbuf, sizeof (tokbuf)); 2791*7c478bd9Sstevel@tonic-gate 2792*7c478bd9Sstevel@tonic-gate switch (token) { 2793*7c478bd9Sstevel@tonic-gate case POUND: 2794*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 2795*7c478bd9Sstevel@tonic-gate break; 2796*7c478bd9Sstevel@tonic-gate case NAME: 2797*7c478bd9Sstevel@tonic-gate case STRING: 2798*7c478bd9Sstevel@tonic-gate name = kmem_alloc(strlen(tokbuf) + 1, KM_SLEEP); 2799*7c478bd9Sstevel@tonic-gate (void) strcpy(name, tokbuf); 2800*7c478bd9Sstevel@tonic-gate switch (state) { 2801*7c478bd9Sstevel@tonic-gate case C_BEGIN: 2802*7c478bd9Sstevel@tonic-gate exporter = name; 2803*7c478bd9Sstevel@tonic-gate state = C_EXPORTER; 2804*7c478bd9Sstevel@tonic-gate break; 2805*7c478bd9Sstevel@tonic-gate case C_EXPORTER: 2806*7c478bd9Sstevel@tonic-gate class = name; 2807*7c478bd9Sstevel@tonic-gate add_class(exporter, class); 2808*7c478bd9Sstevel@tonic-gate state = C_END; 2809*7c478bd9Sstevel@tonic-gate break; 2810*7c478bd9Sstevel@tonic-gate case C_END: 2811*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 2812*7c478bd9Sstevel@tonic-gate "Extra noise after entry"); 2813*7c478bd9Sstevel@tonic-gate kmem_free(name, strlen(name) + 1); 2814*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 2815*7c478bd9Sstevel@tonic-gate break; 2816*7c478bd9Sstevel@tonic-gate } /* End Switch */ 2817*7c478bd9Sstevel@tonic-gate break; 2818*7c478bd9Sstevel@tonic-gate case EOF: 2819*7c478bd9Sstevel@tonic-gate done = 1; 2820*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 2821*7c478bd9Sstevel@tonic-gate case NEWLINE: 2822*7c478bd9Sstevel@tonic-gate kobj_newline(file); 2823*7c478bd9Sstevel@tonic-gate if (state == C_EXPORTER) 2824*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 2825*7c478bd9Sstevel@tonic-gate "Partial entry ignored"); 2826*7c478bd9Sstevel@tonic-gate state = C_BEGIN; 2827*7c478bd9Sstevel@tonic-gate if (exporter) 2828*7c478bd9Sstevel@tonic-gate kmem_free(exporter, strlen(exporter) + 1); 2829*7c478bd9Sstevel@tonic-gate if (class) 2830*7c478bd9Sstevel@tonic-gate kmem_free(class, strlen(class) + 1); 2831*7c478bd9Sstevel@tonic-gate exporter = NULL; 2832*7c478bd9Sstevel@tonic-gate class = NULL; 2833*7c478bd9Sstevel@tonic-gate break; 2834*7c478bd9Sstevel@tonic-gate default: 2835*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 2836*7c478bd9Sstevel@tonic-gate break; 2837*7c478bd9Sstevel@tonic-gate } 2838*7c478bd9Sstevel@tonic-gate } 2839*7c478bd9Sstevel@tonic-gate kobj_close_file(file); 2840*7c478bd9Sstevel@tonic-gate } 2841*7c478bd9Sstevel@tonic-gate 2842*7c478bd9Sstevel@tonic-gate /* 2843*7c478bd9Sstevel@tonic-gate * Given par_list, get a list of parent major number 2844*7c478bd9Sstevel@tonic-gate */ 2845*7c478bd9Sstevel@tonic-gate int 2846*7c478bd9Sstevel@tonic-gate impl_parlist_to_major(struct par_list *pl, char parents[]) 2847*7c478bd9Sstevel@tonic-gate { 2848*7c478bd9Sstevel@tonic-gate struct hwc_spec *hwcp; 2849*7c478bd9Sstevel@tonic-gate struct hwc_class *hcl; 2850*7c478bd9Sstevel@tonic-gate major_t major; 2851*7c478bd9Sstevel@tonic-gate int nmajor = 0; 2852*7c478bd9Sstevel@tonic-gate extern int devcnt; 2853*7c478bd9Sstevel@tonic-gate 2854*7c478bd9Sstevel@tonic-gate for (; pl != NULL; pl = pl->par_next) { 2855*7c478bd9Sstevel@tonic-gate if ((pl->par_major < devcnt) && (parents[pl->par_major] == 0)) { 2856*7c478bd9Sstevel@tonic-gate parents[pl->par_major] = 1; 2857*7c478bd9Sstevel@tonic-gate nmajor++; 2858*7c478bd9Sstevel@tonic-gate continue; 2859*7c478bd9Sstevel@tonic-gate } 2860*7c478bd9Sstevel@tonic-gate 2861*7c478bd9Sstevel@tonic-gate /* parent specs cannot be mapped to a driver */ 2862*7c478bd9Sstevel@tonic-gate if (pl->par_major != (major_t)-1) 2863*7c478bd9Sstevel@tonic-gate continue; 2864*7c478bd9Sstevel@tonic-gate 2865*7c478bd9Sstevel@tonic-gate /* class spec */ 2866*7c478bd9Sstevel@tonic-gate hwcp = pl->par_specs; 2867*7c478bd9Sstevel@tonic-gate ASSERT(hwcp->hwc_class_name); 2868*7c478bd9Sstevel@tonic-gate ASSERT(hwcp->hwc_parent_name == NULL); 2869*7c478bd9Sstevel@tonic-gate 2870*7c478bd9Sstevel@tonic-gate for (hcl = hcl_head; hcl != NULL; hcl = hcl->class_next) { 2871*7c478bd9Sstevel@tonic-gate if (strcmp(hwcp->hwc_class_name, hcl->class_name) != 0) 2872*7c478bd9Sstevel@tonic-gate continue; 2873*7c478bd9Sstevel@tonic-gate major = ddi_name_to_major(hcl->class_exporter); 2874*7c478bd9Sstevel@tonic-gate ASSERT(major != (major_t)-1); 2875*7c478bd9Sstevel@tonic-gate if (parents[major] == 0) { 2876*7c478bd9Sstevel@tonic-gate parents[major] = 1; 2877*7c478bd9Sstevel@tonic-gate nmajor++; 2878*7c478bd9Sstevel@tonic-gate } 2879*7c478bd9Sstevel@tonic-gate } 2880*7c478bd9Sstevel@tonic-gate } 2881*7c478bd9Sstevel@tonic-gate return (nmajor); 2882*7c478bd9Sstevel@tonic-gate } 2883*7c478bd9Sstevel@tonic-gate 2884*7c478bd9Sstevel@tonic-gate /* 2885*7c478bd9Sstevel@tonic-gate * delete a parent list and all its hwc specs 2886*7c478bd9Sstevel@tonic-gate */ 2887*7c478bd9Sstevel@tonic-gate void 2888*7c478bd9Sstevel@tonic-gate impl_delete_par_list(struct par_list *pl) 2889*7c478bd9Sstevel@tonic-gate { 2890*7c478bd9Sstevel@tonic-gate struct par_list *saved_pl; 2891*7c478bd9Sstevel@tonic-gate struct hwc_spec *hp, *hp1; 2892*7c478bd9Sstevel@tonic-gate 2893*7c478bd9Sstevel@tonic-gate while (pl) { 2894*7c478bd9Sstevel@tonic-gate hp = pl->par_specs; 2895*7c478bd9Sstevel@tonic-gate while (hp) { 2896*7c478bd9Sstevel@tonic-gate hp1 = hp; 2897*7c478bd9Sstevel@tonic-gate hp = hp->hwc_next; 2898*7c478bd9Sstevel@tonic-gate hwc_free(hp1); 2899*7c478bd9Sstevel@tonic-gate } 2900*7c478bd9Sstevel@tonic-gate saved_pl = pl; 2901*7c478bd9Sstevel@tonic-gate pl = pl->par_next; 2902*7c478bd9Sstevel@tonic-gate kmem_free(saved_pl, sizeof (*saved_pl)); 2903*7c478bd9Sstevel@tonic-gate } 2904*7c478bd9Sstevel@tonic-gate } 2905*7c478bd9Sstevel@tonic-gate 2906*7c478bd9Sstevel@tonic-gate #if defined(_PSM_MODULES) 2907*7c478bd9Sstevel@tonic-gate void 2908*7c478bd9Sstevel@tonic-gate open_mach_list(void) 2909*7c478bd9Sstevel@tonic-gate { 2910*7c478bd9Sstevel@tonic-gate struct _buf *file; 2911*7c478bd9Sstevel@tonic-gate char tokbuf[MAXNAMELEN]; 2912*7c478bd9Sstevel@tonic-gate token_t token; 2913*7c478bd9Sstevel@tonic-gate struct psm_mach *machp; 2914*7c478bd9Sstevel@tonic-gate 2915*7c478bd9Sstevel@tonic-gate if ((file = kobj_open_file(mach_file)) == (struct _buf *)-1) 2916*7c478bd9Sstevel@tonic-gate return; 2917*7c478bd9Sstevel@tonic-gate 2918*7c478bd9Sstevel@tonic-gate while ((token = kobj_lex(file, tokbuf, sizeof (tokbuf))) != EOF) { 2919*7c478bd9Sstevel@tonic-gate switch (token) { 2920*7c478bd9Sstevel@tonic-gate case POUND: 2921*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 2922*7c478bd9Sstevel@tonic-gate break; 2923*7c478bd9Sstevel@tonic-gate case NAME: 2924*7c478bd9Sstevel@tonic-gate case STRING: 2925*7c478bd9Sstevel@tonic-gate machp = kmem_alloc((sizeof (struct psm_mach) + 2926*7c478bd9Sstevel@tonic-gate strlen(tokbuf) + 1), KM_SLEEP); 2927*7c478bd9Sstevel@tonic-gate machp->m_next = pmach_head; 2928*7c478bd9Sstevel@tonic-gate machp->m_machname = (char *)(machp + 1); 2929*7c478bd9Sstevel@tonic-gate (void) strcpy(machp->m_machname, tokbuf); 2930*7c478bd9Sstevel@tonic-gate pmach_head = machp; 2931*7c478bd9Sstevel@tonic-gate break; 2932*7c478bd9Sstevel@tonic-gate case NEWLINE: 2933*7c478bd9Sstevel@tonic-gate kobj_newline(file); 2934*7c478bd9Sstevel@tonic-gate break; 2935*7c478bd9Sstevel@tonic-gate default: 2936*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 2937*7c478bd9Sstevel@tonic-gate break; 2938*7c478bd9Sstevel@tonic-gate } 2939*7c478bd9Sstevel@tonic-gate } 2940*7c478bd9Sstevel@tonic-gate kobj_close_file(file); 2941*7c478bd9Sstevel@tonic-gate } 2942*7c478bd9Sstevel@tonic-gate 2943*7c478bd9Sstevel@tonic-gate void * 2944*7c478bd9Sstevel@tonic-gate get_next_mach(void *handle, char *buf) 2945*7c478bd9Sstevel@tonic-gate { 2946*7c478bd9Sstevel@tonic-gate struct psm_mach *machp; 2947*7c478bd9Sstevel@tonic-gate 2948*7c478bd9Sstevel@tonic-gate machp = (struct psm_mach *)handle; 2949*7c478bd9Sstevel@tonic-gate if (machp) 2950*7c478bd9Sstevel@tonic-gate machp = machp->m_next; 2951*7c478bd9Sstevel@tonic-gate else 2952*7c478bd9Sstevel@tonic-gate machp = pmach_head; 2953*7c478bd9Sstevel@tonic-gate if (machp) 2954*7c478bd9Sstevel@tonic-gate (void) strcpy(buf, machp->m_machname); 2955*7c478bd9Sstevel@tonic-gate return (machp); 2956*7c478bd9Sstevel@tonic-gate } 2957*7c478bd9Sstevel@tonic-gate 2958*7c478bd9Sstevel@tonic-gate void 2959*7c478bd9Sstevel@tonic-gate close_mach_list(void) 2960*7c478bd9Sstevel@tonic-gate { 2961*7c478bd9Sstevel@tonic-gate struct psm_mach *machp; 2962*7c478bd9Sstevel@tonic-gate 2963*7c478bd9Sstevel@tonic-gate while (pmach_head) { 2964*7c478bd9Sstevel@tonic-gate machp = pmach_head; 2965*7c478bd9Sstevel@tonic-gate pmach_head = machp->m_next; 2966*7c478bd9Sstevel@tonic-gate kmem_free(machp, sizeof (struct psm_mach) + 2967*7c478bd9Sstevel@tonic-gate strlen(machp->m_machname) + 1); 2968*7c478bd9Sstevel@tonic-gate } 2969*7c478bd9Sstevel@tonic-gate } 2970*7c478bd9Sstevel@tonic-gate #endif /* _PSM_MODULES */ 2971*7c478bd9Sstevel@tonic-gate 2972*7c478bd9Sstevel@tonic-gate #if defined(_RTC_CONFIG) 2973*7c478bd9Sstevel@tonic-gate /* 2974*7c478bd9Sstevel@tonic-gate * Read in the 'zone_lag' value from the rtc configuration file, 2975*7c478bd9Sstevel@tonic-gate * and return the value to the caller. Note that there is other information 2976*7c478bd9Sstevel@tonic-gate * in this file (zone_info), so we ignore unknown values. We do spit out 2977*7c478bd9Sstevel@tonic-gate * warnings if the line doesn't begin with an identifier, or if we don't find 2978*7c478bd9Sstevel@tonic-gate * exactly "zone_lag=value". No one should be editing this file by hand 2979*7c478bd9Sstevel@tonic-gate * (use the rtc command instead), but it's better to be careful. 2980*7c478bd9Sstevel@tonic-gate */ 2981*7c478bd9Sstevel@tonic-gate long 2982*7c478bd9Sstevel@tonic-gate process_rtc_config_file(void) 2983*7c478bd9Sstevel@tonic-gate { 2984*7c478bd9Sstevel@tonic-gate enum { 2985*7c478bd9Sstevel@tonic-gate R_NEW, R_NAME, R_EQUALS, R_VALUE 2986*7c478bd9Sstevel@tonic-gate } state; 2987*7c478bd9Sstevel@tonic-gate struct _buf *file; 2988*7c478bd9Sstevel@tonic-gate char tokbuf[MAXNAMELEN]; 2989*7c478bd9Sstevel@tonic-gate token_t token; 2990*7c478bd9Sstevel@tonic-gate long zone_lag = 0; 2991*7c478bd9Sstevel@tonic-gate u_longlong_t tmp; 2992*7c478bd9Sstevel@tonic-gate int done = 0; 2993*7c478bd9Sstevel@tonic-gate 2994*7c478bd9Sstevel@tonic-gate if ((file = kobj_open_file(rtc_config_file)) == (struct _buf *)-1) 2995*7c478bd9Sstevel@tonic-gate return (0); 2996*7c478bd9Sstevel@tonic-gate 2997*7c478bd9Sstevel@tonic-gate state = R_NEW; 2998*7c478bd9Sstevel@tonic-gate 2999*7c478bd9Sstevel@tonic-gate while (!done) { 3000*7c478bd9Sstevel@tonic-gate token = kobj_lex(file, tokbuf, sizeof (tokbuf)); 3001*7c478bd9Sstevel@tonic-gate 3002*7c478bd9Sstevel@tonic-gate switch (token) { 3003*7c478bd9Sstevel@tonic-gate case POUND: 3004*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); 3005*7c478bd9Sstevel@tonic-gate break; 3006*7c478bd9Sstevel@tonic-gate case NAME: 3007*7c478bd9Sstevel@tonic-gate case STRING: 3008*7c478bd9Sstevel@tonic-gate if (state == R_NEW) { 3009*7c478bd9Sstevel@tonic-gate if (strcmp(tokbuf, "zone_lag") == 0) 3010*7c478bd9Sstevel@tonic-gate state = R_NAME; 3011*7c478bd9Sstevel@tonic-gate else 3012*7c478bd9Sstevel@tonic-gate kobj_find_eol(file); /* Ignore */ 3013*7c478bd9Sstevel@tonic-gate } else 3014*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 3015*7c478bd9Sstevel@tonic-gate break; 3016*7c478bd9Sstevel@tonic-gate case EQUALS: 3017*7c478bd9Sstevel@tonic-gate if (state == R_NAME) 3018*7c478bd9Sstevel@tonic-gate state = R_EQUALS; 3019*7c478bd9Sstevel@tonic-gate else 3020*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 3021*7c478bd9Sstevel@tonic-gate break; 3022*7c478bd9Sstevel@tonic-gate case DECVAL: 3023*7c478bd9Sstevel@tonic-gate if (state == R_EQUALS) { 3024*7c478bd9Sstevel@tonic-gate if (kobj_getvalue(tokbuf, &tmp) != 0) 3025*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 3026*7c478bd9Sstevel@tonic-gate "Bad value %s for zone_lag", 3027*7c478bd9Sstevel@tonic-gate tokbuf); 3028*7c478bd9Sstevel@tonic-gate else 3029*7c478bd9Sstevel@tonic-gate zone_lag = (long)tmp; 3030*7c478bd9Sstevel@tonic-gate state = R_VALUE; 3031*7c478bd9Sstevel@tonic-gate } else 3032*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 3033*7c478bd9Sstevel@tonic-gate break; 3034*7c478bd9Sstevel@tonic-gate case EOF: 3035*7c478bd9Sstevel@tonic-gate done = 1; 3036*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 3037*7c478bd9Sstevel@tonic-gate case NEWLINE: 3038*7c478bd9Sstevel@tonic-gate if (state != R_NEW && state != R_VALUE) 3039*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, 3040*7c478bd9Sstevel@tonic-gate "Partial zone_lag entry ignored"); 3041*7c478bd9Sstevel@tonic-gate kobj_newline(file); 3042*7c478bd9Sstevel@tonic-gate state = R_NEW; 3043*7c478bd9Sstevel@tonic-gate break; 3044*7c478bd9Sstevel@tonic-gate default: 3045*7c478bd9Sstevel@tonic-gate kobj_file_err(CE_WARN, file, tok_err, tokbuf); 3046*7c478bd9Sstevel@tonic-gate break; 3047*7c478bd9Sstevel@tonic-gate } 3048*7c478bd9Sstevel@tonic-gate } 3049*7c478bd9Sstevel@tonic-gate kobj_close_file(file); 3050*7c478bd9Sstevel@tonic-gate return (zone_lag); 3051*7c478bd9Sstevel@tonic-gate } 3052*7c478bd9Sstevel@tonic-gate #endif /* _RTC_CONFIG */ 3053*7c478bd9Sstevel@tonic-gate 3054*7c478bd9Sstevel@tonic-gate 3055*7c478bd9Sstevel@tonic-gate /* 3056*7c478bd9Sstevel@tonic-gate * Append node spec to the end of par_list 3057*7c478bd9Sstevel@tonic-gate */ 3058*7c478bd9Sstevel@tonic-gate static void 3059*7c478bd9Sstevel@tonic-gate append(struct hwc_spec *spec, struct par_list *par) 3060*7c478bd9Sstevel@tonic-gate { 3061*7c478bd9Sstevel@tonic-gate struct hwc_spec *hwc, *last; 3062*7c478bd9Sstevel@tonic-gate 3063*7c478bd9Sstevel@tonic-gate ASSERT(par->par_specs); 3064*7c478bd9Sstevel@tonic-gate for (hwc = par->par_specs; hwc; hwc = hwc->hwc_next) 3065*7c478bd9Sstevel@tonic-gate last = hwc; 3066*7c478bd9Sstevel@tonic-gate last->hwc_next = spec; 3067*7c478bd9Sstevel@tonic-gate } 3068*7c478bd9Sstevel@tonic-gate 3069*7c478bd9Sstevel@tonic-gate /* 3070*7c478bd9Sstevel@tonic-gate * Given a parent=/full-pathname, see if the platform 3071*7c478bd9Sstevel@tonic-gate * can resolve the pathname to driver, otherwise, try 3072*7c478bd9Sstevel@tonic-gate * the leaf node name. 3073*7c478bd9Sstevel@tonic-gate */ 3074*7c478bd9Sstevel@tonic-gate static major_t 3075*7c478bd9Sstevel@tonic-gate get_major(char *parent) 3076*7c478bd9Sstevel@tonic-gate { 3077*7c478bd9Sstevel@tonic-gate major_t major = (major_t)-1; 3078*7c478bd9Sstevel@tonic-gate char *tmp, *driver = NULL; 3079*7c478bd9Sstevel@tonic-gate 3080*7c478bd9Sstevel@tonic-gate if (*parent == '/') 3081*7c478bd9Sstevel@tonic-gate major = path_to_major(parent); 3082*7c478bd9Sstevel@tonic-gate 3083*7c478bd9Sstevel@tonic-gate if (major != (major_t)-1) 3084*7c478bd9Sstevel@tonic-gate return (major); 3085*7c478bd9Sstevel@tonic-gate 3086*7c478bd9Sstevel@tonic-gate /* extract the name between '/' and '@' */ 3087*7c478bd9Sstevel@tonic-gate if (*parent == '/') 3088*7c478bd9Sstevel@tonic-gate driver = strrchr(parent, '/') + 1; 3089*7c478bd9Sstevel@tonic-gate else 3090*7c478bd9Sstevel@tonic-gate driver = parent; 3091*7c478bd9Sstevel@tonic-gate if ((tmp = strchr(driver, '@')) != NULL) 3092*7c478bd9Sstevel@tonic-gate *tmp = '\0'; 3093*7c478bd9Sstevel@tonic-gate major = ddi_name_to_major(driver); 3094*7c478bd9Sstevel@tonic-gate if (tmp) 3095*7c478bd9Sstevel@tonic-gate *tmp = '@'; 3096*7c478bd9Sstevel@tonic-gate return (major); 3097*7c478bd9Sstevel@tonic-gate } 3098*7c478bd9Sstevel@tonic-gate 3099*7c478bd9Sstevel@tonic-gate /* 3100*7c478bd9Sstevel@tonic-gate * Chain together specs whose parent's module name is the same. 3101*7c478bd9Sstevel@tonic-gate */ 3102*7c478bd9Sstevel@tonic-gate static void 3103*7c478bd9Sstevel@tonic-gate add_spec(struct hwc_spec *spec, struct par_list **par) 3104*7c478bd9Sstevel@tonic-gate { 3105*7c478bd9Sstevel@tonic-gate major_t maj; 3106*7c478bd9Sstevel@tonic-gate struct par_list *pl, *par_last = NULL; 3107*7c478bd9Sstevel@tonic-gate char *parent = spec->hwc_parent_name; 3108*7c478bd9Sstevel@tonic-gate 3109*7c478bd9Sstevel@tonic-gate ASSERT(parent || spec->hwc_class_name); 3110*7c478bd9Sstevel@tonic-gate 3111*7c478bd9Sstevel@tonic-gate /* 3112*7c478bd9Sstevel@tonic-gate * If given a parent=/full-pathname, see if the platform 3113*7c478bd9Sstevel@tonic-gate * can resolve the pathname to driver, otherwise, try 3114*7c478bd9Sstevel@tonic-gate * the leaf node name. 3115*7c478bd9Sstevel@tonic-gate * 3116*7c478bd9Sstevel@tonic-gate * If parent=/full-pathname doesn't resolve to a driver, 3117*7c478bd9Sstevel@tonic-gate * this could be cause by DR removal of the device. 3118*7c478bd9Sstevel@tonic-gate * We put it on the major=-2 list in case the device 3119*7c478bd9Sstevel@tonic-gate * is brought back into the system by DR. 3120*7c478bd9Sstevel@tonic-gate */ 3121*7c478bd9Sstevel@tonic-gate if (parent) { 3122*7c478bd9Sstevel@tonic-gate maj = get_major(parent); 3123*7c478bd9Sstevel@tonic-gate if (maj == (major_t)-1) { 3124*7c478bd9Sstevel@tonic-gate if ((*parent == '/') && 3125*7c478bd9Sstevel@tonic-gate (strncmp(parent, "/pseudo", 7) != 0)) { 3126*7c478bd9Sstevel@tonic-gate maj = (major_t)-2; 3127*7c478bd9Sstevel@tonic-gate } else { 3128*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3129*7c478bd9Sstevel@tonic-gate "add_spec: No major number for %s", 3130*7c478bd9Sstevel@tonic-gate parent); 3131*7c478bd9Sstevel@tonic-gate hwc_free(spec); 3132*7c478bd9Sstevel@tonic-gate return; 3133*7c478bd9Sstevel@tonic-gate } 3134*7c478bd9Sstevel@tonic-gate } 3135*7c478bd9Sstevel@tonic-gate } else 3136*7c478bd9Sstevel@tonic-gate maj = (major_t)-1; 3137*7c478bd9Sstevel@tonic-gate 3138*7c478bd9Sstevel@tonic-gate /* 3139*7c478bd9Sstevel@tonic-gate * Scan the list looking for a matching parent. 3140*7c478bd9Sstevel@tonic-gate */ 3141*7c478bd9Sstevel@tonic-gate for (pl = *par; pl; pl = pl->par_next) { 3142*7c478bd9Sstevel@tonic-gate if (maj == pl->par_major) { 3143*7c478bd9Sstevel@tonic-gate append(spec, pl); 3144*7c478bd9Sstevel@tonic-gate return; 3145*7c478bd9Sstevel@tonic-gate } 3146*7c478bd9Sstevel@tonic-gate par_last = pl; 3147*7c478bd9Sstevel@tonic-gate } 3148*7c478bd9Sstevel@tonic-gate 3149*7c478bd9Sstevel@tonic-gate /* 3150*7c478bd9Sstevel@tonic-gate * Didn't find a match on the list. Make a new parent list. 3151*7c478bd9Sstevel@tonic-gate */ 3152*7c478bd9Sstevel@tonic-gate pl = kmem_zalloc(sizeof (*pl), KM_SLEEP); 3153*7c478bd9Sstevel@tonic-gate pl->par_major = maj; 3154*7c478bd9Sstevel@tonic-gate pl->par_specs = spec; 3155*7c478bd9Sstevel@tonic-gate if (*par == NULL) { /* null par list */ 3156*7c478bd9Sstevel@tonic-gate *par = pl; 3157*7c478bd9Sstevel@tonic-gate return; 3158*7c478bd9Sstevel@tonic-gate } 3159*7c478bd9Sstevel@tonic-gate /* put "class=" entries last (lower pri if dups) */ 3160*7c478bd9Sstevel@tonic-gate if (maj == (major_t)-1) { 3161*7c478bd9Sstevel@tonic-gate par_last->par_next = pl; 3162*7c478bd9Sstevel@tonic-gate return; 3163*7c478bd9Sstevel@tonic-gate } 3164*7c478bd9Sstevel@tonic-gate 3165*7c478bd9Sstevel@tonic-gate /* ensure unresolved "parent=/full-path" goes first */ 3166*7c478bd9Sstevel@tonic-gate if ((maj != (major_t)-2) && ((*par)->par_major == (major_t)-2)) 3167*7c478bd9Sstevel@tonic-gate par = &(*par)->par_next; 3168*7c478bd9Sstevel@tonic-gate pl->par_next = *par; 3169*7c478bd9Sstevel@tonic-gate *par = pl; 3170*7c478bd9Sstevel@tonic-gate } 3171*7c478bd9Sstevel@tonic-gate 3172*7c478bd9Sstevel@tonic-gate /* 3173*7c478bd9Sstevel@tonic-gate * Add property spec to property list in original order 3174*7c478bd9Sstevel@tonic-gate */ 3175*7c478bd9Sstevel@tonic-gate static void 3176*7c478bd9Sstevel@tonic-gate add_props(struct hwc_spec *spec, ddi_prop_t **props) 3177*7c478bd9Sstevel@tonic-gate { 3178*7c478bd9Sstevel@tonic-gate ASSERT(spec->hwc_devi_name == NULL); 3179*7c478bd9Sstevel@tonic-gate 3180*7c478bd9Sstevel@tonic-gate if (spec->hwc_devi_sys_prop_ptr) { 3181*7c478bd9Sstevel@tonic-gate while (*props) 3182*7c478bd9Sstevel@tonic-gate props = &(*props)->prop_next; 3183*7c478bd9Sstevel@tonic-gate *props = spec->hwc_devi_sys_prop_ptr; 3184*7c478bd9Sstevel@tonic-gate 3185*7c478bd9Sstevel@tonic-gate /* remove these properties from the spec */ 3186*7c478bd9Sstevel@tonic-gate spec->hwc_devi_sys_prop_ptr = NULL; 3187*7c478bd9Sstevel@tonic-gate } 3188*7c478bd9Sstevel@tonic-gate hwc_free(spec); 3189*7c478bd9Sstevel@tonic-gate } 3190