xref: /titanic_41/usr/src/lib/efcode/fcdriver/get_req.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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 2003 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 <fcntl.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <strings.h>
34 #include <errno.h>
35 
36 #include <sys/mman.h>
37 #include <sys/pci.h>
38 #include <sys/stat.h>
39 #include <sys/wait.h>
40 
41 #include <fcode/private.h>
42 #include <fcode/log.h>
43 
44 #include <fcdriver/fcdriver.h>
45 
46 static char *pkg_my_args;
47 static char fcode_dev[] = "/dev/fcode";
48 
49 static void
50 dot_request(fcode_env_t *env)
51 {
52 	common_data_t *cdp = env->private;
53 
54 	log_message(MSG_INFO, "request: cfgadd: %x fc_size: %x unitadd: %s"
55 	    " attach: %x args: '%s'\n", cdp->fc.config_address,
56 	    cdp->fc.fcode_size, cdp->fc.unit_address, cdp->attach,
57 	    pkg_my_args ? pkg_my_args : "<null>");
58 }
59 
60 /*
61  * Get next request from /dev/fcode.
62  */
63 int
64 fc_get_request(common_data_t *cdp)
65 {
66 	char c;
67 	int nbytes;
68 
69 	if (cdp->fcode_fd < 0) {
70 		log_message(MSG_FATAL, "fc_get_request: fcode_fd not open\n");
71 		return (0);
72 	}
73 
74 	if ((nbytes = read(cdp->fcode_fd, &c, sizeof (c))) < 0) {
75 		log_perror(MSG_FATAL, "read(%s) failed", fcode_dev);
76 		return (0);
77 	}
78 
79 	if (ioctl(cdp->fcode_fd, FC_GET_PARAMETERS, &cdp->fc) < 0) {
80 		log_perror(MSG_FATAL, "ioctl(FC_GET_PARAMETERS) failed");
81 		return (0);
82 	}
83 
84 	if ((cdp->attach = fc_get_ap(cdp)) == NULL)
85 		return (0);
86 
87 	return (1);
88 }
89 
90 static void
91 get_my_args(fcode_env_t *env)
92 {
93 	common_data_t *cdp = env->private;
94 	char buffer[BUFSIZ];
95 
96 	/*
97 	 * Don't get if already set.
98 	 */
99 	if (pkg_my_args)
100 		return;
101 
102 	if (ioctl(cdp->fcode_fd, FC_GET_MY_ARGS, buffer) < 0) {
103 		return;
104 	}
105 	pkg_my_args = STRDUP(buffer);
106 }
107 
108 static void
109 set_my_args(fcode_env_t *env)
110 {
111 	if (pkg_my_args)
112 		FREE(pkg_my_args);
113 
114 	parse_word(env);
115 	pkg_my_args = pop_a_duped_string(env, NULL);
116 }
117 
118 static void
119 dot_my_args(fcode_env_t *env)
120 {
121 	if (pkg_my_args)
122 		log_message(MSG_INFO, "%s\n", pkg_my_args);
123 	else
124 		log_message(MSG_INFO, "NULL\n");
125 }
126 
127 void
128 push_my_args(fcode_env_t *env)
129 {
130 	push_a_string(env, pkg_my_args);
131 }
132 
133 void
134 get_fcode_from_device(fcode_env_t *env)
135 {
136 	common_data_t *cdp = env->private;
137 	char *p, *buf;
138 	static char func_name[] = "get_fcode_from_device";
139 	fc_fcode_info_t fcode_info;
140 
141 	if (!cdp->fc.fcode_size) {
142 		debug_msg(DEBUG_FIND_FCODE, "%s: Fcode zero length\n",
143 		    func_name);
144 		push_a_string(env, NULL);
145 		return;
146 	}
147 	fcode_info.fcode_size = cdp->fc.fcode_size;
148 	fcode_info.fcode_ptr = MALLOC(cdp->fc.fcode_size);
149 	if (ioctl(cdp->fcode_fd, FC_GET_FCODE_DATA, &fcode_info) < 0) {
150 		log_perror(MSG_FATAL, "ioctl(FC_GET_FCODE_DATA) failed");
151 		push_a_string(env, NULL);
152 	} else {
153 		debug_msg(DEBUG_FIND_FCODE,
154 		    "%s: Fcode from device: len: 0x%x\n", func_name,
155 		    (int)cdp->fc.fcode_size);
156 		PUSH(DS, (fstack_t)fcode_info.fcode_ptr);
157 		PUSH(DS, (fstack_t)cdp->fc.fcode_size);
158 	}
159 }
160 
161 static void
162 save_fcode_to_file(fcode_env_t *env)
163 {
164 	char *buf, *fname;
165 	int len;
166 	FILE *fd;
167 
168 	CHECK_DEPTH(env, 4, "save-fcode-to-file");
169 	if ((fname = pop_a_string(env, NULL)) == NULL) {
170 		log_message(MSG_DEBUG, "fname?\n");
171 		return;
172 	}
173 	if ((buf = pop_a_string(env, &len)) == NULL) {
174 		log_message(MSG_INFO, "buf?\n");
175 		return;
176 	}
177 	if ((fd = fopen(fname, "w")) == NULL) {
178 		log_perror(MSG_DEBUG, "Save_fcode_to_file: Can't open '%s'",
179 		    fname);
180 		return;
181 	}
182 	log_message(MSG_INFO, "Fcode %p,%x to file '%s'\n", buf, len, fname);
183 	fwrite(buf, len, sizeof (char), fd);
184 	fclose(fd);
185 }
186 
187 void
188 exec_fcode_builtin_method(fcode_env_t *env)
189 {
190 	fstack_t d;
191 	char *method;
192 	extern void exec_parent_method(fcode_env_t *);
193 	extern void exec_builtin_driver(fcode_env_t *);
194 
195 	method = (char *)DS[-1];
196 	exec_parent_method(env);
197 	d = POP(DS);
198 	if (d) {
199 		debug_msg(DEBUG_FIND_FCODE, "builtin-driver: %s -> %s found\n",
200 		    method, (char *)DS[-1]);
201 		exec_builtin_driver(env);
202 		debug_msg(DEBUG_FIND_FCODE, "builtin-driver-exec: %p %x\n",
203 		    (char *)DS[-1], (int)TOS);
204 	} else {
205 		debug_msg(DEBUG_FIND_FCODE, "builtin-driver: %s not found\n",
206 		    method);
207 		PUSH(DS, FALSE);
208 	}
209 }
210 
211 void
212 get_fcode_from_filesystem(fcode_env_t *env)
213 {
214 	fstack_t d;
215 	char *method, *fc_name, *path;
216 	extern void exec_parent_method(fcode_env_t *);
217 	static char fname[] = "get-fcode-from-filesystem";
218 
219 	method = (char *)DS[-1];
220 	exec_parent_method(env);
221 	d = POP(DS);
222 	if (d) {
223 		fc_name = pop_a_string(env, NULL);
224 		debug_msg(DEBUG_FIND_FCODE, "%s: %s -> %s found\n", fname,
225 		    method, fc_name);
226 		if ((path = search_for_fcode_file(env, fc_name)) != NULL) {
227 			debug_msg(DEBUG_FIND_FCODE, "%s: file: %s FOUND\n",
228 			    fname, path);
229 			push_a_string(env, path);
230 			load_file(env);
231 		} else {
232 			debug_msg(DEBUG_FIND_FCODE, "%s: file '%s' not found\n",
233 			    fname, fc_name);
234 			PUSH(DS, FALSE);
235 		}
236 	} else {
237 		debug_msg(DEBUG_FIND_FCODE, "%s: method '%s' not found\n",
238 		    fname, method);
239 		PUSH(DS, FALSE);
240 	}
241 }
242 
243 /*
244  * Looks for "device-id" and "class-id" methods in parent, if there,
245  * executes them to get "builtin drivers" file name or method name, then
246  * executes the builtin-driver method.  If both those fail, try getting the
247  * fcode from the device.  Note that we sleaze resetting the data stack.
248  * This would be cleaner if we had a way to do the equivalent of "catch/throw"
249  * from within C code.
250  */
251 void
252 find_fcode(fcode_env_t *env)
253 {
254 	fstack_t *dp = env->ds;
255 	static char func_name[] = "find_fcode";
256 
257 	my_unit(env);
258 	push_a_string(env, "device-id");
259 	get_fcode_from_filesystem(env);
260 	if (TOS) {
261 		debug_msg(DEBUG_FIND_FCODE, "%s: FS dev-id: len: 0x%x\n",
262 		    func_name, TOS);
263 		return;
264 	}
265 
266 	env->ds = dp;
267 	my_unit(env);
268 	push_a_string(env, "class-id");
269 	get_fcode_from_filesystem(env);
270 	if (TOS) {
271 		debug_msg(DEBUG_FIND_FCODE, "%s: FS cls-id len: 0x%x\n",
272 		    func_name, TOS);
273 		return;
274 	}
275 
276 	env->ds = dp;
277 	get_fcode_from_device(env);
278 	if (TOS) {
279 		debug_msg(DEBUG_FIND_FCODE, "%s: DEV fcode len: 0x%x\n",
280 		    func_name, TOS);
281 		return;
282 	}
283 
284 	env->ds = dp;
285 	my_unit(env);
286 	push_a_string(env, "device-id");
287 	exec_fcode_builtin_method(env);
288 	if (TOS) {
289 		debug_msg(DEBUG_FIND_FCODE, "%s: dropin dev-id len: 0x%x\n",
290 		    func_name, TOS);
291 		return;
292 	}
293 
294 	env->ds = dp;
295 	my_unit(env);
296 	push_a_string(env, "class-id");
297 	exec_fcode_builtin_method(env);
298 	if (TOS) {
299 		debug_msg(DEBUG_FIND_FCODE, "%s: dropin cls-id len: 0x%x\n",
300 		    func_name, TOS);
301 		return;
302 	}
303 	debug_msg(DEBUG_FIND_FCODE, "%s: not found\n", func_name);
304 }
305 
306 int
307 open_fcode_dev(fcode_env_t *env)
308 {
309 	common_data_t *cdp = env->private;
310 
311 	if ((cdp->fcode_fd = open(fcode_dev, O_RDONLY)) < 0)
312 		log_perror(MSG_ERROR, "Can't open '%s'", fcode_dev);
313 	return (cdp->fcode_fd >= 0);
314 }
315 
316 static void
317 get_request(fcode_env_t *env)
318 {
319 	common_data_t *cdp = env->private;
320 
321 	if (cdp->fcode_fd >= 0)
322 		close(cdp->fcode_fd);
323 	if (!open_fcode_dev(env))
324 		exit(1);
325 	if (!fc_get_request(cdp)) {
326 		log_message(MSG_FATAL, "fc_get_request failed\n");
327 		exit(1);
328 	}
329 
330 	get_my_args(env);
331 
332 	DEBUGF(UPLOAD, dot_request(env));
333 }
334 
335 /*
336  * invoked from efdaemon, /dev/fcode event has been read and /dev/fcode opened
337  * file descriptor is fd 0.
338  */
339 static void
340 get_efdaemon_request(fcode_env_t *env)
341 {
342 	common_data_t *cdp = env->private;
343 
344 	cdp->fcode_fd = 0;
345 	if (ioctl(cdp->fcode_fd, FC_GET_PARAMETERS, &cdp->fc) < 0) {
346 		log_perror(MSG_FATAL, "ioctl(FC_GET_PARAMETERS) failed");
347 		exit(1);
348 	}
349 
350 	if ((cdp->attach = fc_get_ap(cdp)) == NULL)
351 		exit(1);
352 
353 	get_my_args(env);
354 
355 	DEBUGF(UPLOAD, dot_request(env));
356 }
357 
358 static void
359 process_request(fcode_env_t *env)
360 {
361 	common_data_t *cdp = env->private;
362 	fstack_t fcode_len;
363 	char *path;
364 
365 	build_tree(env);
366 	install_builtin_nodes(env);
367 	push_my_args(env);
368 	push_a_string(env, cdp->fc.unit_address);
369 	if ((path = get_path(env, env->attachment_pt)) == NULL) {
370 		log_message(MSG_FATAL, "Can't get_path of"
371 		    " attachment_pt %p\n", env->attachment_pt);
372 		exit(1);
373 	}
374 	debug_msg(DEBUG_UPLOAD, "Attach Point: %s\n", path);
375 
376 	push_a_string(env, path);
377 	begin_package(env);
378 	find_fcode(env);
379 	fcode_len = POP(DS);
380 	if (!fcode_len) {
381 		(void) POP(DS);
382 		debug_msg(DEBUG_UPLOAD, "Zero length Fcode\n");
383 		return;
384 	}
385 
386 	debug_msg(DEBUG_UPLOAD, "byte-load fcode_len: %x\n",
387 	    fcode_len);
388 
389 	PUSH(DS, 1);
390 	byte_load(env);
391 	end_package(env);
392 	upload_nodes(env);
393 	validate_nodes(env);
394 	debug_msg(DEBUG_UPLOAD, "Upload Done\n");
395 }
396 
397 static void
398 finish_request(fcode_env_t *env)
399 {
400 	common_data_t *cdp = env->private;
401 
402 	close(cdp->fcode_fd);
403 }
404 
405 /*
406  * Non-daemon "do-request", for debugging
407  */
408 static void
409 do_request(fcode_env_t *env)
410 {
411 	get_request(env);
412 	process_request(env);
413 	finish_request(env);
414 }
415 
416 /*
417  * This process one request from efdaemon, we know that /dev/fcode is already
418  * open and passed in fd0 (stdin).  If it's not, we throw up our hands.
419  */
420 void
421 run_one_efdaemon_request(fcode_env_t *env)
422 {
423 	get_efdaemon_request(env);
424 	process_request(env);
425 	finish_request(env);
426 	exit(0);
427 }
428 
429 void
430 probe_space(fcode_env_t *env)
431 {
432 	fc_cell_t cfg = 0;
433 	int error;
434 
435 	error = fc_run_priv(env->private, FC_PROBE_SPACE, 0, 1, &cfg);
436 	if (error)
437 		throw_from_fclib(env, 1, "FC_PROBE_SPACE failed\n");
438 	PUSH(DS, fc_cell2uint32_t(cfg));
439 }
440 
441 #pragma init(_init)
442 
443 static void
444 _init(void)
445 {
446 	fcode_env_t *env = initial_env;
447 
448 	ASSERT(env);
449 	NOTICE;
450 
451 	FORTH(0,	"get-fcode-from-device",	get_fcode_from_device);
452 	FORTH(0,	"save-fcode-to-file",		save_fcode_to_file);
453 	FORTH(0,	"get-my-args",			get_my_args);
454 	FORTH(0,	"set-my-args",			set_my_args);
455 	FORTH(0,	".my-args",			dot_my_args);
456 	FORTH(0,	".request",			dot_request);
457 	FORTH(0,	"get-request",			get_request);
458 	FORTH(0,	"process-request",		process_request);
459 	FORTH(0,	"finish-request",		finish_request);
460 	FORTH(0,	"do-request",			do_request);
461 	FORTH(0,	"find-fcode",			find_fcode);
462 	FORTH(0,	"exec-fcode-builtin-method", exec_fcode_builtin_method);
463 	FORTH(0,	"run-one-efdaemon-request",  run_one_efdaemon_request);
464 	FORTH(0,	"get-efdaemon-request",		get_efdaemon_request);
465 	FORTH(0,	"probe-space",			probe_space);
466 }
467