1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/param.h> 30 #include <sys/idprom.h> 31 #include <sys/promif.h> 32 #include <sys/salib.h> 33 34 #include <sys/platnames.h> 35 36 /* 37 * This source is (and should be ;-) shared between the boot blocks 38 * and the boot programs. So if you change it, be sure to test them all! 39 */ 40 41 #define MAXNMLEN 1024 /* # of chars in a property */ 42 43 /* 44 * Supplied by modpath.c 45 * 46 * Making these externs here allows all sparc machines to share 47 * get_impl_arch_name(). 48 */ 49 extern char *default_name; 50 extern char *default_path; 51 52 enum ia_state_mach { 53 STATE_NAME, 54 STATE_COMPAT_INIT, 55 STATE_COMPAT, 56 STATE_DEFAULT, 57 STATE_FINI 58 }; 59 60 /* 61 * Return the implementation architecture name (uname -i) for this platform. 62 * 63 * Use the named rootnode property to determine the iarch. 64 */ 65 static char * 66 get_impl_arch_name(enum ia_state_mach *state, int use_default) 67 { 68 static char iarch[MAXNMLEN]; 69 static int len; 70 static char *ia; 71 72 pnode_t n; 73 char *cp; 74 char *namename; 75 76 newstate: 77 switch (*state) { 78 case STATE_NAME: 79 *state = STATE_COMPAT_INIT; 80 namename = OBP_NAME; 81 n = (pnode_t)prom_rootnode(); 82 len = prom_getproplen(n, namename); 83 if (len <= 0 || len >= MAXNMLEN) 84 goto newstate; 85 (void) prom_getprop(n, namename, iarch); 86 iarch[len] = '\0'; /* fix broken clones */ 87 ia = iarch; 88 break; 89 90 case STATE_COMPAT_INIT: 91 *state = STATE_COMPAT; 92 namename = OBP_COMPATIBLE; 93 n = (pnode_t)prom_rootnode(); 94 len = prom_getproplen(n, namename); 95 if (len <= 0 || len >= MAXNMLEN) { 96 *state = STATE_DEFAULT; 97 goto newstate; 98 } 99 (void) prom_getprop(n, namename, iarch); 100 iarch[len] = '\0'; /* ensure null termination */ 101 ia = iarch; 102 break; 103 104 case STATE_COMPAT: 105 /* 106 * Advance 'ia' to point to next string in 107 * compatible property array (if any). 108 */ 109 while (*ia++) 110 ; 111 if ((ia - iarch) >= len) { 112 *state = STATE_DEFAULT; 113 goto newstate; 114 } 115 break; 116 117 case STATE_DEFAULT: 118 *state = STATE_FINI; 119 if (!use_default || default_name == NULL) 120 goto newstate; 121 (void) strcpy(iarch, default_name); 122 ia = iarch; 123 break; 124 125 case STATE_FINI: 126 return (NULL); 127 } 128 129 /* 130 * Crush filesystem-awkward characters. See PSARC/1992/170. 131 * (Convert the property to a sane directory name in UFS) 132 */ 133 for (cp = ia; *cp; cp++) 134 if (*cp == '/' || *cp == ' ' || *cp == '\t') 135 *cp = '_'; 136 return (ia); 137 } 138 139 static void 140 make_platform_path(char *fullpath, char *iarch, char *filename) 141 { 142 (void) strcpy(fullpath, "/platform/"); 143 (void) strcat(fullpath, iarch); 144 if (filename != NULL) { 145 (void) strcat(fullpath, "/"); 146 (void) strcat(fullpath, filename); 147 } 148 } 149 150 /* 151 * Generate impl_arch_name by searching the /platform hierarchy 152 * for a matching directory. We are not looking for any particular 153 * file here, but for a directory hierarchy for the module path. 154 */ 155 int 156 find_platform_dir(int (*isdirfn)(char *), char *iarch, int use_default) 157 { 158 char fullpath[MAXPATHLEN]; 159 char *ia; 160 enum ia_state_mach state = STATE_NAME; 161 162 /* 163 * Hunt the filesystem looking for a directory hierarchy. 164 */ 165 while ((ia = get_impl_arch_name(&state, use_default)) != NULL) { 166 make_platform_path(fullpath, ia, NULL); 167 if (((*isdirfn)(fullpath)) != 0) { 168 (void) strcpy(iarch, ia); 169 return (1); 170 } 171 } 172 return (0); 173 } 174 175 /* 176 * Search the /platform hierarchy looking for a particular file. 177 * 178 * impl_arch_name is given as an optional hint as to where the 179 * file might be found. 180 */ 181 int 182 open_platform_file( 183 char *filename, 184 int (*openfn)(char *, void *), 185 void *arg, 186 char *fullpath, 187 char *given_iarch) 188 { 189 char *ia; 190 int fd; 191 enum ia_state_mach state = STATE_NAME; 192 193 /* 194 * First try the impl_arch_name hint. 195 * 196 * This is only here to support the -I flag to boot. 197 */ 198 if (given_iarch != NULL) { 199 make_platform_path(fullpath, given_iarch, filename); 200 return ((*openfn)(fullpath, arg)); 201 } 202 203 /* 204 * Hunt the filesystem for one that works .. 205 */ 206 while ((ia = get_impl_arch_name(&state, 1)) != NULL) { 207 make_platform_path(fullpath, ia, filename); 208 if ((fd = (*openfn)(fullpath, arg)) != -1) 209 return (fd); 210 } 211 212 return (-1); 213 } 214