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