Use mask instead of modulo, since bo->backoff is always power of 2
[dfdiff.git] / sys / boot / ficl / loader.c
blob0d8fc8e169237b0e96201fc70b136e72e3bac45e
1 /*-
2 * Copyright (c) 2000 Daniel Capo Sobral
3 * All rights reserved.
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.
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.
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 /*******************************************************************
31 ** l o a d e r . c
32 ** Additional FICL words designed for FreeBSD's loader
33 **
34 *******************************************************************/
36 #ifdef TESTMAIN
37 #include <stdlib.h>
38 #else
39 #include <stand.h>
40 #endif
41 #include "bootstrap.h"
42 #include <string.h>
43 #include "ficl.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 )
57 * .# ( value -- )
60 void
61 ficlSetenv(FICL_VM *pVM)
63 #ifndef TESTMAIN
64 char *name, *value;
65 #endif
66 char *namep, *valuep;
67 int names, values;
69 #if FICL_ROBUST > 1
70 vmCheckStack(pVM, 4, 0);
71 #endif
72 names = stackPopINT(pVM->pStack);
73 namep = (char*) stackPopPtr(pVM->pStack);
74 values = stackPopINT(pVM->pStack);
75 valuep = (char*) stackPopPtr(pVM->pStack);
77 #ifndef TESTMAIN
78 name = (char*) ficlMalloc(names+1);
79 if (!name)
80 vmThrowErr(pVM, "Error: out of memory");
81 strncpy(name, namep, names);
82 name[names] = '\0';
83 value = (char*) ficlMalloc(values+1);
84 if (!value)
85 vmThrowErr(pVM, "Error: out of memory");
86 strncpy(value, valuep, values);
87 value[values] = '\0';
89 setenv(name, value, 1);
90 ficlFree(name);
91 ficlFree(value);
92 #endif
94 return;
97 void
98 ficlSetenvq(FICL_VM *pVM)
100 #ifndef TESTMAIN
101 char *name, *value;
102 #endif
103 char *namep, *valuep;
104 int names, values, overwrite;
106 #if FICL_ROBUST > 1
107 vmCheckStack(pVM, 5, 0);
108 #endif
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);
115 #ifndef TESTMAIN
116 name = (char*) ficlMalloc(names+1);
117 if (!name)
118 vmThrowErr(pVM, "Error: out of memory");
119 strncpy(name, namep, names);
120 name[names] = '\0';
121 value = (char*) ficlMalloc(values+1);
122 if (!value)
123 vmThrowErr(pVM, "Error: out of memory");
124 strncpy(value, valuep, values);
125 value[values] = '\0';
127 setenv(name, value, overwrite);
128 ficlFree(name);
129 ficlFree(value);
130 #endif
132 return;
135 void
136 ficlGetenv(FICL_VM *pVM)
138 #ifndef TESTMAIN
139 char *name;
140 #endif
141 char *namep, *value;
142 int names;
144 #if FICL_ROBUST > 1
145 vmCheckStack(pVM, 2, 2);
146 #endif
147 names = stackPopINT(pVM->pStack);
148 namep = (char*) stackPopPtr(pVM->pStack);
150 #ifndef TESTMAIN
151 name = (char*) ficlMalloc(names+1);
152 if (!name)
153 vmThrowErr(pVM, "Error: out of memory");
154 strncpy(name, namep, names);
155 name[names] = '\0';
157 value = getenv(name);
158 ficlFree(name);
160 if(value != NULL) {
161 stackPushPtr(pVM->pStack, value);
162 stackPushINT(pVM->pStack, strlen(value));
163 } else
164 #endif
165 stackPushINT(pVM->pStack, -1);
167 return;
170 void
171 ficlUnsetenv(FICL_VM *pVM)
173 #ifndef TESTMAIN
174 char *name;
175 #endif
176 char *namep;
177 int names;
179 #if FICL_ROBUST > 1
180 vmCheckStack(pVM, 2, 0);
181 #endif
182 names = stackPopINT(pVM->pStack);
183 namep = (char*) stackPopPtr(pVM->pStack);
185 #ifndef TESTMAIN
186 name = (char*) ficlMalloc(names+1);
187 if (!name)
188 vmThrowErr(pVM, "Error: out of memory");
189 strncpy(name, namep, names);
190 name[names] = '\0';
192 unsetenv(name);
193 ficlFree(name);
194 #endif
196 return;
199 void
200 ficlCopyin(FICL_VM *pVM)
202 void* src;
203 vm_offset_t dest;
204 size_t len;
206 #if FICL_ROBUST > 1
207 vmCheckStack(pVM, 3, 0);
208 #endif
210 len = stackPopINT(pVM->pStack);
211 dest = stackPopINT(pVM->pStack);
212 src = stackPopPtr(pVM->pStack);
214 #ifndef TESTMAIN
215 archsw.arch_copyin(src, dest, len);
216 #endif
218 return;
221 void
222 ficlCopyout(FICL_VM *pVM)
224 void* dest;
225 vm_offset_t src;
226 size_t len;
228 #if FICL_ROBUST > 1
229 vmCheckStack(pVM, 3, 0);
230 #endif
232 len = stackPopINT(pVM->pStack);
233 dest = stackPopPtr(pVM->pStack);
234 src = stackPopINT(pVM->pStack);
236 #ifndef TESTMAIN
237 archsw.arch_copyout(src, dest, len);
238 #endif
240 return;
243 void
244 ficlFindfile(FICL_VM *pVM)
246 #ifndef TESTMAIN
247 char *name;
248 #endif
249 char *type, *namep, *typep;
250 struct preloaded_file* fp;
251 int names, types;
253 #if FICL_ROBUST > 1
254 vmCheckStack(pVM, 4, 1);
255 #endif
257 types = stackPopINT(pVM->pStack);
258 typep = (char*) stackPopPtr(pVM->pStack);
259 names = stackPopINT(pVM->pStack);
260 namep = (char*) stackPopPtr(pVM->pStack);
261 #ifndef TESTMAIN
262 name = (char*) ficlMalloc(names+1);
263 if (!name)
264 vmThrowErr(pVM, "Error: out of memory");
265 strncpy(name, namep, names);
266 name[names] = '\0';
267 type = (char*) ficlMalloc(types+1);
268 if (!type)
269 vmThrowErr(pVM, "Error: out of memory");
270 strncpy(type, typep, types);
271 type[types] = '\0';
273 fp = file_findfile(name, type);
274 #else
275 fp = NULL;
276 #endif
277 stackPushPtr(pVM->pStack, fp);
279 return;
282 #ifndef TESTMAIN
283 #ifdef HAVE_PNP
285 void
286 ficlPnpdevices(FICL_VM *pVM)
288 static int pnp_devices_initted = 0;
289 #if FICL_ROBUST > 1
290 vmCheckStack(pVM, 0, 1);
291 #endif
293 if(!pnp_devices_initted) {
294 STAILQ_INIT(&pnp_devices);
295 pnp_devices_initted = 1;
298 stackPushPtr(pVM->pStack, &pnp_devices);
300 return;
303 void
304 ficlPnphandlers(FICL_VM *pVM)
306 #if FICL_ROBUST > 1
307 vmCheckStack(pVM, 0, 1);
308 #endif
310 stackPushPtr(pVM->pStack, pnphandlers);
312 return;
315 #endif
317 #endif /* ndef TESTMAIN */
319 void
320 ficlCcall(FICL_VM *pVM)
322 int (*func)(int, ...);
323 int result, p[10];
324 int nparam, i;
326 #if FICL_ROBUST > 1
327 vmCheckStack(pVM, 2, 0);
328 #endif
330 func = stackPopPtr(pVM->pStack);
331 nparam = stackPopINT(pVM->pStack);
333 #if FICL_ROBUST > 1
334 vmCheckStack(pVM, nparam, 1);
335 #endif
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],
341 p[9]);
343 stackPushINT(pVM->pStack, result);
345 return;
348 /**************************************************************************
349 f i c l E x e c F D
350 ** reads in text from file fd and passes it to ficlExec()
351 * returns VM_OUTOFTEXT on success or the ficlExec() error code on
352 * failure.
354 #define nLINEBUF 256
355 int ficlExecFD(FICL_VM *pVM, int fd)
357 char cp[nLINEBUF];
358 int nLine = 0, rval = VM_OUTOFTEXT;
359 char ch;
360 CELL id;
362 id = pVM->sourceID;
363 pVM->sourceID.i = fd;
365 /* feed each line to ficlExec */
366 while (1) {
367 int status, i;
369 i = 0;
370 while ((status = read(fd, &ch, 1)) > 0 && ch != '\n')
371 cp[i++] = ch;
372 nLine++;
373 if (!i) {
374 if (status < 1)
375 break;
376 continue;
378 rval = ficlExecC(pVM, cp, i);
379 if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT)
381 pVM->sourceID = id;
382 return rval;
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;
390 ficlExec(pVM, "");
392 pVM->sourceID = id;
393 return rval;
396 static void displayCellNoPad(FICL_VM *pVM)
398 CELL c;
399 #if FICL_ROBUST > 1
400 vmCheckStack(pVM, 1, 0);
401 #endif
402 c = stackPop(pVM->pStack);
403 ltoa((c).i, pVM->pad, pVM->base);
404 vmTextOut(pVM, pVM->pad, 0);
405 return;
408 /* fopen - open a file and return new fd on stack.
410 * fopen ( ptr count mode -- fd )
412 static void pfopen(FICL_VM *pVM)
414 int mode, fd, count;
415 char *ptr, *name;
417 #if FICL_ROBUST > 1
418 vmCheckStack(pVM, 3, 1);
419 #endif
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);
427 return;
430 /* ensure that the string is null terminated */
431 name = (char *)malloc(count+1);
432 bcopy(ptr,name,count);
433 name[count] = 0;
435 /* open the file */
436 fd = open(name, mode);
437 free(name);
438 stackPushINT(pVM->pStack, fd);
439 return;
442 /* fclose - close a file who's fd is on stack.
444 * fclose ( fd -- )
446 static void pfclose(FICL_VM *pVM)
448 int fd;
450 #if FICL_ROBUST > 1
451 vmCheckStack(pVM, 1, 0);
452 #endif
453 fd = stackPopINT(pVM->pStack); /* get fd */
454 if (fd != -1)
455 close(fd);
456 return;
459 /* fread - read file contents
461 * fread ( fd buf nbytes -- nread )
463 static void pfread(FICL_VM *pVM)
465 int fd, len;
466 char *buf;
468 #if FICL_ROBUST > 1
469 vmCheckStack(pVM, 3, 1);
470 #endif
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));
476 else
477 stackPushINT(pVM->pStack, -1);
478 return;
481 /* fload - interpret file contents
483 * fload ( fd -- )
485 static void pfload(FICL_VM *pVM)
487 int fd;
489 #if FICL_ROBUST > 1
490 vmCheckStack(pVM, 1, 0);
491 #endif
492 fd = stackPopINT(pVM->pStack); /* get fd */
493 if (fd != -1)
494 ficlExecFD(pVM, fd);
495 return;
498 /* fwrite - write file contents
500 * fwrite ( fd buf nbytes -- nwritten )
502 static void pfwrite(FICL_VM *pVM)
504 int fd, len;
505 char *buf;
507 #if FICL_ROBUST > 1
508 vmCheckStack(pVM, 3, 1);
509 #endif
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));
515 else
516 stackPushINT(pVM->pStack, -1);
517 return;
520 /* fseek - seek to a new position in a file
522 * fseek ( fd ofs whence -- pos )
524 static void pfseek(FICL_VM *pVM)
526 int fd, pos, whence;
528 #if FICL_ROBUST > 1
529 vmCheckStack(pVM, 3, 1);
530 #endif
531 whence = stackPopINT(pVM->pStack);
532 pos = stackPopINT(pVM->pStack);
533 fd = stackPopINT(pVM->pStack);
534 stackPushINT(pVM->pStack, lseek(fd, pos, whence));
535 return;
538 /* key - get a character from stdin
540 * key ( -- char )
542 static void key(FICL_VM *pVM)
544 #if FICL_ROBUST > 1
545 vmCheckStack(pVM, 0, 1);
546 #endif
547 stackPushINT(pVM->pStack, getchar());
548 return;
551 /* key? - check for a character from stdin (FACILITY)
553 * key? ( -- flag )
555 static void keyQuestion(FICL_VM *pVM)
557 #if FICL_ROBUST > 1
558 vmCheckStack(pVM, 0, 1);
559 #endif
560 #ifdef TESTMAIN
561 /* XXX Since we don't fiddle with termios, let it always succeed... */
562 stackPushINT(pVM->pStack, FICL_TRUE);
563 #else
564 /* But here do the right thing. */
565 stackPushINT(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE);
566 #endif
567 return;
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
577 * seconds ( -- u )
579 static void pseconds(FICL_VM *pVM)
581 #if FICL_ROBUST > 1
582 vmCheckStack(pVM,0,1);
583 #endif
584 stackPushUNS(pVM->pStack, (FICL_UNS) time(NULL));
585 return;
588 /* ms - wait at least that many milliseconds (FACILITY)
590 * ms ( u -- )
593 static void ms(FICL_VM *pVM)
595 #if FICL_ROBUST > 1
596 vmCheckStack(pVM,1,0);
597 #endif
598 #ifdef TESTMAIN
599 usleep(stackPopUNS(pVM->pStack)*1000);
600 #else
601 delay(stackPopUNS(pVM->pStack)*1000);
602 #endif
603 return;
606 /* fkey - get a character from a file
608 * fkey ( file -- char )
610 static void fkey(FICL_VM *pVM)
612 int i, fd;
613 char ch;
615 #if FICL_ROBUST > 1
616 vmCheckStack(pVM, 1, 1);
617 #endif
618 fd = stackPopINT(pVM->pStack);
619 i = read(fd, &ch, 1);
620 stackPushINT(pVM->pStack, i > 0 ? ch : -1);
621 return;
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;
654 assert (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);
680 #ifndef TESTMAIN
681 #ifdef __i386__
682 dictAppendWord(dp, "outb", ficlOutb, FW_DEFAULT);
683 dictAppendWord(dp, "inb", ficlInb, FW_DEFAULT);
684 #endif
685 #ifdef HAVE_PNP
686 dictAppendWord(dp, "pnpdevices",ficlPnpdevices, FW_DEFAULT);
687 dictAppendWord(dp, "pnphandlers",ficlPnphandlers, FW_DEFAULT);
688 #endif
689 #endif
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);
697 #endif
699 return;