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