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