FreeBSD/Linux Kernel Cross Reference
sys/boot/ficl/loader.c
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$
27 */
28
29 /*******************************************************************
30 ** l o a d e r . c
31 ** Additional FICL words designed for FreeBSD's loader
32 **
33 *******************************************************************/
34
35 #ifdef TESTMAIN
36 #include <stdlib.h>
37 #else
38 #include <stand.h>
39 #endif
40 #include "bootstrap.h"
41 #include <string.h>
42 #include "ficl.h"
43
44 /* FreeBSD's loader interaction words and extras
45 *
46 * setenv ( value n name n' -- )
47 * setenv? ( value n name n' flag -- )
48 * getenv ( addr n -- addr' n' | -1 )
49 * unsetenv ( addr n -- )
50 * copyin ( addr addr' len -- )
51 * copyout ( addr addr' len -- )
52 * findfile ( name len type len' -- addr )
53 * pnpdevices ( -- addr )
54 * pnphandlers ( -- addr )
55 * ccall ( [[...[p10] p9] ... p1] n addr -- result )
56 * .# ( value -- )
57 */
58
59 void
60 ficlSetenv(FICL_VM *pVM)
61 {
62 #ifndef TESTMAIN
63 char *name, *value;
64 #endif
65 char *namep, *valuep;
66 int names, values;
67
68 #if FICL_ROBUST > 1
69 vmCheckStack(pVM, 4, 0);
70 #endif
71 names = stackPopINT(pVM->pStack);
72 namep = (char*) stackPopPtr(pVM->pStack);
73 values = stackPopINT(pVM->pStack);
74 valuep = (char*) stackPopPtr(pVM->pStack);
75
76 #ifndef TESTMAIN
77 name = (char*) ficlMalloc(names+1);
78 if (!name)
79 vmThrowErr(pVM, "Error: out of memory");
80 strncpy(name, namep, names);
81 name[names] = '\0';
82 value = (char*) ficlMalloc(values+1);
83 if (!value)
84 vmThrowErr(pVM, "Error: out of memory");
85 strncpy(value, valuep, values);
86 value[values] = '\0';
87
88 setenv(name, value, 1);
89 ficlFree(name);
90 ficlFree(value);
91 #endif
92
93 return;
94 }
95
96 void
97 ficlSetenvq(FICL_VM *pVM)
98 {
99 #ifndef TESTMAIN
100 char *name, *value;
101 #endif
102 char *namep, *valuep;
103 int names, values, overwrite;
104
105 #if FICL_ROBUST > 1
106 vmCheckStack(pVM, 5, 0);
107 #endif
108 overwrite = stackPopINT(pVM->pStack);
109 names = stackPopINT(pVM->pStack);
110 namep = (char*) stackPopPtr(pVM->pStack);
111 values = stackPopINT(pVM->pStack);
112 valuep = (char*) stackPopPtr(pVM->pStack);
113
114 #ifndef TESTMAIN
115 name = (char*) ficlMalloc(names+1);
116 if (!name)
117 vmThrowErr(pVM, "Error: out of memory");
118 strncpy(name, namep, names);
119 name[names] = '\0';
120 value = (char*) ficlMalloc(values+1);
121 if (!value)
122 vmThrowErr(pVM, "Error: out of memory");
123 strncpy(value, valuep, values);
124 value[values] = '\0';
125
126 setenv(name, value, overwrite);
127 ficlFree(name);
128 ficlFree(value);
129 #endif
130
131 return;
132 }
133
134 void
135 ficlGetenv(FICL_VM *pVM)
136 {
137 #ifndef TESTMAIN
138 char *name;
139 #endif
140 char *namep, *value;
141 int names;
142
143 #if FICL_ROBUST > 1
144 vmCheckStack(pVM, 2, 2);
145 #endif
146 names = stackPopINT(pVM->pStack);
147 namep = (char*) stackPopPtr(pVM->pStack);
148
149 #ifndef TESTMAIN
150 name = (char*) ficlMalloc(names+1);
151 if (!name)
152 vmThrowErr(pVM, "Error: out of memory");
153 strncpy(name, namep, names);
154 name[names] = '\0';
155
156 value = getenv(name);
157 ficlFree(name);
158
159 if(value != NULL) {
160 stackPushPtr(pVM->pStack, value);
161 stackPushINT(pVM->pStack, strlen(value));
162 } else
163 #endif
164 stackPushINT(pVM->pStack, -1);
165
166 return;
167 }
168
169 void
170 ficlUnsetenv(FICL_VM *pVM)
171 {
172 #ifndef TESTMAIN
173 char *name;
174 #endif
175 char *namep;
176 int names;
177
178 #if FICL_ROBUST > 1
179 vmCheckStack(pVM, 2, 0);
180 #endif
181 names = stackPopINT(pVM->pStack);
182 namep = (char*) stackPopPtr(pVM->pStack);
183
184 #ifndef TESTMAIN
185 name = (char*) ficlMalloc(names+1);
186 if (!name)
187 vmThrowErr(pVM, "Error: out of memory");
188 strncpy(name, namep, names);
189 name[names] = '\0';
190
191 unsetenv(name);
192 ficlFree(name);
193 #endif
194
195 return;
196 }
197
198 void
199 ficlCopyin(FICL_VM *pVM)
200 {
201 void* src;
202 vm_offset_t dest;
203 size_t len;
204
205 #if FICL_ROBUST > 1
206 vmCheckStack(pVM, 3, 0);
207 #endif
208
209 len = stackPopINT(pVM->pStack);
210 dest = stackPopINT(pVM->pStack);
211 src = stackPopPtr(pVM->pStack);
212
213 #ifndef TESTMAIN
214 archsw.arch_copyin(src, dest, len);
215 #endif
216
217 return;
218 }
219
220 void
221 ficlCopyout(FICL_VM *pVM)
222 {
223 void* dest;
224 vm_offset_t src;
225 size_t len;
226
227 #if FICL_ROBUST > 1
228 vmCheckStack(pVM, 3, 0);
229 #endif
230
231 len = stackPopINT(pVM->pStack);
232 dest = stackPopPtr(pVM->pStack);
233 src = stackPopINT(pVM->pStack);
234
235 #ifndef TESTMAIN
236 archsw.arch_copyout(src, dest, len);
237 #endif
238
239 return;
240 }
241
242 void
243 ficlFindfile(FICL_VM *pVM)
244 {
245 #ifndef TESTMAIN
246 char *name;
247 #endif
248 char *type, *namep, *typep;
249 struct preloaded_file* fp;
250 int names, types;
251
252 #if FICL_ROBUST > 1
253 vmCheckStack(pVM, 4, 1);
254 #endif
255
256 types = stackPopINT(pVM->pStack);
257 typep = (char*) stackPopPtr(pVM->pStack);
258 names = stackPopINT(pVM->pStack);
259 namep = (char*) stackPopPtr(pVM->pStack);
260 #ifndef TESTMAIN
261 name = (char*) ficlMalloc(names+1);
262 if (!name)
263 vmThrowErr(pVM, "Error: out of memory");
264 strncpy(name, namep, names);
265 name[names] = '\0';
266 type = (char*) ficlMalloc(types+1);
267 if (!type)
268 vmThrowErr(pVM, "Error: out of memory");
269 strncpy(type, typep, types);
270 type[types] = '\0';
271
272 fp = file_findfile(name, type);
273 #else
274 fp = NULL;
275 #endif
276 stackPushPtr(pVM->pStack, fp);
277
278 return;
279 }
280
281 #ifndef TESTMAIN
282 #ifdef HAVE_PNP
283
284 void
285 ficlPnpdevices(FICL_VM *pVM)
286 {
287 static int pnp_devices_initted = 0;
288 #if FICL_ROBUST > 1
289 vmCheckStack(pVM, 0, 1);
290 #endif
291
292 if(!pnp_devices_initted) {
293 STAILQ_INIT(&pnp_devices);
294 pnp_devices_initted = 1;
295 }
296
297 stackPushPtr(pVM->pStack, &pnp_devices);
298
299 return;
300 }
301
302 void
303 ficlPnphandlers(FICL_VM *pVM)
304 {
305 #if FICL_ROBUST > 1
306 vmCheckStack(pVM, 0, 1);
307 #endif
308
309 stackPushPtr(pVM->pStack, pnphandlers);
310
311 return;
312 }
313
314 #endif
315
316 #endif /* ndef TESTMAIN */
317
318 void
319 ficlCcall(FICL_VM *pVM)
320 {
321 int (*func)(int, ...);
322 int result, p[10];
323 int nparam, i;
324
325 #if FICL_ROBUST > 1
326 vmCheckStack(pVM, 2, 0);
327 #endif
328
329 func = stackPopPtr(pVM->pStack);
330 nparam = stackPopINT(pVM->pStack);
331
332 #if FICL_ROBUST > 1
333 vmCheckStack(pVM, nparam, 1);
334 #endif
335
336 for (i = 0; i < nparam; i++)
337 p[i] = stackPopINT(pVM->pStack);
338
339 result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8],
340 p[9]);
341
342 stackPushINT(pVM->pStack, result);
343
344 return;
345 }
346
347 /**************************************************************************
348 f i c l E x e c F D
349 ** reads in text from file fd and passes it to ficlExec()
350 * returns VM_OUTOFTEXT on success or the ficlExec() error code on
351 * failure.
352 */
353 #define nLINEBUF 256
354 int ficlExecFD(FICL_VM *pVM, int fd)
355 {
356 char cp[nLINEBUF];
357 int nLine = 0, rval = VM_OUTOFTEXT;
358 char ch;
359 CELL id;
360
361 id = pVM->sourceID;
362 pVM->sourceID.i = fd;
363
364 /* feed each line to ficlExec */
365 while (1) {
366 int status, i;
367
368 i = 0;
369 while ((status = read(fd, &ch, 1)) > 0 && ch != '\n')
370 cp[i++] = ch;
371 nLine++;
372 if (!i) {
373 if (status < 1)
374 break;
375 continue;
376 }
377 rval = ficlExecC(pVM, cp, i);
378 if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT)
379 {
380 pVM->sourceID = id;
381 return rval;
382 }
383 }
384 /*
385 ** Pass an empty line with SOURCE-ID == -1 to flush
386 ** any pending REFILLs (as required by FILE wordset)
387 */
388 pVM->sourceID.i = -1;
389 ficlExec(pVM, "");
390
391 pVM->sourceID = id;
392 return rval;
393 }
394
395 static void displayCellNoPad(FICL_VM *pVM)
396 {
397 CELL c;
398 #if FICL_ROBUST > 1
399 vmCheckStack(pVM, 1, 0);
400 #endif
401 c = stackPop(pVM->pStack);
402 ltoa((c).i, pVM->pad, pVM->base);
403 vmTextOut(pVM, pVM->pad, 0);
404 return;
405 }
406
407 /* fopen - open a file and return new fd on stack.
408 *
409 * fopen ( ptr count mode -- fd )
410 */
411 static void pfopen(FICL_VM *pVM)
412 {
413 int mode, fd, count;
414 char *ptr, *name;
415
416 #if FICL_ROBUST > 1
417 vmCheckStack(pVM, 3, 1);
418 #endif
419
420 mode = stackPopINT(pVM->pStack); /* get mode */
421 count = stackPopINT(pVM->pStack); /* get count */
422 ptr = stackPopPtr(pVM->pStack); /* get ptr */
423
424 if ((count < 0) || (ptr == NULL)) {
425 stackPushINT(pVM->pStack, -1);
426 return;
427 }
428
429 /* ensure that the string is null terminated */
430 name = (char *)malloc(count+1);
431 bcopy(ptr,name,count);
432 name[count] = 0;
433
434 /* open the file */
435 fd = open(name, mode);
436 free(name);
437 stackPushINT(pVM->pStack, fd);
438 return;
439 }
440
441 /* fclose - close a file who's fd is on stack.
442 *
443 * fclose ( fd -- )
444 */
445 static void pfclose(FICL_VM *pVM)
446 {
447 int fd;
448
449 #if FICL_ROBUST > 1
450 vmCheckStack(pVM, 1, 0);
451 #endif
452 fd = stackPopINT(pVM->pStack); /* get fd */
453 if (fd != -1)
454 close(fd);
455 return;
456 }
457
458 /* fread - read file contents
459 *
460 * fread ( fd buf nbytes -- nread )
461 */
462 static void pfread(FICL_VM *pVM)
463 {
464 int fd, len;
465 char *buf;
466
467 #if FICL_ROBUST > 1
468 vmCheckStack(pVM, 3, 1);
469 #endif
470 len = stackPopINT(pVM->pStack); /* get number of bytes to read */
471 buf = stackPopPtr(pVM->pStack); /* get buffer */
472 fd = stackPopINT(pVM->pStack); /* get fd */
473 if (len > 0 && buf && fd != -1)
474 stackPushINT(pVM->pStack, read(fd, buf, len));
475 else
476 stackPushINT(pVM->pStack, -1);
477 return;
478 }
479
480 /* fload - interpret file contents
481 *
482 * fload ( fd -- )
483 */
484 static void pfload(FICL_VM *pVM)
485 {
486 int fd;
487
488 #if FICL_ROBUST > 1
489 vmCheckStack(pVM, 1, 0);
490 #endif
491 fd = stackPopINT(pVM->pStack); /* get fd */
492 if (fd != -1)
493 ficlExecFD(pVM, fd);
494 return;
495 }
496
497 /* fwrite - write file contents
498 *
499 * fwrite ( fd buf nbytes -- nwritten )
500 */
501 static void pfwrite(FICL_VM *pVM)
502 {
503 int fd, len;
504 char *buf;
505
506 #if FICL_ROBUST > 1
507 vmCheckStack(pVM, 3, 1);
508 #endif
509 len = stackPopINT(pVM->pStack); /* get number of bytes to read */
510 buf = stackPopPtr(pVM->pStack); /* get buffer */
511 fd = stackPopINT(pVM->pStack); /* get fd */
512 if (len > 0 && buf && fd != -1)
513 stackPushINT(pVM->pStack, write(fd, buf, len));
514 else
515 stackPushINT(pVM->pStack, -1);
516 return;
517 }
518
519 /* fseek - seek to a new position in a file
520 *
521 * fseek ( fd ofs whence -- pos )
522 */
523 static void pfseek(FICL_VM *pVM)
524 {
525 int fd, pos, whence;
526
527 #if FICL_ROBUST > 1
528 vmCheckStack(pVM, 3, 1);
529 #endif
530 whence = stackPopINT(pVM->pStack);
531 pos = stackPopINT(pVM->pStack);
532 fd = stackPopINT(pVM->pStack);
533 stackPushINT(pVM->pStack, lseek(fd, pos, whence));
534 return;
535 }
536
537 /* key - get a character from stdin
538 *
539 * key ( -- char )
540 */
541 static void key(FICL_VM *pVM)
542 {
543 #if FICL_ROBUST > 1
544 vmCheckStack(pVM, 0, 1);
545 #endif
546 stackPushINT(pVM->pStack, getchar());
547 return;
548 }
549
550 /* key? - check for a character from stdin (FACILITY)
551 *
552 * key? ( -- flag )
553 */
554 static void keyQuestion(FICL_VM *pVM)
555 {
556 #if FICL_ROBUST > 1
557 vmCheckStack(pVM, 0, 1);
558 #endif
559 #ifdef TESTMAIN
560 /* XXX Since we don't fiddle with termios, let it always succeed... */
561 stackPushINT(pVM->pStack, FICL_TRUE);
562 #else
563 /* But here do the right thing. */
564 stackPushINT(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE);
565 #endif
566 return;
567 }
568
569 /* seconds - gives number of seconds since beginning of time
570 *
571 * beginning of time is defined as:
572 *
573 * BTX - number of seconds since midnight
574 * FreeBSD - number of seconds since Jan 1 1970
575 *
576 * seconds ( -- u )
577 */
578 static void pseconds(FICL_VM *pVM)
579 {
580 #if FICL_ROBUST > 1
581 vmCheckStack(pVM,0,1);
582 #endif
583 stackPushUNS(pVM->pStack, (FICL_UNS) time(NULL));
584 return;
585 }
586
587 /* ms - wait at least that many milliseconds (FACILITY)
588 *
589 * ms ( u -- )
590 *
591 */
592 static void ms(FICL_VM *pVM)
593 {
594 #if FICL_ROBUST > 1
595 vmCheckStack(pVM,1,0);
596 #endif
597 #ifdef TESTMAIN
598 usleep(stackPopUNS(pVM->pStack)*1000);
599 #else
600 delay(stackPopUNS(pVM->pStack)*1000);
601 #endif
602 return;
603 }
604
605 /* fkey - get a character from a file
606 *
607 * fkey ( file -- char )
608 */
609 static void fkey(FICL_VM *pVM)
610 {
611 int i, fd;
612 char ch;
613
614 #if FICL_ROBUST > 1
615 vmCheckStack(pVM, 1, 1);
616 #endif
617 fd = stackPopINT(pVM->pStack);
618 i = read(fd, &ch, 1);
619 stackPushINT(pVM->pStack, i > 0 ? ch : -1);
620 return;
621 }
622
623 /*
624 ** Retrieves free space remaining on the dictionary
625 */
626
627 static void freeHeap(FICL_VM *pVM)
628 {
629 stackPushINT(pVM->pStack, dictCellsAvail(ficlGetDict(pVM->pSys)));
630 }
631
632
633 /******************* Increase dictionary size on-demand ******************/
634
635 static void ficlDictThreshold(FICL_VM *pVM)
636 {
637 stackPushPtr(pVM->pStack, &dictThreshold);
638 }
639
640 static void ficlDictIncrease(FICL_VM *pVM)
641 {
642 stackPushPtr(pVM->pStack, &dictIncrease);
643 }
644
645
646 /**************************************************************************
647 f i c l C o m p i l e P l a t f o r m
648 ** Build FreeBSD platform extensions into the system dictionary
649 **************************************************************************/
650 void ficlCompilePlatform(FICL_SYSTEM *pSys)
651 {
652 FICL_DICT *dp = pSys->dp;
653 assert (dp);
654
655 dictAppendWord(dp, ".#", displayCellNoPad, FW_DEFAULT);
656 dictAppendWord(dp, "fopen", pfopen, FW_DEFAULT);
657 dictAppendWord(dp, "fclose", pfclose, FW_DEFAULT);
658 dictAppendWord(dp, "fread", pfread, FW_DEFAULT);
659 dictAppendWord(dp, "fload", pfload, FW_DEFAULT);
660 dictAppendWord(dp, "fkey", fkey, FW_DEFAULT);
661 dictAppendWord(dp, "fseek", pfseek, FW_DEFAULT);
662 dictAppendWord(dp, "fwrite", pfwrite, FW_DEFAULT);
663 dictAppendWord(dp, "key", key, FW_DEFAULT);
664 dictAppendWord(dp, "key?", keyQuestion, FW_DEFAULT);
665 dictAppendWord(dp, "ms", ms, FW_DEFAULT);
666 dictAppendWord(dp, "seconds", pseconds, FW_DEFAULT);
667 dictAppendWord(dp, "heap?", freeHeap, FW_DEFAULT);
668 dictAppendWord(dp, "dictthreshold", ficlDictThreshold, FW_DEFAULT);
669 dictAppendWord(dp, "dictincrease", ficlDictIncrease, FW_DEFAULT);
670
671 dictAppendWord(dp, "setenv", ficlSetenv, FW_DEFAULT);
672 dictAppendWord(dp, "setenv?", ficlSetenvq, FW_DEFAULT);
673 dictAppendWord(dp, "getenv", ficlGetenv, FW_DEFAULT);
674 dictAppendWord(dp, "unsetenv", ficlUnsetenv, FW_DEFAULT);
675 dictAppendWord(dp, "copyin", ficlCopyin, FW_DEFAULT);
676 dictAppendWord(dp, "copyout", ficlCopyout, FW_DEFAULT);
677 dictAppendWord(dp, "findfile", ficlFindfile, FW_DEFAULT);
678 dictAppendWord(dp, "ccall", ficlCcall, FW_DEFAULT);
679 #ifndef TESTMAIN
680 #ifdef __i386__
681 dictAppendWord(dp, "outb", ficlOutb, FW_DEFAULT);
682 dictAppendWord(dp, "inb", ficlInb, FW_DEFAULT);
683 #endif
684 #ifdef HAVE_PNP
685 dictAppendWord(dp, "pnpdevices",ficlPnpdevices, FW_DEFAULT);
686 dictAppendWord(dp, "pnphandlers",ficlPnphandlers, FW_DEFAULT);
687 #endif
688 #endif
689
690 #if defined(PC98)
691 ficlSetEnv(pSys, "arch-pc98", FICL_TRUE);
692 #elif defined(__i386__)
693 ficlSetEnv(pSys, "arch-i386", FICL_TRUE);
694 ficlSetEnv(pSys, "arch-ia64", FICL_FALSE);
695 ficlSetEnv(pSys, "arch-powerpc", FICL_FALSE);
696 #elif defined(__ia64__)
697 ficlSetEnv(pSys, "arch-i386", FICL_FALSE);
698 ficlSetEnv(pSys, "arch-ia64", FICL_TRUE);
699 ficlSetEnv(pSys, "arch-powerpc", FICL_FALSE);
700 #elif defined(__powerpc__)
701 ficlSetEnv(pSys, "arch-i386", FICL_FALSE);
702 ficlSetEnv(pSys, "arch-ia64", FICL_FALSE);
703 ficlSetEnv(pSys, "arch-powerpc", FICL_TRUE);
704 #endif
705
706 return;
707 }
708
Cache object: d681d3a23712617d76898f01baf9deb7
|