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