]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/boot/ficl/loader.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / 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