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(0x%lx`%s')\n",
264 (unsigned long)args
.phandle
,
265 (unsigned long)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(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
,
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(0x%lx`%s')\n",
313 (unsigned long)args
.phandle
,
314 (unsigned long)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(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
,
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(0x%lx`%s')\n",
359 (unsigned long)args
.phandle
,
360 (unsigned long)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(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
,
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(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
) {
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(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
,
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(0x%lx`%s') name=`%s'\n",
452 (unsigned long)args
.phandle
,
453 (unsigned long)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(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
)),
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(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
))));
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(0x%lx`%s') previous=`%s' buf=0x%lx\n",
589 (unsigned long)args
.phandle
,
590 (unsigned long)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(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
,
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(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
) {
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(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
) {
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(0x%lx`%s')\n",
876 (unsigned long)data
->n_args
,
877 (unsigned long)data
->n_returns
,
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");
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(0x%lx`%s')\n",
939 (unsigned long)args
.ihandle
,
940 (unsigned long)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(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");
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(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");
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(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");
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(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");
1153 status
= device_instance_seek(ihandle
, args
.pos_hi
, args
.pos_lo
);
1154 args
.status
= status
;
1156 /* return the result */
1157 TRACE(trace_os_emul
, ("seek - out - status=%ld\n",
1158 (long)args
.status
));
1159 chirp_write_h2t_args(&args
,
1170 chirp_emul_claim(os_emul_data
*data
,
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)
1182 unsigned_cell align
;
1184 unsigned_cell baseaddr
;
1187 if (chirp_read_t2h_args(&args
, sizeof(args
),
1188 3 /*n_args*/, 1 /*n_returns*/,
1189 data
, processor
, cia
))
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
,
1195 /* use the memory device to allocate (real) memory at the requested
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
,
1210 args
.baseaddr
= mem_out
[0];
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");
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
,
1227 chirp_emul_release(os_emul_data
*data
,
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)
1242 if (chirp_read_t2h_args(&args
, sizeof(args
),
1243 2 /*n_args*/, 0 /*n_returns*/,
1244 data
, processor
, cia
))
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
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
);
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");
1266 /* return the base address */
1267 TRACE(trace_os_emul
, ("release - out\n"));
1268 chirp_write_h2t_args(&args
,
1276 /* Control transfer */
1279 chirp_emul_boot(os_emul_data
*data
,
1283 /* unlike OpenFirmware this one can take an argument */
1286 unsigned_cell bootspec
;
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
),
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);
1306 chirp_emul_enter(os_emul_data
*data
,
1310 error("chirp: enter method not implemented\n");
1315 chirp_emul_exit(os_emul_data
*data
,
1319 /* unlike OpenBoot this one can take an argument */
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
);
1332 chirp_emul_chain(os_emul_data
*data
,
1336 error("chirp: chain method not implemented\n");
1341 /* user interface */
1344 chirp_emul_interpret(os_emul_data
*data
,
1348 error("chirp: interpret method not implemented\n");
1353 chirp_emul_set_callback(os_emul_data
*data
,
1357 error("chirp: set_callback method not implemented\n");
1362 chirp_emul_set_symbol_lookup(os_emul_data
*data
,
1366 error("chirp: set_symbol_lookup method not implemented\n");
1374 chirp_emul_milliseconds(os_emul_data
*data
,
1384 /* read in the arguments */
1385 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
1387 /* make up a number */
1388 time
= event_queue_time(psim_event_queue(cpu_system(processor
))) / 1000000;
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
,
1403 static chirp_services services
[] = {
1405 /* client interface */
1406 { "test", chirp_emul_test
},
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
},
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
},
1432 { "claim", chirp_emul_claim
},
1433 { "release", chirp_emul_release
},
1435 /* control transfer */
1436 { "boot", chirp_emul_boot
},
1437 { "enter", chirp_emul_enter
},
1438 { "exit", chirp_emul_exit
},
1439 { "chain", chirp_emul_chain
},
1441 /* user interface */
1442 { "interpret", chirp_emul_interpret
},
1443 { "set_callback", chirp_emul_set_callback
},
1444 { "set_symbol_lookup", chirp_emul_set_symbol_lookup
},
1447 { "milliseconds", chirp_emul_milliseconds
},
1449 { 0, /* sentinal */ },
1455 /* Any starting address greater than this is assumed to be an Chirp
1458 #ifndef CHIRP_START_ADDRESS
1459 #define CHIRP_START_ADDRESS 0x80000000
1461 #ifndef CHIRP_LOAD_BASE
1462 #define CHIRP_LOAD_BASE -1
1466 typedef struct _chirp_note_desc
{
1479 } note_found_status
;
1480 typedef struct _chirp_note
{
1481 chirp_note_desc desc
;
1482 note_found_status found
;
1485 typedef struct _chirp_note_head
{
1492 map_over_chirp_note(bfd
*image
,
1496 chirp_note
*note
= (chirp_note
*)obj
;
1497 if (strcmp(sect
->name
, ".note") == 0) {
1498 chirp_note_head head
;
1500 /* check the head */
1501 if (!bfd_get_section_contents(image
, sect
,
1502 &head
, 0, sizeof(head
)))
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)
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
));
1513 if (!bfd_get_section_contents(image
, sect
,
1514 name
, sizeof(head
), head
.namesz
)) {
1515 error("chirp: note name unreadable\n");
1517 if (strcmp(name
, "PowerPC") != 0) {
1518 printf_filtered("chirp: note name (%s) not `PowerPC'\n", name
);
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");
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
;
1529 note
->found
= note_correct
;
1530 /* get the contents */
1531 if (!bfd_get_section_contents(image
, sect
,
1532 ¬e
->desc
, /* page align start */
1533 ((sizeof(head
) + head
.namesz
) + 3) & ~3,
1535 error("chirp: note descriptor unreadable\n");
1537 note
->desc
.real_mode
= bfd_get_32(image
, (void*)¬e
->desc
.real_mode
);
1538 note
->desc
.real_base
= bfd_get_32(image
, (void*)¬e
->desc
.real_base
);
1539 note
->desc
.real_size
= bfd_get_32(image
, (void*)¬e
->desc
.real_size
);
1540 note
->desc
.virt_base
= bfd_get_32(image
, (void*)¬e
->desc
.virt_base
);
1541 note
->desc
.virt_size
= bfd_get_32(image
, (void*)¬e
->desc
.virt_size
);
1542 if (head
.descsz
== sizeof(note
->desc
))
1543 note
->desc
.load_base
= bfd_get_32(image
, (void*)¬e
->desc
.load_base
);
1545 note
->desc
.load_base
= (signed32
)-1;
1550 static os_emul_data
*
1551 emul_chirp_create(device
*root
,
1555 os_emul_data
*chirp
;
1560 /* Sanity check that this really is the chosen emulation */
1561 if (name
== NULL
&& image
== 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)
1571 /* look for an elf note section, enter its values into the device tree */
1572 memset(¬e
, 0, sizeof(note
));
1574 bfd_map_over_sections(image
, map_over_chirp_note
, ¬e
);
1575 if (name
== NULL
&& image
!= NULL
&& note
.found
== note_missing
)
1578 /* Assume that it is a chirp emulation */
1580 chirp
= ZALLOC(os_emul_data
);
1582 chirp
->services
= services
;
1585 tree_parse(root
, "/name \"gpl,clayton");
1587 /* default options */
1588 emul_add_tree_options(root
, image
, "chirp", "oea",
1589 0 /*oea-interrupt-prefix*/);
1592 emul_add_tree_hardware(root
);
1594 /* basic information */
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");
1605 /* Perform an interum layout of the openboot firmware in memory */
1608 /* a page for firmware calls */
1609 chirp
->sizeof_code
= 4096;
1610 chirp
->code_offset
= 0x4000; /* possible space for interrupt table */
1613 chirp
->sizeof_stack
= 32 * 1024;
1614 chirp
->stack_offset
= chirp
->code_offset
+ chirp
->sizeof_code
;
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;
1623 chirp
->htab_offset
= chirp
->stack_offset
+ chirp
->sizeof_stack
;
1625 /* the actual amount of space needed */
1626 chirp
->real_size
= chirp
->htab_offset
+ chirp
->sizeof_htab
;
1629 /* now go through and see if it fits in what is available */
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?");
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");
1645 tree_parse(root
, "/options/real-mode? %s",
1646 chirp
->real_mode
? "true" : "false");
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");
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");
1661 tree_parse(root
, "/options/real-base 0x%lx",
1662 (unsigned long)chirp
->real_base
);
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");
1675 tree_parse(root
, "/options/real-size 0x%lx",
1676 (unsigned long)chirp
->real_size
);
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");
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");
1693 tree_parse(root
, "/options/virt-base 0x%lx",
1694 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_base
);
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");
1709 tree_parse(root
, "/options/virt-size 0x%lx",
1710 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_size
);
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");
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");
1725 tree_parse(root
, "/options/load-base 0x%lx",
1726 (unsigned long)chirp
->load_base
);
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
;
1733 /* the virtual addresses. In real mode these are real addresses. */
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
;
1739 chirp
->code_client_va
= chirp
->code_va
;
1740 chirp
->code_client_ra
= chirp
->code_ra
;
1742 chirp
->code_callback_va
= chirp
->code_client_va
+ 16;
1743 chirp
->code_callback_ra
= chirp
->code_client_ra
+ 16;
1745 chirp
->code_loop_va
= chirp
->code_callback_va
+ 16;
1746 chirp
->code_loop_ra
= chirp
->code_callback_ra
+ 16;
1748 /* initialization */
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
1760 : (msr_instruction_relocate
1761 | msr_data_relocate
))
1762 | (chirp
->little_endian
1763 ? (msr_little_endian_mode
1764 | msr_interrupt_little_endian_mode
)
1766 | (chirp
->floating_point_available
1767 ? msr_floating_point_available
1769 | (chirp
->interrupt_prefix
1770 ? msr_interrupt_prefix
1773 tree_parse(root
, "/openprom/init/register/sdr1 0x%lx",
1774 (unsigned long)(chirp
->htab_ra
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
);
1783 /* establish an initial state for all processors */
1786 /* the client interface address */
1787 tree_parse(root
, "/openprom/init/register/r5 0x%lx",
1788 (unsigned long)chirp
->code_client_va
);
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");
1796 /* client interface - emul-call followed by return instruction */
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
);
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
);
1816 /* return address for client callbacks - an emul-call instruction
1817 that is again followed by a return instruction */
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
);
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
);
1836 /* loop to keep other processors busy */
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
);
1848 /* create a hash table */
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
);
1860 /* map in the stack */
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);
1877 /* map in the chrp openboot callback code */
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);
1894 /* map in the program to run */
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");
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);
1912 /* map in the interrupt vectors */
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);
1928 emul_chirp_init(os_emul_data
*emul_data
,
1931 emul_data
->state
= serving
;
1935 emul_chirp_instruction_call(cpu
*processor
,
1938 os_emul_data
*emul_data
)
1940 unsigned_word service_name_addr
;
1941 unsigned_word result
;
1942 char service_buf
[32];
1944 chirp_services
*service
;
1946 switch (emul_data
->state
) {
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
)
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],
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
),
1962 emul_data
->n_returns
= emul_read_word(emul_data
->arguments
+ 2 * sizeof(unsigned_cell
),
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
);
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
);
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
,
1984 TRACE(trace_os_emul
, ("%s called from 0x%lx with args 0x%lx\n",
1986 (unsigned long)emul_data
->return_address
,
1987 (unsigned long)emul_data
->arguments
));
1989 while (service
->name
!= NULL
&& strcmp(service
->name
, service_name
) != 0)
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;
1998 emul_data
->service
= service
;
2000 result
= service
->handler(emul_data
, processor
, cia
);
2002 TRACE(trace_os_emul
, ("%s aborted with %ld\n", service_name
, (long)result
));
2003 cpu_registers(processor
)->gpr
[3] = result
;
2008 error("emul_chirp_instruction_call() unknown internal state\n");
2014 /* return to caller - instruction following this is a function return */
2018 const os_emul emul_chirp
= {
2022 NULL
, /*system_call*/
2023 emul_chirp_instruction_call
,