2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License, Version 1.0 only
2N/A * (the "License"). You may not use this file except in compliance
2N/A * with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2000 by Sun Microsystems, Inc.
2N/A * All rights reserved.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <unistd.h>
2N/A#include <strings.h>
2N/A
2N/A#include <fcode/private.h>
2N/A#include <fcode/log.h>
2N/A
2N/A#include <fcdriver/fcdriver.h>
2N/A
2N/Astatic device_t *builtin_driver_device;
2N/A
2N/Astatic int
2N/Ais_device_builtin_package(fcode_env_t *env, device_t *d)
2N/A{
2N/A return (d == builtin_driver_device);
2N/A}
2N/A
2N/Astatic char *dropin_name;
2N/A
2N/A/*
2N/A * do-builtin-dropin ( -- )
2N/A * Convoluted name just in case someone has "do-dropin" word in Fcode.
2N/A * Somewhat different from do-dropin in OBP, as we just load the Fcode, we
2N/A * don't do a byte-load.
2N/A */
2N/Astatic void
2N/Ado_builtin_dropin(fcode_env_t *env)
2N/A{
2N/A fc_cell_t len, result;
2N/A char *buf;
2N/A int error;
2N/A static char func_name[] = "do-builtin-dropin";
2N/A extern int check_fcode_header(char *, uchar_t *, int);
2N/A
2N/A if (dropin_name == NULL) {
2N/A log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name);
2N/A return;
2N/A }
2N/A debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name);
2N/A error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
2N/A fc_ptr2cell(dropin_name), &len);
2N/A if (error)
2N/A return;
2N/A if (len == 0) {
2N/A log_message(MSG_WARN, "%s: '%s' zero length Fcode\n",
2N/A func_name, dropin_name);
2N/A return;
2N/A }
2N/A buf = MALLOC(len);
2N/A error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1,
2N/A fc_ptr2cell(dropin_name), fc_ptr2cell(buf), len, &result);
2N/A if (error) {
2N/A FREE(buf);
2N/A return;
2N/A }
2N/A
2N/A if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0)
2N/A log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n",
2N/A func_name, dropin_name);
2N/A
2N/A debug_msg(DEBUG_FIND_FCODE,
2N/A "%s: '%s' doing byte-load len: %x\n", func_name, dropin_name,
2N/A (int)len);
2N/A PUSH(DS, (fstack_t)buf);
2N/A PUSH(DS, 1);
2N/A byte_load(env);
2N/A}
2N/A
2N/Astatic void
2N/Ado_builtin_file(fcode_env_t *env)
2N/A{
2N/A char *fname;
2N/A static char func_name[] = "do-builtin-file";
2N/A fstack_t d;
2N/A
2N/A if (dropin_name == NULL) {
2N/A log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name);
2N/A return;
2N/A }
2N/A debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name);
2N/A push_a_string(env, dropin_name);
2N/A load_file(env);
2N/A d = POP(DS);
2N/A if (d) {
2N/A debug_msg(DEBUG_FIND_FCODE, "%s: byte-load '%s'\n", func_name,
2N/A dropin_name);
2N/A PUSH(DS, 1);
2N/A byte_load(env);
2N/A } else
2N/A debug_msg(DEBUG_FIND_FCODE, "%s: load_file '%s' FAIL\n",
2N/A func_name, dropin_name);
2N/A}
2N/A
2N/A/*
2N/A * We need to lookup the builtin name via an FC_RUN_PRIV call to make sure
2N/A * the builtin exists. If it exists, then we need to leave the xt of
2N/A * do-builtin-dropin on the stack and remember the name for do-dropin. This is
2N/A * extremely convoluted because we can't a priori populate
2N/A * SUNW,builtin-drivers.
2N/A */
2N/Astatic void
2N/Abuiltin_driver_method_hook(fcode_env_t *env)
2N/A{
2N/A device_t *device;
2N/A char *method, *path;
2N/A fc_cell_t len;
2N/A fstack_t d;
2N/A int error;
2N/A static char func_name[] = "builtin-driver-method-hook";
2N/A
2N/A d = POP(DS);
2N/A CONVERT_PHANDLE(env, device, d);
2N/A if (!is_device_builtin_package(env, device)) {
2N/A PUSH(DS, d);
2N/A PUSH(DS, FALSE);
2N/A return;
2N/A }
2N/A
2N/A method = pop_a_string(env, NULL);
2N/A
2N/A /*
2N/A * Check for file in filesystem. If it exists, we'll just try to do
2N/A * a do-dropin-file.
2N/A */
2N/A if ((path = search_for_fcode_file(env, method)) != NULL) {
2N/A debug_msg(DEBUG_FIND_FCODE, "%s: '%s' file: '%s'\n", func_name,
2N/A method, path);
2N/A if (dropin_name) {
2N/A FREE(dropin_name);
2N/A }
2N/A dropin_name = STRDUP(path);
2N/A push_a_string(env, "do-builtin-file");
2N/A dollar_find(env);
2N/A return;
2N/A }
2N/A
2N/A error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
2N/A fc_ptr2cell(method), &len);
2N/A if (error || len == 0) {
2N/A if (len == 0)
2N/A debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n",
2N/A func_name, method);
2N/A push_a_string(env, method);
2N/A PUSH(DS, d);
2N/A PUSH(DS, FALSE);
2N/A } else {
2N/A debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n",
2N/A func_name, method, (int)len);
2N/A if (dropin_name) {
2N/A FREE(dropin_name);
2N/A }
2N/A dropin_name = STRDUP(method);
2N/A push_a_string(env, "do-builtin-dropin");
2N/A dollar_find(env);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Amake_a_node(fcode_env_t *env, char *name, int finish)
2N/A{
2N/A new_device(env);
2N/A push_a_string(env, name);
2N/A device_name(env);
2N/A if (finish)
2N/A finish_device(env);
2N/A}
2N/A
2N/Avoid
2N/Ainstall_package_nodes(fcode_env_t *env)
2N/A{
2N/A MYSELF = open_instance_chain(env, env->root_node, 0);
2N/A if (MYSELF != NULL) {
2N/A make_a_node(env, "packages", 0);
2N/A make_a_node(env, "disk-label", 0);
2N/A finish_device(env);
2N/A make_a_node(env, "SUNW,builtin-drivers", 0);
2N/A builtin_driver_device = env->current_device;
2N/A finish_device(env);
2N/A finish_device(env);
2N/A close_instance_chain(env, MYSELF, 0);
2N/A device_end(env);
2N/A MYSELF = 0;
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * find-builtin-driver ( str len -- xt true | false )
2N/A */
2N/Avoid
2N/Afind_builtin_driver(fcode_env_t *env)
2N/A{
2N/A fstack_t d;
2N/A
2N/A CHECK_DEPTH(env, 2, "find-builtin-driver");
2N/A push_a_string(env, "SUNW,builtin-drivers");
2N/A find_package(env);
2N/A d = POP(DS);
2N/A if (d) {
2N/A find_method(env);
2N/A } else {
2N/A two_drop(env);
2N/A PUSH(DS, FALSE);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Aexec_builtin_driver(fcode_env_t *env)
2N/A{
2N/A fstack_t d;
2N/A char *method, *path, *buf;
2N/A fc_cell_t len, result;
2N/A int error;
2N/A static char func_name[] = "exec-builtin-driver";
2N/A extern int check_fcode_header(char *, uchar_t *, int);
2N/A
2N/A CHECK_DEPTH(env, 2, func_name);
2N/A method = pop_a_string(env, NULL);
2N/A
2N/A /*
2N/A * Check for file in filesystem. If it exists, we'll just try to do
2N/A * a do-dropin-file.
2N/A */
2N/A if ((path = search_for_fcode_file(env, method)) != NULL) {
2N/A push_a_string(env, path);
2N/A load_file(env);
2N/A return;
2N/A }
2N/A
2N/A error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
2N/A fc_ptr2cell(method), &len);
2N/A if (error || len == 0) {
2N/A if (len == 0)
2N/A debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n",
2N/A func_name, method);
2N/A PUSH(DS, 0);
2N/A return;
2N/A }
2N/A debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n",
2N/A func_name, method, (int)len);
2N/A buf = MALLOC(len);
2N/A error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1,
2N/A fc_ptr2cell(method), fc_ptr2cell(buf), len, &result);
2N/A if (error) {
2N/A FREE(buf);
2N/A PUSH(DS, 0);
2N/A return;
2N/A }
2N/A
2N/A if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0)
2N/A log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n",
2N/A func_name, method);
2N/A
2N/A debug_msg(DEBUG_FIND_FCODE, "%s: '%s' dropin Fcode: 0x%p/0x%x\n",
2N/A func_name, method, buf, (int)len);
2N/A PUSH(DS, (fstack_t)buf);
2N/A PUSH(DS, len);
2N/A}
2N/A
2N/A#pragma init(_init)
2N/A
2N/Astatic void
2N/A_init(void)
2N/A{
2N/A extern void set_find_method_hook(fcode_env_t *,
2N/A void (*)(fcode_env_t *));
2N/A fcode_env_t *env = initial_env;
2N/A fstack_t d;
2N/A
2N/A ASSERT(env);
2N/A NOTICE;
2N/A
2N/A set_find_method_hook(env, builtin_driver_method_hook);
2N/A
2N/A FORTH(0, "install-package-nodes", install_package_nodes);
2N/A FORTH(0, "find-builtin-driver", find_builtin_driver);
2N/A FORTH(0, "exec-builtin-driver", exec_builtin_driver);
2N/A FORTH(0, "builtin-driver-method-hook",
2N/A builtin_driver_method_hook);
2N/A FORTH(0, "do-builtin-dropin", do_builtin_dropin);
2N/A FORTH(0, "do-builtin-file", do_builtin_file);
2N/A}