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 (c) 2000 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <strings.h> 33 34 #include <fcode/private.h> 35 #include <fcode/log.h> 36 37 #include <fcdriver/fcdriver.h> 38 39 static device_t *builtin_driver_device; 40 41 static int 42 is_device_builtin_package(fcode_env_t *env, device_t *d) 43 { 44 return (d == builtin_driver_device); 45 } 46 47 static char *dropin_name; 48 49 /* 50 * do-builtin-dropin ( -- ) 51 * Convoluted name just in case someone has "do-dropin" word in Fcode. 52 * Somewhat different from do-dropin in OBP, as we just load the Fcode, we 53 * don't do a byte-load. 54 */ 55 static void 56 do_builtin_dropin(fcode_env_t *env) 57 { 58 fc_cell_t len, result; 59 char *buf; 60 int error; 61 static char func_name[] = "do-builtin-dropin"; 62 extern int check_fcode_header(char *, uchar_t *, int); 63 64 if (dropin_name == NULL) { 65 log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name); 66 return; 67 } 68 debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name); 69 error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1, 70 fc_ptr2cell(dropin_name), &len); 71 if (error) 72 return; 73 if (len == 0) { 74 log_message(MSG_WARN, "%s: '%s' zero length Fcode\n", 75 func_name, dropin_name); 76 return; 77 } 78 buf = MALLOC(len); 79 error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1, 80 fc_ptr2cell(dropin_name), fc_ptr2cell(buf), len, &result); 81 if (error) { 82 FREE(buf); 83 return; 84 } 85 86 if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0) 87 log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n", 88 func_name, dropin_name); 89 90 debug_msg(DEBUG_FIND_FCODE, 91 "%s: '%s' doing byte-load len: %x\n", func_name, dropin_name, 92 (int)len); 93 PUSH(DS, (fstack_t)buf); 94 PUSH(DS, 1); 95 byte_load(env); 96 } 97 98 static void 99 do_builtin_file(fcode_env_t *env) 100 { 101 char *fname; 102 static char func_name[] = "do-builtin-file"; 103 fstack_t d; 104 105 if (dropin_name == NULL) { 106 log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name); 107 return; 108 } 109 debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name); 110 push_a_string(env, dropin_name); 111 load_file(env); 112 d = POP(DS); 113 if (d) { 114 debug_msg(DEBUG_FIND_FCODE, "%s: byte-load '%s'\n", func_name, 115 dropin_name); 116 PUSH(DS, 1); 117 byte_load(env); 118 } else 119 debug_msg(DEBUG_FIND_FCODE, "%s: load_file '%s' FAIL\n", 120 func_name, dropin_name); 121 } 122 123 /* 124 * We need to lookup the builtin name via an FC_RUN_PRIV call to make sure 125 * the builtin exists. If it exists, then we need to leave the xt of 126 * do-builtin-dropin on the stack and remember the name for do-dropin. This is 127 * extremely convoluted because we can't a priori populate 128 * SUNW,builtin-drivers. 129 */ 130 static void 131 builtin_driver_method_hook(fcode_env_t *env) 132 { 133 device_t *device; 134 char *method, *path; 135 fc_cell_t len; 136 fstack_t d; 137 int error; 138 static char func_name[] = "builtin-driver-method-hook"; 139 140 d = POP(DS); 141 CONVERT_PHANDLE(env, device, d); 142 if (!is_device_builtin_package(env, device)) { 143 PUSH(DS, d); 144 PUSH(DS, FALSE); 145 return; 146 } 147 148 method = pop_a_string(env, NULL); 149 150 /* 151 * Check for file in filesystem. If it exists, we'll just try to do 152 * a do-dropin-file. 153 */ 154 if ((path = search_for_fcode_file(env, method)) != NULL) { 155 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' file: '%s'\n", func_name, 156 method, path); 157 if (dropin_name) { 158 FREE(dropin_name); 159 } 160 dropin_name = STRDUP(path); 161 push_a_string(env, "do-builtin-file"); 162 dollar_find(env); 163 return; 164 } 165 166 error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1, 167 fc_ptr2cell(method), &len); 168 if (error || len == 0) { 169 if (len == 0) 170 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n", 171 func_name, method); 172 push_a_string(env, method); 173 PUSH(DS, d); 174 PUSH(DS, FALSE); 175 } else { 176 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n", 177 func_name, method, (int)len); 178 if (dropin_name) { 179 FREE(dropin_name); 180 } 181 dropin_name = STRDUP(method); 182 push_a_string(env, "do-builtin-dropin"); 183 dollar_find(env); 184 } 185 } 186 187 void 188 make_a_node(fcode_env_t *env, char *name, int finish) 189 { 190 new_device(env); 191 push_a_string(env, name); 192 device_name(env); 193 if (finish) 194 finish_device(env); 195 } 196 197 void 198 install_package_nodes(fcode_env_t *env) 199 { 200 MYSELF = open_instance_chain(env, env->root_node, 0); 201 if (MYSELF != NULL) { 202 make_a_node(env, "packages", 0); 203 make_a_node(env, "disk-label", 0); 204 finish_device(env); 205 make_a_node(env, "SUNW,builtin-drivers", 0); 206 builtin_driver_device = env->current_device; 207 finish_device(env); 208 finish_device(env); 209 close_instance_chain(env, MYSELF, 0); 210 device_end(env); 211 MYSELF = 0; 212 } 213 } 214 215 /* 216 * find-builtin-driver ( str len -- xt true | false ) 217 */ 218 void 219 find_builtin_driver(fcode_env_t *env) 220 { 221 fstack_t d; 222 223 CHECK_DEPTH(env, 2, "find-builtin-driver"); 224 push_a_string(env, "SUNW,builtin-drivers"); 225 find_package(env); 226 d = POP(DS); 227 if (d) { 228 find_method(env); 229 } else { 230 two_drop(env); 231 PUSH(DS, FALSE); 232 } 233 } 234 235 void 236 exec_builtin_driver(fcode_env_t *env) 237 { 238 fstack_t d; 239 char *method, *path, *buf; 240 fc_cell_t len, result; 241 int error; 242 static char func_name[] = "exec-builtin-driver"; 243 extern int check_fcode_header(char *, uchar_t *, int); 244 245 CHECK_DEPTH(env, 2, func_name); 246 method = pop_a_string(env, NULL); 247 248 /* 249 * Check for file in filesystem. If it exists, we'll just try to do 250 * a do-dropin-file. 251 */ 252 if ((path = search_for_fcode_file(env, method)) != NULL) { 253 push_a_string(env, path); 254 load_file(env); 255 return; 256 } 257 258 error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1, 259 fc_ptr2cell(method), &len); 260 if (error || len == 0) { 261 if (len == 0) 262 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n", 263 func_name, method); 264 PUSH(DS, 0); 265 return; 266 } 267 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n", 268 func_name, method, (int)len); 269 buf = MALLOC(len); 270 error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1, 271 fc_ptr2cell(method), fc_ptr2cell(buf), len, &result); 272 if (error) { 273 FREE(buf); 274 PUSH(DS, 0); 275 return; 276 } 277 278 if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0) 279 log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n", 280 func_name, method); 281 282 debug_msg(DEBUG_FIND_FCODE, "%s: '%s' dropin Fcode: 0x%p/0x%x\n", 283 func_name, method, buf, (int)len); 284 PUSH(DS, (fstack_t)buf); 285 PUSH(DS, len); 286 } 287 288 #pragma init(_init) 289 290 static void 291 _init(void) 292 { 293 extern void set_find_method_hook(fcode_env_t *, 294 void (*)(fcode_env_t *)); 295 fcode_env_t *env = initial_env; 296 fstack_t d; 297 298 ASSERT(env); 299 NOTICE; 300 301 set_find_method_hook(env, builtin_driver_method_hook); 302 303 FORTH(0, "install-package-nodes", install_package_nodes); 304 FORTH(0, "find-builtin-driver", find_builtin_driver); 305 FORTH(0, "exec-builtin-driver", exec_builtin_driver); 306 FORTH(0, "builtin-driver-method-hook", 307 builtin_driver_method_hook); 308 FORTH(0, "do-builtin-dropin", do_builtin_dropin); 309 FORTH(0, "do-builtin-file", do_builtin_file); 310 } 311