diff options
Diffstat (limited to 'usr/src/lib/efcode/packages/populate.c')
-rw-r--r-- | usr/src/lib/efcode/packages/populate.c | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/usr/src/lib/efcode/packages/populate.c b/usr/src/lib/efcode/packages/populate.c new file mode 100644 index 0000000000..6d9cc7501e --- /dev/null +++ b/usr/src/lib/efcode/packages/populate.c @@ -0,0 +1,310 @@ +/* + * 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); +} |