loader.c revision 82941
1/*- 2 * Copyright (c) 2000 Daniel Capo Sobral 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/boot/ficl/loader.c 82941 2001-09-04 08:51:15Z dfr $ 27 */ 28 29/******************************************************************* 30** l o a d e r . c 31** Additional FICL words designed for FreeBSD's loader 32** 33*******************************************************************/ 34 35#include <stand.h> 36#include "bootstrap.h" 37#include <string.h> 38#include "ficl.h" 39 40/* FreeBSD's loader interaction words and extras 41 * 42 * setenv ( value n name n' -- ) 43 * setenv? ( value n name n' flag -- ) 44 * getenv ( addr n -- addr' n' | -1 ) 45 * unsetenv ( addr n -- ) 46 * copyin ( addr addr' len -- ) 47 * copyout ( addr addr' len -- ) 48 * findfile ( name len type len' -- addr ) 49 * pnpdevices ( -- addr ) 50 * pnphandlers ( -- addr ) 51 * ccall ( [[...[p10] p9] ... p1] n addr -- result ) 52 * .# ( value -- ) 53 */ 54 55#ifndef TESTMAIN 56void 57ficlSetenv(FICL_VM *pVM) 58{ 59 char *namep, *valuep, *name, *value; 60 int names, values; 61 62#if FICL_ROBUST > 1 63 vmCheckStack(pVM, 4, 0); 64#endif 65 names = stackPopINT(pVM->pStack); 66 namep = (char*) stackPopPtr(pVM->pStack); 67 values = stackPopINT(pVM->pStack); 68 valuep = (char*) stackPopPtr(pVM->pStack); 69 70 name = (char*) ficlMalloc(names+1); 71 if (!name) 72 vmThrowErr(pVM, "Error: out of memory"); 73 strncpy(name, namep, names); 74 name[names] = '\0'; 75 value = (char*) ficlMalloc(values+1); 76 if (!value) 77 vmThrowErr(pVM, "Error: out of memory"); 78 strncpy(value, valuep, values); 79 value[values] = '\0'; 80 81 setenv(name, value, 1); 82 ficlFree(name); 83 ficlFree(value); 84 85 return; 86} 87 88void 89ficlSetenvq(FICL_VM *pVM) 90{ 91 char *namep, *valuep, *name, *value; 92 int names, values, overwrite; 93 94#if FICL_ROBUST > 1 95 vmCheckStack(pVM, 5, 0); 96#endif 97 overwrite = stackPopINT(pVM->pStack); 98 names = stackPopINT(pVM->pStack); 99 namep = (char*) stackPopPtr(pVM->pStack); 100 values = stackPopINT(pVM->pStack); 101 valuep = (char*) stackPopPtr(pVM->pStack); 102 103 name = (char*) ficlMalloc(names+1); 104 if (!name) 105 vmThrowErr(pVM, "Error: out of memory"); 106 strncpy(name, namep, names); 107 name[names] = '\0'; 108 value = (char*) ficlMalloc(values+1); 109 if (!value) 110 vmThrowErr(pVM, "Error: out of memory"); 111 strncpy(value, valuep, values); 112 value[values] = '\0'; 113 114 setenv(name, value, overwrite); 115 ficlFree(name); 116 ficlFree(value); 117 118 return; 119} 120 121void 122ficlGetenv(FICL_VM *pVM) 123{ 124 char *namep, *name, *value; 125 int names; 126 127#if FICL_ROBUST > 1 128 vmCheckStack(pVM, 2, 2); 129#endif 130 names = stackPopINT(pVM->pStack); 131 namep = (char*) stackPopPtr(pVM->pStack); 132 133 name = (char*) ficlMalloc(names+1); 134 if (!name) 135 vmThrowErr(pVM, "Error: out of memory"); 136 strncpy(name, namep, names); 137 name[names] = '\0'; 138 139 value = getenv(name); 140 ficlFree(name); 141 142 if(value != NULL) { 143 stackPushPtr(pVM->pStack, value); 144 stackPushINT(pVM->pStack, strlen(value)); 145 } else 146 stackPushINT(pVM->pStack, -1); 147 148 return; 149} 150 151void 152ficlUnsetenv(FICL_VM *pVM) 153{ 154 char *namep, *name; 155 int names; 156 157#if FICL_ROBUST > 1 158 vmCheckStack(pVM, 2, 0); 159#endif 160 names = stackPopINT(pVM->pStack); 161 namep = (char*) stackPopPtr(pVM->pStack); 162 163 name = (char*) ficlMalloc(names+1); 164 if (!name) 165 vmThrowErr(pVM, "Error: out of memory"); 166 strncpy(name, namep, names); 167 name[names] = '\0'; 168 169 unsetenv(name); 170 ficlFree(name); 171 172 return; 173} 174 175void 176ficlCopyin(FICL_VM *pVM) 177{ 178 void* src; 179 vm_offset_t dest; 180 size_t len; 181 182#if FICL_ROBUST > 1 183 vmCheckStack(pVM, 3, 0); 184#endif 185 186 len = stackPopINT(pVM->pStack); 187 dest = stackPopINT(pVM->pStack); 188 src = stackPopPtr(pVM->pStack); 189 190 archsw.arch_copyin(src, dest, len); 191 192 return; 193} 194 195void 196ficlCopyout(FICL_VM *pVM) 197{ 198 void* dest; 199 vm_offset_t src; 200 size_t len; 201 202#if FICL_ROBUST > 1 203 vmCheckStack(pVM, 3, 0); 204#endif 205 206 len = stackPopINT(pVM->pStack); 207 dest = stackPopPtr(pVM->pStack); 208 src = stackPopINT(pVM->pStack); 209 210 archsw.arch_copyout(src, dest, len); 211 212 return; 213} 214 215void 216ficlFindfile(FICL_VM *pVM) 217{ 218 char *name, *type, *namep, *typep; 219 struct preloaded_file* fp; 220 int names, types; 221 222#if FICL_ROBUST > 1 223 vmCheckStack(pVM, 4, 1); 224#endif 225 226 types = stackPopINT(pVM->pStack); 227 typep = (char*) stackPopPtr(pVM->pStack); 228 names = stackPopINT(pVM->pStack); 229 namep = (char*) stackPopPtr(pVM->pStack); 230 name = (char*) ficlMalloc(names+1); 231 if (!name) 232 vmThrowErr(pVM, "Error: out of memory"); 233 strncpy(name, namep, names); 234 name[names] = '\0'; 235 type = (char*) ficlMalloc(types+1); 236 if (!type) 237 vmThrowErr(pVM, "Error: out of memory"); 238 strncpy(type, typep, types); 239 type[types] = '\0'; 240 241 fp = file_findfile(name, type); 242 stackPushPtr(pVM->pStack, fp); 243 244 return; 245} 246 247#ifdef HAVE_PNP 248 249void 250ficlPnpdevices(FICL_VM *pVM) 251{ 252 static int pnp_devices_initted = 0; 253#if FICL_ROBUST > 1 254 vmCheckStack(pVM, 0, 1); 255#endif 256 257 if(!pnp_devices_initted) { 258 STAILQ_INIT(&pnp_devices); 259 pnp_devices_initted = 1; 260 } 261 262 stackPushPtr(pVM->pStack, &pnp_devices); 263 264 return; 265} 266 267void 268ficlPnphandlers(FICL_VM *pVM) 269{ 270#if FICL_ROBUST > 1 271 vmCheckStack(pVM, 0, 1); 272#endif 273 274 stackPushPtr(pVM->pStack, pnphandlers); 275 276 return; 277} 278 279#endif 280 281#endif /* ndef TESTMAIN */ 282 283void 284ficlCcall(FICL_VM *pVM) 285{ 286 int (*func)(int, ...); 287 int result, p[10]; 288 int nparam, i; 289 290#if FICL_ROBUST > 1 291 vmCheckStack(pVM, 2, 0); 292#endif 293 294 func = stackPopPtr(pVM->pStack); 295 nparam = stackPopINT(pVM->pStack); 296 297#if FICL_ROBUST > 1 298 vmCheckStack(pVM, nparam, 1); 299#endif 300 301 for (i = 0; i < nparam; i++) 302 p[i] = stackPopINT(pVM->pStack); 303 304 result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], 305 p[9]); 306 307 stackPushINT(pVM->pStack, result); 308 309 return; 310} 311 312/************************************************************************** 313 f i c l E x e c F D 314** reads in text from file fd and passes it to ficlExec() 315 * returns VM_OUTOFTEXT on success or the ficlExec() error code on 316 * failure. 317 */ 318#define nLINEBUF 256 319int ficlExecFD(FICL_VM *pVM, int fd) 320{ 321 char cp[nLINEBUF]; 322 int nLine = 0, rval = VM_OUTOFTEXT; 323 char ch; 324 CELL id; 325 326 id = pVM->sourceID; 327 pVM->sourceID.i = fd; 328 329 /* feed each line to ficlExec */ 330 while (1) { 331 int status, i; 332 333 i = 0; 334 while ((status = read(fd, &ch, 1)) > 0 && ch != '\n') 335 cp[i++] = ch; 336 nLine++; 337 if (!i) { 338 if (status < 1) 339 break; 340 continue; 341 } 342 rval = ficlExecC(pVM, cp, i); 343 if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT) 344 { 345 pVM->sourceID = id; 346 return rval; 347 } 348 } 349 /* 350 ** Pass an empty line with SOURCE-ID == -1 to flush 351 ** any pending REFILLs (as required by FILE wordset) 352 */ 353 pVM->sourceID.i = -1; 354 ficlExec(pVM, ""); 355 356 pVM->sourceID = id; 357 return rval; 358} 359 360static void displayCellNoPad(FICL_VM *pVM) 361{ 362 CELL c; 363#if FICL_ROBUST > 1 364 vmCheckStack(pVM, 1, 0); 365#endif 366 c = stackPop(pVM->pStack); 367 ltoa((c).i, pVM->pad, pVM->base); 368 vmTextOut(pVM, pVM->pad, 0); 369 return; 370} 371 372/* fopen - open a file and return new fd on stack. 373 * 374 * fopen ( count ptr -- fd ) 375 */ 376static void pfopen(FICL_VM *pVM) 377{ 378 int fd; 379 char *p; 380 381#if FICL_ROBUST > 1 382 vmCheckStack(pVM, 2, 1); 383#endif 384 (void)stackPopINT(pVM->pStack); /* don't need count value */ 385 p = stackPopPtr(pVM->pStack); 386 fd = open(p, O_RDONLY); 387 stackPushINT(pVM->pStack, fd); 388 return; 389 } 390 391/* fclose - close a file who's fd is on stack. 392 * 393 * fclose ( fd -- ) 394 */ 395static void pfclose(FICL_VM *pVM) 396{ 397 int fd; 398 399#if FICL_ROBUST > 1 400 vmCheckStack(pVM, 1, 0); 401#endif 402 fd = stackPopINT(pVM->pStack); /* get fd */ 403 if (fd != -1) 404 close(fd); 405 return; 406} 407 408/* fread - read file contents 409 * 410 * fread ( fd buf nbytes -- nread ) 411 */ 412static void pfread(FICL_VM *pVM) 413{ 414 int fd, len; 415 char *buf; 416 417#if FICL_ROBUST > 1 418 vmCheckStack(pVM, 3, 1); 419#endif 420 len = stackPopINT(pVM->pStack); /* get number of bytes to read */ 421 buf = stackPopPtr(pVM->pStack); /* get buffer */ 422 fd = stackPopINT(pVM->pStack); /* get fd */ 423 if (len > 0 && buf && fd != -1) 424 stackPushINT(pVM->pStack, read(fd, buf, len)); 425 else 426 stackPushINT(pVM->pStack, -1); 427 return; 428} 429 430/* fload - interpret file contents 431 * 432 * fload ( fd -- ) 433 */ 434static void pfload(FICL_VM *pVM) 435{ 436 int fd; 437 438#if FICL_ROBUST > 1 439 vmCheckStack(pVM, 1, 0); 440#endif 441 fd = stackPopINT(pVM->pStack); /* get fd */ 442 if (fd != -1) 443 ficlExecFD(pVM, fd); 444 return; 445} 446 447/* key - get a character from stdin 448 * 449 * key ( -- char ) 450 */ 451static void key(FICL_VM *pVM) 452{ 453#if FICL_ROBUST > 1 454 vmCheckStack(pVM, 0, 1); 455#endif 456 stackPushINT(pVM->pStack, getchar()); 457 return; 458} 459 460/* key? - check for a character from stdin (FACILITY) 461 * 462 * key? ( -- flag ) 463 */ 464static void keyQuestion(FICL_VM *pVM) 465{ 466#if FICL_ROBUST > 1 467 vmCheckStack(pVM, 0, 1); 468#endif 469#ifdef TESTMAIN 470 /* XXX Since we don't fiddle with termios, let it always succeed... */ 471 stackPushINT(pVM->pStack, FICL_TRUE); 472#else 473 /* But here do the right thing. */ 474 stackPushINT(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE); 475#endif 476 return; 477} 478 479/* seconds - gives number of seconds since beginning of time 480 * 481 * beginning of time is defined as: 482 * 483 * BTX - number of seconds since midnight 484 * FreeBSD - number of seconds since Jan 1 1970 485 * 486 * seconds ( -- u ) 487 */ 488static void pseconds(FICL_VM *pVM) 489{ 490#if FICL_ROBUST > 1 491 vmCheckStack(pVM,0,1); 492#endif 493 stackPushUNS(pVM->pStack, (FICL_UNS) time(NULL)); 494 return; 495} 496 497/* ms - wait at least that many milliseconds (FACILITY) 498 * 499 * ms ( u -- ) 500 * 501 */ 502static void ms(FICL_VM *pVM) 503{ 504#if FICL_ROBUST > 1 505 vmCheckStack(pVM,1,0); 506#endif 507#ifdef TESTMAIN 508 usleep(stackPopUNS(pVM->pStack)*1000); 509#else 510 delay(stackPopUNS(pVM->pStack)*1000); 511#endif 512 return; 513} 514 515/* fkey - get a character from a file 516 * 517 * fkey ( file -- char ) 518 */ 519static void fkey(FICL_VM *pVM) 520{ 521 int i, fd; 522 char ch; 523 524#if FICL_ROBUST > 1 525 vmCheckStack(pVM, 1, 1); 526#endif 527 fd = stackPopINT(pVM->pStack); 528 i = read(fd, &ch, 1); 529 stackPushINT(pVM->pStack, i > 0 ? ch : -1); 530 return; 531} 532 533/* 534** Retrieves free space remaining on the dictionary 535*/ 536 537static void freeHeap(FICL_VM *pVM) 538{ 539 stackPushINT(pVM->pStack, dictCellsAvail(ficlGetDict())); 540} 541 542 543/******************* Increase dictionary size on-demand ******************/ 544 545static void ficlDictThreshold(FICL_VM *pVM) 546{ 547 stackPushPtr(pVM->pStack, &dictThreshold); 548} 549 550static void ficlDictIncrease(FICL_VM *pVM) 551{ 552 stackPushPtr(pVM->pStack, &dictIncrease); 553} 554 555 556/************************************************************************** 557 f i c l C o m p i l e P l a t f o r m 558** Build FreeBSD platform extensions into the system dictionary 559**************************************************************************/ 560void ficlCompilePlatform(FICL_SYSTEM *pSys) 561{ 562 FICL_DICT *dp = pSys->dp; 563 assert (dp); 564 565 dictAppendWord(dp, ".#", displayCellNoPad, FW_DEFAULT); 566 dictAppendWord(dp, "fopen", pfopen, FW_DEFAULT); 567 dictAppendWord(dp, "fclose", pfclose, FW_DEFAULT); 568 dictAppendWord(dp, "fread", pfread, FW_DEFAULT); 569 dictAppendWord(dp, "fload", pfload, FW_DEFAULT); 570 dictAppendWord(dp, "fkey", fkey, FW_DEFAULT); 571 dictAppendWord(dp, "key", key, FW_DEFAULT); 572 dictAppendWord(dp, "key?", keyQuestion, FW_DEFAULT); 573 dictAppendWord(dp, "ms", ms, FW_DEFAULT); 574 dictAppendWord(dp, "seconds", pseconds, FW_DEFAULT); 575 dictAppendWord(dp, "heap?", freeHeap, FW_DEFAULT); 576 dictAppendWord(dp, "dictthreshold", ficlDictThreshold, FW_DEFAULT); 577 dictAppendWord(dp, "dictincrease", ficlDictIncrease, FW_DEFAULT); 578 579#ifndef TESTMAIN 580#ifdef __i386__ 581 dictAppendWord(dp, "outb", ficlOutb, FW_DEFAULT); 582 dictAppendWord(dp, "inb", ficlInb, FW_DEFAULT); 583#endif 584 dictAppendWord(dp, "setenv", ficlSetenv, FW_DEFAULT); 585 dictAppendWord(dp, "setenv?", ficlSetenvq, FW_DEFAULT); 586 dictAppendWord(dp, "getenv", ficlGetenv, FW_DEFAULT); 587 dictAppendWord(dp, "unsetenv", ficlUnsetenv, FW_DEFAULT); 588 dictAppendWord(dp, "copyin", ficlCopyin, FW_DEFAULT); 589 dictAppendWord(dp, "copyout", ficlCopyout, FW_DEFAULT); 590 dictAppendWord(dp, "findfile", ficlFindfile, FW_DEFAULT); 591#ifdef HAVE_PNP 592 dictAppendWord(dp, "pnpdevices",ficlPnpdevices, FW_DEFAULT); 593 dictAppendWord(dp, "pnphandlers",ficlPnphandlers, FW_DEFAULT); 594#endif 595 dictAppendWord(dp, "ccall", ficlCcall, FW_DEFAULT); 596#endif 597 598#if defined(__i386__) 599 ficlSetEnv("arch-i386", FICL_TRUE); 600 ficlSetEnv("arch-alpha", FICL_FALSE); 601 ficlSetEnv("arch-ia64", FICL_FALSE); 602#elif defined(__alpha__) 603 ficlSetEnv("arch-i386", FICL_FALSE); 604 ficlSetEnv("arch-alpha", FICL_TRUE); 605 ficlSetEnv("arch-ia64", FICL_FALSE); 606#elif defined(__ia64__) 607 ficlSetEnv("arch-i386", FICL_FALSE); 608 ficlSetEnv("arch-alpha", FICL_FALSE); 609 ficlSetEnv("arch-ia64", FICL_TRUE); 610#endif 611 612 return; 613} 614 615