2 * Copyright (c) 2000 Daniel Capo Sobral
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * $FreeBSD: src/sys/boot/ficl/loader.c,v 1.12 2006/05/12 04:07:42 jhb Exp $
27 * $DragonFly: src/sys/boot/ficl/loader.c,v 1.7 2008/09/02 17:21:14 dillon Exp $
30 /*******************************************************************
32 ** Additional FICL words designed for FreeBSD's loader
34 *******************************************************************/
41 #include "bootstrap.h"
45 /* FreeBSD's loader interaction words and extras
47 * setenv ( value n name n' -- )
48 * setenv? ( value n name n' flag -- )
49 * getenv ( addr n -- addr' n' | -1 )
50 * unsetenv ( addr n -- )
51 * copyin ( addr addr' len -- )
52 * copyout ( addr addr' len -- )
53 * findfile ( name len type len' -- addr )
54 * pnpdevices ( -- addr )
55 * pnphandlers ( -- addr )
56 * ccall ( [[...[p10] p9] ... p1] n addr -- result )
61 ficlSetenv(FICL_VM *pVM)
70 vmCheckStack(pVM, 4, 0);
72 names = stackPopINT(pVM->pStack);
73 namep = (char*) stackPopPtr(pVM->pStack);
74 values = stackPopINT(pVM->pStack);
75 valuep = (char*) stackPopPtr(pVM->pStack);
78 name = (char*) ficlMalloc(names+1);
80 vmThrowErr(pVM, "Error: out of memory");
81 strncpy(name, namep, names);
83 value = (char*) ficlMalloc(values+1);
85 vmThrowErr(pVM, "Error: out of memory");
86 strncpy(value, valuep, values);
89 setenv(name, value, 1);
98 ficlSetenvq(FICL_VM *pVM)
103 char *namep, *valuep;
104 int names, values, overwrite;
107 vmCheckStack(pVM, 5, 0);
109 overwrite = stackPopINT(pVM->pStack);
110 names = stackPopINT(pVM->pStack);
111 namep = (char*) stackPopPtr(pVM->pStack);
112 values = stackPopINT(pVM->pStack);
113 valuep = (char*) stackPopPtr(pVM->pStack);
116 name = (char*) ficlMalloc(names+1);
118 vmThrowErr(pVM, "Error: out of memory");
119 strncpy(name, namep, names);
121 value = (char*) ficlMalloc(values+1);
123 vmThrowErr(pVM, "Error: out of memory");
124 strncpy(value, valuep, values);
125 value[values] = '\0';
127 setenv(name, value, overwrite);
136 ficlGetenv(FICL_VM *pVM)
145 vmCheckStack(pVM, 2, 2);
147 names = stackPopINT(pVM->pStack);
148 namep = (char*) stackPopPtr(pVM->pStack);
151 name = (char*) ficlMalloc(names+1);
153 vmThrowErr(pVM, "Error: out of memory");
154 strncpy(name, namep, names);
157 value = getenv(name);
161 stackPushPtr(pVM->pStack, value);
162 stackPushINT(pVM->pStack, strlen(value));
165 stackPushINT(pVM->pStack, -1);
171 ficlUnsetenv(FICL_VM *pVM)
180 vmCheckStack(pVM, 2, 0);
182 names = stackPopINT(pVM->pStack);
183 namep = (char*) stackPopPtr(pVM->pStack);
186 name = (char*) ficlMalloc(names+1);
188 vmThrowErr(pVM, "Error: out of memory");
189 strncpy(name, namep, names);
200 ficlCopyin(FICL_VM *pVM)
207 vmCheckStack(pVM, 3, 0);
210 len = stackPopINT(pVM->pStack);
211 dest = stackPopINT(pVM->pStack);
212 src = stackPopPtr(pVM->pStack);
215 archsw.arch_copyin(src, dest, len);
222 ficlCopyout(FICL_VM *pVM)
229 vmCheckStack(pVM, 3, 0);
232 len = stackPopINT(pVM->pStack);
233 dest = stackPopPtr(pVM->pStack);
234 src = stackPopINT(pVM->pStack);
237 archsw.arch_copyout(src, dest, len);
244 ficlFindfile(FICL_VM *pVM)
249 char *type, *namep, *typep;
250 struct preloaded_file* fp;
254 vmCheckStack(pVM, 4, 1);
257 types = stackPopINT(pVM->pStack);
258 typep = (char*) stackPopPtr(pVM->pStack);
259 names = stackPopINT(pVM->pStack);
260 namep = (char*) stackPopPtr(pVM->pStack);
262 name = (char*) ficlMalloc(names+1);
264 vmThrowErr(pVM, "Error: out of memory");
265 strncpy(name, namep, names);
267 type = (char*) ficlMalloc(types+1);
269 vmThrowErr(pVM, "Error: out of memory");
270 strncpy(type, typep, types);
273 fp = file_findfile(name, type);
277 stackPushPtr(pVM->pStack, fp);
286 ficlPnpdevices(FICL_VM *pVM)
288 static int pnp_devices_initted = 0;
290 vmCheckStack(pVM, 0, 1);
293 if(!pnp_devices_initted) {
294 STAILQ_INIT(&pnp_devices);
295 pnp_devices_initted = 1;
298 stackPushPtr(pVM->pStack, &pnp_devices);
304 ficlPnphandlers(FICL_VM *pVM)
307 vmCheckStack(pVM, 0, 1);
310 stackPushPtr(pVM->pStack, pnphandlers);
317 #endif /* ndef TESTMAIN */
320 ficlCcall(FICL_VM *pVM)
322 int (*func)(int, ...);
327 vmCheckStack(pVM, 2, 0);
330 func = stackPopPtr(pVM->pStack);
331 nparam = stackPopINT(pVM->pStack);
334 vmCheckStack(pVM, nparam, 1);
337 for (i = 0; i < nparam; i++)
338 p[i] = stackPopINT(pVM->pStack);
340 result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8],
343 stackPushINT(pVM->pStack, result);
348 /**************************************************************************
350 ** reads in text from file fd and passes it to ficlExec()
351 * returns VM_OUTOFTEXT on success or the ficlExec() error code on
355 int ficlExecFD(FICL_VM *pVM, int fd)
358 int nLine = 0, rval = VM_OUTOFTEXT;
363 pVM->sourceID.i = fd;
365 /* feed each line to ficlExec */
370 while ((status = read(fd, &ch, 1)) > 0 && ch != '\n')
378 rval = ficlExecC(pVM, cp, i);
379 if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT)
386 ** Pass an empty line with SOURCE-ID == -1 to flush
387 ** any pending REFILLs (as required by FILE wordset)
389 pVM->sourceID.i = -1;
396 static void displayCellNoPad(FICL_VM *pVM)
400 vmCheckStack(pVM, 1, 0);
402 c = stackPop(pVM->pStack);
403 ltoa((c).i, pVM->pad, pVM->base);
404 vmTextOut(pVM, pVM->pad, 0);
408 /* fopen - open a file and return new fd on stack.
410 * fopen ( ptr count mode -- fd )
412 static void pfopen(FICL_VM *pVM)
418 vmCheckStack(pVM, 3, 1);
421 mode = stackPopINT(pVM->pStack); /* get mode */
422 count = stackPopINT(pVM->pStack); /* get count */
423 ptr = stackPopPtr(pVM->pStack); /* get ptr */
425 if ((count < 0) || (ptr == NULL)) {
426 stackPushINT(pVM->pStack, -1);
430 /* ensure that the string is null terminated */
431 name = (char *)malloc(count+1);
432 bcopy(ptr,name,count);
436 fd = rel_open(name, mode);
438 stackPushINT(pVM->pStack, fd);
442 /* fclose - close a file who's fd is on stack.
446 static void pfclose(FICL_VM *pVM)
451 vmCheckStack(pVM, 1, 0);
453 fd = stackPopINT(pVM->pStack); /* get fd */
459 /* fread - read file contents
461 * fread ( fd buf nbytes -- nread )
463 static void pfread(FICL_VM *pVM)
469 vmCheckStack(pVM, 3, 1);
471 len = stackPopINT(pVM->pStack); /* get number of bytes to read */
472 buf = stackPopPtr(pVM->pStack); /* get buffer */
473 fd = stackPopINT(pVM->pStack); /* get fd */
474 if (len > 0 && buf && fd != -1)
475 stackPushINT(pVM->pStack, read(fd, buf, len));
477 stackPushINT(pVM->pStack, -1);
481 /* fload - interpret file contents
485 static void pfload(FICL_VM *pVM)
490 vmCheckStack(pVM, 1, 0);
492 fd = stackPopINT(pVM->pStack); /* get fd */
498 /* fwrite - write file contents
500 * fwrite ( fd buf nbytes -- nwritten )
502 static void pfwrite(FICL_VM *pVM)
508 vmCheckStack(pVM, 3, 1);
510 len = stackPopINT(pVM->pStack); /* get number of bytes to read */
511 buf = stackPopPtr(pVM->pStack); /* get buffer */
512 fd = stackPopINT(pVM->pStack); /* get fd */
513 if (len > 0 && buf && fd != -1)
514 stackPushINT(pVM->pStack, write(fd, buf, len));
516 stackPushINT(pVM->pStack, -1);
520 /* fseek - seek to a new position in a file
522 * fseek ( fd ofs whence -- pos )
524 static void pfseek(FICL_VM *pVM)
529 vmCheckStack(pVM, 3, 1);
531 whence = stackPopINT(pVM->pStack);
532 pos = stackPopINT(pVM->pStack);
533 fd = stackPopINT(pVM->pStack);
534 stackPushINT(pVM->pStack, lseek(fd, pos, whence));
538 /* key - get a character from stdin
542 static void key(FICL_VM *pVM)
545 vmCheckStack(pVM, 0, 1);
547 stackPushINT(pVM->pStack, getchar());
551 /* key? - check for a character from stdin (FACILITY)
555 static void keyQuestion(FICL_VM *pVM)
558 vmCheckStack(pVM, 0, 1);
561 /* XXX Since we don't fiddle with termios, let it always succeed... */
562 stackPushINT(pVM->pStack, FICL_TRUE);
564 /* But here do the right thing. */
565 stackPushINT(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE);
570 /* seconds - gives number of seconds since beginning of time
572 * beginning of time is defined as:
574 * BTX - number of seconds since midnight
575 * FreeBSD - number of seconds since Jan 1 1970
579 static void pseconds(FICL_VM *pVM)
582 vmCheckStack(pVM,0,1);
584 stackPushUNS(pVM->pStack, (FICL_UNS) time(NULL));
588 /* ms - wait at least that many milliseconds (FACILITY)
593 static void ms(FICL_VM *pVM)
596 vmCheckStack(pVM,1,0);
599 usleep(stackPopUNS(pVM->pStack)*1000);
601 delay(stackPopUNS(pVM->pStack)*1000);
606 /* fkey - get a character from a file
608 * fkey ( file -- char )
610 static void fkey(FICL_VM *pVM)
616 vmCheckStack(pVM, 1, 1);
618 fd = stackPopINT(pVM->pStack);
619 i = read(fd, &ch, 1);
620 stackPushINT(pVM->pStack, i > 0 ? ch : -1);
625 ** Retrieves free space remaining on the dictionary
628 static void freeHeap(FICL_VM *pVM)
630 stackPushINT(pVM->pStack, dictCellsAvail(ficlGetDict(pVM->pSys)));
634 /******************* Increase dictionary size on-demand ******************/
636 static void ficlDictThreshold(FICL_VM *pVM)
638 stackPushPtr(pVM->pStack, &dictThreshold);
641 static void ficlDictIncrease(FICL_VM *pVM)
643 stackPushPtr(pVM->pStack, &dictIncrease);
647 /**************************************************************************
648 f i c l C o m p i l e P l a t f o r m
649 ** Build FreeBSD platform extensions into the system dictionary
650 **************************************************************************/
651 void ficlCompilePlatform(FICL_SYSTEM *pSys)
653 FICL_DICT *dp = pSys->dp;
656 dictAppendWord(dp, ".#", displayCellNoPad, FW_DEFAULT);
657 dictAppendWord(dp, "fopen", pfopen, FW_DEFAULT);
658 dictAppendWord(dp, "fclose", pfclose, FW_DEFAULT);
659 dictAppendWord(dp, "fread", pfread, FW_DEFAULT);
660 dictAppendWord(dp, "fload", pfload, FW_DEFAULT);
661 dictAppendWord(dp, "fkey", fkey, FW_DEFAULT);
662 dictAppendWord(dp, "fseek", pfseek, FW_DEFAULT);
663 dictAppendWord(dp, "fwrite", pfwrite, FW_DEFAULT);
664 dictAppendWord(dp, "key", key, FW_DEFAULT);
665 dictAppendWord(dp, "key?", keyQuestion, FW_DEFAULT);
666 dictAppendWord(dp, "ms", ms, FW_DEFAULT);
667 dictAppendWord(dp, "seconds", pseconds, FW_DEFAULT);
668 dictAppendWord(dp, "heap?", freeHeap, FW_DEFAULT);
669 dictAppendWord(dp, "dictthreshold", ficlDictThreshold, FW_DEFAULT);
670 dictAppendWord(dp, "dictincrease", ficlDictIncrease, FW_DEFAULT);
672 dictAppendWord(dp, "setenv", ficlSetenv, FW_DEFAULT);
673 dictAppendWord(dp, "setenv?", ficlSetenvq, FW_DEFAULT);
674 dictAppendWord(dp, "getenv", ficlGetenv, FW_DEFAULT);
675 dictAppendWord(dp, "unsetenv", ficlUnsetenv, FW_DEFAULT);
676 dictAppendWord(dp, "copyin", ficlCopyin, FW_DEFAULT);
677 dictAppendWord(dp, "copyout", ficlCopyout, FW_DEFAULT);
678 dictAppendWord(dp, "findfile", ficlFindfile, FW_DEFAULT);
679 dictAppendWord(dp, "ccall", ficlCcall, FW_DEFAULT);
682 dictAppendWord(dp, "outb", ficlOutb, FW_DEFAULT);
683 dictAppendWord(dp, "inb", ficlInb, FW_DEFAULT);
686 dictAppendWord(dp, "pnpdevices",ficlPnpdevices, FW_DEFAULT);
687 dictAppendWord(dp, "pnphandlers",ficlPnphandlers, FW_DEFAULT);
691 #if defined(__i386__)
692 ficlSetEnv(pSys, "arch-i386", FICL_TRUE);
693 ficlSetEnv(pSys, "arch-ia64", FICL_FALSE);
694 #elif defined(__ia64__)
695 ficlSetEnv(pSys, "arch-i386", FICL_FALSE);
696 ficlSetEnv(pSys, "arch-ia64", FICL_TRUE);