gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / sim / ppc / emul_chirp.c
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 &note->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*)&note->desc.real_mode);
1545 note->desc.real_base = bfd_get_32(image, (void*)&note->desc.real_base);
1546 note->desc.real_size = bfd_get_32(image, (void*)&note->desc.real_size);
1547 note->desc.virt_base = bfd_get_32(image, (void*)&note->desc.virt_base);
1548 note->desc.virt_size = bfd_get_32(image, (void*)&note->desc.virt_size);
1549 if (head.descsz == sizeof(note->desc))
1550 note->desc.load_base = bfd_get_32(image, (void*)&note->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(&note, 0, sizeof(note));
1580 if (image != NULL)
1581 bfd_map_over_sections(image, map_over_chirp_note, &note);
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
This page took 0.125727 seconds and 4 git commands to generate.