xref: /titanic_52/usr/src/lib/efcode/fcdriver/get_req.c (revision ea8dc4b6d2251b437950c0056bc626b311c73c27)
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 <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 	common_data_t *cdp = env->private;
256 	static char func_name[] = "find_fcode";
257 	int error;
258 
259 	my_unit(env);
260 	push_a_string(env, "device-id");
261 	get_fcode_from_filesystem(env);
262 	if (TOS) {
263 		debug_msg(DEBUG_FIND_FCODE, "%s: FS dev-id: len: 0x%x\n",
264 		    func_name, TOS);
265 		return;
266 	}
267 
268 	env->ds = dp;
269 	my_unit(env);
270 	push_a_string(env, "class-id");
271 	get_fcode_from_filesystem(env);
272 	if (TOS) {
273 		debug_msg(DEBUG_FIND_FCODE, "%s: FS cls-id len: 0x%x\n",
274 		    func_name, TOS);
275 		return;
276 	}
277 
278 	env->ds = dp;
279 	get_fcode_from_device(env);
280 	if (TOS) {
281 		debug_msg(DEBUG_FIND_FCODE, "%s: DEV fcode len: 0x%x\n",
282 		    func_name, TOS);
283 		return;
284 	}
285 
286 	env->ds = dp;
287 	my_unit(env);
288 	push_a_string(env, "device-id");
289 	exec_fcode_builtin_method(env);
290 	if (TOS) {
291 		debug_msg(DEBUG_FIND_FCODE, "%s: dropin dev-id len: 0x%x\n",
292 		    func_name, TOS);
293 		return;
294 	}
295 
296 	env->ds = dp;
297 	my_unit(env);
298 	push_a_string(env, "class-id");
299 	exec_fcode_builtin_method(env);
300 	if (TOS) {
301 		debug_msg(DEBUG_FIND_FCODE, "%s: dropin cls-id len: 0x%x\n",
302 		    func_name, TOS);
303 		return;
304 	}
305 
306 	debug_msg(DEBUG_FIND_FCODE, "%s: not found\n", func_name);
307 	error = FC_NO_FCODE;
308 	if (ioctl(cdp->fcode_fd, FC_SET_FCODE_ERROR, &error) < 0) {
309 		log_perror(MSG_FATAL, "ioctl(FC_SET_FCODE_ERROR) failed");
310 		return;
311 	}
312 }
313 
314 int
315 open_fcode_dev(fcode_env_t *env)
316 {
317 	common_data_t *cdp = env->private;
318 
319 	if ((cdp->fcode_fd = open(fcode_dev, O_RDONLY)) < 0)
320 		log_perror(MSG_ERROR, "Can't open '%s'", fcode_dev);
321 	return (cdp->fcode_fd >= 0);
322 }
323 
324 static void
325 get_request(fcode_env_t *env)
326 {
327 	common_data_t *cdp = env->private;
328 
329 	if (cdp->fcode_fd >= 0)
330 		close(cdp->fcode_fd);
331 	if (!open_fcode_dev(env))
332 		exit(1);
333 	if (!fc_get_request(cdp)) {
334 		log_message(MSG_FATAL, "fc_get_request failed\n");
335 		exit(1);
336 	}
337 
338 	get_my_args(env);
339 
340 	DEBUGF(UPLOAD, dot_request(env));
341 }
342 
343 /*
344  * invoked from efdaemon, /dev/fcode event has been read and /dev/fcode opened
345  * file descriptor is fd 0.
346  */
347 static void
348 get_efdaemon_request(fcode_env_t *env)
349 {
350 	common_data_t *cdp = env->private;
351 
352 	cdp->fcode_fd = 0;
353 	if (ioctl(cdp->fcode_fd, FC_GET_PARAMETERS, &cdp->fc) < 0) {
354 		log_perror(MSG_FATAL, "ioctl(FC_GET_PARAMETERS) failed");
355 		exit(1);
356 	}
357 
358 	if ((cdp->attach = fc_get_ap(cdp)) == NULL)
359 		exit(1);
360 
361 	get_my_args(env);
362 
363 	DEBUGF(UPLOAD, dot_request(env));
364 }
365 
366 static void
367 process_request(fcode_env_t *env)
368 {
369 	common_data_t *cdp = env->private;
370 	fstack_t fcode_len;
371 	char *path;
372 
373 	build_tree(env);
374 	install_builtin_nodes(env);
375 	push_my_args(env);
376 	push_a_string(env, cdp->fc.unit_address);
377 	if ((path = get_path(env, env->attachment_pt)) == NULL) {
378 		log_message(MSG_FATAL, "Can't get_path of"
379 		    " attachment_pt %p\n", env->attachment_pt);
380 		exit(1);
381 	}
382 	debug_msg(DEBUG_UPLOAD, "Attach Point: %s\n", path);
383 
384 	push_a_string(env, path);
385 	begin_package(env);
386 	find_fcode(env);
387 	fcode_len = POP(DS);
388 	if (!fcode_len) {
389 		(void) POP(DS);
390 		debug_msg(DEBUG_UPLOAD, "Zero length Fcode\n");
391 		return;
392 	}
393 
394 	debug_msg(DEBUG_UPLOAD, "byte-load fcode_len: %x\n",
395 	    fcode_len);
396 
397 	PUSH(DS, 1);
398 	byte_load(env);
399 	end_package(env);
400 	upload_nodes(env);
401 	validate_nodes(env);
402 	debug_msg(DEBUG_UPLOAD, "Upload Done\n");
403 }
404 
405 static void
406 finish_request(fcode_env_t *env)
407 {
408 	common_data_t *cdp = env->private;
409 
410 	close(cdp->fcode_fd);
411 }
412 
413 /*
414  * Non-daemon "do-request", for debugging
415  */
416 static void
417 do_request(fcode_env_t *env)
418 {
419 	get_request(env);
420 	process_request(env);
421 	finish_request(env);
422 }
423 
424 /*
425  * This process one request from efdaemon, we know that /dev/fcode is already
426  * open and passed in fd0 (stdin).  If it's not, we throw up our hands.
427  */
428 void
429 run_one_efdaemon_request(fcode_env_t *env)
430 {
431 	get_efdaemon_request(env);
432 	process_request(env);
433 	finish_request(env);
434 	exit(0);
435 }
436 
437 void
438 probe_space(fcode_env_t *env)
439 {
440 	fc_cell_t cfg = 0;
441 	int error;
442 
443 	error = fc_run_priv(env->private, FC_PROBE_SPACE, 0, 1, &cfg);
444 	if (error)
445 		throw_from_fclib(env, 1, "FC_PROBE_SPACE failed\n");
446 	PUSH(DS, fc_cell2uint32_t(cfg));
447 }
448 
449 #pragma init(_init)
450 
451 static void
452 _init(void)
453 {
454 	fcode_env_t *env = initial_env;
455 
456 	ASSERT(env);
457 	NOTICE;
458 
459 	FORTH(0,	"get-fcode-from-device",	get_fcode_from_device);
460 	FORTH(0,	"save-fcode-to-file",		save_fcode_to_file);
461 	FORTH(0,	"get-my-args",			get_my_args);
462 	FORTH(0,	"set-my-args",			set_my_args);
463 	FORTH(0,	".my-args",			dot_my_args);
464 	FORTH(0,	".request",			dot_request);
465 	FORTH(0,	"get-request",			get_request);
466 	FORTH(0,	"process-request",		process_request);
467 	FORTH(0,	"finish-request",		finish_request);
468 	FORTH(0,	"do-request",			do_request);
469 	FORTH(0,	"find-fcode",			find_fcode);
470 	FORTH(0,	"exec-fcode-builtin-method", exec_fcode_builtin_method);
471 	FORTH(0,	"run-one-efdaemon-request",  run_one_efdaemon_request);
472 	FORTH(0,	"get-efdaemon-request",		get_efdaemon_request);
473 	FORTH(0,	"probe-space",			probe_space);
474 }
475