/* * 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 #include #include #include #include #include #include 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); }