xref: /NextBSD/sys/boot/ficl/loader.c (revision 4bd223b0371c53deeecdce2da1261be49546bd6e)
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 <sys/types.h>
37 #include <sys/stat.h>
38 #include <dirent.h>
39 #include <fcntl.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #else
44 #include <stand.h>
45 #endif
46 #include "bootstrap.h"
47 #include <string.h>
48 #include "ficl.h"
49 
50 /*		FreeBSD's loader interaction words and extras
51  *
52  * 		setenv      ( value n name n' -- )
53  * 		setenv?     ( value n name n' flag -- )
54  * 		getenv      ( addr n -- addr' n' | -1 )
55  * 		unsetenv    ( addr n -- )
56  * 		copyin      ( addr addr' len -- )
57  * 		copyout     ( addr addr' len -- )
58  * 		findfile    ( name len type len' -- addr )
59  * 		pnpdevices  ( -- addr )
60  * 		pnphandlers ( -- addr )
61  * 		ccall       ( [[...[p10] p9] ... p1] n addr -- result )
62  * 		.#	    ( value -- )
63  */
64 
65 void
ficlSetenv(FICL_VM * pVM)66 ficlSetenv(FICL_VM *pVM)
67 {
68 #ifndef TESTMAIN
69 	char	*name, *value;
70 #endif
71 	char	*namep, *valuep;
72 	int	names, values;
73 
74 #if FICL_ROBUST > 1
75 	vmCheckStack(pVM, 4, 0);
76 #endif
77 	names = stackPopINT(pVM->pStack);
78 	namep = (char*) stackPopPtr(pVM->pStack);
79 	values = stackPopINT(pVM->pStack);
80 	valuep = (char*) stackPopPtr(pVM->pStack);
81 
82 #ifndef TESTMAIN
83 	name = (char*) ficlMalloc(names+1);
84 	if (!name)
85 		vmThrowErr(pVM, "Error: out of memory");
86 	strncpy(name, namep, names);
87 	name[names] = '\0';
88 	value = (char*) ficlMalloc(values+1);
89 	if (!value)
90 		vmThrowErr(pVM, "Error: out of memory");
91 	strncpy(value, valuep, values);
92 	value[values] = '\0';
93 
94 	setenv(name, value, 1);
95 	ficlFree(name);
96 	ficlFree(value);
97 #endif
98 
99 	return;
100 }
101 
102 void
ficlSetenvq(FICL_VM * pVM)103 ficlSetenvq(FICL_VM *pVM)
104 {
105 #ifndef TESTMAIN
106 	char	*name, *value;
107 #endif
108 	char	*namep, *valuep;
109 	int	names, values, overwrite;
110 
111 #if FICL_ROBUST > 1
112 	vmCheckStack(pVM, 5, 0);
113 #endif
114 	overwrite = stackPopINT(pVM->pStack);
115 	names = stackPopINT(pVM->pStack);
116 	namep = (char*) stackPopPtr(pVM->pStack);
117 	values = stackPopINT(pVM->pStack);
118 	valuep = (char*) stackPopPtr(pVM->pStack);
119 
120 #ifndef TESTMAIN
121 	name = (char*) ficlMalloc(names+1);
122 	if (!name)
123 		vmThrowErr(pVM, "Error: out of memory");
124 	strncpy(name, namep, names);
125 	name[names] = '\0';
126 	value = (char*) ficlMalloc(values+1);
127 	if (!value)
128 		vmThrowErr(pVM, "Error: out of memory");
129 	strncpy(value, valuep, values);
130 	value[values] = '\0';
131 
132 	setenv(name, value, overwrite);
133 	ficlFree(name);
134 	ficlFree(value);
135 #endif
136 
137 	return;
138 }
139 
140 void
ficlGetenv(FICL_VM * pVM)141 ficlGetenv(FICL_VM *pVM)
142 {
143 #ifndef TESTMAIN
144 	char	*name, *value;
145 #endif
146 	char	*namep;
147 	int	names;
148 
149 #if FICL_ROBUST > 1
150 	vmCheckStack(pVM, 2, 2);
151 #endif
152 	names = stackPopINT(pVM->pStack);
153 	namep = (char*) stackPopPtr(pVM->pStack);
154 
155 #ifndef TESTMAIN
156 	name = (char*) ficlMalloc(names+1);
157 	if (!name)
158 		vmThrowErr(pVM, "Error: out of memory");
159 	strncpy(name, namep, names);
160 	name[names] = '\0';
161 
162 	value = getenv(name);
163 	ficlFree(name);
164 
165 	if(value != NULL) {
166 		stackPushPtr(pVM->pStack, value);
167 		stackPushINT(pVM->pStack, strlen(value));
168 	} else
169 #endif
170 		stackPushINT(pVM->pStack, -1);
171 
172 	return;
173 }
174 
175 void
ficlUnsetenv(FICL_VM * pVM)176 ficlUnsetenv(FICL_VM *pVM)
177 {
178 #ifndef TESTMAIN
179 	char	*name;
180 #endif
181 	char	*namep;
182 	int	names;
183 
184 #if FICL_ROBUST > 1
185 	vmCheckStack(pVM, 2, 0);
186 #endif
187 	names = stackPopINT(pVM->pStack);
188 	namep = (char*) stackPopPtr(pVM->pStack);
189 
190 #ifndef TESTMAIN
191 	name = (char*) ficlMalloc(names+1);
192 	if (!name)
193 		vmThrowErr(pVM, "Error: out of memory");
194 	strncpy(name, namep, names);
195 	name[names] = '\0';
196 
197 	unsetenv(name);
198 	ficlFree(name);
199 #endif
200 
201 	return;
202 }
203 
204 void
ficlCopyin(FICL_VM * pVM)205 ficlCopyin(FICL_VM *pVM)
206 {
207 	void*		src;
208 	vm_offset_t	dest;
209 	size_t		len;
210 
211 #if FICL_ROBUST > 1
212 	vmCheckStack(pVM, 3, 0);
213 #endif
214 
215 	len = stackPopINT(pVM->pStack);
216 	dest = stackPopINT(pVM->pStack);
217 	src = stackPopPtr(pVM->pStack);
218 
219 #ifndef TESTMAIN
220 	archsw.arch_copyin(src, dest, len);
221 #endif
222 
223 	return;
224 }
225 
226 void
ficlCopyout(FICL_VM * pVM)227 ficlCopyout(FICL_VM *pVM)
228 {
229 	void*		dest;
230 	vm_offset_t	src;
231 	size_t		len;
232 
233 #if FICL_ROBUST > 1
234 	vmCheckStack(pVM, 3, 0);
235 #endif
236 
237 	len = stackPopINT(pVM->pStack);
238 	dest = stackPopPtr(pVM->pStack);
239 	src = stackPopINT(pVM->pStack);
240 
241 #ifndef TESTMAIN
242 	archsw.arch_copyout(src, dest, len);
243 #endif
244 
245 	return;
246 }
247 
248 void
ficlFindfile(FICL_VM * pVM)249 ficlFindfile(FICL_VM *pVM)
250 {
251 #ifndef TESTMAIN
252 	char	*name, *type;
253 #endif
254 	char	*namep, *typep;
255 	struct	preloaded_file* fp;
256 	int	names, types;
257 
258 #if FICL_ROBUST > 1
259 	vmCheckStack(pVM, 4, 1);
260 #endif
261 
262 	types = stackPopINT(pVM->pStack);
263 	typep = (char*) stackPopPtr(pVM->pStack);
264 	names = stackPopINT(pVM->pStack);
265 	namep = (char*) stackPopPtr(pVM->pStack);
266 #ifndef TESTMAIN
267 	name = (char*) ficlMalloc(names+1);
268 	if (!name)
269 		vmThrowErr(pVM, "Error: out of memory");
270 	strncpy(name, namep, names);
271 	name[names] = '\0';
272 	type = (char*) ficlMalloc(types+1);
273 	if (!type)
274 		vmThrowErr(pVM, "Error: out of memory");
275 	strncpy(type, typep, types);
276 	type[types] = '\0';
277 
278 	fp = file_findfile(name, type);
279 #else
280 	fp = NULL;
281 #endif
282 	stackPushPtr(pVM->pStack, fp);
283 
284 	return;
285 }
286 
287 #ifndef TESTMAIN
288 #ifdef HAVE_PNP
289 
290 void
ficlPnpdevices(FICL_VM * pVM)291 ficlPnpdevices(FICL_VM *pVM)
292 {
293 	static int pnp_devices_initted = 0;
294 #if FICL_ROBUST > 1
295 	vmCheckStack(pVM, 0, 1);
296 #endif
297 
298 	if(!pnp_devices_initted) {
299 		STAILQ_INIT(&pnp_devices);
300 		pnp_devices_initted = 1;
301 	}
302 
303 	stackPushPtr(pVM->pStack, &pnp_devices);
304 
305 	return;
306 }
307 
308 void
ficlPnphandlers(FICL_VM * pVM)309 ficlPnphandlers(FICL_VM *pVM)
310 {
311 #if FICL_ROBUST > 1
312 	vmCheckStack(pVM, 0, 1);
313 #endif
314 
315 	stackPushPtr(pVM->pStack, pnphandlers);
316 
317 	return;
318 }
319 
320 #endif
321 
322 #endif /* ndef TESTMAIN */
323 
324 void
ficlCcall(FICL_VM * pVM)325 ficlCcall(FICL_VM *pVM)
326 {
327 	int (*func)(int, ...);
328 	int result, p[10];
329 	int nparam, i;
330 
331 #if FICL_ROBUST > 1
332 	vmCheckStack(pVM, 2, 0);
333 #endif
334 
335 	func = stackPopPtr(pVM->pStack);
336 	nparam = stackPopINT(pVM->pStack);
337 
338 #if FICL_ROBUST > 1
339 	vmCheckStack(pVM, nparam, 1);
340 #endif
341 
342 	for (i = 0; i < nparam; i++)
343 		p[i] = stackPopINT(pVM->pStack);
344 
345 	result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8],
346 	    p[9]);
347 
348 	stackPushINT(pVM->pStack, result);
349 
350 	return;
351 }
352 
353 /**************************************************************************
354                         f i c l E x e c F D
355 ** reads in text from file fd and passes it to ficlExec()
356  * returns VM_OUTOFTEXT on success or the ficlExec() error code on
357  * failure.
358  */
359 #define nLINEBUF 256
ficlExecFD(FICL_VM * pVM,int fd)360 int ficlExecFD(FICL_VM *pVM, int fd)
361 {
362     char    cp[nLINEBUF];
363     int     nLine = 0, rval = VM_OUTOFTEXT;
364     char    ch;
365     CELL    id;
366 
367     id = pVM->sourceID;
368     pVM->sourceID.i = fd;
369 
370     /* feed each line to ficlExec */
371     while (1) {
372 	int status, i;
373 
374 	i = 0;
375 	while ((status = read(fd, &ch, 1)) > 0 && ch != '\n')
376 	    cp[i++] = ch;
377         nLine++;
378 	if (!i) {
379 	    if (status < 1)
380 		break;
381 	    continue;
382 	}
383         rval = ficlExecC(pVM, cp, i);
384 	if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT)
385         {
386             pVM->sourceID = id;
387             return rval;
388         }
389     }
390     /*
391     ** Pass an empty line with SOURCE-ID == -1 to flush
392     ** any pending REFILLs (as required by FILE wordset)
393     */
394     pVM->sourceID.i = -1;
395     ficlExec(pVM, "");
396 
397     pVM->sourceID = id;
398     return rval;
399 }
400 
displayCellNoPad(FICL_VM * pVM)401 static void displayCellNoPad(FICL_VM *pVM)
402 {
403     CELL c;
404 #if FICL_ROBUST > 1
405     vmCheckStack(pVM, 1, 0);
406 #endif
407     c = stackPop(pVM->pStack);
408     ltoa((c).i, pVM->pad, pVM->base);
409     vmTextOut(pVM, pVM->pad, 0);
410     return;
411 }
412 
413 /*      isdir? - Return whether an fd corresponds to a directory.
414  *
415  * isdir? ( fd -- bool )
416  */
isdirQuestion(FICL_VM * pVM)417 static void isdirQuestion(FICL_VM *pVM)
418 {
419     struct stat sb;
420     FICL_INT flag;
421     int fd;
422 
423 #if FICL_ROBUST > 1
424     vmCheckStack(pVM, 1, 1);
425 #endif
426 
427     fd = stackPopINT(pVM->pStack);
428     flag = FICL_FALSE;
429     do {
430         if (fd < 0)
431             break;
432         if (fstat(fd, &sb) < 0)
433             break;
434         if (!S_ISDIR(sb.st_mode))
435             break;
436         flag = FICL_TRUE;
437     } while (0);
438     stackPushINT(pVM->pStack, flag);
439 }
440 
441 /*          fopen - open a file and return new fd on stack.
442  *
443  * fopen ( ptr count mode -- fd )
444  */
pfopen(FICL_VM * pVM)445 static void pfopen(FICL_VM *pVM)
446 {
447     int     mode, fd, count;
448     char    *ptr, *name;
449 
450 #if FICL_ROBUST > 1
451     vmCheckStack(pVM, 3, 1);
452 #endif
453 
454     mode = stackPopINT(pVM->pStack);    /* get mode */
455     count = stackPopINT(pVM->pStack);   /* get count */
456     ptr = stackPopPtr(pVM->pStack);     /* get ptr */
457 
458     if ((count < 0) || (ptr == NULL)) {
459         stackPushINT(pVM->pStack, -1);
460         return;
461     }
462 
463     /* ensure that the string is null terminated */
464     name = (char *)malloc(count+1);
465     bcopy(ptr,name,count);
466     name[count] = 0;
467 
468     /* open the file */
469     fd = open(name, mode);
470     free(name);
471     stackPushINT(pVM->pStack, fd);
472     return;
473 }
474 
475 /*          fclose - close a file who's fd is on stack.
476  *
477  * fclose ( fd -- )
478  */
pfclose(FICL_VM * pVM)479 static void pfclose(FICL_VM *pVM)
480 {
481     int fd;
482 
483 #if FICL_ROBUST > 1
484     vmCheckStack(pVM, 1, 0);
485 #endif
486     fd = stackPopINT(pVM->pStack); /* get fd */
487     if (fd != -1)
488 	close(fd);
489     return;
490 }
491 
492 /*          fread - read file contents
493  *
494  * fread  ( fd buf nbytes  -- nread )
495  */
pfread(FICL_VM * pVM)496 static void pfread(FICL_VM *pVM)
497 {
498     int     fd, len;
499     char *buf;
500 
501 #if FICL_ROBUST > 1
502     vmCheckStack(pVM, 3, 1);
503 #endif
504     len = stackPopINT(pVM->pStack); /* get number of bytes to read */
505     buf = stackPopPtr(pVM->pStack); /* get buffer */
506     fd = stackPopINT(pVM->pStack); /* get fd */
507     if (len > 0 && buf && fd != -1)
508 	stackPushINT(pVM->pStack, read(fd, buf, len));
509     else
510 	stackPushINT(pVM->pStack, -1);
511     return;
512 }
513 
514 /*      freaddir - read directory contents
515  *
516  * freaddir ( fd -- ptr len TRUE | FALSE )
517  */
pfreaddir(FICL_VM * pVM)518 static void pfreaddir(FICL_VM *pVM)
519 {
520 #ifdef TESTMAIN
521     static struct dirent dirent;
522     struct stat sb;
523     char *buf;
524     off_t off, ptr;
525     u_int blksz;
526     int bufsz;
527 #endif
528     struct dirent *d;
529     int fd;
530 
531 #if FICL_ROBUST > 1
532     vmCheckStack(pVM, 1, 3);
533 #endif
534 
535     fd = stackPopINT(pVM->pStack);
536 #if TESTMAIN
537     /*
538      * The readdirfd() function is specific to the loader environment.
539      * We do the best we can to make freaddir work, but it's not at
540      * all guaranteed.
541      */
542     d = NULL;
543     buf = NULL;
544     do {
545 	if (fd == -1)
546 	    break;
547 	if (fstat(fd, &sb) == -1)
548 	    break;
549 	blksz = (sb.st_blksize) ? sb.st_blksize : getpagesize();
550 	if ((blksz & (blksz - 1)) != 0)
551 	    break;
552 	buf = malloc(blksz);
553 	if (buf == NULL)
554 	    break;
555 	off = lseek(fd, 0LL, SEEK_CUR);
556 	if (off == -1)
557 	    break;
558 	ptr = off;
559 	if (lseek(fd, 0, SEEK_SET) == -1)
560 	    break;
561 	bufsz = getdents(fd, buf, blksz);
562 	while (bufsz > 0 && bufsz <= ptr) {
563 	    ptr -= bufsz;
564 	    bufsz = getdents(fd, buf, blksz);
565 	}
566 	if (bufsz <= 0)
567 	    break;
568 	d = (void *)(buf + ptr);
569 	dirent = *d;
570 	off += d->d_reclen;
571 	d = (lseek(fd, off, SEEK_SET) != off) ? NULL : &dirent;
572     } while (0);
573     if (buf != NULL)
574 	free(buf);
575 #else
576     d = readdirfd(fd);
577 #endif
578     if (d != NULL) {
579         stackPushPtr(pVM->pStack, d->d_name);
580         stackPushINT(pVM->pStack, strlen(d->d_name));
581         stackPushINT(pVM->pStack, FICL_TRUE);
582     } else {
583         stackPushINT(pVM->pStack, FICL_FALSE);
584     }
585 }
586 
587 /*          fload - interpret file contents
588  *
589  * fload  ( fd -- )
590  */
pfload(FICL_VM * pVM)591 static void pfload(FICL_VM *pVM)
592 {
593     int     fd;
594 
595 #if FICL_ROBUST > 1
596     vmCheckStack(pVM, 1, 0);
597 #endif
598     fd = stackPopINT(pVM->pStack); /* get fd */
599     if (fd != -1)
600 	ficlExecFD(pVM, fd);
601     return;
602 }
603 
604 /*          fwrite - write file contents
605  *
606  * fwrite  ( fd buf nbytes  -- nwritten )
607  */
pfwrite(FICL_VM * pVM)608 static void pfwrite(FICL_VM *pVM)
609 {
610     int     fd, len;
611     char *buf;
612 
613 #if FICL_ROBUST > 1
614     vmCheckStack(pVM, 3, 1);
615 #endif
616     len = stackPopINT(pVM->pStack); /* get number of bytes to read */
617     buf = stackPopPtr(pVM->pStack); /* get buffer */
618     fd = stackPopINT(pVM->pStack); /* get fd */
619     if (len > 0 && buf && fd != -1)
620 	stackPushINT(pVM->pStack, write(fd, buf, len));
621     else
622 	stackPushINT(pVM->pStack, -1);
623     return;
624 }
625 
626 /*          fseek - seek to a new position in a file
627  *
628  * fseek  ( fd ofs whence  -- pos )
629  */
pfseek(FICL_VM * pVM)630 static void pfseek(FICL_VM *pVM)
631 {
632     int     fd, pos, whence;
633 
634 #if FICL_ROBUST > 1
635     vmCheckStack(pVM, 3, 1);
636 #endif
637     whence = stackPopINT(pVM->pStack);
638     pos = stackPopINT(pVM->pStack);
639     fd = stackPopINT(pVM->pStack);
640     stackPushINT(pVM->pStack, lseek(fd, pos, whence));
641     return;
642 }
643 
644 /*           key - get a character from stdin
645  *
646  * key ( -- char )
647  */
key(FICL_VM * pVM)648 static void key(FICL_VM *pVM)
649 {
650 #if FICL_ROBUST > 1
651     vmCheckStack(pVM, 0, 1);
652 #endif
653     stackPushINT(pVM->pStack, getchar());
654     return;
655 }
656 
657 /*           key? - check for a character from stdin (FACILITY)
658  *
659  * key? ( -- flag )
660  */
keyQuestion(FICL_VM * pVM)661 static void keyQuestion(FICL_VM *pVM)
662 {
663 #if FICL_ROBUST > 1
664     vmCheckStack(pVM, 0, 1);
665 #endif
666 #ifdef TESTMAIN
667     /* XXX Since we don't fiddle with termios, let it always succeed... */
668     stackPushINT(pVM->pStack, FICL_TRUE);
669 #else
670     /* But here do the right thing. */
671     stackPushINT(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE);
672 #endif
673     return;
674 }
675 
676 /* seconds - gives number of seconds since beginning of time
677  *
678  * beginning of time is defined as:
679  *
680  *	BTX	- number of seconds since midnight
681  *	FreeBSD	- number of seconds since Jan 1 1970
682  *
683  * seconds ( -- u )
684  */
pseconds(FICL_VM * pVM)685 static void pseconds(FICL_VM *pVM)
686 {
687 #if FICL_ROBUST > 1
688     vmCheckStack(pVM,0,1);
689 #endif
690     stackPushUNS(pVM->pStack, (FICL_UNS) time(NULL));
691     return;
692 }
693 
694 /* ms - wait at least that many milliseconds (FACILITY)
695  *
696  * ms ( u -- )
697  *
698  */
ms(FICL_VM * pVM)699 static void ms(FICL_VM *pVM)
700 {
701 #if FICL_ROBUST > 1
702     vmCheckStack(pVM,1,0);
703 #endif
704 #ifdef TESTMAIN
705     usleep(stackPopUNS(pVM->pStack)*1000);
706 #else
707     delay(stackPopUNS(pVM->pStack)*1000);
708 #endif
709     return;
710 }
711 
712 /*           fkey - get a character from a file
713  *
714  * fkey ( file -- char )
715  */
fkey(FICL_VM * pVM)716 static void fkey(FICL_VM *pVM)
717 {
718     int i, fd;
719     char ch;
720 
721 #if FICL_ROBUST > 1
722     vmCheckStack(pVM, 1, 1);
723 #endif
724     fd = stackPopINT(pVM->pStack);
725     i = read(fd, &ch, 1);
726     stackPushINT(pVM->pStack, i > 0 ? ch : -1);
727     return;
728 }
729 
730 
731 #ifdef __i386__
732 /*
733  * pcibios-device-count (devid -- count)
734  *
735  * Returns the PCI BIOS' count of how many devices matching devid are in the system.
736  * devid is the 32-bit vendor + device.
737  */
738 static void
ficlPciBiosCountDevices(FICL_VM * pVM)739 ficlPciBiosCountDevices(FICL_VM *pVM)
740 {
741 	uint32_t devid;
742 	int i;
743 
744 	devid = stackPopINT(pVM->pStack);
745 
746 	i = biospci_count_device_type(devid);
747 
748 	stackPushINT(pVM->pStack, i);
749 }
750 
751 /*
752  * pcibios-write-config (locator offset width value -- )
753  *
754  * Writes the specified config register.
755  * Locator is bus << 8 | device << 3 | fuction
756  * offset is the pci config register
757  * width is 0 for byte, 1 for word, 2 for dword
758  * value is the value to write
759  */
760 static void
ficlPciBiosWriteConfig(FICL_VM * pVM)761 ficlPciBiosWriteConfig(FICL_VM *pVM)
762 {
763 	uint32_t value, width, offset, locator;
764 
765 	value = stackPopINT(pVM->pStack);
766 	width = stackPopINT(pVM->pStack);
767 	offset = stackPopINT(pVM->pStack);
768 	locator = stackPopINT(pVM->pStack);
769 
770 	biospci_write_config(locator, offset, width, value);
771 }
772 
773 /*
774  * pcibios-read-config (locator offset width -- value)
775  *
776  * Reads the specified config register.
777  * Locator is bus << 8 | device << 3 | fuction
778  * offset is the pci config register
779  * width is 0 for byte, 1 for word, 2 for dword
780  * value is the value to read from the register
781  */
782 static void
ficlPciBiosReadConfig(FICL_VM * pVM)783 ficlPciBiosReadConfig(FICL_VM *pVM)
784 {
785 	uint32_t value, width, offset, locator;
786 
787 	width = stackPopINT(pVM->pStack);
788 	offset = stackPopINT(pVM->pStack);
789 	locator = stackPopINT(pVM->pStack);
790 
791 	biospci_read_config(locator, offset, width, &value);
792 
793 	stackPushINT(pVM->pStack, value);
794 }
795 
796 /*
797  * pcibios-find-devclass (class index -- locator)
798  *
799  * Finds the index'th instance of class in the pci tree.
800  * must be an exact match.
801  * class is the class to search for.
802  * index 0..N (set to 0, increment until error)
803  *
804  * Locator is bus << 8 | device << 3 | fuction (or -1 on error)
805  */
806 static void
ficlPciBiosFindDevclass(FICL_VM * pVM)807 ficlPciBiosFindDevclass(FICL_VM *pVM)
808 {
809 	uint32_t index, class, locator;
810 
811 	index = stackPopINT(pVM->pStack);
812 	class = stackPopINT(pVM->pStack);
813 
814 	if (biospci_find_devclass(class, index, &locator))
815 		locator = 0xffffffff;
816 
817 	stackPushINT(pVM->pStack, locator);
818 }
819 
820 /*
821  * pcibios-find-device(devid index -- locator)
822  *
823  * Finds the index'th instance of devid in the pci tree.
824  * must be an exact match.
825  * class is the class to search for.
826  * index 0..N (set to 0, increment until error)
827  *
828  * Locator is bus << 8 | device << 3 | fuction (or -1 on error)
829  */
830 static void
ficlPciBiosFindDevice(FICL_VM * pVM)831 ficlPciBiosFindDevice(FICL_VM *pVM)
832 {
833 	uint32_t index, devid, locator;
834 
835 	index = stackPopINT(pVM->pStack);
836 	devid = stackPopINT(pVM->pStack);
837 
838 	if (biospci_find_device(devid, index, &locator))
839 		locator = 0xffffffff;
840 
841 	stackPushINT(pVM->pStack, locator);
842 }
843 
844 /*
845  * pcibios-find-device(bus device function -- locator)
846  *
847  * converts bus, device, function to locator.
848  *
849  * Locator is bus << 8 | device << 3 | fuction
850  */
851 static void
ficlPciBiosLocator(FICL_VM * pVM)852 ficlPciBiosLocator(FICL_VM *pVM)
853 {
854 	uint32_t bus, device, function, locator;
855 
856 	function = stackPopINT(pVM->pStack);
857 	device = stackPopINT(pVM->pStack);
858 	bus = stackPopINT(pVM->pStack);
859 
860 	locator = biospci_locator(bus, device, function);
861 
862 	stackPushINT(pVM->pStack, locator);
863 }
864 #endif
865 
866 /*
867 ** Retrieves free space remaining on the dictionary
868 */
869 
freeHeap(FICL_VM * pVM)870 static void freeHeap(FICL_VM *pVM)
871 {
872     stackPushINT(pVM->pStack, dictCellsAvail(ficlGetDict(pVM->pSys)));
873 }
874 
875 
876 /******************* Increase dictionary size on-demand ******************/
877 
ficlDictThreshold(FICL_VM * pVM)878 static void ficlDictThreshold(FICL_VM *pVM)
879 {
880     stackPushPtr(pVM->pStack, &dictThreshold);
881 }
882 
ficlDictIncrease(FICL_VM * pVM)883 static void ficlDictIncrease(FICL_VM *pVM)
884 {
885     stackPushPtr(pVM->pStack, &dictIncrease);
886 }
887 
888 /**************************************************************************
889                         f i c l C o m p i l e P l a t f o r m
890 ** Build FreeBSD platform extensions into the system dictionary
891 **************************************************************************/
ficlCompilePlatform(FICL_SYSTEM * pSys)892 void ficlCompilePlatform(FICL_SYSTEM *pSys)
893 {
894     FICL_DICT *dp = pSys->dp;
895     assert (dp);
896 
897     dictAppendWord(dp, ".#",        displayCellNoPad,    FW_DEFAULT);
898     dictAppendWord(dp, "isdir?",    isdirQuestion,  FW_DEFAULT);
899     dictAppendWord(dp, "fopen",	    pfopen,	    FW_DEFAULT);
900     dictAppendWord(dp, "fclose",    pfclose,	    FW_DEFAULT);
901     dictAppendWord(dp, "fread",	    pfread,	    FW_DEFAULT);
902     dictAppendWord(dp, "freaddir",  pfreaddir,	    FW_DEFAULT);
903     dictAppendWord(dp, "fload",	    pfload,	    FW_DEFAULT);
904     dictAppendWord(dp, "fkey",	    fkey,	    FW_DEFAULT);
905     dictAppendWord(dp, "fseek",     pfseek,	    FW_DEFAULT);
906     dictAppendWord(dp, "fwrite",    pfwrite,	    FW_DEFAULT);
907     dictAppendWord(dp, "key",	    key,	    FW_DEFAULT);
908     dictAppendWord(dp, "key?",	    keyQuestion,    FW_DEFAULT);
909     dictAppendWord(dp, "ms",        ms,             FW_DEFAULT);
910     dictAppendWord(dp, "seconds",   pseconds,       FW_DEFAULT);
911     dictAppendWord(dp, "heap?",     freeHeap,       FW_DEFAULT);
912     dictAppendWord(dp, "dictthreshold", ficlDictThreshold, FW_DEFAULT);
913     dictAppendWord(dp, "dictincrease", ficlDictIncrease, FW_DEFAULT);
914 
915     dictAppendWord(dp, "setenv",    ficlSetenv,	    FW_DEFAULT);
916     dictAppendWord(dp, "setenv?",   ficlSetenvq,    FW_DEFAULT);
917     dictAppendWord(dp, "getenv",    ficlGetenv,	    FW_DEFAULT);
918     dictAppendWord(dp, "unsetenv",  ficlUnsetenv,   FW_DEFAULT);
919     dictAppendWord(dp, "copyin",    ficlCopyin,	    FW_DEFAULT);
920     dictAppendWord(dp, "copyout",   ficlCopyout,    FW_DEFAULT);
921     dictAppendWord(dp, "findfile",  ficlFindfile,   FW_DEFAULT);
922     dictAppendWord(dp, "ccall",	    ficlCcall,	    FW_DEFAULT);
923 #ifndef TESTMAIN
924 #ifdef __i386__
925     dictAppendWord(dp, "outb",      ficlOutb,       FW_DEFAULT);
926     dictAppendWord(dp, "inb",       ficlInb,        FW_DEFAULT);
927 #endif
928 #ifdef HAVE_PNP
929     dictAppendWord(dp, "pnpdevices",ficlPnpdevices, FW_DEFAULT);
930     dictAppendWord(dp, "pnphandlers",ficlPnphandlers, FW_DEFAULT);
931 #endif
932 #endif
933 #ifdef __i386__
934     dictAppendWord(dp, "pcibios-device-count", ficlPciBiosCountDevices, FW_DEFAULT);
935     dictAppendWord(dp, "pcibios-read-config", ficlPciBiosReadConfig, FW_DEFAULT);
936     dictAppendWord(dp, "pcibios-write-config", ficlPciBiosWriteConfig, FW_DEFAULT);
937     dictAppendWord(dp, "pcibios-find-devclass", ficlPciBiosFindDevclass, FW_DEFAULT);
938     dictAppendWord(dp, "pcibios-find-device", ficlPciBiosFindDevice, FW_DEFAULT);
939     dictAppendWord(dp, "pcibios-locator", ficlPciBiosLocator, FW_DEFAULT);
940 #endif
941 
942 #if defined(PC98)
943     ficlSetEnv(pSys, "arch-pc98",         FICL_TRUE);
944 #elif defined(__i386__)
945     ficlSetEnv(pSys, "arch-i386",         FICL_TRUE);
946     ficlSetEnv(pSys, "arch-powerpc",      FICL_FALSE);
947 #elif defined(__powerpc__)
948     ficlSetEnv(pSys, "arch-i386",         FICL_FALSE);
949     ficlSetEnv(pSys, "arch-powerpc",      FICL_TRUE);
950 #endif
951 
952     return;
953 }
954