1 /* This file is part of the program psim.
3 Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
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.
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.
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/>.
21 #ifndef _EMUL_CHIRP_C_
22 #define _EMUL_CHIRP_C_
24 /* Note: this module is called via a table. There is no benefit in
27 #include "emul_generic.h"
28 #include "emul_chirp.h"
35 #ifndef STATIC_INLINE_EMUL_CHIRP
36 #define STATIC_INLINE_EMUL_CHIRP STATIC_INLINE
43 OpenFirmware - IEEE Standard for Boot (Initialization
44 Configuration) Firmware.
53 This code assumes that the memory node has #address-cells and
54 #size-cells set to one. For future implementations, this may not
62 /* Descriptor of the open boot services being emulated */
64 typedef int (chirp_handler
)
69 typedef struct _chirp_services
{
71 chirp_handler
*handler
;
75 /* The OpenBoot emulation is, at any time either waiting for a client
76 request or waiting on a client callback */
83 struct _os_emul_data
{
84 chirp_emul_state state
;
85 unsigned_word return_address
;
86 unsigned_word arguments
;
88 unsigned_word n_returns
;
89 chirp_services
*service
;
91 chirp_services
*services
;
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
;
100 int floating_point_available
;
101 int interrupt_prefix
;
102 unsigned_word load_base
;
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
;
128 /* returns the name of the corresponding Ihandle */
130 ihandle_name(device_instance
*ihandle
)
135 return device_name(device_instance_device(ihandle
));
140 /* Read/write the argument list making certain that all values are
141 converted to/from host byte order.
143 In the below only n_args+n_returns is read/written */
146 chirp_read_t2h_args(void *args
,
154 unsigned_cell
*words
;
156 /* check against the number of arguments specified by the client
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",
163 (long)data
->n_returns
));
166 /* check that there is enough space */
167 if (sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
) > sizeof_args
)
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
),
174 /* convert all words to host format */
176 for (i
= 0; i
< (sizeof_args
/ sizeof(unsigned_cell
)); i
++)
177 words
[i
] = T2H_cell(words
[i
]);
182 chirp_write_h2t_args(void *args
,
189 unsigned_cell
*words
;
190 /* convert to target everything */
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
),
201 /* OpenBoot emulation functions */
203 /* client interface */
206 chirp_emul_test(os_emul_data
*data
,
212 unsigned_cell name
; /*string*/
214 unsigned_cell missing
;
217 chirp_services
*service
= NULL
;
218 /* read in the arguments */
219 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
221 emul_read_string(name
, args
.name
, sizeof(name
),
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) {
229 if (service
->name
== NULL
)
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
,
247 chirp_emul_peer(os_emul_data
*data
,
253 unsigned_cell phandle
;
255 unsigned_cell sibling_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
))
262 phandle
= external_to_device(data
->root
, args
.phandle
);
263 TRACE(trace_os_emul
, ("peer - in - phandle=0x%lx(%p`%s')\n",
264 (unsigned long)args
.phandle
,
266 (phandle
== NULL
? "" : device_name(phandle
))));
268 if (args
.phandle
== 0) {
269 sibling_phandle
= data
->root
;
270 args
.sibling_phandle
= device_to_external(sibling_phandle
);
272 else if (phandle
== NULL
) {
273 sibling_phandle
= NULL
;
274 args
.sibling_phandle
= -1;
277 sibling_phandle
= device_sibling(phandle
);
278 if (sibling_phandle
== NULL
)
279 args
.sibling_phandle
= 0;
281 args
.sibling_phandle
= device_to_external(sibling_phandle
);
283 /* write the arguments back out */
284 TRACE(trace_os_emul
, ("peer - out - sibling_phandle=0x%lx(%p`%s')\n",
285 (unsigned long)args
.sibling_phandle
,
287 (sibling_phandle
== NULL
? "" : device_name(sibling_phandle
))));
288 chirp_write_h2t_args(&args
,
296 chirp_emul_child(os_emul_data
*data
,
302 unsigned_cell phandle
;
304 unsigned_cell child_phandle
;
307 device
*child_phandle
;
308 /* read the arguments in */
309 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
311 phandle
= external_to_device(data
->root
, args
.phandle
);
312 TRACE(trace_os_emul
, ("child - in - phandle=0x%lx(%p`%s')\n",
313 (unsigned long)args
.phandle
,
315 (phandle
== NULL
? "" : device_name(phandle
))));
317 if (args
.phandle
== 0
318 || phandle
== NULL
) {
319 child_phandle
= NULL
;
320 args
.child_phandle
= -1;
323 child_phandle
= device_child(phandle
);
324 if (child_phandle
== NULL
)
325 args
.child_phandle
= 0;
327 args
.child_phandle
= device_to_external(child_phandle
);
329 /* write the result out */
330 TRACE(trace_os_emul
, ("child - out - child_phandle=0x%lx(%p`%s')\n",
331 (unsigned long)args
.child_phandle
,
333 (child_phandle
== NULL
? "" : device_name(child_phandle
))));
334 chirp_write_h2t_args(&args
,
342 chirp_emul_parent(os_emul_data
*data
,
348 unsigned_cell phandle
;
350 unsigned_cell parent_phandle
;
353 device
*parent_phandle
;
354 /* read the args in */
355 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
357 phandle
= external_to_device(data
->root
, args
.phandle
);
358 TRACE(trace_os_emul
, ("parent - in - phandle=0x%lx(%p`%s')\n",
359 (unsigned long)args
.phandle
,
361 (phandle
== NULL
? "" : device_name(phandle
))));
363 if (args
.phandle
== 0
364 || phandle
== NULL
) {
365 parent_phandle
= NULL
;
366 args
.parent_phandle
= -1;
369 parent_phandle
= device_parent(phandle
);
370 if (parent_phandle
== NULL
)
371 args
.parent_phandle
= 0;
373 args
.parent_phandle
= device_to_external(parent_phandle
);
375 /* return the result */
376 TRACE(trace_os_emul
, ("parent - out - parent_phandle=0x%lx(%p`%s')\n",
377 (unsigned long)args
.parent_phandle
,
379 (parent_phandle
== NULL
? "" : device_name(parent_phandle
))));
380 chirp_write_h2t_args(&args
,
388 chirp_emul_instance_to_package(os_emul_data
*data
,
392 struct instance_to_package_args
{
394 unsigned_cell ihandle
;
396 unsigned_cell phandle
;
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
))
403 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
404 TRACE(trace_os_emul
, ("instance-to-package - in - ihandle=0x%lx(%p`%s')\n",
405 (unsigned long)args
.ihandle
,
407 ihandle_name(ihandle
)));
408 /* find the corresponding phandle */
409 if (ihandle
== NULL
) {
414 phandle
= device_instance_device(ihandle
);
415 args
.phandle
= device_to_external(phandle
);
417 /* return the result */
418 TRACE(trace_os_emul
, ("instance-to-package - out - phandle=0x%lx(%p`%s')\n",
419 (unsigned long)args
.phandle
,
421 (phandle
== NULL
? "" : device_name(phandle
))));
422 chirp_write_h2t_args(&args
,
430 chirp_emul_getproplen(os_emul_data
*data
,
434 struct getproplen_args
{
436 unsigned_cell phandle
;
439 unsigned_cell proplen
;
443 /* read the args in */
444 if (chirp_read_t2h_args(&args
, sizeof(args
), 2, 1, data
, processor
, cia
))
446 phandle
= external_to_device(data
->root
, args
.phandle
);
447 emul_read_string(name
,
451 TRACE(trace_os_emul
, ("getproplen - in - phandle=0x%lx(%p`%s') name=`%s'\n",
452 (unsigned long)args
.phandle
,
454 (phandle
== NULL
? "" : device_name(phandle
)),
456 /* find our prop and get its length */
457 if (args
.phandle
== 0
458 || phandle
== NULL
) {
462 const device_property
*prop
= device_find_property(phandle
, name
);
463 if (prop
== (device_property
*)0) {
467 args
.proplen
= prop
->sizeof_array
;
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
,
481 chirp_emul_getprop(os_emul_data
*data
,
485 struct getprop_args
{
487 unsigned_cell phandle
;
490 unsigned_cell buflen
;
496 /* read in the args, the return is optional */
497 if (chirp_read_t2h_args(&args
, sizeof(args
), 4, -1, data
, processor
, cia
))
499 phandle
= external_to_device(data
->root
, args
.phandle
);
500 emul_read_string(name
,
504 TRACE(trace_os_emul
, ("getprop - in - phandle=0x%lx(%p`%s') name=`%s' buf=0x%lx buflen=%ld\n",
505 (unsigned long)args
.phandle
,
507 (phandle
== NULL
? "" : device_name(phandle
)),
509 (unsigned long)args
.buf
,
510 (unsigned long)args
.buflen
));
511 /* get the property */
512 if (args
.phandle
== 0
513 || phandle
== NULL
) {
517 const device_property
*prop
= device_find_property(phandle
, name
);
522 int size
= args
.buflen
;
523 if (size
> prop
->sizeof_array
)
524 size
= prop
->sizeof_array
;
525 emul_write_buffer(prop
->array
, args
.buf
,
529 switch (prop
->type
) {
530 case string_property
:
531 TRACE(trace_os_emul
, ("getprop - string `%s'\n",
532 device_find_string_property(phandle
, name
)));
534 case ihandle_property
:
535 TRACE(trace_os_emul
, ("getprop - ihandle=0x%lx(%p`%s')\n",
536 (unsigned long)BE2H_cell(*(unsigned_cell
*)prop
->array
),
537 device_find_ihandle_property(phandle
, name
),
538 ihandle_name(device_find_ihandle_property(phandle
, name
))));
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
));
550 TRACE(trace_os_emul
, ("getprop - out - size=%ld\n",
551 (unsigned long)args
.size
));
552 chirp_write_h2t_args(&args
,
561 chirp_emul_nextprop(os_emul_data
*data
,
565 struct nextprop_args
{
567 unsigned_cell phandle
;
568 unsigned_cell previous
;
575 /* read in the args */
576 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
578 phandle
= external_to_device(data
->root
, args
.phandle
);
579 if (args
.previous
!= 0)
580 emul_read_string(previous
,
585 /* If previous is NULL, make it look like the empty string. The
586 next property after the empty string is the first property. */
587 strcpy (previous
, "");
588 TRACE(trace_os_emul
, ("nextprop - in - phandle=0x%lx(%p`%s') previous=`%s' buf=0x%lx\n",
589 (unsigned long)args
.phandle
,
591 (phandle
== NULL
? "" : device_name(phandle
)),
593 (unsigned long)args
.buf
));
594 /* find the next property */
595 if (args
.phandle
== 0
596 || phandle
== NULL
) {
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 */
605 args
.flag
= -1; /* name invalid */
608 const device_property
*next_prop
;
609 if (strcmp (previous
, "") == 0) {
610 next_prop
= prev_prop
; /* The first property. */
613 next_prop
= device_next_property(prev_prop
);
615 if (next_prop
== NULL
) {
616 args
.flag
= 0; /* last property */
619 emul_write_buffer(next_prop
->name
, args
.buf
, strlen(next_prop
->name
),
621 TRACE(trace_os_emul
, ("nextprop - name=`%s'\n", next_prop
->name
));
622 args
.flag
= 1; /* worked ok */
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
,
638 chirp_emul_setprop(os_emul_data
*data
,
642 error("chirp: setprop method not implemented\n");
648 chirp_emul_canon(os_emul_data
*data
,
654 unsigned_cell device_specifier
;
656 unsigned_cell buflen
;
658 unsigned_cell length
;
660 char device_specifier
[1024];
664 /* read in the args */
665 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
667 emul_read_string(device_specifier
,
668 args
.device_specifier
,
669 sizeof(device_specifier
),
671 TRACE(trace_os_emul
, ("canon - in - device_specifier=`%s' buf=0x%lx buflen=%lx\n",
673 (unsigned long)args
.buf
,
674 (unsigned long)args
.buflen
));
676 phandle
= tree_find_device(data
->root
, device_specifier
);
677 if (phandle
== NULL
) {
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
,
689 args
.length
= length
;
691 /* write back the result */
692 TRACE(trace_os_emul
, ("canon - out - length=%ld buf=`%s'\n",
693 (unsigned long)args
.length
,
695 chirp_write_h2t_args(&args
,
703 chirp_emul_finddevice(os_emul_data
*data
,
707 struct finddevice_args
{
709 unsigned_cell device_specifier
;
711 unsigned_cell phandle
;
713 char device_specifier
[1024];
716 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
718 emul_read_string(device_specifier
,
719 args
.device_specifier
,
720 sizeof(device_specifier
),
722 TRACE(trace_os_emul
, ("finddevice - in - device_specifier=`%s'\n",
724 /* find the device */
725 phandle
= tree_find_device(data
->root
, device_specifier
);
729 args
.phandle
= device_to_external(phandle
);
730 /* return its phandle */
731 TRACE(trace_os_emul
, ("finddevice - out - phandle=0x%lx(%p`%s')\n",
732 (unsigned long)args
.phandle
,
734 (phandle
== NULL
? "" : device_name(phandle
))));
735 chirp_write_h2t_args(&args
,
743 chirp_emul_instance_to_path(os_emul_data
*data
,
747 struct instance_to_path_args
{
749 unsigned_cell ihandle
;
751 unsigned_cell buflen
;
753 unsigned_cell length
;
755 device_instance
*ihandle
;
759 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
761 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
762 TRACE(trace_os_emul
, ("instance-to-path - in - ihandle=0x%lx(%p`%s') buf=0x%lx buflen=%ld\n",
763 (unsigned long)args
.ihandle
,
765 ihandle_name(ihandle
),
766 (unsigned long)args
.buf
,
767 (unsigned long)args
.buflen
));
768 /* get the devices name */
769 if (ihandle
== NULL
) {
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
,
780 args
.length
= length
;
782 /* return its phandle */
783 TRACE(trace_os_emul
, ("instance-to-path - out - length=%ld buf=`%s')\n",
784 (unsigned long)args
.length
,
786 chirp_write_h2t_args(&args
,
794 chirp_emul_package_to_path(os_emul_data
*data
,
798 struct package_to_path_args
{
800 unsigned_cell phandle
;
802 unsigned_cell buflen
;
804 unsigned_cell length
;
809 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
811 phandle
= external_to_device(data
->root
, args
.phandle
);
812 TRACE(trace_os_emul
, ("package-to-path - in - phandle=0x%lx(%p`%s') buf=0x%lx buflen=%ld\n",
813 (unsigned long)args
.phandle
,
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
) {
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
,
831 args
.length
= length
;
833 /* return its phandle */
834 TRACE(trace_os_emul
, ("package-to-path - out - length=%ld buf=`%s')\n",
835 (unsigned long)args
.length
,
837 chirp_write_h2t_args(&args
,
845 chirp_emul_call_method(os_emul_data
*data
,
849 struct call_method_args
{
851 unsigned_cell method
;
852 unsigned_cell ihandle
;
854 unsigned_cell stack
[13]; /*6in + 6out + catch */
857 device_instance
*ihandle
;
858 /* some useful info about our mini stack */
861 int stack_catch_result
;
864 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, -1, data
, processor
, cia
))
866 emul_read_string(method
,
870 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
871 n_stack_args
= data
->n_args
- 2;
872 n_stack_returns
= data
->n_returns
- 1;
873 stack_catch_result
= n_stack_args
;
874 stack_returns
= stack_catch_result
+ 1;
875 TRACE(trace_os_emul
, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(%p`%s')\n",
876 (unsigned long)data
->n_args
,
877 (unsigned long)data
->n_returns
,
879 (unsigned long)args
.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");
888 args
.stack
[stack_catch_result
] =
889 device_instance_call_method(ihandle
,
894 &args
.stack
[stack_returns
]);
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
,
910 chirp_emul_open(os_emul_data
*data
,
916 unsigned_cell device_specifier
;
918 unsigned_cell ihandle
;
920 char device_specifier
[1024];
921 device_instance
*ihandle
;
923 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
925 emul_read_string(device_specifier
,
926 args
.device_specifier
,
927 sizeof(device_specifier
),
929 TRACE(trace_os_emul
, ("open - in - device_specifier=`%s'\n",
931 /* open the device */
932 ihandle
= tree_instance(data
->root
, device_specifier
);
936 args
.ihandle
= device_instance_to_external(ihandle
);
937 /* return the ihandle result */
938 TRACE(trace_os_emul
, ("open - out - ihandle=0x%lx(%p`%s')\n",
939 (unsigned long)args
.ihandle
,
941 ihandle_name(ihandle
)));
942 chirp_write_h2t_args(&args
,
950 chirp_emul_close(os_emul_data
*data
,
956 unsigned_cell ihandle
;
959 device_instance
*ihandle
;
961 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 0, data
, processor
, cia
))
963 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
964 TRACE(trace_os_emul
, ("close - in - ihandle=0x%lx(%p`%s')\n",
965 (unsigned long)args
.ihandle
,
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");
974 device_instance_delete(ihandle
);
976 /* return the ihandle result */
977 TRACE(trace_os_emul
, ("close - out\n"));
978 chirp_write_h2t_args(&args
,
986 chirp_emul_read(os_emul_data
*data
,
992 unsigned_cell ihandle
;
996 unsigned_cell actual
;
999 device_instance
*ihandle
;
1001 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1003 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1004 TRACE(trace_os_emul
, ("read - in - ihandle=0x%lx(%p`%s') addr=0x%lx len=%ld\n",
1005 (unsigned long)args
.ihandle
,
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");
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
);
1022 actual
= nr_read
; /* the error */
1025 else if (nr_read
== 0) {
1028 emul_write_buffer(buf
,
1035 args
.actual
= actual
;
1036 if (actual
< sizeof(buf
))
1039 buf
[sizeof(buf
) - 1] = '\0';
1046 case sim_io_not_ready
:
1047 ASSERT(sim_io_not_ready
== -2);
1048 args
.actual
= sim_io_not_ready
;
1051 error("Bad error value %ld", (long)actual
);
1056 /* return the result */
1057 TRACE(trace_os_emul
, ("read - out - actual=%ld `%s'\n",
1059 ((args
.actual
> 0 && args
.actual
< sizeof(buf
)) ? buf
: "")
1061 chirp_write_h2t_args(&args
,
1069 chirp_emul_write(os_emul_data
*data
,
1075 unsigned_cell ihandle
;
1079 unsigned_cell actual
;
1082 device_instance
*ihandle
;
1085 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1088 if (actual
>= sizeof(buf
))
1089 actual
= sizeof(buf
) - 1;
1090 emul_read_buffer(buf
,
1095 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1096 TRACE(trace_os_emul
, ("write - in - ihandle=0x%lx(%p`%s') `%s' (%ld)\n",
1097 (unsigned long)args
.ihandle
,
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");
1107 actual
= device_instance_write(ihandle
, buf
, actual
);
1111 args
.actual
= actual
;
1113 /* return the result */
1114 TRACE(trace_os_emul
, ("write - out - actual=%ld\n",
1115 (long)args
.actual
));
1116 chirp_write_h2t_args(&args
,
1124 chirp_emul_seek(os_emul_data
*data
,
1130 unsigned_cell ihandle
;
1131 unsigned_cell pos_hi
;
1132 unsigned_cell pos_lo
;
1134 unsigned_cell status
;
1137 device_instance
*ihandle
;
1139 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1141 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1142 TRACE(trace_os_emul
, ("seek - in - ihandle=0x%lx(%p`%s') pos.hi=0x%lx pos.lo=0x%lx\n",
1143 (unsigned long)args
.ihandle
,
1145 ihandle_name(ihandle
),
1146 (unsigned long)args
.pos_hi
,
1147 (unsigned long)args
.pos_lo
));
1148 if (ihandle
== NULL
) {
1149 /* OpenFirmware doesn't define this error */
1150 error("chirp: invalid ihandle passed to seek method");
1154 status
= device_instance_seek(ihandle
, args
.pos_hi
, args
.pos_lo
);
1155 args
.status
= status
;
1157 /* return the result */
1158 TRACE(trace_os_emul
, ("seek - out - status=%ld\n",
1159 (long)args
.status
));
1160 chirp_write_h2t_args(&args
,
1171 chirp_emul_claim(os_emul_data
*data
,
1175 /* NOTE: the client interface claim routine is *very* different to
1176 the "claim" method described in IEEE-1275 appendix A. The latter
1177 uses real addresses while this uses virtual (effective)
1183 unsigned_cell align
;
1185 unsigned_cell baseaddr
;
1188 if (chirp_read_t2h_args(&args
, sizeof(args
),
1189 3 /*n_args*/, 1 /*n_returns*/,
1190 data
, processor
, cia
))
1192 TRACE(trace_os_emul
, ("claim - in - virt=0x%lx size=%ld align=%d\n",
1193 (unsigned long)args
.virt
,
1194 (long int)args
.size
,
1196 /* use the memory device to allocate (real) memory at the requested
1199 device_instance
*memory
= tree_find_ihandle_property(data
->root
, "/chosen/memory");
1200 unsigned_cell mem_in
[3];
1201 unsigned_cell mem_out
[1];
1202 mem_in
[0] = args
.align
; /*top-of-stack*/
1203 mem_in
[1] = args
.size
;
1204 mem_in
[2] = args
.virt
;
1205 if (device_instance_call_method(memory
, "claim",
1206 3, mem_in
, 1, mem_out
) < 0)
1207 error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d",
1208 (unsigned long)args
.virt
,
1209 (long int)args
.size
,
1211 args
.baseaddr
= mem_out
[0];
1213 /* if using virtual addresses, create a 1-1 map of this address space */
1214 if (!data
->real_mode
) {
1215 error("chirp: claim method does not support virtual mode");
1217 /* return the base address */
1218 TRACE(trace_os_emul
, ("claim - out - baseaddr=0x%lx\n",
1219 (unsigned long)args
.baseaddr
));
1220 chirp_write_h2t_args(&args
,
1228 chirp_emul_release(os_emul_data
*data
,
1232 /* NOTE: the client interface release routine is *very* different to
1233 the "claim" method described in IEEE-1275 appendix A. The latter
1234 uses real addresses while this uses virtual (effective)
1243 if (chirp_read_t2h_args(&args
, sizeof(args
),
1244 2 /*n_args*/, 0 /*n_returns*/,
1245 data
, processor
, cia
))
1247 TRACE(trace_os_emul
, ("release - in - virt=0x%lx size=%ld\n",
1248 (unsigned long)args
.virt
,
1249 (long int)args
.size
));
1250 /* use the memory device to release (real) memory at the requested
1253 device_instance
*memory
= tree_find_ihandle_property(data
->root
, "/chosen/memory");
1254 unsigned_cell mem_in
[2];
1255 mem_in
[0] = args
.size
;
1256 mem_in
[1] = args
.virt
;
1257 if (device_instance_call_method(memory
, "release",
1258 2, mem_in
, 0, NULL
) < 0)
1259 error("chirp: claim failed to release memory virt=0x%lx size=%ld",
1260 (unsigned long)args
.virt
,
1261 (long int)args
.size
);
1263 /* if using virtual addresses, remove the 1-1 map of this address space */
1264 if (!data
->real_mode
) {
1265 error("chirp: release method does not support virtual mode");
1267 /* return the base address */
1268 TRACE(trace_os_emul
, ("release - out\n"));
1269 chirp_write_h2t_args(&args
,
1277 /* Control transfer */
1280 chirp_emul_boot(os_emul_data
*data
,
1284 /* unlike OpenFirmware this one can take an argument */
1287 unsigned_cell bootspec
;
1290 char bootspec
[1024];
1291 /* read in the arguments */
1292 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, 0, data
, processor
, cia
))
1293 cpu_halt(processor
, cia
, was_exited
, -1);
1294 if (args
.bootspec
!= 0)
1295 emul_read_string(bootspec
, args
.bootspec
, sizeof(bootspec
),
1298 strcpy(bootspec
, "(null)");
1299 TRACE(trace_os_emul
, ("boot - in bootspec=`%s'\n", bootspec
));
1300 /* just report this and exit */
1301 printf_filtered("chrp: boot %s called, exiting.\n", bootspec
);
1302 cpu_halt(processor
, cia
, was_exited
, 0);
1307 chirp_emul_enter(os_emul_data
*data
,
1311 error("chirp: enter method not implemented\n");
1316 chirp_emul_exit(os_emul_data
*data
,
1320 /* unlike OpenBoot this one can take an argument */
1326 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, 0, data
, processor
, cia
))
1327 cpu_halt(processor
, cia
, was_exited
, -1);
1328 cpu_halt(processor
, cia
, was_exited
, args
.status
);
1333 chirp_emul_chain(os_emul_data
*data
,
1337 error("chirp: chain method not implemented\n");
1342 /* user interface */
1345 chirp_emul_interpret(os_emul_data
*data
,
1349 error("chirp: interpret method not implemented\n");
1354 chirp_emul_set_callback(os_emul_data
*data
,
1358 error("chirp: set_callback method not implemented\n");
1363 chirp_emul_set_symbol_lookup(os_emul_data
*data
,
1367 error("chirp: set_symbol_lookup method not implemented\n");
1375 chirp_emul_milliseconds(os_emul_data
*data
,
1385 /* read in the arguments */
1386 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
1388 /* make up a number */
1389 time
= event_queue_time(psim_event_queue(cpu_system(processor
))) / 1000000;
1391 /* write the arguments back out */
1392 TRACE(trace_os_emul
, ("milliseconds - out - ms=%ld\n",
1393 (unsigned long)args
.ms
));
1394 chirp_write_h2t_args(&args
,
1404 static chirp_services services
[] = {
1406 /* client interface */
1407 { "test", chirp_emul_test
},
1410 { "peer", chirp_emul_peer
},
1411 { "child", chirp_emul_child
},
1412 { "parent", chirp_emul_parent
},
1413 { "instance-to-package", chirp_emul_instance_to_package
},
1414 { "getproplen", chirp_emul_getproplen
},
1415 { "getprop", chirp_emul_getprop
},
1416 { "nextprop", chirp_emul_nextprop
},
1417 /* { "setprop", chirp_emul_setprop }, */
1418 { "canon", chirp_emul_canon
},
1419 { "finddevice", chirp_emul_finddevice
},
1420 { "instance-to-path", chirp_emul_instance_to_path
},
1421 { "package-to-path", chirp_emul_package_to_path
},
1422 { "call-method", chirp_emul_call_method
},
1425 { "open", chirp_emul_open
},
1426 { "close", chirp_emul_close
},
1427 { "read", chirp_emul_read
},
1428 { "write", chirp_emul_write
},
1429 { "seek", chirp_emul_seek
},
1430 { "write", chirp_emul_write
},
1433 { "claim", chirp_emul_claim
},
1434 { "release", chirp_emul_release
},
1436 /* control transfer */
1437 { "boot", chirp_emul_boot
},
1438 { "enter", chirp_emul_enter
},
1439 { "exit", chirp_emul_exit
},
1440 { "chain", chirp_emul_chain
},
1442 /* user interface */
1443 { "interpret", chirp_emul_interpret
},
1444 { "set_callback", chirp_emul_set_callback
},
1445 { "set_symbol_lookup", chirp_emul_set_symbol_lookup
},
1448 { "milliseconds", chirp_emul_milliseconds
},
1450 { 0, /* sentinal */ },
1456 /* Any starting address greater than this is assumed to be an Chirp
1459 #ifndef CHIRP_START_ADDRESS
1460 #define CHIRP_START_ADDRESS 0x80000000
1462 #ifndef CHIRP_LOAD_BASE
1463 #define CHIRP_LOAD_BASE -1
1467 typedef struct _chirp_note_desc
{
1480 } note_found_status
;
1481 typedef struct _chirp_note
{
1482 chirp_note_desc desc
;
1483 note_found_status found
;
1486 typedef struct _chirp_note_head
{
1493 map_over_chirp_note(bfd
*image
,
1497 chirp_note
*note
= (chirp_note
*)obj
;
1498 if (strcmp(sect
->name
, ".note") == 0) {
1499 chirp_note_head head
;
1501 /* check the head */
1502 if (!bfd_get_section_contents(image
, sect
,
1503 &head
, 0, sizeof(head
)))
1505 head
.namesz
= bfd_get_32(image
, (void*)&head
.namesz
);
1506 head
.descsz
= bfd_get_32(image
, (void*)&head
.descsz
);
1507 head
.type
= bfd_get_32(image
, (void*)&head
.type
);
1508 if (head
.type
!= 0x1275)
1510 /* check the name field */
1511 if (head
.namesz
> sizeof(name
)) {
1512 error("chirp: note name too long (%d > %d)\n", (int)head
.namesz
, (int)sizeof(name
));
1514 if (!bfd_get_section_contents(image
, sect
,
1515 name
, sizeof(head
), head
.namesz
)) {
1516 error("chirp: note name unreadable\n");
1518 if (strcmp(name
, "PowerPC") != 0) {
1519 printf_filtered("chirp: note name (%s) not `PowerPC'\n", name
);
1521 /* check the size */
1522 if (head
.descsz
== sizeof(note
->desc
) - sizeof(int32_t)) {
1523 sim_io_printf_filtered("chirp: note descriptor missing load-base\n");
1525 else if (head
.descsz
!= sizeof(note
->desc
)) {
1526 sim_io_printf_filtered("chirp: note descriptor of wrong size\n");
1527 note
->found
= note_found
;
1530 note
->found
= note_correct
;
1531 /* get the contents */
1532 if (!bfd_get_section_contents(image
, sect
,
1533 ¬e
->desc
, /* page align start */
1534 ((sizeof(head
) + head
.namesz
) + 3) & ~3,
1536 error("chirp: note descriptor unreadable\n");
1538 note
->desc
.real_mode
= bfd_get_32(image
, (void*)¬e
->desc
.real_mode
);
1539 note
->desc
.real_base
= bfd_get_32(image
, (void*)¬e
->desc
.real_base
);
1540 note
->desc
.real_size
= bfd_get_32(image
, (void*)¬e
->desc
.real_size
);
1541 note
->desc
.virt_base
= bfd_get_32(image
, (void*)¬e
->desc
.virt_base
);
1542 note
->desc
.virt_size
= bfd_get_32(image
, (void*)¬e
->desc
.virt_size
);
1543 if (head
.descsz
== sizeof(note
->desc
))
1544 note
->desc
.load_base
= bfd_get_32(image
, (void*)¬e
->desc
.load_base
);
1546 note
->desc
.load_base
= (int32_t)-1;
1551 static os_emul_data
*
1552 emul_chirp_create(device
*root
,
1556 os_emul_data
*chirp
;
1561 /* Sanity check that this really is the chosen emulation */
1562 if (name
== NULL
&& image
== NULL
)
1565 && strcmp(name
, "ob") != 0
1566 && strcmp(name
, "ieee1274") != 0
1567 && strcmp(name
, "chrp") != 0
1568 && strcmp(name
, "chirp") != 0
1569 && strcmp(name
, "openboot") != 0)
1572 /* look for an elf note section, enter its values into the device tree */
1573 memset(¬e
, 0, sizeof(note
));
1575 bfd_map_over_sections(image
, map_over_chirp_note
, ¬e
);
1576 if (name
== NULL
&& image
!= NULL
&& note
.found
== note_missing
)
1579 /* Assume that it is a chirp emulation */
1581 chirp
= ZALLOC(os_emul_data
);
1583 chirp
->services
= services
;
1586 tree_parse(root
, "/name \"gpl,clayton");
1588 /* default options */
1589 emul_add_tree_options(root
, image
, "chirp", "oea",
1590 0 /*oea-interrupt-prefix*/);
1593 emul_add_tree_hardware(root
);
1595 /* basic information */
1597 = tree_find_integer_property(root
, "/openprom/options/oea-memory-size");
1598 chirp
->little_endian
1599 = tree_find_boolean_property(root
, "/options/little-endian?");
1600 chirp
->floating_point_available
1601 = tree_find_boolean_property(root
, "/openprom/options/floating-point?");
1602 chirp
->interrupt_prefix
=
1603 tree_find_integer_property(root
, "/openprom/options/oea-interrupt-prefix");
1606 /* Perform an interum layout of the openboot firmware in memory */
1609 /* a page for firmware calls */
1610 chirp
->sizeof_code
= 4096;
1611 chirp
->code_offset
= 0x4000; /* possible space for interrupt table */
1614 chirp
->sizeof_stack
= 32 * 1024;
1615 chirp
->stack_offset
= chirp
->code_offset
+ chirp
->sizeof_code
;
1617 /* the hash table */
1618 if (!note
.desc
.real_mode
) {
1619 chirp
->nr_page_table_entry_groups
= (chirp
->memory_size
< 0x800000
1620 ? 1024 /* min allowed */
1621 : (chirp
->memory_size
/ 4096 / 2));
1622 chirp
->sizeof_htab
= chirp
->nr_page_table_entry_groups
* 64;
1624 chirp
->htab_offset
= chirp
->stack_offset
+ chirp
->sizeof_stack
;
1626 /* the actual amount of space needed */
1627 chirp
->real_size
= chirp
->htab_offset
+ chirp
->sizeof_htab
;
1630 /* now go through and see if it fits in what is available */
1633 /* resolve real-mode? */
1634 if (note
.found
== note_correct
)
1635 chirp
->real_mode
= note
.desc
.real_mode
;
1636 else if (tree_find_property(root
, "/options/real-mode?") != NULL
)
1637 chirp
->real_mode
= tree_find_boolean_property(root
, "/options/real-mode?");
1639 chirp
->real_mode
= 0;
1640 if (tree_find_property(root
, "/options/real-mode?") != NULL
) {
1641 if (!chirp
->real_mode
1642 != !tree_find_boolean_property(root
, "/options/real-mode?"))
1643 error("chirp: /options/real-mode? conflicts with note section\n");
1646 tree_parse(root
, "/options/real-mode? %s",
1647 chirp
->real_mode
? "true" : "false");
1649 /* resolve real-base */
1650 if (note
.found
== note_correct
1651 && note
.desc
.real_base
!= (int32_t)-1)
1652 chirp
->real_base
= note
.desc
.real_base
;
1653 else if (tree_find_property(root
, "/options/real-base") != NULL
)
1654 chirp
->real_base
= tree_find_integer_property(root
, "/options/real-base");
1656 chirp
->real_base
= chirp
->memory_size
- chirp
->real_size
;
1657 if (tree_find_property(root
, "/options/real-base") != NULL
) {
1658 if (chirp
->real_base
!= tree_find_integer_property(root
, "/options/real-base"))
1659 error("chirp: /options/real-base conflicts with note section\n");
1662 tree_parse(root
, "/options/real-base 0x%lx",
1663 (unsigned long)chirp
->real_base
);
1665 /* resolve real-size */
1666 if (note
.found
== note_correct
1667 && note
.desc
.real_size
!= (int32_t)-1
1668 && note
.desc
.real_size
!= 0
1669 && chirp
->real_size
> note
.desc
.real_size
)
1670 error("chirp: insufficient physical memory for firmware\n");
1671 if (tree_find_property(root
, "/options/real-size") != NULL
) {
1672 if (chirp
->real_size
> tree_find_integer_property(root
, "/options/real-size"))
1673 error("chirp: /options/real-size conflicts with note section\n");
1676 tree_parse(root
, "/options/real-size 0x%lx",
1677 (unsigned long)chirp
->real_size
);
1679 /* resolve virt-base */
1680 if (chirp
->real_mode
)
1681 chirp
->virt_base
= chirp
->real_base
;
1682 else if (note
.found
== note_correct
&& note
.desc
.virt_base
!= -1)
1683 chirp
->virt_base
= note
.desc
.virt_base
;
1684 else if (tree_find_property(root
, "/options/virt-base") != NULL
)
1685 chirp
->virt_base
= tree_find_integer_property(root
, "/options/virt-base");
1687 chirp
->virt_base
= CHIRP_START_ADDRESS
;
1688 if (tree_find_property(root
, "/options/virt-base") != NULL
) {
1689 unsigned_word virt_base
= tree_find_integer_property(root
, "/options/virt-base");
1690 if (virt_base
!= -1 && chirp
->virt_base
!= virt_base
)
1691 error("chirp: /options/virt-base conflicts with note section\n");
1694 tree_parse(root
, "/options/virt-base 0x%lx",
1695 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_base
);
1697 /* resolve virt-size */
1698 chirp
->virt_size
= chirp
->real_size
;
1699 if (note
.found
== note_correct
1700 && note
.desc
.virt_size
!= (int32_t)-1
1701 && note
.desc
.virt_size
!= 0
1702 && !chirp
->real_mode
1703 && chirp
->virt_size
> note
.desc
.virt_size
)
1704 error("chirp: insufficent virtual memory for firmware\n");
1705 if (tree_find_property(root
, "/options/virt-size") != NULL
) {
1706 if (chirp
->virt_size
> tree_find_integer_property(root
, "/options/virt-size"))
1707 error("chirp: /options/virt-size conflicts with note section\n");
1710 tree_parse(root
, "/options/virt-size 0x%lx",
1711 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_size
);
1713 /* resolve load-base */
1714 if (note
.found
== note_correct
1715 && note
.desc
.load_base
!= (int32_t)-1)
1716 chirp
->load_base
= note
.desc
.load_base
;
1717 else if (tree_find_property(root
, "/options/load-base") != NULL
)
1718 chirp
->load_base
= tree_find_integer_property(root
, "/options/load-base");
1720 chirp
->load_base
= CHIRP_LOAD_BASE
;
1721 if (tree_find_property(root
, "/options/load-base") != NULL
) {
1722 if (chirp
->load_base
!= tree_find_integer_property(root
, "/options/load-base"))
1723 error("chirp: /options/load-base conflicts with note section\n");
1726 tree_parse(root
, "/options/load-base 0x%lx",
1727 (unsigned long)chirp
->load_base
);
1729 /* now adjust the preliminary firmware addresses to final values */
1730 chirp
->code_ra
= chirp
->code_offset
+ chirp
->real_base
;
1731 chirp
->stack_ra
= chirp
->stack_offset
+ chirp
->real_base
;
1732 chirp
->htab_ra
= chirp
->htab_offset
+ chirp
->real_base
;
1734 /* the virtual addresses. In real mode these are real addresses. */
1736 chirp
->code_va
= chirp
->code_offset
+ chirp
->virt_base
;
1737 chirp
->stack_va
= chirp
->stack_offset
+ chirp
->virt_base
;
1738 chirp
->htab_va
= chirp
->htab_offset
+ chirp
->virt_base
;
1740 chirp
->code_client_va
= chirp
->code_va
;
1741 chirp
->code_client_ra
= chirp
->code_ra
;
1743 chirp
->code_callback_va
= chirp
->code_client_va
+ 16;
1744 chirp
->code_callback_ra
= chirp
->code_client_ra
+ 16;
1746 chirp
->code_loop_va
= chirp
->code_callback_va
+ 16;
1747 chirp
->code_loop_ra
= chirp
->code_callback_ra
+ 16;
1749 /* initialization */
1751 tree_parse(root
, "/openprom/init");
1752 tree_parse(root
, "/openprom/init/register");
1753 tree_parse(root
, "/openprom/init/register/0.pc 0x%lx",
1754 (unsigned long)bfd_get_start_address(image
));
1755 tree_parse(root
, "/openprom/init/register/pc 0x%lx",
1756 (unsigned long)chirp
->code_loop_va
);
1757 tree_parse(root
, "/openprom/init/register/msr 0x%x",
1758 (msr_machine_check_enable
1761 : (msr_instruction_relocate
1762 | msr_data_relocate
))
1763 | (chirp
->little_endian
1764 ? (msr_little_endian_mode
1765 | msr_interrupt_little_endian_mode
)
1767 | (chirp
->floating_point_available
1768 ? msr_floating_point_available
1770 | (chirp
->interrupt_prefix
1771 ? msr_interrupt_prefix
1774 tree_parse(root
, "/openprom/init/register/sdr1 0x%lx",
1775 (unsigned long)(chirp
->htab_ra
1777 | ((chirp
->sizeof_htab
- 1) >> 16)));
1778 /* make certain that the segment registers map straight through */
1779 for (i
= 0; i
< 16; i
++) {
1780 tree_parse(root
, "/openprom/init/register/sr%d 0x%lx",
1781 i
, (unsigned long)i
);
1784 /* establish an initial state for all processors */
1787 /* the client interface address */
1788 tree_parse(root
, "/openprom/init/register/r5 0x%lx",
1789 (unsigned long)chirp
->code_client_va
);
1791 tree_parse(root
, "/openprom/init/register/sp 0x%lx",
1792 (unsigned long)(chirp
->stack_va
+ chirp
->sizeof_stack
- 16));
1793 /* in chrp mode any arguments end up being concatinated */
1794 tree_parse(root
, "/openprom/init/stack/stack-type chirp");
1797 /* client interface - emul-call followed by return instruction */
1800 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1801 (unsigned long)chirp
->code_client_ra
);
1802 tree_parse(node
, "./psim,description \"client-interface instruction");
1803 tree_parse(node
, "./real-address 0x%lx",
1804 (unsigned long)chirp
->code_client_ra
);
1805 tree_parse(node
, "./data 0x%lx",
1806 (unsigned long)emul_call_instruction
);
1808 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1809 (unsigned long)(chirp
->code_client_ra
+ 4));
1810 tree_parse(node
, "./psim,description \"client-interface return instruction");
1811 tree_parse(node
, "./real-address 0x%lx",
1812 (unsigned long)(chirp
->code_client_ra
+ 4));
1813 tree_parse(node
, "./data 0x%lx",
1814 (unsigned long)emul_blr_instruction
);
1817 /* return address for client callbacks - an emul-call instruction
1818 that is again followed by a return instruction */
1821 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1822 (unsigned long)chirp
->code_callback_ra
);
1823 tree_parse(node
, "./psim,description \"client-callback instruction");
1824 tree_parse(node
, "./real-address 0x%lx",
1825 (unsigned long)chirp
->code_callback_ra
);
1826 tree_parse(node
, "./data 0x%lx",
1827 (unsigned long)emul_call_instruction
);
1829 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1830 (unsigned long)(chirp
->code_callback_ra
+ 4));
1831 tree_parse(node
, "./psim,description \"client-callback return instruction");
1832 tree_parse(node
, "./real-address 0x%lx",
1833 (unsigned long)(chirp
->code_callback_ra
+ 4));
1834 tree_parse(node
, "./data 0x%lx",
1835 (unsigned long)emul_blr_instruction
);
1837 /* loop to keep other processors busy */
1839 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1840 (unsigned long)chirp
->code_loop_ra
);
1841 tree_parse(node
, "./psim,description \"processor busy loop");
1842 tree_parse(node
, "./real-address 0x%lx",
1843 (unsigned long)chirp
->code_loop_ra
);
1844 tree_parse(node
, "./data 0x%lx",
1845 (unsigned long)emul_loop_instruction
);
1849 /* create a hash table */
1851 if (!chirp
->real_mode
) {
1852 node
= tree_parse(root
, "/openprom/init/htab@0x%lx",
1853 (unsigned long)chirp
->htab_ra
);
1854 tree_parse(node
, "./claim 0");
1855 tree_parse(node
, "./real-address 0x%lx",
1856 (unsigned long)chirp
->htab_ra
);
1857 tree_parse(node
, "./nr-bytes 0x%lx",
1858 (unsigned long)chirp
->sizeof_htab
);
1861 /* map in the stack */
1863 if (!chirp
->real_mode
) {
1864 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1865 (unsigned long)chirp
->stack_ra
);
1866 tree_parse(node
, "./psim,description \"map in the stack");
1867 tree_parse(node
, "./claim 1");
1868 tree_parse(node
, "./virtual-address 0x%lx",
1869 (unsigned long)chirp
->stack_va
);
1870 tree_parse(node
, "./real-address 0x%lx",
1871 (unsigned long)chirp
->stack_ra
);
1872 tree_parse(node
, "./nr-bytes 0x%lx",
1873 (unsigned long)chirp
->sizeof_stack
);
1874 tree_parse(node
, "./wimg %d", 0x7);
1875 tree_parse(node
, "./pp %d", 0x2);
1878 /* map in the chrp openboot callback code */
1880 if (!chirp
->real_mode
) {
1881 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1882 (unsigned long)chirp
->code_ra
);
1883 tree_parse(node
, "./psim,description \"map in chrp openboot callback code");
1884 tree_parse(node
, "./claim 1");
1885 tree_parse(node
, "./virtual-address 0x%lx",
1886 (unsigned long)chirp
->code_va
);
1887 tree_parse(node
, "./real-address 0x%lx",
1888 (unsigned long)chirp
->code_ra
);
1889 tree_parse(node
, "./nr-bytes 0x%lx",
1890 (unsigned long)chirp
->sizeof_code
);
1891 tree_parse(node
, "./wimg %d", 0x7);
1892 tree_parse(node
, "./pp %d", 0x2);
1895 /* map in the program to run */
1897 if (chirp
->real_mode
) {
1898 node
= tree_parse(node
, "/openprom/init/load-binary");
1899 tree_parse(node
, "./psim,description \"load the binary");
1900 tree_parse(node
, "./file-name %s", bfd_get_filename(image
));
1901 tree_parse(node
, "./claim 1");
1904 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1905 (unsigned long)chirp
->load_base
);
1906 tree_parse(node
, "./psim,description \"load & map the binary");
1907 tree_parse(node
, "./claim 1");
1908 tree_parse(node
, "./file-name \"%s", bfd_get_filename(image
));
1909 tree_parse(node
, "./wimg %d", 0x7);
1910 tree_parse(node
, "./pp %d", 0x2);
1913 /* map in the interrupt vectors */
1915 if (!chirp
->real_mode
) {
1916 node
= tree_parse(root
, "/openprom/init/htab/pte@0x0");
1917 tree_parse(node
, "./psim,description \"map in interrupt vectors");
1918 tree_parse(node
, "./virtual-address 0x0");
1919 tree_parse(node
, "./real-address 0x0");
1920 tree_parse(node
, "./nr-bytes 0x3000");
1921 tree_parse(node
, "./wimg %d", 0x7);
1922 tree_parse(node
, "./pp %d", 0x2);
1929 emul_chirp_init(os_emul_data
*emul_data
,
1932 emul_data
->state
= serving
;
1936 emul_chirp_instruction_call(cpu
*processor
,
1939 os_emul_data
*emul_data
)
1941 unsigned_word service_name_addr
;
1942 unsigned_word result
;
1943 char service_buf
[32];
1945 chirp_services
*service
;
1947 switch (emul_data
->state
) {
1950 /* we are waiting on an OpenBoot request from the client program
1951 via the client interface */
1952 if (cia
!= emul_data
->code_client_va
)
1954 emul_data
->return_address
= LR
;
1955 emul_data
->arguments
= cpu_registers(processor
)->gpr
[3];
1956 /* try to determine what to do */
1957 service_name_addr
= emul_read_word(cpu_registers(processor
)->gpr
[3],
1959 service_name
= emul_read_string(service_buf
, service_name_addr
,
1960 sizeof(service_buf
), processor
, cia
);
1961 emul_data
->n_args
= emul_read_word(emul_data
->arguments
+ sizeof(unsigned_cell
),
1963 emul_data
->n_returns
= emul_read_word(emul_data
->arguments
+ 2 * sizeof(unsigned_cell
),
1965 /* verify what was passed */
1966 if (service_name_addr
== 0
1967 || service_name
== NULL
) {
1968 error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n",
1969 (unsigned long)emul_data
->return_address
,
1970 (unsigned long)emul_data
->arguments
);
1972 if (emul_data
->n_args
> 6) { /* See iee1275 requirements on nr returns */
1973 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n",
1975 (unsigned long)emul_data
->return_address
,
1976 (unsigned long)emul_data
->arguments
,
1977 emul_data
->n_returns
);
1979 if (emul_data
->n_returns
> 6) {
1980 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, with too many returns (%d)\n",
1982 (unsigned long)emul_data
->return_address
,
1983 (unsigned long)emul_data
->arguments
,
1987 TRACE(trace_os_emul
, ("%s called from 0x%lx with args 0x%lx\n",
1989 (unsigned long)emul_data
->return_address
,
1990 (unsigned long)emul_data
->arguments
));
1992 while (service
->name
!= NULL
&& strcmp(service
->name
, service_name
) != 0)
1995 if (service
->name
== NULL
) {
1996 error("OpenBoot service `%s' not found\n", service_name
);
1997 TRACE(trace_os_emul
, ("%s not found\n", service_name
));
1998 cpu_registers(processor
)->gpr
[3] = -1;
2001 emul_data
->service
= service
;
2003 result
= service
->handler(emul_data
, processor
, cia
);
2005 TRACE(trace_os_emul
, ("%s aborted with %ld\n", service_name
, (long)result
));
2006 cpu_registers(processor
)->gpr
[3] = result
;
2011 error("emul_chirp_instruction_call() unknown internal state\n");
2017 /* return to caller - instruction following this is a function return */
2021 const os_emul emul_chirp
= {
2025 NULL
, /*system_call*/
2026 emul_chirp_instruction_call
,