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