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 (c) 2000 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <strings.h>
33
34 #include <fcode/private.h>
35 #include <fcode/log.h>
36
37 #include <fcdriver/fcdriver.h>
38
39 static device_t *builtin_driver_device;
40
41 static int
is_device_builtin_package(fcode_env_t * env,device_t * d)42 is_device_builtin_package(fcode_env_t *env, device_t *d)
43 {
44 return (d == builtin_driver_device);
45 }
46
47 static char *dropin_name;
48
49 /*
50 * do-builtin-dropin ( -- )
51 * Convoluted name just in case someone has "do-dropin" word in Fcode.
52 * Somewhat different from do-dropin in OBP, as we just load the Fcode, we
53 * don't do a byte-load.
54 */
55 static void
do_builtin_dropin(fcode_env_t * env)56 do_builtin_dropin(fcode_env_t *env)
57 {
58 fc_cell_t len, result;
59 char *buf;
60 int error;
61 static char func_name[] = "do-builtin-dropin";
62 extern int check_fcode_header(char *, uchar_t *, int);
63
64 if (dropin_name == NULL) {
65 log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name);
66 return;
67 }
68 debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name);
69 error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
70 fc_ptr2cell(dropin_name), &len);
71 if (error)
72 return;
73 if (len == 0) {
74 log_message(MSG_WARN, "%s: '%s' zero length Fcode\n",
75 func_name, dropin_name);
76 return;
77 }
78 buf = MALLOC(len);
79 error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1,
80 fc_ptr2cell(dropin_name), fc_ptr2cell(buf), len, &result);
81 if (error) {
82 FREE(buf);
83 return;
84 }
85
86 if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0)
87 log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n",
88 func_name, dropin_name);
89
90 debug_msg(DEBUG_FIND_FCODE,
91 "%s: '%s' doing byte-load len: %x\n", func_name, dropin_name,
92 (int)len);
93 PUSH(DS, (fstack_t)buf);
94 PUSH(DS, 1);
95 byte_load(env);
96 }
97
98 static void
do_builtin_file(fcode_env_t * env)99 do_builtin_file(fcode_env_t *env)
100 {
101 char *fname;
102 static char func_name[] = "do-builtin-file";
103 fstack_t d;
104
105 if (dropin_name == NULL) {
106 log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name);
107 return;
108 }
109 debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name);
110 push_a_string(env, dropin_name);
111 load_file(env);
112 d = POP(DS);
113 if (d) {
114 debug_msg(DEBUG_FIND_FCODE, "%s: byte-load '%s'\n", func_name,
115 dropin_name);
116 PUSH(DS, 1);
117 byte_load(env);
118 } else
119 debug_msg(DEBUG_FIND_FCODE, "%s: load_file '%s' FAIL\n",
120 func_name, dropin_name);
121 }
122
123 /*
124 * We need to lookup the builtin name via an FC_RUN_PRIV call to make sure
125 * the builtin exists. If it exists, then we need to leave the xt of
126 * do-builtin-dropin on the stack and remember the name for do-dropin. This is
127 * extremely convoluted because we can't a priori populate
128 * SUNW,builtin-drivers.
129 */
130 static void
builtin_driver_method_hook(fcode_env_t * env)131 builtin_driver_method_hook(fcode_env_t *env)
132 {
133 device_t *device;
134 char *method, *path;
135 fc_cell_t len;
136 fstack_t d;
137 int error;
138 static char func_name[] = "builtin-driver-method-hook";
139
140 d = POP(DS);
141 CONVERT_PHANDLE(env, device, d);
142 if (!is_device_builtin_package(env, device)) {
143 PUSH(DS, d);
144 PUSH(DS, FALSE);
145 return;
146 }
147
148 method = pop_a_string(env, NULL);
149
150 /*
151 * Check for file in filesystem. If it exists, we'll just try to do
152 * a do-dropin-file.
153 */
154 if ((path = search_for_fcode_file(env, method)) != NULL) {
155 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' file: '%s'\n", func_name,
156 method, path);
157 if (dropin_name) {
158 FREE(dropin_name);
159 }
160 dropin_name = STRDUP(path);
161 push_a_string(env, "do-builtin-file");
162 dollar_find(env);
163 return;
164 }
165
166 error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
167 fc_ptr2cell(method), &len);
168 if (error || len == 0) {
169 if (len == 0)
170 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n",
171 func_name, method);
172 push_a_string(env, method);
173 PUSH(DS, d);
174 PUSH(DS, FALSE);
175 } else {
176 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n",
177 func_name, method, (int)len);
178 if (dropin_name) {
179 FREE(dropin_name);
180 }
181 dropin_name = STRDUP(method);
182 push_a_string(env, "do-builtin-dropin");
183 dollar_find(env);
184 }
185 }
186
187 void
make_a_node(fcode_env_t * env,char * name,int finish)188 make_a_node(fcode_env_t *env, char *name, int finish)
189 {
190 new_device(env);
191 push_a_string(env, name);
192 device_name(env);
193 if (finish)
194 finish_device(env);
195 }
196
197 void
install_package_nodes(fcode_env_t * env)198 install_package_nodes(fcode_env_t *env)
199 {
200 MYSELF = open_instance_chain(env, env->root_node, 0);
201 if (MYSELF != NULL) {
202 make_a_node(env, "packages", 0);
203 make_a_node(env, "disk-label", 0);
204 finish_device(env);
205 make_a_node(env, "SUNW,builtin-drivers", 0);
206 builtin_driver_device = env->current_device;
207 finish_device(env);
208 finish_device(env);
209 close_instance_chain(env, MYSELF, 0);
210 device_end(env);
211 MYSELF = 0;
212 }
213 }
214
215 /*
216 * find-builtin-driver ( str len -- xt true | false )
217 */
218 void
find_builtin_driver(fcode_env_t * env)219 find_builtin_driver(fcode_env_t *env)
220 {
221 fstack_t d;
222
223 CHECK_DEPTH(env, 2, "find-builtin-driver");
224 push_a_string(env, "SUNW,builtin-drivers");
225 find_package(env);
226 d = POP(DS);
227 if (d) {
228 find_method(env);
229 } else {
230 two_drop(env);
231 PUSH(DS, FALSE);
232 }
233 }
234
235 void
exec_builtin_driver(fcode_env_t * env)236 exec_builtin_driver(fcode_env_t *env)
237 {
238 fstack_t d;
239 char *method, *path, *buf;
240 fc_cell_t len, result;
241 int error;
242 static char func_name[] = "exec-builtin-driver";
243 extern int check_fcode_header(char *, uchar_t *, int);
244
245 CHECK_DEPTH(env, 2, func_name);
246 method = pop_a_string(env, NULL);
247
248 /*
249 * Check for file in filesystem. If it exists, we'll just try to do
250 * a do-dropin-file.
251 */
252 if ((path = search_for_fcode_file(env, method)) != NULL) {
253 push_a_string(env, path);
254 load_file(env);
255 return;
256 }
257
258 error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
259 fc_ptr2cell(method), &len);
260 if (error || len == 0) {
261 if (len == 0)
262 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n",
263 func_name, method);
264 PUSH(DS, 0);
265 return;
266 }
267 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n",
268 func_name, method, (int)len);
269 buf = MALLOC(len);
270 error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1,
271 fc_ptr2cell(method), fc_ptr2cell(buf), len, &result);
272 if (error) {
273 FREE(buf);
274 PUSH(DS, 0);
275 return;
276 }
277
278 if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0)
279 log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n",
280 func_name, method);
281
282 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' dropin Fcode: 0x%p/0x%x\n",
283 func_name, method, buf, (int)len);
284 PUSH(DS, (fstack_t)buf);
285 PUSH(DS, len);
286 }
287
288 #pragma init(_init)
289
290 static void
_init(void)291 _init(void)
292 {
293 extern void set_find_method_hook(fcode_env_t *,
294 void (*)(fcode_env_t *));
295 fcode_env_t *env = initial_env;
296 fstack_t d;
297
298 ASSERT(env);
299 NOTICE;
300
301 set_find_method_hook(env, builtin_driver_method_hook);
302
303 FORTH(0, "install-package-nodes", install_package_nodes);
304 FORTH(0, "find-builtin-driver", find_builtin_driver);
305 FORTH(0, "exec-builtin-driver", exec_builtin_driver);
306 FORTH(0, "builtin-driver-method-hook",
307 builtin_driver_method_hook);
308 FORTH(0, "do-builtin-dropin", do_builtin_dropin);
309 FORTH(0, "do-builtin-file", do_builtin_file);
310 }
311