OpenSolaris_b135/lib/efcode/packages/populate.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 2000 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>

#include <fcode/private.h>
#include <fcode/log.h>

#include <fcdriver/fcdriver.h>

static device_t *builtin_driver_device;

static int
is_device_builtin_package(fcode_env_t *env, device_t *d)
{
	return (d == builtin_driver_device);
}

static char *dropin_name;

/*
 * do-builtin-dropin  ( -- )
 * Convoluted name just in case someone has "do-dropin" word in Fcode.
 * Somewhat different from do-dropin in OBP, as we just load the Fcode, we
 * don't do a byte-load.
 */
static void
do_builtin_dropin(fcode_env_t *env)
{
	fc_cell_t len, result;
	char *buf;
	int error;
	static char func_name[] = "do-builtin-dropin";
	extern int check_fcode_header(char *, uchar_t *, int);

	if (dropin_name == NULL) {
		log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name);
		return;
	}
	debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name);
	error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
	    fc_ptr2cell(dropin_name), &len);
	if (error)
		return;
	if (len == 0) {
		log_message(MSG_WARN, "%s: '%s' zero length Fcode\n",
		    func_name, dropin_name);
		return;
	}
	buf = MALLOC(len);
	error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1,
	    fc_ptr2cell(dropin_name), fc_ptr2cell(buf), len, &result);
	if (error) {
		FREE(buf);
		return;
	}

	if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0)
		log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n",
		    func_name, dropin_name);

	debug_msg(DEBUG_FIND_FCODE,
	    "%s: '%s' doing byte-load len: %x\n", func_name, dropin_name,
	    (int)len);
	PUSH(DS, (fstack_t)buf);
	PUSH(DS, 1);
	byte_load(env);
}

static void
do_builtin_file(fcode_env_t *env)
{
	char *fname;
	static char func_name[] = "do-builtin-file";
	fstack_t d;

	if (dropin_name == NULL) {
		log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name);
		return;
	}
	debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name);
	push_a_string(env, dropin_name);
	load_file(env);
	d = POP(DS);
	if (d) {
		debug_msg(DEBUG_FIND_FCODE, "%s: byte-load '%s'\n", func_name,
		    dropin_name);
		PUSH(DS, 1);
		byte_load(env);
	} else
		debug_msg(DEBUG_FIND_FCODE, "%s: load_file '%s' FAIL\n",
		    func_name, dropin_name);
}

/*
 * We need to lookup the builtin name via an FC_RUN_PRIV call to make sure
 * the builtin exists.  If it exists, then we need to leave the xt of
 * do-builtin-dropin on the stack and remember the name for do-dropin.  This is
 * extremely convoluted because we can't a priori populate
 * SUNW,builtin-drivers.
 */
static void
builtin_driver_method_hook(fcode_env_t *env)
{
	device_t *device;
	char *method, *path;
	fc_cell_t len;
	fstack_t d;
	int error;
	static char func_name[] = "builtin-driver-method-hook";

	d = POP(DS);
	CONVERT_PHANDLE(env, device, d);
	if (!is_device_builtin_package(env, device)) {
		PUSH(DS, d);
		PUSH(DS, FALSE);
		return;
	}

	method = pop_a_string(env, NULL);

	/*
	 * Check for file in filesystem.  If it exists, we'll just try to do
	 * a do-dropin-file.
	 */
	if ((path = search_for_fcode_file(env, method)) != NULL) {
		debug_msg(DEBUG_FIND_FCODE, "%s: '%s' file: '%s'\n", func_name,
		    method, path);
		if (dropin_name) {
			FREE(dropin_name);
		}
		dropin_name = STRDUP(path);
		push_a_string(env, "do-builtin-file");
		dollar_find(env);
		return;
	}

	error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
	    fc_ptr2cell(method), &len);
	if (error || len == 0) {
		if (len == 0)
			debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n",
			    func_name, method);
		push_a_string(env, method);
		PUSH(DS, d);
		PUSH(DS, FALSE);
	} else {
		debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n",
		    func_name, method, (int)len);
		if (dropin_name) {
			FREE(dropin_name);
		}
		dropin_name = STRDUP(method);
		push_a_string(env, "do-builtin-dropin");
		dollar_find(env);
	}
}

void
make_a_node(fcode_env_t *env, char *name, int finish)
{
	new_device(env);
	push_a_string(env, name);
	device_name(env);
	if (finish)
		finish_device(env);
}

void
install_package_nodes(fcode_env_t *env)
{
	MYSELF = open_instance_chain(env, env->root_node, 0);
	if (MYSELF != NULL) {
		make_a_node(env, "packages", 0);
		make_a_node(env, "disk-label", 0);
		finish_device(env);
		make_a_node(env, "SUNW,builtin-drivers", 0);
		builtin_driver_device = env->current_device;
		finish_device(env);
		finish_device(env);
		close_instance_chain(env, MYSELF, 0);
		device_end(env);
		MYSELF = 0;
	}
}

/*
 * find-builtin-driver  ( str len -- xt true | false )
 */
void
find_builtin_driver(fcode_env_t *env)
{
	fstack_t d;

	CHECK_DEPTH(env, 2, "find-builtin-driver");
	push_a_string(env, "SUNW,builtin-drivers");
	find_package(env);
	d = POP(DS);
	if (d) {
		find_method(env);
	} else {
		two_drop(env);
		PUSH(DS, FALSE);
	}
}

void
exec_builtin_driver(fcode_env_t *env)
{
	fstack_t d;
	char *method, *path, *buf;
	fc_cell_t len, result;
	int error;
	static char func_name[] = "exec-builtin-driver";
	extern int check_fcode_header(char *, uchar_t *, int);

	CHECK_DEPTH(env, 2, func_name);
	method = pop_a_string(env, NULL);

	/*
	 * Check for file in filesystem.  If it exists, we'll just try to do
	 * a do-dropin-file.
	 */
	if ((path = search_for_fcode_file(env, method)) != NULL) {
		push_a_string(env, path);
		load_file(env);
		return;
	}

	error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
	    fc_ptr2cell(method), &len);
	if (error || len == 0) {
		if (len == 0)
			debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n",
			    func_name, method);
		PUSH(DS, 0);
		return;
	}
	debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n",
	    func_name, method, (int)len);
	buf = MALLOC(len);
	error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1,
	    fc_ptr2cell(method), fc_ptr2cell(buf), len, &result);
	if (error) {
		FREE(buf);
		PUSH(DS, 0);
		return;
	}

	if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0)
		log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n",
		    func_name, method);

	debug_msg(DEBUG_FIND_FCODE, "%s: '%s' dropin Fcode: 0x%p/0x%x\n",
	    func_name, method, buf, (int)len);
	PUSH(DS, (fstack_t)buf);
	PUSH(DS, len);
}

#pragma init(_init)

static void
_init(void)
{
	extern void set_find_method_hook(fcode_env_t *,
	    void (*)(fcode_env_t *));
	fcode_env_t *env = initial_env;
	fstack_t d;

	ASSERT(env);
	NOTICE;

	set_find_method_hook(env, builtin_driver_method_hook);

	FORTH(0,	"install-package-nodes",	install_package_nodes);
	FORTH(0,	"find-builtin-driver",		find_builtin_driver);
	FORTH(0,	"exec-builtin-driver",		exec_builtin_driver);
	FORTH(0,	"builtin-driver-method-hook",
	    builtin_driver_method_hook);
	FORTH(0,	"do-builtin-dropin",		do_builtin_dropin);
	FORTH(0,	"do-builtin-file",		do_builtin_file);
}