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.6 2008/03/29 23:31:07 swildner 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
= 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
);