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.9 2003/06/08 03:11:16 nyan Exp $
27 * $DragonFly: src/sys/boot/ficl/loader.c,v 1.3 2003/11/10 06:08:33 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 )
62 ficlSetenv(FICL_VM *pVM)
64 char *namep, *valuep, *name, *value;
68 vmCheckStack(pVM, 4, 0);
70 names = stackPopINT(pVM->pStack);
71 namep = (char*) stackPopPtr(pVM->pStack);
72 values = stackPopINT(pVM->pStack);
73 valuep = (char*) stackPopPtr(pVM->pStack);
75 name = (char*) ficlMalloc(names+1);
77 vmThrowErr(pVM, "Error: out of memory");
78 strncpy(name, namep, names);
80 value = (char*) ficlMalloc(values+1);
82 vmThrowErr(pVM, "Error: out of memory");
83 strncpy(value, valuep, values);
86 setenv(name, value, 1);
94 ficlSetenvq(FICL_VM *pVM)
96 char *namep, *valuep, *name, *value;
97 int names, values, overwrite;
100 vmCheckStack(pVM, 5, 0);
102 overwrite = stackPopINT(pVM->pStack);
103 names = stackPopINT(pVM->pStack);
104 namep = (char*) stackPopPtr(pVM->pStack);
105 values = stackPopINT(pVM->pStack);
106 valuep = (char*) stackPopPtr(pVM->pStack);
108 name = (char*) ficlMalloc(names+1);
110 vmThrowErr(pVM, "Error: out of memory");
111 strncpy(name, namep, names);
113 value = (char*) ficlMalloc(values+1);
115 vmThrowErr(pVM, "Error: out of memory");
116 strncpy(value, valuep, values);
117 value[values] = '\0';
119 setenv(name, value, overwrite);
127 ficlGetenv(FICL_VM *pVM)
129 char *namep, *name, *value;
133 vmCheckStack(pVM, 2, 2);
135 names = stackPopINT(pVM->pStack);
136 namep = (char*) stackPopPtr(pVM->pStack);
138 name = (char*) ficlMalloc(names+1);
140 vmThrowErr(pVM, "Error: out of memory");
141 strncpy(name, namep, names);
144 value = getenv(name);
148 stackPushPtr(pVM->pStack, value);
149 stackPushINT(pVM->pStack, strlen(value));
151 stackPushINT(pVM->pStack, -1);
157 ficlUnsetenv(FICL_VM *pVM)
163 vmCheckStack(pVM, 2, 0);
165 names = stackPopINT(pVM->pStack);
166 namep = (char*) stackPopPtr(pVM->pStack);
168 name = (char*) ficlMalloc(names+1);
170 vmThrowErr(pVM, "Error: out of memory");
171 strncpy(name, namep, names);
181 ficlCopyin(FICL_VM *pVM)
188 vmCheckStack(pVM, 3, 0);
191 len = stackPopINT(pVM->pStack);
192 dest = stackPopINT(pVM->pStack);
193 src = stackPopPtr(pVM->pStack);
195 archsw.arch_copyin(src, dest, len);
201 ficlCopyout(FICL_VM *pVM)
208 vmCheckStack(pVM, 3, 0);
211 len = stackPopINT(pVM->pStack);
212 dest = stackPopPtr(pVM->pStack);
213 src = stackPopINT(pVM->pStack);
215 archsw.arch_copyout(src, dest, len);
221 ficlFindfile(FICL_VM *pVM)
223 char *name, *type, *namep, *typep;
224 struct preloaded_file* fp;
228 vmCheckStack(pVM, 4, 1);
231 types = stackPopINT(pVM->pStack);
232 typep = (char*) stackPopPtr(pVM->pStack);
233 names = stackPopINT(pVM->pStack);
234 namep = (char*) stackPopPtr(pVM->pStack);
235 name = (char*) ficlMalloc(names+1);
237 vmThrowErr(pVM, "Error: out of memory");
238 strncpy(name, namep, names);
240 type = (char*) ficlMalloc(types+1);
242 vmThrowErr(pVM, "Error: out of memory");
243 strncpy(type, typep, types);
246 fp = file_findfile(name, type);
247 stackPushPtr(pVM->pStack, fp);
255 ficlPnpdevices(FICL_VM *pVM)
257 static int pnp_devices_initted = 0;
259 vmCheckStack(pVM, 0, 1);
262 if(!pnp_devices_initted) {
263 STAILQ_INIT(&pnp_devices);
264 pnp_devices_initted = 1;
267 stackPushPtr(pVM->pStack, &pnp_devices);
273 ficlPnphandlers(FICL_VM *pVM)
276 vmCheckStack(pVM, 0, 1);
279 stackPushPtr(pVM->pStack, pnphandlers);
286 #endif /* ndef TESTMAIN */
289 ficlCcall(FICL_VM *pVM)
291 int (*func)(int, ...);
296 vmCheckStack(pVM, 2, 0);
299 func = stackPopPtr(pVM->pStack);
300 nparam = stackPopINT(pVM->pStack);
303 vmCheckStack(pVM, nparam, 1);
306 for (i = 0; i < nparam; i++)
307 p[i] = stackPopINT(pVM->pStack);
309 result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8],
312 stackPushINT(pVM->pStack, result);
317 /**************************************************************************
319 ** reads in text from file fd and passes it to ficlExec()
320 * returns VM_OUTOFTEXT on success or the ficlExec() error code on
324 int ficlExecFD(FICL_VM *pVM, int fd)
327 int nLine = 0, rval = VM_OUTOFTEXT;
332 pVM->sourceID.i = fd;
334 /* feed each line to ficlExec */
339 while ((status = read(fd, &ch, 1)) > 0 && ch != '\n')
347 rval = ficlExecC(pVM, cp, i);
348 if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT)
355 ** Pass an empty line with SOURCE-ID == -1 to flush
356 ** any pending REFILLs (as required by FILE wordset)
358 pVM->sourceID.i = -1;
365 static void displayCellNoPad(FICL_VM *pVM)
369 vmCheckStack(pVM, 1, 0);
371 c = stackPop(pVM->pStack);
372 ltoa((c).i, pVM->pad, pVM->base);
373 vmTextOut(pVM, pVM->pad, 0);
377 /* fopen - open a file and return new fd on stack.
379 * fopen ( ptr count mode -- fd )
381 static void pfopen(FICL_VM *pVM)
387 vmCheckStack(pVM, 3, 1);
390 mode = stackPopINT(pVM->pStack); /* get mode */
391 count = stackPopINT(pVM->pStack); /* get count */
392 ptr = stackPopPtr(pVM->pStack); /* get ptr */
394 if ((count < 0) || (ptr == NULL)) {
395 stackPushINT(pVM->pStack, -1);
399 /* ensure that the string is null terminated */
400 name = (char *)malloc(count+1);
401 bcopy(ptr,name,count);
405 fd = open(name, mode);
407 stackPushINT(pVM->pStack, fd);
411 /* fclose - close a file who's fd is on stack.
415 static void pfclose(FICL_VM *pVM)
420 vmCheckStack(pVM, 1, 0);
422 fd = stackPopINT(pVM->pStack); /* get fd */
428 /* fread - read file contents
430 * fread ( fd buf nbytes -- nread )
432 static void pfread(FICL_VM *pVM)
438 vmCheckStack(pVM, 3, 1);
440 len = stackPopINT(pVM->pStack); /* get number of bytes to read */
441 buf = stackPopPtr(pVM->pStack); /* get buffer */
442 fd = stackPopINT(pVM->pStack); /* get fd */
443 if (len > 0 && buf && fd != -1)
444 stackPushINT(pVM->pStack, read(fd, buf, len));
446 stackPushINT(pVM->pStack, -1);
450 /* fload - interpret file contents
454 static void pfload(FICL_VM *pVM)
459 vmCheckStack(pVM, 1, 0);
461 fd = stackPopINT(pVM->pStack); /* get fd */
467 /* fwrite - write file contents
469 * fwrite ( fd buf nbytes -- nwritten )
471 static void pfwrite(FICL_VM *pVM)
477 vmCheckStack(pVM, 3, 1);
479 len = stackPopINT(pVM->pStack); /* get number of bytes to read */
480 buf = stackPopPtr(pVM->pStack); /* get buffer */
481 fd = stackPopINT(pVM->pStack); /* get fd */
482 if (len > 0 && buf && fd != -1)
483 stackPushINT(pVM->pStack, write(fd, buf, len));
485 stackPushINT(pVM->pStack, -1);
489 /* fseek - seek to a new position in a file
491 * fseek ( fd ofs whence -- pos )
493 static void pfseek(FICL_VM *pVM)
498 vmCheckStack(pVM, 3, 1);
500 whence = stackPopINT(pVM->pStack);
501 pos = stackPopINT(pVM->pStack);
502 fd = stackPopINT(pVM->pStack);
503 stackPushINT(pVM->pStack, lseek(fd, pos, whence));
507 /* key - get a character from stdin
511 static void key(FICL_VM *pVM)
514 vmCheckStack(pVM, 0, 1);
516 stackPushINT(pVM->pStack, getchar());
520 /* key? - check for a character from stdin (FACILITY)
524 static void keyQuestion(FICL_VM *pVM)
527 vmCheckStack(pVM, 0, 1);
530 /* XXX Since we don't fiddle with termios, let it always succeed... */
531 stackPushINT(pVM->pStack, FICL_TRUE);
533 /* But here do the right thing. */
534 stackPushINT(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE);
539 /* seconds - gives number of seconds since beginning of time
541 * beginning of time is defined as:
543 * BTX - number of seconds since midnight
544 * FreeBSD - number of seconds since Jan 1 1970
548 static void pseconds(FICL_VM *pVM)
551 vmCheckStack(pVM,0,1);
553 stackPushUNS(pVM->pStack, (FICL_UNS) time(NULL));
557 /* ms - wait at least that many milliseconds (FACILITY)
562 static void ms(FICL_VM *pVM)
565 vmCheckStack(pVM,1,0);
568 usleep(stackPopUNS(pVM->pStack)*1000);
570 delay(stackPopUNS(pVM->pStack)*1000);
575 /* fkey - get a character from a file
577 * fkey ( file -- char )
579 static void fkey(FICL_VM *pVM)
585 vmCheckStack(pVM, 1, 1);
587 fd = stackPopINT(pVM->pStack);
588 i = read(fd, &ch, 1);
589 stackPushINT(pVM->pStack, i > 0 ? ch : -1);
594 ** Retrieves free space remaining on the dictionary
597 static void freeHeap(FICL_VM *pVM)
599 stackPushINT(pVM->pStack, dictCellsAvail(ficlGetDict(pVM->pSys)));
603 /******************* Increase dictionary size on-demand ******************/
605 static void ficlDictThreshold(FICL_VM *pVM)
607 stackPushPtr(pVM->pStack, &dictThreshold);
610 static void ficlDictIncrease(FICL_VM *pVM)
612 stackPushPtr(pVM->pStack, &dictIncrease);
616 /**************************************************************************
617 f i c l C o m p i l e P l a t f o r m
618 ** Build FreeBSD platform extensions into the system dictionary
619 **************************************************************************/
620 void ficlCompilePlatform(FICL_SYSTEM *pSys)
622 FICL_DICT *dp = pSys->dp;
625 dictAppendWord(dp, ".#", displayCellNoPad, FW_DEFAULT);
626 dictAppendWord(dp, "fopen", pfopen, FW_DEFAULT);
627 dictAppendWord(dp, "fclose", pfclose, FW_DEFAULT);
628 dictAppendWord(dp, "fread", pfread, FW_DEFAULT);
629 dictAppendWord(dp, "fload", pfload, FW_DEFAULT);
630 dictAppendWord(dp, "fkey", fkey, FW_DEFAULT);
631 dictAppendWord(dp, "fseek", pfseek, FW_DEFAULT);
632 dictAppendWord(dp, "fwrite", pfwrite, FW_DEFAULT);
633 dictAppendWord(dp, "key", key, FW_DEFAULT);
634 dictAppendWord(dp, "key?", keyQuestion, FW_DEFAULT);
635 dictAppendWord(dp, "ms", ms, FW_DEFAULT);
636 dictAppendWord(dp, "seconds", pseconds, FW_DEFAULT);
637 dictAppendWord(dp, "heap?", freeHeap, FW_DEFAULT);
638 dictAppendWord(dp, "dictthreshold", ficlDictThreshold, FW_DEFAULT);
639 dictAppendWord(dp, "dictincrease", ficlDictIncrease, FW_DEFAULT);
643 dictAppendWord(dp, "outb", ficlOutb, FW_DEFAULT);
644 dictAppendWord(dp, "inb", ficlInb, FW_DEFAULT);
646 dictAppendWord(dp, "setenv", ficlSetenv, FW_DEFAULT);
647 dictAppendWord(dp, "setenv?", ficlSetenvq, FW_DEFAULT);
648 dictAppendWord(dp, "getenv", ficlGetenv, FW_DEFAULT);
649 dictAppendWord(dp, "unsetenv", ficlUnsetenv, FW_DEFAULT);
650 dictAppendWord(dp, "copyin", ficlCopyin, FW_DEFAULT);
651 dictAppendWord(dp, "copyout", ficlCopyout, FW_DEFAULT);
652 dictAppendWord(dp, "findfile", ficlFindfile, FW_DEFAULT);
654 dictAppendWord(dp, "pnpdevices",ficlPnpdevices, FW_DEFAULT);
655 dictAppendWord(dp, "pnphandlers",ficlPnphandlers, FW_DEFAULT);
657 dictAppendWord(dp, "ccall", ficlCcall, FW_DEFAULT);
661 ficlSetEnv(pSys, "arch-pc98", FICL_TRUE);
662 #elif defined(__i386__)
663 ficlSetEnv(pSys, "arch-i386", FICL_TRUE);
664 ficlSetEnv(pSys, "arch-alpha", FICL_FALSE);
665 ficlSetEnv(pSys, "arch-ia64", FICL_FALSE);
666 #elif defined(__alpha__)
667 ficlSetEnv(pSys, "arch-i386", FICL_FALSE);
668 ficlSetEnv(pSys, "arch-alpha", FICL_TRUE);
669 ficlSetEnv(pSys, "arch-ia64", FICL_FALSE);
670 #elif defined(__ia64__)
671 ficlSetEnv(pSys, "arch-i386", FICL_FALSE);
672 ficlSetEnv(pSys, "arch-alpha", FICL_FALSE);
673 ficlSetEnv(pSys, "arch-ia64", FICL_TRUE);