1 /* This file is part of the program psim. 2 3 Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, see <http://www.gnu.org/licenses/>. 17 18 */ 19 20 21 #ifndef _EMUL_CHIRP_C_ 22 #define _EMUL_CHIRP_C_ 23 24 /* Note: this module is called via a table. There is no benefit in 25 making it inline */ 26 27 #include "emul_generic.h" 28 #include "emul_chirp.h" 29 30 #include <string.h> 31 #ifdef HAVE_UNISTD_H 32 #include <unistd.h> 33 #endif 34 35 #ifndef STATIC_INLINE_EMUL_CHIRP 36 #define STATIC_INLINE_EMUL_CHIRP STATIC_INLINE 37 #endif 38 39 40 /* EMULATION 41 42 43 OpenFirmware - IEEE Standard for Boot (Initialization 44 Configuration) Firmware. 45 46 47 DESCRIPTION 48 49 50 BUGS 51 52 53 This code assumes that the memory node has #address-cells and 54 #size-cells set to one. For future implementations, this may not 55 be the case. 56 57 */ 58 59 60 61 62 /* Descriptor of the open boot services being emulated */ 63 64 typedef int (chirp_handler) 65 (os_emul_data *data, 66 cpu *processor, 67 unsigned_word cia); 68 69 typedef struct _chirp_services { 70 const char *name; 71 chirp_handler *handler; 72 } chirp_services; 73 74 75 /* The OpenBoot emulation is, at any time either waiting for a client 76 request or waiting on a client callback */ 77 typedef enum { 78 serving, 79 emulating, 80 faulting, 81 } chirp_emul_state; 82 83 struct _os_emul_data { 84 chirp_emul_state state; 85 unsigned_word return_address; 86 unsigned_word arguments; 87 unsigned_word n_args; 88 unsigned_word n_returns; 89 chirp_services *service; 90 device *root; 91 chirp_services *services; 92 /* configuration */ 93 unsigned_word memory_size; 94 unsigned_word real_base; 95 unsigned_word real_size; 96 unsigned_word virt_base; 97 unsigned_word virt_size; 98 int real_mode; 99 int little_endian; 100 int floating_point_available; 101 int interrupt_prefix; 102 unsigned_word load_base; 103 /* hash table */ 104 unsigned_word nr_page_table_entry_groups; 105 unsigned_word htab_offset; 106 unsigned_word htab_ra; 107 unsigned_word htab_va; 108 unsigned_word sizeof_htab; 109 /* virtual address of htab */ 110 unsigned_word stack_offset; 111 unsigned_word stack_ra; 112 unsigned_word stack_va; 113 unsigned_word sizeof_stack; 114 /* addresses of emulation instructions virtual/real */ 115 unsigned_word code_offset; 116 unsigned_word code_va; 117 unsigned_word code_ra; 118 unsigned_word sizeof_code; 119 unsigned_word code_client_va; 120 unsigned_word code_client_ra; 121 unsigned_word code_callback_va; 122 unsigned_word code_callback_ra; 123 unsigned_word code_loop_va; 124 unsigned_word code_loop_ra; 125 }; 126 127 128 /* returns the name of the corresponding Ihandle */ 129 static const char * 130 ihandle_name(device_instance *ihandle) 131 { 132 if (ihandle == NULL) 133 return ""; 134 else 135 return device_name(device_instance_device(ihandle)); 136 } 137 138 139 140 /* Read/write the argument list making certain that all values are 141 converted to/from host byte order. 142 143 In the below only n_args+n_returns is read/written */ 144 145 static int 146 chirp_read_t2h_args(void *args, 147 int sizeof_args, 148 int n_args, 149 int n_returns, 150 os_emul_data *data, 151 cpu *processor, 152 unsigned_word cia) 153 { 154 unsigned_cell *words; 155 int i; 156 /* check against the number of arguments specified by the client 157 program */ 158 if ((n_args >= 0 && data->n_args != n_args) 159 || (n_returns >= 0 && data->n_returns != n_returns)) { 160 TRACE(trace_os_emul, ("%s - invalid nr of args - n_args=%ld, n_returns=%ld\n", 161 data->service->name, 162 (long)data->n_args, 163 (long)data->n_returns)); 164 return -1; 165 } 166 /* check that there is enough space */ 167 if (sizeof(unsigned_cell) * (data->n_args + data->n_returns) > sizeof_args) 168 return -1; 169 /* bring in the data */ 170 memset(args, 0, sizeof_args); 171 emul_read_buffer(args, data->arguments + 3 * sizeof(unsigned_cell), 172 sizeof(unsigned_cell) * (data->n_args + data->n_returns), 173 processor, cia); 174 /* convert all words to host format */ 175 words = args; 176 for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++) 177 words[i] = T2H_cell(words[i]); 178 return 0; 179 } 180 181 static void 182 chirp_write_h2t_args(void *args, 183 int sizeof_args, 184 os_emul_data *data, 185 cpu *processor, 186 unsigned_word cia) 187 { 188 int i; 189 unsigned_cell *words; 190 /* convert to target everything */ 191 words = args; 192 for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++) 193 words[i] = H2T_cell(words[i]); 194 /* bring in the data */ 195 emul_write_buffer(args, data->arguments + 3 * sizeof(unsigned_cell), 196 sizeof(unsigned_cell) * (data->n_args + data->n_returns), 197 processor, cia); 198 } 199 200 201 /* OpenBoot emulation functions */ 202 203 /* client interface */ 204 205 static int 206 chirp_emul_test(os_emul_data *data, 207 cpu *processor, 208 unsigned_word cia) 209 { 210 struct test_args { 211 /*in*/ 212 unsigned_cell name; /*string*/ 213 /*out*/ 214 unsigned_cell missing; 215 } args; 216 char name[32]; 217 chirp_services *service = NULL; 218 /* read in the arguments */ 219 if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) 220 return -1; 221 emul_read_string(name, args.name, sizeof(name), 222 processor, cia); 223 TRACE(trace_os_emul, ("test - in - name=`%s'\n", name)); 224 /* see if we know about the service */ 225 service = data->services; 226 while (service->name != NULL && strcmp(service->name, name) != 0) { 227 service++; 228 } 229 if (service->name == NULL) 230 args.missing = -1; 231 else 232 args.missing = 0; 233 /* write the arguments back out */ 234 TRACE(trace_os_emul, ("test - out - missing=%ld\n", 235 (long)args.missing)); 236 chirp_write_h2t_args(&args, 237 sizeof(args), 238 data, 239 processor, cia); 240 return 0; 241 } 242 243 244 /* Device tree */ 245 246 static int 247 chirp_emul_peer(os_emul_data *data, 248 cpu *processor, 249 unsigned_word cia) 250 { 251 struct peer_args { 252 /*in*/ 253 unsigned_cell phandle; 254 /*out*/ 255 unsigned_cell sibling_phandle; 256 } args; 257 device *phandle; 258 device *sibling_phandle = NULL; 259 /* read in the arguments */ 260 if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) 261 return -1; 262 phandle = external_to_device(data->root, args.phandle); 263 TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(%p`%s')\n", 264 (unsigned long)args.phandle, 265 phandle, 266 (phandle == NULL ? "" : device_name(phandle)))); 267 /* find the peer */ 268 if (args.phandle == 0) { 269 sibling_phandle = data->root; 270 args.sibling_phandle = device_to_external(sibling_phandle); 271 } 272 else if (phandle == NULL) { 273 sibling_phandle = NULL; 274 args.sibling_phandle = -1; 275 } 276 else { 277 sibling_phandle = device_sibling(phandle); 278 if (sibling_phandle == NULL) 279 args.sibling_phandle = 0; 280 else 281 args.sibling_phandle = device_to_external(sibling_phandle); 282 } 283 /* write the arguments back out */ 284 TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(%p`%s')\n", 285 (unsigned long)args.sibling_phandle, 286 sibling_phandle, 287 (sibling_phandle == NULL ? "" : device_name(sibling_phandle)))); 288 chirp_write_h2t_args(&args, 289 sizeof(args), 290 data, 291 processor, cia); 292 return 0; 293 } 294 295 static int 296 chirp_emul_child(os_emul_data *data, 297 cpu *processor, 298 unsigned_word cia) 299 { 300 struct child_args { 301 /*in*/ 302 unsigned_cell phandle; 303 /*out*/ 304 unsigned_cell child_phandle; 305 } args; 306 device *phandle; 307 device *child_phandle; 308 /* read the arguments in */ 309 if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) 310 return -1; 311 phandle = external_to_device(data->root, args.phandle); 312 TRACE(trace_os_emul, ("child - in - phandle=0x%lx(%p`%s')\n", 313 (unsigned long)args.phandle, 314 phandle, 315 (phandle == NULL ? "" : device_name(phandle)))); 316 /* find a child */ 317 if (args.phandle == 0 318 || phandle == NULL) { 319 child_phandle = NULL; 320 args.child_phandle = -1; 321 } 322 else { 323 child_phandle = device_child(phandle); 324 if (child_phandle == NULL) 325 args.child_phandle = 0; 326 else 327 args.child_phandle = device_to_external(child_phandle); 328 } 329 /* write the result out */ 330 TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(%p`%s')\n", 331 (unsigned long)args.child_phandle, 332 child_phandle, 333 (child_phandle == NULL ? "" : device_name(child_phandle)))); 334 chirp_write_h2t_args(&args, 335 sizeof(args), 336 data, 337 processor, cia); 338 return 0; 339 } 340 341 static int 342 chirp_emul_parent(os_emul_data *data, 343 cpu *processor, 344 unsigned_word cia) 345 { 346 struct parent_args { 347 /*in*/ 348 unsigned_cell phandle; 349 /*out*/ 350 unsigned_cell parent_phandle; 351 } args; 352 device *phandle; 353 device *parent_phandle; 354 /* read the args in */ 355 if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) 356 return -1; 357 phandle = external_to_device(data->root, args.phandle); 358 TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(%p`%s')\n", 359 (unsigned long)args.phandle, 360 phandle, 361 (phandle == NULL ? "" : device_name(phandle)))); 362 /* find a parent */ 363 if (args.phandle == 0 364 || phandle == NULL) { 365 parent_phandle = NULL; 366 args.parent_phandle = -1; 367 } 368 else { 369 parent_phandle = device_parent(phandle); 370 if (parent_phandle == NULL) 371 args.parent_phandle = 0; 372 else 373 args.parent_phandle = device_to_external(parent_phandle); 374 } 375 /* return the result */ 376 TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(%p`%s')\n", 377 (unsigned long)args.parent_phandle, 378 parent_phandle, 379 (parent_phandle == NULL ? "" : device_name(parent_phandle)))); 380 chirp_write_h2t_args(&args, 381 sizeof(args), 382 data, 383 processor, cia); 384 return 0; 385 } 386 387 static int 388 chirp_emul_instance_to_package(os_emul_data *data, 389 cpu *processor, 390 unsigned_word cia) 391 { 392 struct instance_to_package_args { 393 /*in*/ 394 unsigned_cell ihandle; 395 /*out*/ 396 unsigned_cell phandle; 397 } args; 398 device_instance *ihandle; 399 device *phandle = NULL; 400 /* read the args in */ 401 if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) 402 return -1; 403 ihandle = external_to_device_instance(data->root, args.ihandle); 404 TRACE(trace_os_emul, ("instance-to-package - in - ihandle=0x%lx(%p`%s')\n", 405 (unsigned long)args.ihandle, 406 ihandle, 407 ihandle_name(ihandle))); 408 /* find the corresponding phandle */ 409 if (ihandle == NULL) { 410 phandle = NULL; 411 args.phandle = -1; 412 } 413 else { 414 phandle = device_instance_device(ihandle); 415 args.phandle = device_to_external(phandle); 416 } 417 /* return the result */ 418 TRACE(trace_os_emul, ("instance-to-package - out - phandle=0x%lx(%p`%s')\n", 419 (unsigned long)args.phandle, 420 phandle, 421 (phandle == NULL ? "" : device_name(phandle)))); 422 chirp_write_h2t_args(&args, 423 sizeof(args), 424 data, 425 processor, cia); 426 return 0; 427 } 428 429 static int 430 chirp_emul_getproplen(os_emul_data *data, 431 cpu *processor, 432 unsigned_word cia) 433 { 434 struct getproplen_args { 435 /*in*/ 436 unsigned_cell phandle; 437 unsigned_cell name; 438 /*out*/ 439 unsigned_cell proplen; 440 } args; 441 char name[32]; 442 device *phandle; 443 /* read the args in */ 444 if (chirp_read_t2h_args(&args, sizeof(args), 2, 1, data, processor, cia)) 445 return -1; 446 phandle = external_to_device(data->root, args.phandle); 447 emul_read_string(name, 448 args.name, 449 sizeof(name), 450 processor, cia); 451 TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(%p`%s') name=`%s'\n", 452 (unsigned long)args.phandle, 453 phandle, 454 (phandle == NULL ? "" : device_name(phandle)), 455 name)); 456 /* find our prop and get its length */ 457 if (args.phandle == 0 458 || phandle == NULL) { 459 args.proplen = -1; 460 } 461 else { 462 const device_property *prop = device_find_property(phandle, name); 463 if (prop == (device_property*)0) { 464 args.proplen = -1; 465 } 466 else { 467 args.proplen = prop->sizeof_array; 468 } 469 } 470 /* return the result */ 471 TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n", 472 (unsigned long)args.proplen)); 473 chirp_write_h2t_args(&args, 474 sizeof(args), 475 data, 476 processor, cia); 477 return 0; 478 } 479 480 static int 481 chirp_emul_getprop(os_emul_data *data, 482 cpu *processor, 483 unsigned_word cia) 484 { 485 struct getprop_args { 486 /*in*/ 487 unsigned_cell phandle; 488 unsigned_cell name; 489 unsigned_cell buf; 490 unsigned_cell buflen; 491 /*out*/ 492 unsigned_cell size; 493 } args; 494 char name[32]; 495 device *phandle; 496 /* read in the args, the return is optional */ 497 if (chirp_read_t2h_args(&args, sizeof(args), 4, -1, data, processor, cia)) 498 return -1; 499 phandle = external_to_device(data->root, args.phandle); 500 emul_read_string(name, 501 args.name, 502 sizeof(name), 503 processor, cia); 504 TRACE(trace_os_emul, ("getprop - in - phandle=0x%lx(%p`%s') name=`%s' buf=0x%lx buflen=%ld\n", 505 (unsigned long)args.phandle, 506 phandle, 507 (phandle == NULL ? "" : device_name(phandle)), 508 name, 509 (unsigned long)args.buf, 510 (unsigned long)args.buflen)); 511 /* get the property */ 512 if (args.phandle == 0 513 || phandle == NULL) { 514 args.size = -1; 515 } 516 else { 517 const device_property *prop = device_find_property(phandle, name); 518 if (prop == NULL) { 519 args.size = -1; 520 } 521 else { 522 int size = args.buflen; 523 if (size > prop->sizeof_array) 524 size = prop->sizeof_array; 525 emul_write_buffer(prop->array, args.buf, 526 size, 527 processor, cia); 528 args.size = size; 529 switch (prop->type) { 530 case string_property: 531 TRACE(trace_os_emul, ("getprop - string `%s'\n", 532 device_find_string_property(phandle, name))); 533 break; 534 case ihandle_property: 535 TRACE(trace_os_emul, ("getprop - ihandle=0x%lx(%p`%s')\n", 536 (unsigned long)BE2H_cell(*(unsigned_cell*)prop->array), 537 device_find_ihandle_property(phandle, name), 538 ihandle_name(device_find_ihandle_property(phandle, name)))); 539 break; 540 default: 541 break; 542 } 543 } 544 } 545 /* write back the result */ 546 if (data->n_returns == 0) 547 TRACE(trace_os_emul, ("getprop - out - size=%ld (not returned)\n", 548 (unsigned long)args.size)); 549 else { 550 TRACE(trace_os_emul, ("getprop - out - size=%ld\n", 551 (unsigned long)args.size)); 552 chirp_write_h2t_args(&args, 553 sizeof(args), 554 data, 555 processor, cia); 556 } 557 return 0; 558 } 559 560 static int 561 chirp_emul_nextprop(os_emul_data *data, 562 cpu *processor, 563 unsigned_word cia) 564 { 565 struct nextprop_args { 566 /*in*/ 567 unsigned_cell phandle; 568 unsigned_cell previous; 569 unsigned_cell buf; 570 /*out*/ 571 unsigned_cell flag; 572 } args; 573 char previous[32]; 574 device *phandle; 575 /* read in the args */ 576 if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) 577 return -1; 578 phandle = external_to_device(data->root, args.phandle); 579 if (args.previous != 0) 580 emul_read_string(previous, 581 args.previous, 582 sizeof(previous), 583 processor, cia); 584 else 585 /* If previous is NULL, make it look like the empty string. The 586 next property after the empty string is the first property. */ 587 strcpy (previous, ""); 588 TRACE(trace_os_emul, ("nextprop - in - phandle=0x%lx(%p`%s') previous=`%s' buf=0x%lx\n", 589 (unsigned long)args.phandle, 590 phandle, 591 (phandle == NULL ? "" : device_name(phandle)), 592 previous, 593 (unsigned long)args.buf)); 594 /* find the next property */ 595 if (args.phandle == 0 596 || phandle == NULL) { 597 args.flag = -1; 598 } 599 else { 600 const device_property *prev_prop = device_find_property(phandle, previous); 601 if (prev_prop == NULL) { 602 if (strcmp (previous, "") == 0) 603 args.flag = 0; /* No properties */ 604 else 605 args.flag = -1; /* name invalid */ 606 } 607 else { 608 const device_property *next_prop; 609 if (strcmp (previous, "") == 0) { 610 next_prop = prev_prop; /* The first property. */ 611 } 612 else { 613 next_prop = device_next_property(prev_prop); 614 } 615 if (next_prop == NULL) { 616 args.flag = 0; /* last property */ 617 } 618 else { 619 emul_write_buffer(next_prop->name, args.buf, strlen(next_prop->name), 620 processor, cia); 621 TRACE(trace_os_emul, ("nextprop - name=`%s'\n", next_prop->name)); 622 args.flag = 1; /* worked ok */ 623 } 624 } 625 } 626 /* write back the result */ 627 TRACE(trace_os_emul, ("nextprop - out - flag=%ld\n", 628 (unsigned long)args.flag)); 629 chirp_write_h2t_args(&args, 630 sizeof(args), 631 data, 632 processor, cia); 633 return 0; 634 } 635 636 #if 0 637 static int 638 chirp_emul_setprop(os_emul_data *data, 639 cpu *processor, 640 unsigned_word cia) 641 { 642 error("chirp: setprop method not implemented\n"); 643 return 0; 644 } 645 #endif 646 647 static int 648 chirp_emul_canon(os_emul_data *data, 649 cpu *processor, 650 unsigned_word cia) 651 { 652 struct canon_args { 653 /*in*/ 654 unsigned_cell device_specifier; 655 unsigned_cell buf; 656 unsigned_cell buflen; 657 /*out*/ 658 unsigned_cell length; 659 } args; 660 char device_specifier[1024]; 661 device *phandle; 662 const char *path; 663 int length; 664 /* read in the args */ 665 if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) 666 return -1; 667 emul_read_string(device_specifier, 668 args.device_specifier, 669 sizeof(device_specifier), 670 processor, cia); 671 TRACE(trace_os_emul, ("canon - in - device_specifier=`%s' buf=0x%lx buflen=%lx\n", 672 device_specifier, 673 (unsigned long)args.buf, 674 (unsigned long)args.buflen)); 675 /* canon the name */ 676 phandle = tree_find_device(data->root, device_specifier); 677 if (phandle == NULL) { 678 length = -1; 679 path = ""; 680 args.length = -1; 681 } 682 else { 683 path = device_path(phandle); 684 length = strlen(path); 685 if (length >= args.buflen) 686 length = args.buflen - 1; 687 emul_write_buffer(path, args.buf, length, 688 processor, cia); 689 args.length = length; 690 } 691 /* write back the result */ 692 TRACE(trace_os_emul, ("canon - out - length=%ld buf=`%s'\n", 693 (unsigned long)args.length, 694 path)); 695 chirp_write_h2t_args(&args, 696 sizeof(args), 697 data, 698 processor, cia); 699 return 0; 700 } 701 702 static int 703 chirp_emul_finddevice(os_emul_data *data, 704 cpu *processor, 705 unsigned_word cia) 706 { 707 struct finddevice_args { 708 /*in*/ 709 unsigned_cell device_specifier; 710 /*out*/ 711 unsigned_cell phandle; 712 } args; 713 char device_specifier[1024]; 714 device *phandle; 715 /* get the args */ 716 if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) 717 return -1; 718 emul_read_string(device_specifier, 719 args.device_specifier, 720 sizeof(device_specifier), 721 processor, cia); 722 TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n", 723 device_specifier)); 724 /* find the device */ 725 phandle = tree_find_device(data->root, device_specifier); 726 if (phandle == NULL) 727 args.phandle = -1; 728 else 729 args.phandle = device_to_external(phandle); 730 /* return its phandle */ 731 TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(%p`%s')\n", 732 (unsigned long)args.phandle, 733 phandle, 734 (phandle == NULL ? "" : device_name(phandle)))); 735 chirp_write_h2t_args(&args, 736 sizeof(args), 737 data, 738 processor, cia); 739 return 0; 740 } 741 742 static int 743 chirp_emul_instance_to_path(os_emul_data *data, 744 cpu *processor, 745 unsigned_word cia) 746 { 747 struct instance_to_path_args { 748 /*in*/ 749 unsigned_cell ihandle; 750 unsigned_cell buf; 751 unsigned_cell buflen; 752 /*out*/ 753 unsigned_cell length; 754 } args; 755 device_instance *ihandle; 756 const char *path; 757 int length; 758 /* get the args */ 759 if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) 760 return -1; 761 ihandle = external_to_device_instance(data->root, args.ihandle); 762 TRACE(trace_os_emul, ("instance-to-path - in - ihandle=0x%lx(%p`%s') buf=0x%lx buflen=%ld\n", 763 (unsigned long)args.ihandle, 764 ihandle, 765 ihandle_name(ihandle), 766 (unsigned long)args.buf, 767 (unsigned long)args.buflen)); 768 /* get the devices name */ 769 if (ihandle == NULL) { 770 args.length = -1; 771 path = "(null)"; 772 } 773 else { 774 path = device_instance_path(ihandle); 775 length = strlen(path); 776 if (length >= args.buflen) 777 length = args.buflen - 1; 778 emul_write_buffer(path, args.buf, length, 779 processor, cia); 780 args.length = length; 781 } 782 /* return its phandle */ 783 TRACE(trace_os_emul, ("instance-to-path - out - length=%ld buf=`%s')\n", 784 (unsigned long)args.length, 785 path)); 786 chirp_write_h2t_args(&args, 787 sizeof(args), 788 data, 789 processor, cia); 790 return 0; 791 } 792 793 static int 794 chirp_emul_package_to_path(os_emul_data *data, 795 cpu *processor, 796 unsigned_word cia) 797 { 798 struct package_to_path_args { 799 /*in*/ 800 unsigned_cell phandle; 801 unsigned_cell buf; 802 unsigned_cell buflen; 803 /*out*/ 804 unsigned_cell length; 805 } args; 806 device *phandle; 807 const char *path; 808 /* get the args */ 809 if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) 810 return -1; 811 phandle = external_to_device(data->root, args.phandle); 812 TRACE(trace_os_emul, ("package-to-path - in - phandle=0x%lx(%p`%s') buf=0x%lx buflen=%ld\n", 813 (unsigned long)args.phandle, 814 phandle, 815 (phandle == NULL ? "" : device_name(phandle)), 816 (unsigned long)args.buf, 817 (unsigned long)args.buflen)); 818 /* get the devices name */ 819 if (phandle == NULL) { 820 args.length = -1; 821 path = "(null)"; 822 } 823 else { 824 int length; 825 path = device_path(phandle); 826 length = strlen(path); 827 if (length >= args.buflen) 828 length = args.buflen - 1; 829 emul_write_buffer(path, args.buf, length, 830 processor, cia); 831 args.length = length; 832 } 833 /* return its phandle */ 834 TRACE(trace_os_emul, ("package-to-path - out - length=%ld buf=`%s')\n", 835 (unsigned long)args.length, 836 path)); 837 chirp_write_h2t_args(&args, 838 sizeof(args), 839 data, 840 processor, cia); 841 return 0; 842 } 843 844 static int 845 chirp_emul_call_method(os_emul_data *data, 846 cpu *processor, 847 unsigned_word cia) 848 { 849 struct call_method_args { 850 /*in*/ 851 unsigned_cell method; 852 unsigned_cell ihandle; 853 /*in/out*/ 854 unsigned_cell stack[13]; /*6in + 6out + catch */ 855 } args; 856 char method[32]; 857 device_instance *ihandle; 858 /* some useful info about our mini stack */ 859 int n_stack_args; 860 int n_stack_returns; 861 int stack_catch_result; 862 int stack_returns; 863 /* read the args */ 864 if (chirp_read_t2h_args(&args, sizeof(args), -1, -1, data, processor, cia)) 865 return -1; 866 emul_read_string(method, 867 args.method, 868 sizeof(method), 869 processor, cia); 870 ihandle = external_to_device_instance(data->root, args.ihandle); 871 n_stack_args = data->n_args - 2; 872 n_stack_returns = data->n_returns - 1; 873 stack_catch_result = n_stack_args; 874 stack_returns = stack_catch_result + 1; 875 TRACE(trace_os_emul, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(%p`%s')\n", 876 (unsigned long)data->n_args, 877 (unsigned long)data->n_returns, 878 method, 879 (unsigned long)args.ihandle, 880 ihandle, 881 ihandle_name(ihandle))); 882 /* see if we can emulate this method */ 883 if (ihandle == NULL) { 884 /* OpenFirmware doesn't define this error */ 885 error("chirp: invalid ihandle passed to call-method method"); 886 } 887 else { 888 args.stack[stack_catch_result] = 889 device_instance_call_method(ihandle, 890 method, 891 n_stack_args, 892 &args.stack[0], 893 n_stack_returns, 894 &args.stack[stack_returns]); 895 } 896 /* finished */ 897 TRACE(trace_os_emul, ("call-method - out - catch-result=%ld\n", 898 (unsigned long)args.stack[stack_catch_result])); 899 chirp_write_h2t_args(&args, 900 sizeof(args), 901 data, 902 processor, cia); 903 return 0; 904 } 905 906 907 /* Device I/O */ 908 909 static int 910 chirp_emul_open(os_emul_data *data, 911 cpu *processor, 912 unsigned_word cia) 913 { 914 struct open_args { 915 /*in*/ 916 unsigned_cell device_specifier; 917 /*out*/ 918 unsigned_cell ihandle; 919 } args; 920 char device_specifier[1024]; 921 device_instance *ihandle; 922 /* read the args */ 923 if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) 924 return -1; 925 emul_read_string(device_specifier, 926 args.device_specifier, 927 sizeof(device_specifier), 928 processor, cia); 929 TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n", 930 device_specifier)); 931 /* open the device */ 932 ihandle = tree_instance(data->root, device_specifier); 933 if (ihandle == NULL) 934 args.ihandle = -1; 935 else 936 args.ihandle = device_instance_to_external(ihandle); 937 /* return the ihandle result */ 938 TRACE(trace_os_emul, ("open - out - ihandle=0x%lx(%p`%s')\n", 939 (unsigned long)args.ihandle, 940 ihandle, 941 ihandle_name(ihandle))); 942 chirp_write_h2t_args(&args, 943 sizeof(args), 944 data, 945 processor, cia); 946 return 0; 947 } 948 949 static int 950 chirp_emul_close(os_emul_data *data, 951 cpu *processor, 952 unsigned_word cia) 953 { 954 struct close_args { 955 /*in*/ 956 unsigned_cell ihandle; 957 /*out*/ 958 } args; 959 device_instance *ihandle; 960 /* read the args */ 961 if (chirp_read_t2h_args(&args, sizeof(args), 1, 0, data, processor, cia)) 962 return -1; 963 ihandle = external_to_device_instance(data->root, args.ihandle); 964 TRACE(trace_os_emul, ("close - in - ihandle=0x%lx(%p`%s')\n", 965 (unsigned long)args.ihandle, 966 ihandle, 967 ihandle_name(ihandle))); 968 /* close the device */ 969 if (ihandle == NULL) { 970 /* OpenFirmware doesn't define this error */ 971 error("chirp: invalid ihandle passed to close method"); 972 } 973 else { 974 device_instance_delete(ihandle); 975 } 976 /* return the ihandle result */ 977 TRACE(trace_os_emul, ("close - out\n")); 978 chirp_write_h2t_args(&args, 979 sizeof(args), 980 data, 981 processor, cia); 982 return 0; 983 } 984 985 static int 986 chirp_emul_read(os_emul_data *data, 987 cpu *processor, 988 unsigned_word cia) 989 { 990 struct read_args { 991 /*in*/ 992 unsigned_cell ihandle; 993 unsigned_cell addr; 994 unsigned_cell len; 995 /*out*/ 996 unsigned_cell actual; 997 } args; 998 char buf[1024]; 999 device_instance *ihandle; 1000 /* read the args */ 1001 if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) 1002 return -1; 1003 ihandle = external_to_device_instance(data->root, args.ihandle); 1004 TRACE(trace_os_emul, ("read - in - ihandle=0x%lx(%p`%s') addr=0x%lx len=%ld\n", 1005 (unsigned long)args.ihandle, 1006 ihandle, 1007 ihandle_name(ihandle), 1008 (unsigned long)args.addr, 1009 (unsigned long)args.len)); 1010 if (ihandle == NULL) { 1011 /* OpenFirmware doesn't define this error */ 1012 error("chirp: invalid ihandle passed to read method"); 1013 } 1014 else { 1015 /* do the reads */ 1016 int actual = 0; 1017 while (actual < args.len) { 1018 int remaining = args.len - actual; 1019 int to_read = (remaining <= sizeof(buf) ? remaining : sizeof(buf)); 1020 int nr_read = device_instance_read(ihandle, buf, to_read); 1021 if (nr_read < 0) { 1022 actual = nr_read; /* the error */ 1023 break; 1024 } 1025 else if (nr_read == 0) { 1026 break; 1027 } 1028 emul_write_buffer(buf, 1029 args.addr + actual, 1030 nr_read, 1031 processor, cia); 1032 actual += nr_read; 1033 } 1034 if (actual >= 0) { 1035 args.actual = actual; 1036 if (actual < sizeof(buf)) 1037 buf[actual] = '\0'; 1038 else 1039 buf[sizeof(buf) - 1] = '\0'; 1040 } 1041 else { 1042 switch (actual) { 1043 case sim_io_eof: 1044 args.actual = 0; 1045 break; 1046 case sim_io_not_ready: 1047 ASSERT(sim_io_not_ready == -2); 1048 args.actual = sim_io_not_ready; 1049 break; 1050 default: 1051 error("Bad error value %ld", (long)actual); 1052 break; 1053 } 1054 } 1055 } 1056 /* return the result */ 1057 TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n", 1058 (long)args.actual, 1059 ((args.actual > 0 && args.actual < sizeof(buf)) ? buf : "") 1060 )); 1061 chirp_write_h2t_args(&args, 1062 sizeof(args), 1063 data, 1064 processor, cia); 1065 return 0; 1066 } 1067 1068 static int 1069 chirp_emul_write(os_emul_data *data, 1070 cpu *processor, 1071 unsigned_word cia) 1072 { 1073 struct write_args { 1074 /*in*/ 1075 unsigned_cell ihandle; 1076 unsigned_cell addr; 1077 unsigned_cell len; 1078 /*out*/ 1079 unsigned_cell actual; 1080 } args; 1081 char buf[1024]; 1082 device_instance *ihandle; 1083 int actual; 1084 /* get the args */ 1085 if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) 1086 return -1; 1087 actual = args.len; 1088 if (actual >= sizeof(buf)) 1089 actual = sizeof(buf) - 1; 1090 emul_read_buffer(buf, 1091 args.addr, 1092 actual, 1093 processor, cia); 1094 buf[actual] = '\0'; 1095 ihandle = external_to_device_instance(data->root, args.ihandle); 1096 TRACE(trace_os_emul, ("write - in - ihandle=0x%lx(%p`%s') `%s' (%ld)\n", 1097 (unsigned long)args.ihandle, 1098 ihandle, 1099 ihandle_name(ihandle), 1100 buf, (long)actual)); 1101 if (ihandle == NULL) { 1102 /* OpenFirmware doesn't define this error */ 1103 error("chirp: invalid ihandle passed to write method"); 1104 } 1105 else { 1106 /* write it out */ 1107 actual = device_instance_write(ihandle, buf, actual); 1108 if (actual < 0) 1109 args.actual = 0; 1110 else 1111 args.actual = actual; 1112 } 1113 /* return the result */ 1114 TRACE(trace_os_emul, ("write - out - actual=%ld\n", 1115 (long)args.actual)); 1116 chirp_write_h2t_args(&args, 1117 sizeof(args), 1118 data, 1119 processor, cia); 1120 return 0; 1121 } 1122 1123 static int 1124 chirp_emul_seek(os_emul_data *data, 1125 cpu *processor, 1126 unsigned_word cia) 1127 { 1128 struct seek_args { 1129 /*in*/ 1130 unsigned_cell ihandle; 1131 unsigned_cell pos_hi; 1132 unsigned_cell pos_lo; 1133 /*out*/ 1134 unsigned_cell status; 1135 } args; 1136 int status; 1137 device_instance *ihandle; 1138 /* get the args */ 1139 if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) 1140 return -1; 1141 ihandle = external_to_device_instance(data->root, args.ihandle); 1142 TRACE(trace_os_emul, ("seek - in - ihandle=0x%lx(%p`%s') pos.hi=0x%lx pos.lo=0x%lx\n", 1143 (unsigned long)args.ihandle, 1144 ihandle, 1145 ihandle_name(ihandle), 1146 (unsigned long)args.pos_hi, 1147 (unsigned long)args.pos_lo)); 1148 if (ihandle == NULL) { 1149 /* OpenFirmware doesn't define this error */ 1150 error("chirp: invalid ihandle passed to seek method"); 1151 } 1152 else { 1153 /* seek it out */ 1154 status = device_instance_seek(ihandle, args.pos_hi, args.pos_lo); 1155 args.status = status; 1156 } 1157 /* return the result */ 1158 TRACE(trace_os_emul, ("seek - out - status=%ld\n", 1159 (long)args.status)); 1160 chirp_write_h2t_args(&args, 1161 sizeof(args), 1162 data, 1163 processor, cia); 1164 return 0; 1165 } 1166 1167 1168 /* memory */ 1169 1170 static int 1171 chirp_emul_claim(os_emul_data *data, 1172 cpu *processor, 1173 unsigned_word cia) 1174 { 1175 /* NOTE: the client interface claim routine is *very* different to 1176 the "claim" method described in IEEE-1275 appendix A. The latter 1177 uses real addresses while this uses virtual (effective) 1178 addresses. */ 1179 struct claim_args { 1180 /* in */ 1181 unsigned_cell virt; 1182 unsigned_cell size; 1183 unsigned_cell align; 1184 /* out */ 1185 unsigned_cell baseaddr; 1186 } args; 1187 /* read the args */ 1188 if (chirp_read_t2h_args(&args, sizeof(args), 1189 3 /*n_args*/, 1 /*n_returns*/, 1190 data, processor, cia)) 1191 return -1; 1192 TRACE(trace_os_emul, ("claim - in - virt=0x%lx size=%ld align=%d\n", 1193 (unsigned long)args.virt, 1194 (long int)args.size, 1195 (int)args.align)); 1196 /* use the memory device to allocate (real) memory at the requested 1197 address */ 1198 { 1199 device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory"); 1200 unsigned_cell mem_in[3]; 1201 unsigned_cell mem_out[1]; 1202 mem_in[0] = args.align; /*top-of-stack*/ 1203 mem_in[1] = args.size; 1204 mem_in[2] = args.virt; 1205 if (device_instance_call_method(memory, "claim", 1206 3, mem_in, 1, mem_out) < 0) 1207 error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d", 1208 (unsigned long)args.virt, 1209 (long int)args.size, 1210 (int)args.align); 1211 args.baseaddr = mem_out[0]; 1212 } 1213 /* if using virtual addresses, create a 1-1 map of this address space */ 1214 if (!data->real_mode) { 1215 error("chirp: claim method does not support virtual mode"); 1216 } 1217 /* return the base address */ 1218 TRACE(trace_os_emul, ("claim - out - baseaddr=0x%lx\n", 1219 (unsigned long)args.baseaddr)); 1220 chirp_write_h2t_args(&args, 1221 sizeof(args), 1222 data, 1223 processor, cia); 1224 return 0; 1225 } 1226 1227 static int 1228 chirp_emul_release(os_emul_data *data, 1229 cpu *processor, 1230 unsigned_word cia) 1231 { 1232 /* NOTE: the client interface release routine is *very* different to 1233 the "claim" method described in IEEE-1275 appendix A. The latter 1234 uses real addresses while this uses virtual (effective) 1235 addresses. */ 1236 struct claim_args { 1237 /* in */ 1238 unsigned_cell virt; 1239 unsigned_cell size; 1240 /* out */ 1241 } args; 1242 /* read the args */ 1243 if (chirp_read_t2h_args(&args, sizeof(args), 1244 2 /*n_args*/, 0 /*n_returns*/, 1245 data, processor, cia)) 1246 return -1; 1247 TRACE(trace_os_emul, ("release - in - virt=0x%lx size=%ld\n", 1248 (unsigned long)args.virt, 1249 (long int)args.size)); 1250 /* use the memory device to release (real) memory at the requested 1251 address */ 1252 { 1253 device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory"); 1254 unsigned_cell mem_in[2]; 1255 mem_in[0] = args.size; 1256 mem_in[1] = args.virt; 1257 if (device_instance_call_method(memory, "release", 1258 2, mem_in, 0, NULL) < 0) 1259 error("chirp: claim failed to release memory virt=0x%lx size=%ld", 1260 (unsigned long)args.virt, 1261 (long int)args.size); 1262 } 1263 /* if using virtual addresses, remove the 1-1 map of this address space */ 1264 if (!data->real_mode) { 1265 error("chirp: release method does not support virtual mode"); 1266 } 1267 /* return the base address */ 1268 TRACE(trace_os_emul, ("release - out\n")); 1269 chirp_write_h2t_args(&args, 1270 sizeof(args), 1271 data, 1272 processor, cia); 1273 return 0; 1274 } 1275 1276 1277 /* Control transfer */ 1278 1279 static int 1280 chirp_emul_boot(os_emul_data *data, 1281 cpu *processor, 1282 unsigned_word cia) 1283 { 1284 /* unlike OpenFirmware this one can take an argument */ 1285 struct boot_args { 1286 /*in*/ 1287 unsigned_cell bootspec; 1288 /*out*/ 1289 } args; 1290 char bootspec[1024]; 1291 /* read in the arguments */ 1292 if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia)) 1293 cpu_halt(processor, cia, was_exited, -1); 1294 if (args.bootspec != 0) 1295 emul_read_string(bootspec, args.bootspec, sizeof(bootspec), 1296 processor, cia); 1297 else 1298 strcpy(bootspec, "(null)"); 1299 TRACE(trace_os_emul, ("boot - in bootspec=`%s'\n", bootspec)); 1300 /* just report this and exit */ 1301 printf_filtered("chrp: boot %s called, exiting.\n", bootspec); 1302 cpu_halt(processor, cia, was_exited, 0); 1303 return 0; 1304 } 1305 1306 static int 1307 chirp_emul_enter(os_emul_data *data, 1308 cpu *processor, 1309 unsigned_word cia) 1310 { 1311 error("chirp: enter method not implemented\n"); 1312 return 0; 1313 } 1314 1315 static int 1316 chirp_emul_exit(os_emul_data *data, 1317 cpu *processor, 1318 unsigned_word cia) 1319 { 1320 /* unlike OpenBoot this one can take an argument */ 1321 struct exit_args { 1322 /*in*/ 1323 signed_cell status; 1324 /*out*/ 1325 } args; 1326 if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia)) 1327 cpu_halt(processor, cia, was_exited, -1); 1328 cpu_halt(processor, cia, was_exited, args.status); 1329 return 0; 1330 } 1331 1332 static int 1333 chirp_emul_chain(os_emul_data *data, 1334 cpu *processor, 1335 unsigned_word cia) 1336 { 1337 error("chirp: chain method not implemented\n"); 1338 return 0; 1339 } 1340 1341 1342 /* user interface */ 1343 1344 static int 1345 chirp_emul_interpret(os_emul_data *data, 1346 cpu *processor, 1347 unsigned_word cia) 1348 { 1349 error("chirp: interpret method not implemented\n"); 1350 return 0; 1351 } 1352 1353 static int 1354 chirp_emul_set_callback(os_emul_data *data, 1355 cpu *processor, 1356 unsigned_word cia) 1357 { 1358 error("chirp: set_callback method not implemented\n"); 1359 return 0; 1360 } 1361 1362 static int 1363 chirp_emul_set_symbol_lookup(os_emul_data *data, 1364 cpu *processor, 1365 unsigned_word cia) 1366 { 1367 error("chirp: set_symbol_lookup method not implemented\n"); 1368 return 0; 1369 } 1370 1371 1372 /* Time */ 1373 1374 static int 1375 chirp_emul_milliseconds(os_emul_data *data, 1376 cpu *processor, 1377 unsigned_word cia) 1378 { 1379 struct test_args { 1380 /*in*/ 1381 /*out*/ 1382 unsigned_cell ms; 1383 } args; 1384 uint64_t time; 1385 /* read in the arguments */ 1386 if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) 1387 return -1; 1388 /* make up a number */ 1389 time = event_queue_time(psim_event_queue(cpu_system(processor))) / 1000000; 1390 args.ms = time; 1391 /* write the arguments back out */ 1392 TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n", 1393 (unsigned long)args.ms)); 1394 chirp_write_h2t_args(&args, 1395 sizeof(args), 1396 data, 1397 processor, cia); 1398 return 0; 1399 } 1400 1401 1402 1403 1404 static chirp_services services[] = { 1405 1406 /* client interface */ 1407 { "test", chirp_emul_test }, 1408 1409 /* device tree */ 1410 { "peer", chirp_emul_peer }, 1411 { "child", chirp_emul_child }, 1412 { "parent", chirp_emul_parent }, 1413 { "instance-to-package", chirp_emul_instance_to_package }, 1414 { "getproplen", chirp_emul_getproplen }, 1415 { "getprop", chirp_emul_getprop }, 1416 { "nextprop", chirp_emul_nextprop }, 1417 /* { "setprop", chirp_emul_setprop }, */ 1418 { "canon", chirp_emul_canon }, 1419 { "finddevice", chirp_emul_finddevice }, 1420 { "instance-to-path", chirp_emul_instance_to_path }, 1421 { "package-to-path", chirp_emul_package_to_path }, 1422 { "call-method", chirp_emul_call_method }, 1423 1424 /* device I/O */ 1425 { "open", chirp_emul_open }, 1426 { "close", chirp_emul_close }, 1427 { "read", chirp_emul_read }, 1428 { "write", chirp_emul_write }, 1429 { "seek", chirp_emul_seek }, 1430 { "write", chirp_emul_write }, 1431 1432 /* memory */ 1433 { "claim", chirp_emul_claim }, 1434 { "release", chirp_emul_release }, 1435 1436 /* control transfer */ 1437 { "boot", chirp_emul_boot }, 1438 { "enter", chirp_emul_enter }, 1439 { "exit", chirp_emul_exit }, 1440 { "chain", chirp_emul_chain }, 1441 1442 /* user interface */ 1443 { "interpret", chirp_emul_interpret }, 1444 { "set_callback", chirp_emul_set_callback }, 1445 { "set_symbol_lookup", chirp_emul_set_symbol_lookup }, 1446 1447 /* time */ 1448 { "milliseconds", chirp_emul_milliseconds }, 1449 1450 { 0, /* sentinal */ }, 1451 }; 1452 1453 1454 /* main handlers */ 1455 1456 /* Any starting address greater than this is assumed to be an Chirp 1457 rather than VEA */ 1458 1459 #ifndef CHIRP_START_ADDRESS 1460 #define CHIRP_START_ADDRESS 0x80000000 1461 #endif 1462 #ifndef CHIRP_LOAD_BASE 1463 #define CHIRP_LOAD_BASE -1 1464 #endif 1465 1466 1467 typedef struct _chirp_note_desc { 1468 int32_t real_mode; 1469 int32_t real_base; 1470 int32_t real_size; 1471 int32_t virt_base; 1472 int32_t virt_size; 1473 int32_t load_base; 1474 } chirp_note_desc; 1475 1476 typedef enum { 1477 note_missing, 1478 note_found, 1479 note_correct, 1480 } note_found_status; 1481 typedef struct _chirp_note { 1482 chirp_note_desc desc; 1483 note_found_status found; 1484 } chirp_note; 1485 1486 typedef struct _chirp_note_head { 1487 uint32_t namesz; 1488 uint32_t descsz; 1489 uint32_t type; 1490 } chirp_note_head; 1491 1492 static void 1493 map_over_chirp_note(bfd *image, 1494 asection *sect, 1495 void *obj) 1496 { 1497 chirp_note *note = (chirp_note*)obj; 1498 if (strcmp(sect->name, ".note") == 0) { 1499 chirp_note_head head; 1500 char name[16]; 1501 /* check the head */ 1502 if (!bfd_get_section_contents(image, sect, 1503 &head, 0, sizeof(head))) 1504 return; 1505 head.namesz = bfd_get_32(image, (void*)&head.namesz); 1506 head.descsz = bfd_get_32(image, (void*)&head.descsz); 1507 head.type = bfd_get_32(image, (void*)&head.type); 1508 if (head.type != 0x1275) 1509 return; 1510 /* check the name field */ 1511 if (head.namesz > sizeof(name)) { 1512 error("chirp: note name too long (%d > %d)\n", (int)head.namesz, (int)sizeof(name)); 1513 } 1514 if (!bfd_get_section_contents(image, sect, 1515 name, sizeof(head), head.namesz)) { 1516 error("chirp: note name unreadable\n"); 1517 } 1518 if (strcmp(name, "PowerPC") != 0) { 1519 printf_filtered("chirp: note name (%s) not `PowerPC'\n", name); 1520 } 1521 /* check the size */ 1522 if (head.descsz == sizeof(note->desc) - sizeof(int32_t)) { 1523 sim_io_printf_filtered("chirp: note descriptor missing load-base\n"); 1524 } 1525 else if (head.descsz != sizeof(note->desc)) { 1526 sim_io_printf_filtered("chirp: note descriptor of wrong size\n"); 1527 note->found = note_found; 1528 return; 1529 } 1530 note->found = note_correct; 1531 /* get the contents */ 1532 if (!bfd_get_section_contents(image, sect, 1533 ¬e->desc, /* page align start */ 1534 ((sizeof(head) + head.namesz) + 3) & ~3, 1535 head.descsz)) { 1536 error("chirp: note descriptor unreadable\n"); 1537 } 1538 note->desc.real_mode = bfd_get_32(image, (void*)¬e->desc.real_mode); 1539 note->desc.real_base = bfd_get_32(image, (void*)¬e->desc.real_base); 1540 note->desc.real_size = bfd_get_32(image, (void*)¬e->desc.real_size); 1541 note->desc.virt_base = bfd_get_32(image, (void*)¬e->desc.virt_base); 1542 note->desc.virt_size = bfd_get_32(image, (void*)¬e->desc.virt_size); 1543 if (head.descsz == sizeof(note->desc)) 1544 note->desc.load_base = bfd_get_32(image, (void*)¬e->desc.load_base); 1545 else 1546 note->desc.load_base = (int32_t)-1; 1547 } 1548 } 1549 1550 1551 static os_emul_data * 1552 emul_chirp_create(device *root, 1553 bfd *image, 1554 const char *name) 1555 { 1556 os_emul_data *chirp; 1557 device *node; 1558 chirp_note note; 1559 int i; 1560 1561 /* Sanity check that this really is the chosen emulation */ 1562 if (name == NULL && image == NULL) 1563 return NULL; 1564 if (name != NULL 1565 && strcmp(name, "ob") != 0 1566 && strcmp(name, "ieee1274") != 0 1567 && strcmp(name, "chrp") != 0 1568 && strcmp(name, "chirp") != 0 1569 && strcmp(name, "openboot") != 0) 1570 return NULL; 1571 1572 /* look for an elf note section, enter its values into the device tree */ 1573 memset(¬e, 0, sizeof(note)); 1574 if (image != NULL) 1575 bfd_map_over_sections(image, map_over_chirp_note, ¬e); 1576 if (name == NULL && image != NULL && note.found == note_missing) 1577 return NULL; 1578 1579 /* Assume that it is a chirp emulation */ 1580 1581 chirp = ZALLOC(os_emul_data); 1582 chirp->root = root; 1583 chirp->services = services; 1584 1585 /* the root node */ 1586 tree_parse(root, "/name \"gpl,clayton"); 1587 1588 /* default options */ 1589 emul_add_tree_options(root, image, "chirp", "oea", 1590 0 /*oea-interrupt-prefix*/); 1591 1592 /* hardware */ 1593 emul_add_tree_hardware(root); 1594 1595 /* basic information */ 1596 chirp->memory_size 1597 = tree_find_integer_property(root, "/openprom/options/oea-memory-size"); 1598 chirp->little_endian 1599 = tree_find_boolean_property(root, "/options/little-endian?"); 1600 chirp->floating_point_available 1601 = tree_find_boolean_property(root, "/openprom/options/floating-point?"); 1602 chirp->interrupt_prefix = 1603 tree_find_integer_property(root, "/openprom/options/oea-interrupt-prefix"); 1604 1605 1606 /* Perform an interum layout of the openboot firmware in memory */ 1607 1608 1609 /* a page for firmware calls */ 1610 chirp->sizeof_code = 4096; 1611 chirp->code_offset = 0x4000; /* possible space for interrupt table */ 1612 1613 /* the stack */ 1614 chirp->sizeof_stack = 32 * 1024; 1615 chirp->stack_offset = chirp->code_offset + chirp->sizeof_code; 1616 1617 /* the hash table */ 1618 if (!note.desc.real_mode) { 1619 chirp->nr_page_table_entry_groups = (chirp->memory_size < 0x800000 1620 ? 1024 /* min allowed */ 1621 : (chirp->memory_size / 4096 / 2)); 1622 chirp->sizeof_htab = chirp->nr_page_table_entry_groups * 64; 1623 } 1624 chirp->htab_offset = chirp->stack_offset + chirp->sizeof_stack; 1625 1626 /* the actual amount of space needed */ 1627 chirp->real_size = chirp->htab_offset + chirp->sizeof_htab; 1628 1629 1630 /* now go through and see if it fits in what is available */ 1631 1632 1633 /* resolve real-mode? */ 1634 if (note.found == note_correct) 1635 chirp->real_mode = note.desc.real_mode; 1636 else if (tree_find_property(root, "/options/real-mode?") != NULL) 1637 chirp->real_mode = tree_find_boolean_property(root, "/options/real-mode?"); 1638 else 1639 chirp->real_mode = 0; 1640 if (tree_find_property(root, "/options/real-mode?") != NULL) { 1641 if (!chirp->real_mode 1642 != !tree_find_boolean_property(root, "/options/real-mode?")) 1643 error("chirp: /options/real-mode? conflicts with note section\n"); 1644 } 1645 else 1646 tree_parse(root, "/options/real-mode? %s", 1647 chirp->real_mode ? "true" : "false"); 1648 1649 /* resolve real-base */ 1650 if (note.found == note_correct 1651 && note.desc.real_base != (int32_t)-1) 1652 chirp->real_base = note.desc.real_base; 1653 else if (tree_find_property(root, "/options/real-base") != NULL) 1654 chirp->real_base = tree_find_integer_property(root, "/options/real-base"); 1655 else 1656 chirp->real_base = chirp->memory_size - chirp->real_size; 1657 if (tree_find_property(root, "/options/real-base") != NULL) { 1658 if (chirp->real_base != tree_find_integer_property(root, "/options/real-base")) 1659 error("chirp: /options/real-base conflicts with note section\n"); 1660 } 1661 else 1662 tree_parse(root, "/options/real-base 0x%lx", 1663 (unsigned long)chirp->real_base); 1664 1665 /* resolve real-size */ 1666 if (note.found == note_correct 1667 && note.desc.real_size != (int32_t)-1 1668 && note.desc.real_size != 0 1669 && chirp->real_size > note.desc.real_size) 1670 error("chirp: insufficient physical memory for firmware\n"); 1671 if (tree_find_property(root, "/options/real-size") != NULL) { 1672 if (chirp->real_size > tree_find_integer_property(root, "/options/real-size")) 1673 error("chirp: /options/real-size conflicts with note section\n"); 1674 } 1675 else 1676 tree_parse(root, "/options/real-size 0x%lx", 1677 (unsigned long)chirp->real_size); 1678 1679 /* resolve virt-base */ 1680 if (chirp->real_mode) 1681 chirp->virt_base = chirp->real_base; 1682 else if (note.found == note_correct && note.desc.virt_base != -1) 1683 chirp->virt_base = note.desc.virt_base; 1684 else if (tree_find_property(root, "/options/virt-base") != NULL) 1685 chirp->virt_base = tree_find_integer_property(root, "/options/virt-base"); 1686 else 1687 chirp->virt_base = CHIRP_START_ADDRESS; 1688 if (tree_find_property(root, "/options/virt-base") != NULL) { 1689 unsigned_word virt_base = tree_find_integer_property(root, "/options/virt-base"); 1690 if (virt_base != -1 && chirp->virt_base != virt_base) 1691 error("chirp: /options/virt-base conflicts with note section\n"); 1692 } 1693 else 1694 tree_parse(root, "/options/virt-base 0x%lx", 1695 chirp->real_mode ? -1 : (unsigned long)chirp->virt_base); 1696 1697 /* resolve virt-size */ 1698 chirp->virt_size = chirp->real_size; 1699 if (note.found == note_correct 1700 && note.desc.virt_size != (int32_t)-1 1701 && note.desc.virt_size != 0 1702 && !chirp->real_mode 1703 && chirp->virt_size > note.desc.virt_size) 1704 error("chirp: insufficent virtual memory for firmware\n"); 1705 if (tree_find_property(root, "/options/virt-size") != NULL) { 1706 if (chirp->virt_size > tree_find_integer_property(root, "/options/virt-size")) 1707 error("chirp: /options/virt-size conflicts with note section\n"); 1708 } 1709 else 1710 tree_parse(root, "/options/virt-size 0x%lx", 1711 chirp->real_mode ? -1 : (unsigned long)chirp->virt_size); 1712 1713 /* resolve load-base */ 1714 if (note.found == note_correct 1715 && note.desc.load_base != (int32_t)-1) 1716 chirp->load_base = note.desc.load_base; 1717 else if (tree_find_property(root, "/options/load-base") != NULL) 1718 chirp->load_base = tree_find_integer_property(root, "/options/load-base"); 1719 else 1720 chirp->load_base = CHIRP_LOAD_BASE; 1721 if (tree_find_property(root, "/options/load-base") != NULL) { 1722 if (chirp->load_base != tree_find_integer_property(root, "/options/load-base")) 1723 error("chirp: /options/load-base conflicts with note section\n"); 1724 } 1725 else 1726 tree_parse(root, "/options/load-base 0x%lx", 1727 (unsigned long)chirp->load_base); 1728 1729 /* now adjust the preliminary firmware addresses to final values */ 1730 chirp->code_ra = chirp->code_offset + chirp->real_base; 1731 chirp->stack_ra = chirp->stack_offset + chirp->real_base; 1732 chirp->htab_ra = chirp->htab_offset + chirp->real_base; 1733 1734 /* the virtual addresses. In real mode these are real addresses. */ 1735 1736 chirp->code_va = chirp->code_offset + chirp->virt_base; 1737 chirp->stack_va = chirp->stack_offset + chirp->virt_base; 1738 chirp->htab_va = chirp->htab_offset + chirp->virt_base; 1739 1740 chirp->code_client_va = chirp->code_va; 1741 chirp->code_client_ra = chirp->code_ra; 1742 1743 chirp->code_callback_va = chirp->code_client_va + 16; 1744 chirp->code_callback_ra = chirp->code_client_ra + 16; 1745 1746 chirp->code_loop_va = chirp->code_callback_va + 16; 1747 chirp->code_loop_ra = chirp->code_callback_ra + 16; 1748 1749 /* initialization */ 1750 1751 tree_parse(root, "/openprom/init"); 1752 tree_parse(root, "/openprom/init/register"); 1753 tree_parse(root, "/openprom/init/register/0.pc 0x%lx", 1754 (unsigned long)bfd_get_start_address(image)); 1755 tree_parse(root, "/openprom/init/register/pc 0x%lx", 1756 (unsigned long)chirp->code_loop_va); 1757 tree_parse(root, "/openprom/init/register/msr 0x%x", 1758 (msr_machine_check_enable 1759 | (chirp->real_mode 1760 ? 0 1761 : (msr_instruction_relocate 1762 | msr_data_relocate)) 1763 | (chirp->little_endian 1764 ? (msr_little_endian_mode 1765 | msr_interrupt_little_endian_mode) 1766 : 0) 1767 | (chirp->floating_point_available 1768 ? msr_floating_point_available 1769 : 0) 1770 | (chirp->interrupt_prefix 1771 ? msr_interrupt_prefix 1772 : 0) 1773 )); 1774 tree_parse(root, "/openprom/init/register/sdr1 0x%lx", 1775 (unsigned long)(chirp->htab_ra 1776 | MASK32(16, 22) 1777 | ((chirp->sizeof_htab - 1) >> 16))); 1778 /* make certain that the segment registers map straight through */ 1779 for (i = 0; i < 16; i++) { 1780 tree_parse(root, "/openprom/init/register/sr%d 0x%lx", 1781 i, (unsigned long)i); 1782 } 1783 1784 /* establish an initial state for all processors */ 1785 1786 1787 /* the client interface address */ 1788 tree_parse(root, "/openprom/init/register/r5 0x%lx", 1789 (unsigned long)chirp->code_client_va); 1790 /* a stack */ 1791 tree_parse(root, "/openprom/init/register/sp 0x%lx", 1792 (unsigned long)(chirp->stack_va + chirp->sizeof_stack - 16)); 1793 /* in chrp mode any arguments end up being concatinated */ 1794 tree_parse(root, "/openprom/init/stack/stack-type chirp"); 1795 1796 1797 /* client interface - emul-call followed by return instruction */ 1798 1799 1800 node = tree_parse(root, "/openprom/init/data@0x%lx", 1801 (unsigned long)chirp->code_client_ra); 1802 tree_parse(node, "./psim,description \"client-interface instruction"); 1803 tree_parse(node, "./real-address 0x%lx", 1804 (unsigned long)chirp->code_client_ra); 1805 tree_parse(node, "./data 0x%lx", 1806 (unsigned long)emul_call_instruction); 1807 1808 node = tree_parse(root, "/openprom/init/data@0x%lx", 1809 (unsigned long)(chirp->code_client_ra + 4)); 1810 tree_parse(node, "./psim,description \"client-interface return instruction"); 1811 tree_parse(node, "./real-address 0x%lx", 1812 (unsigned long)(chirp->code_client_ra + 4)); 1813 tree_parse(node, "./data 0x%lx", 1814 (unsigned long)emul_blr_instruction); 1815 1816 1817 /* return address for client callbacks - an emul-call instruction 1818 that is again followed by a return instruction */ 1819 1820 1821 node = tree_parse(root, "/openprom/init/data@0x%lx", 1822 (unsigned long)chirp->code_callback_ra); 1823 tree_parse(node, "./psim,description \"client-callback instruction"); 1824 tree_parse(node, "./real-address 0x%lx", 1825 (unsigned long)chirp->code_callback_ra); 1826 tree_parse(node, "./data 0x%lx", 1827 (unsigned long)emul_call_instruction); 1828 1829 node = tree_parse(root, "/openprom/init/data@0x%lx", 1830 (unsigned long)(chirp->code_callback_ra + 4)); 1831 tree_parse(node, "./psim,description \"client-callback return instruction"); 1832 tree_parse(node, "./real-address 0x%lx", 1833 (unsigned long)(chirp->code_callback_ra + 4)); 1834 tree_parse(node, "./data 0x%lx", 1835 (unsigned long)emul_blr_instruction); 1836 1837 /* loop to keep other processors busy */ 1838 1839 node = tree_parse(root, "/openprom/init/data@0x%lx", 1840 (unsigned long)chirp->code_loop_ra); 1841 tree_parse(node, "./psim,description \"processor busy loop"); 1842 tree_parse(node, "./real-address 0x%lx", 1843 (unsigned long)chirp->code_loop_ra); 1844 tree_parse(node, "./data 0x%lx", 1845 (unsigned long)emul_loop_instruction); 1846 1847 /* hash table */ 1848 1849 /* create a hash table */ 1850 1851 if (!chirp->real_mode) { 1852 node = tree_parse(root, "/openprom/init/htab@0x%lx", 1853 (unsigned long)chirp->htab_ra); 1854 tree_parse(node, "./claim 0"); 1855 tree_parse(node, "./real-address 0x%lx", 1856 (unsigned long)chirp->htab_ra); 1857 tree_parse(node, "./nr-bytes 0x%lx", 1858 (unsigned long)chirp->sizeof_htab); 1859 } 1860 1861 /* map in the stack */ 1862 1863 if (!chirp->real_mode) { 1864 node = tree_parse(root, "/openprom/init/htab/pte@0x%lx", 1865 (unsigned long)chirp->stack_ra); 1866 tree_parse(node, "./psim,description \"map in the stack"); 1867 tree_parse(node, "./claim 1"); 1868 tree_parse(node, "./virtual-address 0x%lx", 1869 (unsigned long)chirp->stack_va); 1870 tree_parse(node, "./real-address 0x%lx", 1871 (unsigned long)chirp->stack_ra); 1872 tree_parse(node, "./nr-bytes 0x%lx", 1873 (unsigned long)chirp->sizeof_stack); 1874 tree_parse(node, "./wimg %d", 0x7); 1875 tree_parse(node, "./pp %d", 0x2); 1876 } 1877 1878 /* map in the chrp openboot callback code */ 1879 1880 if (!chirp->real_mode) { 1881 node = tree_parse(root, "/openprom/init/htab/pte@0x%lx", 1882 (unsigned long)chirp->code_ra); 1883 tree_parse(node, "./psim,description \"map in chrp openboot callback code"); 1884 tree_parse(node, "./claim 1"); 1885 tree_parse(node, "./virtual-address 0x%lx", 1886 (unsigned long)chirp->code_va); 1887 tree_parse(node, "./real-address 0x%lx", 1888 (unsigned long)chirp->code_ra); 1889 tree_parse(node, "./nr-bytes 0x%lx", 1890 (unsigned long)chirp->sizeof_code); 1891 tree_parse(node, "./wimg %d", 0x7); 1892 tree_parse(node, "./pp %d", 0x2); 1893 } 1894 1895 /* map in the program to run */ 1896 1897 if (chirp->real_mode) { 1898 node = tree_parse(node, "/openprom/init/load-binary"); 1899 tree_parse(node, "./psim,description \"load the binary"); 1900 tree_parse(node, "./file-name %s", bfd_get_filename(image)); 1901 tree_parse(node, "./claim 1"); 1902 } 1903 else { 1904 node = tree_parse(root, "/openprom/init/htab/pte@0x%lx", 1905 (unsigned long)chirp->load_base); 1906 tree_parse(node, "./psim,description \"load & map the binary"); 1907 tree_parse(node, "./claim 1"); 1908 tree_parse(node, "./file-name \"%s", bfd_get_filename(image)); 1909 tree_parse(node, "./wimg %d", 0x7); 1910 tree_parse(node, "./pp %d", 0x2); 1911 } 1912 1913 /* map in the interrupt vectors */ 1914 1915 if (!chirp->real_mode) { 1916 node = tree_parse(root, "/openprom/init/htab/pte@0x0"); 1917 tree_parse(node, "./psim,description \"map in interrupt vectors"); 1918 tree_parse(node, "./virtual-address 0x0"); 1919 tree_parse(node, "./real-address 0x0"); 1920 tree_parse(node, "./nr-bytes 0x3000"); 1921 tree_parse(node, "./wimg %d", 0x7); 1922 tree_parse(node, "./pp %d", 0x2); 1923 } 1924 1925 return chirp; 1926 } 1927 1928 static void 1929 emul_chirp_init(os_emul_data *emul_data, 1930 int nr_cpus) 1931 { 1932 emul_data->state = serving; 1933 } 1934 1935 static int 1936 emul_chirp_instruction_call(cpu *processor, 1937 unsigned_word cia, 1938 unsigned_word ra, 1939 os_emul_data *emul_data) 1940 { 1941 unsigned_word service_name_addr; 1942 unsigned_word result; 1943 char service_buf[32]; 1944 char *service_name; 1945 chirp_services *service; 1946 1947 switch (emul_data->state) { 1948 1949 case serving: 1950 /* we are waiting on an OpenBoot request from the client program 1951 via the client interface */ 1952 if (cia != emul_data->code_client_va) 1953 return 0; 1954 emul_data->return_address = LR; 1955 emul_data->arguments = cpu_registers(processor)->gpr[3]; 1956 /* try to determine what to do */ 1957 service_name_addr = emul_read_word(cpu_registers(processor)->gpr[3], 1958 processor, cia); 1959 service_name = emul_read_string(service_buf, service_name_addr, 1960 sizeof(service_buf), processor, cia); 1961 emul_data->n_args = emul_read_word(emul_data->arguments + sizeof(unsigned_cell), 1962 processor, cia); 1963 emul_data->n_returns = emul_read_word(emul_data->arguments + 2 * sizeof(unsigned_cell), 1964 processor, cia); 1965 /* verify what was passed */ 1966 if (service_name_addr == 0 1967 || service_name == NULL) { 1968 error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n", 1969 (unsigned long)emul_data->return_address, 1970 (unsigned long)emul_data->arguments); 1971 } 1972 if (emul_data->n_args > 6) { /* See iee1275 requirements on nr returns */ 1973 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n", 1974 service_name, 1975 (unsigned long)emul_data->return_address, 1976 (unsigned long)emul_data->arguments, 1977 emul_data->n_returns); 1978 } 1979 if (emul_data->n_returns > 6) { 1980 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, with too many returns (%d)\n", 1981 service_name, 1982 (unsigned long)emul_data->return_address, 1983 (unsigned long)emul_data->arguments, 1984 emul_data->n_args); 1985 } 1986 /* look it up */ 1987 TRACE(trace_os_emul, ("%s called from 0x%lx with args 0x%lx\n", 1988 service_name, 1989 (unsigned long)emul_data->return_address, 1990 (unsigned long)emul_data->arguments)); 1991 service = services; 1992 while (service->name != NULL && strcmp(service->name, service_name) != 0) 1993 service++; 1994 /* found or not? */ 1995 if (service->name == NULL) { 1996 error("OpenBoot service `%s' not found\n", service_name); 1997 TRACE(trace_os_emul, ("%s not found\n", service_name)); 1998 cpu_registers(processor)->gpr[3] = -1; 1999 } 2000 else { 2001 emul_data->service = service; 2002 /* call upon it */ 2003 result = service->handler(emul_data, processor, cia); 2004 if (result != 0) 2005 TRACE(trace_os_emul, ("%s aborted with %ld\n", service_name, (long)result)); 2006 cpu_registers(processor)->gpr[3] = result; 2007 } 2008 break; 2009 2010 default: 2011 error("emul_chirp_instruction_call() unknown internal state\n"); 2012 result = -1; 2013 break; 2014 2015 } 2016 2017 /* return to caller - instruction following this is a function return */ 2018 return 1; 2019 } 2020 2021 const os_emul emul_chirp = { 2022 "chirp", 2023 emul_chirp_create, 2024 emul_chirp_init, 2025 NULL, /*system_call*/ 2026 emul_chirp_instruction_call, 2027 0 /*data*/ 2028 }; 2029 2030 #endif 2031