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