1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
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 2 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #ifndef _EMUL_CHIRP_C_
23 #define _EMUL_CHIRP_C_
25 /* Note: this module is called via a table. There is no benefit in
28 #include "emul_generic.h"
29 #include "emul_chirp.h"
41 #ifndef STATIC_INLINE_EMUL_CHIRP
42 #define STATIC_INLINE_EMUL_CHIRP STATIC_INLINE
49 OpenFirmware - IEEE Standard for Boot (Initialization
50 Configuration) Firmware.
59 This code assumes that the memory node has #address-cells and
60 #size-cells set to one. For future implementations, this may not
68 /* Descriptor of the open boot services being emulated */
70 typedef int (chirp_handler
)
75 typedef struct _chirp_services
{
77 chirp_handler
*handler
;
81 /* The OpenBoot emulation is, at any time either waiting for a client
82 request or waiting on a client callback */
89 struct _os_emul_data
{
90 chirp_emul_state state
;
91 unsigned_word return_address
;
92 unsigned_word arguments
;
94 unsigned_word n_returns
;
95 chirp_services
*service
;
97 chirp_services
*services
;
99 unsigned_word memory_size
;
100 unsigned_word real_base
;
101 unsigned_word real_size
;
102 unsigned_word virt_base
;
103 unsigned_word virt_size
;
106 int floating_point_available
;
107 int interrupt_prefix
;
108 unsigned_word load_base
;
110 unsigned_word nr_page_table_entry_groups
;
111 unsigned_word htab_offset
;
112 unsigned_word htab_ra
;
113 unsigned_word htab_va
;
114 unsigned_word sizeof_htab
;
115 /* virtual address of htab */
116 unsigned_word stack_offset
;
117 unsigned_word stack_ra
;
118 unsigned_word stack_va
;
119 unsigned_word sizeof_stack
;
120 /* addresses of emulation instructions virtual/real */
121 unsigned_word code_offset
;
122 unsigned_word code_va
;
123 unsigned_word code_ra
;
124 unsigned_word sizeof_code
;
125 unsigned_word code_client_va
;
126 unsigned_word code_client_ra
;
127 unsigned_word code_callback_va
;
128 unsigned_word code_callback_ra
;
129 unsigned_word code_loop_va
;
130 unsigned_word code_loop_ra
;
134 /* returns the name of the corresponding Ihandle */
136 ihandle_name(device_instance
*ihandle
)
141 return device_name(device_instance_device(ihandle
));
146 /* Read/write the argument list making certain that all values are
147 converted to/from host byte order.
149 In the below only n_args+n_returns is read/written */
152 chirp_read_t2h_args(void *args
,
160 unsigned_cell
*words
;
162 /* check against the number of arguments specified by the client
164 if ((n_args
>= 0 && data
->n_args
!= n_args
)
165 || (n_returns
>= 0 && data
->n_returns
!= n_returns
)) {
166 TRACE(trace_os_emul
, ("%s - invalid nr of args - n_args=%ld, n_returns=%ld\n",
169 (long)data
->n_returns
));
172 /* check that there is enough space */
173 if (sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
) > sizeof_args
)
175 /* bring in the data */
176 memset(args
, 0, sizeof_args
);
177 emul_read_buffer(args
, data
->arguments
+ 3 * sizeof(unsigned_cell
),
178 sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
),
180 /* convert all words to host format */
182 for (i
= 0; i
< (sizeof_args
/ sizeof(unsigned_cell
)); i
++)
183 words
[i
] = T2H_cell(words
[i
]);
188 chirp_write_h2t_args(void *args
,
195 unsigned_cell
*words
;
196 /* convert to target everything */
198 for (i
= 0; i
< (sizeof_args
/ sizeof(unsigned_cell
)); i
++)
199 words
[i
] = H2T_cell(words
[i
]);
200 /* bring in the data */
201 emul_write_buffer(args
, data
->arguments
+ 3 * sizeof(unsigned_cell
),
202 sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
),
207 /* OpenBoot emulation functions */
209 /* client interface */
212 chirp_emul_test(os_emul_data
*data
,
218 unsigned_cell name
; /*string*/
220 unsigned_cell missing
;
223 chirp_services
*service
= NULL
;
224 /* read in the arguments */
225 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
227 emul_read_string(name
, args
.name
, sizeof(name
),
229 TRACE(trace_os_emul
, ("test - in - name=`%s'\n", name
));
230 /* see if we know about the service */
231 service
= data
->services
;
232 while (service
->name
!= NULL
&& strcmp(service
->name
, name
) != 0) {
235 if (service
->name
== NULL
)
239 /* write the arguments back out */
240 TRACE(trace_os_emul
, ("test - out - missing=%ld\n",
241 (long)args
.missing
));
242 chirp_write_h2t_args(&args
,
253 chirp_emul_peer(os_emul_data
*data
,
259 unsigned_cell phandle
;
261 unsigned_cell sibling_phandle
;
264 device
*sibling_phandle
= NULL
;
265 /* read in the arguments */
266 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
268 phandle
= external_to_device(data
->root
, args
.phandle
);
269 TRACE(trace_os_emul
, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
270 (unsigned long)args
.phandle
,
271 (unsigned long)phandle
,
272 (phandle
== NULL
? "" : device_name(phandle
))));
274 if (args
.phandle
== 0) {
275 sibling_phandle
= data
->root
;
276 args
.sibling_phandle
= device_to_external(sibling_phandle
);
278 else if (phandle
== NULL
) {
279 sibling_phandle
= NULL
;
280 args
.sibling_phandle
= -1;
283 sibling_phandle
= device_sibling(phandle
);
284 if (sibling_phandle
== NULL
)
285 args
.sibling_phandle
= 0;
287 args
.sibling_phandle
= device_to_external(sibling_phandle
);
289 /* write the arguments back out */
290 TRACE(trace_os_emul
, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
291 (unsigned long)args
.sibling_phandle
,
292 (unsigned long)sibling_phandle
,
293 (sibling_phandle
== NULL
? "" : device_name(sibling_phandle
))));
294 chirp_write_h2t_args(&args
,
302 chirp_emul_child(os_emul_data
*data
,
308 unsigned_cell phandle
;
310 unsigned_cell child_phandle
;
313 device
*child_phandle
;
314 /* read the arguments in */
315 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
317 phandle
= external_to_device(data
->root
, args
.phandle
);
318 TRACE(trace_os_emul
, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
319 (unsigned long)args
.phandle
,
320 (unsigned long)phandle
,
321 (phandle
== NULL
? "" : device_name(phandle
))));
323 if (args
.phandle
== 0
324 || phandle
== NULL
) {
325 child_phandle
= NULL
;
326 args
.child_phandle
= -1;
329 child_phandle
= device_child(phandle
);
330 if (child_phandle
== NULL
)
331 args
.child_phandle
= 0;
333 args
.child_phandle
= device_to_external(child_phandle
);
335 /* write the result out */
336 TRACE(trace_os_emul
, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
337 (unsigned long)args
.child_phandle
,
338 (unsigned long)child_phandle
,
339 (child_phandle
== NULL
? "" : device_name(child_phandle
))));
340 chirp_write_h2t_args(&args
,
348 chirp_emul_parent(os_emul_data
*data
,
354 unsigned_cell phandle
;
356 unsigned_cell parent_phandle
;
359 device
*parent_phandle
;
360 /* read the args in */
361 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
363 phandle
= external_to_device(data
->root
, args
.phandle
);
364 TRACE(trace_os_emul
, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
365 (unsigned long)args
.phandle
,
366 (unsigned long)phandle
,
367 (phandle
== NULL
? "" : device_name(phandle
))));
369 if (args
.phandle
== 0
370 || phandle
== NULL
) {
371 parent_phandle
= NULL
;
372 args
.parent_phandle
= -1;
375 parent_phandle
= device_parent(phandle
);
376 if (parent_phandle
== NULL
)
377 args
.parent_phandle
= 0;
379 args
.parent_phandle
= device_to_external(parent_phandle
);
381 /* return the result */
382 TRACE(trace_os_emul
, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
383 (unsigned long)args
.parent_phandle
,
384 (unsigned long)parent_phandle
,
385 (parent_phandle
== NULL
? "" : device_name(parent_phandle
))));
386 chirp_write_h2t_args(&args
,
394 chirp_emul_instance_to_package(os_emul_data
*data
,
398 struct instance_to_package_args
{
400 unsigned_cell ihandle
;
402 unsigned_cell phandle
;
404 device_instance
*ihandle
;
405 device
*phandle
= NULL
;
406 /* read the args in */
407 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
409 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
410 TRACE(trace_os_emul
, ("instance-to-package - in - ihandle=0x%lx(0x%lx`%s')\n",
411 (unsigned long)args
.ihandle
,
412 (unsigned long)ihandle
,
413 ihandle_name(ihandle
)));
414 /* find the corresponding phandle */
415 if (ihandle
== NULL
) {
420 phandle
= device_instance_device(ihandle
);
421 args
.phandle
= device_to_external(phandle
);
423 /* return the result */
424 TRACE(trace_os_emul
, ("instance-to-package - out - phandle=0x%lx(0x%lx`%s')\n",
425 (unsigned long)args
.phandle
,
426 (unsigned long)phandle
,
427 (phandle
== NULL
? "" : device_name(phandle
))));
428 chirp_write_h2t_args(&args
,
436 chirp_emul_getproplen(os_emul_data
*data
,
440 struct getproplen_args
{
442 unsigned_cell phandle
;
445 unsigned_cell proplen
;
449 /* read the args in */
450 if (chirp_read_t2h_args(&args
, sizeof(args
), 2, 1, data
, processor
, cia
))
452 phandle
= external_to_device(data
->root
, args
.phandle
);
453 emul_read_string(name
,
457 TRACE(trace_os_emul
, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
458 (unsigned long)args
.phandle
,
459 (unsigned long)phandle
,
460 (phandle
== NULL
? "" : device_name(phandle
)),
462 /* find our prop and get its length */
463 if (args
.phandle
== 0
464 || phandle
== NULL
) {
468 const device_property
*prop
= device_find_property(phandle
, name
);
469 if (prop
== (device_property
*)0) {
473 args
.proplen
= prop
->sizeof_array
;
476 /* return the result */
477 TRACE(trace_os_emul
, ("getproplen - out - proplen=%ld\n",
478 (unsigned long)args
.proplen
));
479 chirp_write_h2t_args(&args
,
487 chirp_emul_getprop(os_emul_data
*data
,
491 struct getprop_args
{
493 unsigned_cell phandle
;
496 unsigned_cell buflen
;
502 /* read in the args, the return is optional */
503 if (chirp_read_t2h_args(&args
, sizeof(args
), 4, -1, data
, processor
, cia
))
505 phandle
= external_to_device(data
->root
, args
.phandle
);
506 emul_read_string(name
,
510 TRACE(trace_os_emul
, ("getprop - in - phandle=0x%lx(0x%lx`%s') name=`%s' buf=0x%lx buflen=%ld\n",
511 (unsigned long)args
.phandle
,
512 (unsigned long)phandle
,
513 (phandle
== NULL
? "" : device_name(phandle
)),
515 (unsigned long)args
.buf
,
516 (unsigned long)args
.buflen
));
517 /* get the property */
518 if (args
.phandle
== 0
519 || phandle
== NULL
) {
523 const device_property
*prop
= device_find_property(phandle
, name
);
528 int size
= args
.buflen
;
529 if (size
> prop
->sizeof_array
)
530 size
= prop
->sizeof_array
;
531 emul_write_buffer(prop
->array
, args
.buf
,
535 switch (prop
->type
) {
536 case string_property
:
537 TRACE(trace_os_emul
, ("getprop - string `%s'\n",
538 device_find_string_property(phandle
, name
)));
540 case ihandle_property
:
541 TRACE(trace_os_emul
, ("getprop - ihandle=0x%lx(0x%lx`%s')\n",
542 BE2H_cell(*(unsigned_cell
*)prop
->array
),
543 (unsigned long)device_find_ihandle_property(phandle
, name
),
544 ihandle_name(device_find_ihandle_property(phandle
, name
))));
551 /* write back the result */
552 if (data
->n_returns
== 0)
553 TRACE(trace_os_emul
, ("getprop - out - size=%ld (not returned)\n",
554 (unsigned long)args
.size
));
556 TRACE(trace_os_emul
, ("getprop - out - size=%ld\n",
557 (unsigned long)args
.size
));
558 chirp_write_h2t_args(&args
,
567 chirp_emul_nextprop(os_emul_data
*data
,
571 struct nextprop_args
{
573 unsigned_cell phandle
;
574 unsigned_cell previous
;
581 /* read in the args */
582 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
584 phandle
= external_to_device(data
->root
, args
.phandle
);
585 emul_read_string(previous
,
589 TRACE(trace_os_emul
, ("nextprop - in - phandle=0x%lx(0x%lx`%s') previous=`%s' buf=0x%lx\n",
590 (unsigned long)args
.phandle
,
591 (unsigned long)phandle
,
592 (phandle
== NULL
? "" : device_name(phandle
)),
594 (unsigned long)args
.buf
));
595 /* find the next property */
596 if (args
.phandle
== 0
597 || phandle
== NULL
) {
601 const device_property
*prev_prop
= device_find_property(phandle
, previous
);
602 if (prev_prop
== NULL
) {
603 args
.flag
= -1; /* name invalid */
606 const device_property
*next_prop
;
607 next_prop
= device_next_property(prev_prop
);
608 if (next_prop
== NULL
) {
609 args
.flag
= 0; /* last property */
612 emul_write_buffer(next_prop
->name
, args
.buf
, strlen(next_prop
->name
),
614 TRACE(trace_os_emul
, ("nextprop - name=`%s'\n", next_prop
->name
));
615 args
.flag
= 1; /* worked ok */
619 /* write back the result */
620 TRACE(trace_os_emul
, ("nextprop - out - flag=%ld\n",
621 (unsigned long)args
.flag
));
622 chirp_write_h2t_args(&args
,
631 chirp_emul_setprop(os_emul_data
*data
,
635 error("chirp: setprop method not implemented\n");
641 chirp_emul_canon(os_emul_data
*data
,
647 unsigned_cell device_specifier
;
649 unsigned_cell buflen
;
651 unsigned_cell length
;
653 char device_specifier
[1024];
657 /* read in the args */
658 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
660 emul_read_string(device_specifier
,
661 args
.device_specifier
,
662 sizeof(device_specifier
),
664 TRACE(trace_os_emul
, ("canon - in - device_specifier=`%s' buf=0x%lx buflen=%lx\n",
666 (unsigned long)args
.buf
,
667 (unsigned long)args
.buflen
));
669 phandle
= tree_find_device(data
->root
, device_specifier
);
670 if (phandle
== NULL
) {
676 path
= device_path(phandle
);
677 length
= strlen(path
);
678 if (length
>= args
.buflen
)
679 length
= args
.buflen
- 1;
680 emul_write_buffer(path
, args
.buf
, length
,
682 args
.length
= length
;
684 /* write back the result */
685 TRACE(trace_os_emul
, ("canon - out - length=%ld buf=`%s'\n",
686 (unsigned long)args
.length
,
688 chirp_write_h2t_args(&args
,
696 chirp_emul_finddevice(os_emul_data
*data
,
700 struct finddevice_args
{
702 unsigned_cell device_specifier
;
704 unsigned_cell phandle
;
706 char device_specifier
[1024];
709 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
711 emul_read_string(device_specifier
,
712 args
.device_specifier
,
713 sizeof(device_specifier
),
715 TRACE(trace_os_emul
, ("finddevice - in - device_specifier=`%s'\n",
717 /* find the device */
718 phandle
= tree_find_device(data
->root
, device_specifier
);
722 args
.phandle
= device_to_external(phandle
);
723 /* return its phandle */
724 TRACE(trace_os_emul
, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
725 (unsigned long)args
.phandle
,
726 (unsigned long)phandle
,
727 (phandle
== NULL
? "" : device_name(phandle
))));
728 chirp_write_h2t_args(&args
,
736 chirp_emul_instance_to_path(os_emul_data
*data
,
740 struct instance_to_path_args
{
742 unsigned_cell ihandle
;
744 unsigned_cell buflen
;
746 unsigned_cell length
;
748 device_instance
*ihandle
;
752 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
754 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
755 TRACE(trace_os_emul
, ("instance-to-path - in - ihandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
756 (unsigned long)args
.ihandle
,
757 (unsigned long)ihandle
,
758 ihandle_name(ihandle
),
759 (unsigned long)args
.buf
,
760 (unsigned long)args
.buflen
));
761 /* get the devices name */
762 if (ihandle
== NULL
) {
767 path
= device_instance_path(ihandle
);
768 length
= strlen(path
);
769 if (length
>= args
.buflen
)
770 length
= args
.buflen
- 1;
771 emul_write_buffer(path
, args
.buf
, length
,
773 args
.length
= length
;
775 /* return its phandle */
776 TRACE(trace_os_emul
, ("instance-to-path - out - length=%ld buf=`%s')\n",
777 (unsigned long)args
.length
,
779 chirp_write_h2t_args(&args
,
787 chirp_emul_package_to_path(os_emul_data
*data
,
791 struct package_to_path_args
{
793 unsigned_cell phandle
;
795 unsigned_cell buflen
;
797 unsigned_cell length
;
802 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
804 phandle
= external_to_device(data
->root
, args
.phandle
);
805 TRACE(trace_os_emul
, ("package-to-path - in - phandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
806 (unsigned long)args
.phandle
,
807 (unsigned long)phandle
,
808 (phandle
== NULL
? "" : device_name(phandle
)),
809 (unsigned long)args
.buf
,
810 (unsigned long)args
.buflen
));
811 /* get the devices name */
812 if (phandle
== NULL
) {
818 path
= device_path(phandle
);
819 length
= strlen(path
);
820 if (length
>= args
.buflen
)
821 length
= args
.buflen
- 1;
822 emul_write_buffer(path
, args
.buf
, length
,
824 args
.length
= length
;
826 /* return its phandle */
827 TRACE(trace_os_emul
, ("package-to-path - out - length=%ld buf=`%s')\n",
828 (unsigned long)args
.length
,
830 chirp_write_h2t_args(&args
,
838 chirp_emul_call_method(os_emul_data
*data
,
842 struct call_method_args
{
844 unsigned_cell method
;
845 unsigned_cell ihandle
;
847 unsigned_cell stack
[13]; /*6in + 6out + catch */
850 device_instance
*ihandle
;
851 /* some useful info about our mini stack */
854 int stack_catch_result
;
857 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, -1, data
, processor
, cia
))
859 emul_read_string(method
,
863 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
864 n_stack_args
= data
->n_args
- 2;
865 n_stack_returns
= data
->n_returns
- 1;
866 stack_catch_result
= n_stack_args
;
867 stack_returns
= stack_catch_result
+ 1;
868 TRACE(trace_os_emul
, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(0x%lx`%s')\n",
869 (unsigned long)data
->n_args
,
870 (unsigned long)data
->n_returns
,
872 (unsigned long)args
.ihandle
,
873 (unsigned long)ihandle
,
874 ihandle_name(ihandle
)));
875 /* see if we can emulate this method */
876 if (ihandle
== NULL
) {
877 /* OpenFirmware doesn't define this error */
878 error("chirp: invalid ihandle passed to call-method method");
881 args
.stack
[stack_catch_result
] =
882 device_instance_call_method(ihandle
,
887 &args
.stack
[stack_returns
]);
890 TRACE(trace_os_emul
, ("call-method - out - catch-result=%ld\n",
891 (unsigned long)args
.stack
[stack_catch_result
]));
892 chirp_write_h2t_args(&args
,
903 chirp_emul_open(os_emul_data
*data
,
909 unsigned_cell device_specifier
;
911 unsigned_cell ihandle
;
913 char device_specifier
[1024];
914 device_instance
*ihandle
;
916 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
918 emul_read_string(device_specifier
,
919 args
.device_specifier
,
920 sizeof(device_specifier
),
922 TRACE(trace_os_emul
, ("open - in - device_specifier=`%s'\n",
924 /* open the device */
925 ihandle
= tree_instance(data
->root
, device_specifier
);
929 args
.ihandle
= device_instance_to_external(ihandle
);
930 /* return the ihandle result */
931 TRACE(trace_os_emul
, ("open - out - ihandle=0x%lx(0x%lx`%s')\n",
932 (unsigned long)args
.ihandle
,
933 (unsigned long)ihandle
,
934 ihandle_name(ihandle
)));
935 chirp_write_h2t_args(&args
,
943 chirp_emul_close(os_emul_data
*data
,
949 unsigned_cell ihandle
;
952 device_instance
*ihandle
;
954 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 0, data
, processor
, cia
))
956 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
957 TRACE(trace_os_emul
, ("close - in - ihandle=0x%lx(0x%lx`%s')\n",
958 (unsigned long)args
.ihandle
,
959 (unsigned long)ihandle
,
960 ihandle_name(ihandle
)));
961 /* close the device */
962 if (ihandle
== NULL
) {
963 /* OpenFirmware doesn't define this error */
964 error("chirp: invalid ihandle passed to close method");
967 device_instance_delete(ihandle
);
969 /* return the ihandle result */
970 TRACE(trace_os_emul
, ("close - out\n"));
971 chirp_write_h2t_args(&args
,
979 chirp_emul_read(os_emul_data
*data
,
985 unsigned_cell ihandle
;
989 unsigned_cell actual
;
992 device_instance
*ihandle
;
994 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
996 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
997 TRACE(trace_os_emul
, ("read - in - ihandle=0x%lx(0x%lx`%s') addr=0x%lx len=%ld\n",
998 (unsigned long)args
.ihandle
,
999 (unsigned long)ihandle
,
1000 ihandle_name(ihandle
),
1001 (unsigned long)args
.addr
,
1002 (unsigned long)args
.len
));
1003 if (ihandle
== NULL
) {
1004 /* OpenFirmware doesn't define this error */
1005 error("chirp: invalid ihandle passed to read method");
1010 while (actual
< args
.len
) {
1011 int remaining
= args
.len
- actual
;
1012 int to_read
= (remaining
<= sizeof(buf
) ? remaining
: sizeof(buf
));
1013 int nr_read
= device_instance_read(ihandle
, buf
, to_read
);
1015 actual
= nr_read
; /* the error */
1018 else if (nr_read
== 0) {
1021 emul_write_buffer(buf
,
1028 args
.actual
= actual
;
1029 if (actual
< sizeof(buf
))
1032 buf
[sizeof(buf
) - 1] = '\0';
1039 case sim_io_not_ready
:
1040 ASSERT(sim_io_not_ready
== -2);
1041 args
.actual
= sim_io_not_ready
;
1044 error("Bad error value %ld", (long)actual
);
1049 /* return the result */
1050 TRACE(trace_os_emul
, ("read - out - actual=%ld `%s'\n",
1052 ((args
.actual
> 0 && args
.actual
< sizeof(buf
)) ? buf
: "")
1054 chirp_write_h2t_args(&args
,
1062 chirp_emul_write(os_emul_data
*data
,
1068 unsigned_cell ihandle
;
1072 unsigned_cell actual
;
1075 device_instance
*ihandle
;
1078 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1081 if (actual
>= sizeof(buf
))
1082 actual
= sizeof(buf
) - 1;
1083 emul_read_buffer(buf
,
1088 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1089 TRACE(trace_os_emul
, ("write - in - ihandle=0x%lx(0x%lx`%s') `%s' (%ld)\n",
1090 (unsigned long)args
.ihandle
,
1091 (unsigned long)ihandle
,
1092 ihandle_name(ihandle
),
1093 buf
, (long)actual
));
1094 if (ihandle
== NULL
) {
1095 /* OpenFirmware doesn't define this error */
1096 error("chirp: invalid ihandle passed to write method");
1100 actual
= device_instance_write(ihandle
, buf
, actual
);
1104 args
.actual
= actual
;
1106 /* return the result */
1107 TRACE(trace_os_emul
, ("write - out - actual=%ld\n",
1108 (long)args
.actual
));
1109 chirp_write_h2t_args(&args
,
1117 chirp_emul_seek(os_emul_data
*data
,
1123 unsigned_cell ihandle
;
1124 unsigned_cell pos_hi
;
1125 unsigned_cell pos_lo
;
1127 unsigned_cell status
;
1130 device_instance
*ihandle
;
1132 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1134 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1135 TRACE(trace_os_emul
, ("seek - in - ihandle=0x%lx(0x%lx`%s') pos.hi=0x%lx pos.lo=0x%lx\n",
1136 (unsigned long)args
.ihandle
,
1137 (unsigned long)ihandle
,
1138 ihandle_name(ihandle
),
1139 args
.pos_hi
, args
.pos_lo
));
1140 if (ihandle
== NULL
) {
1141 /* OpenFirmware doesn't define this error */
1142 error("chirp: invalid ihandle passed to seek method");
1146 status
= device_instance_seek(ihandle
, args
.pos_hi
, args
.pos_lo
);
1147 args
.status
= status
;
1149 /* return the result */
1150 TRACE(trace_os_emul
, ("seek - out - status=%ld\n",
1151 (long)args
.status
));
1152 chirp_write_h2t_args(&args
,
1163 chirp_emul_claim(os_emul_data
*data
,
1167 /* NOTE: the client interface claim routine is *very* different to
1168 the "claim" method described in IEEE-1275 appendix A. The latter
1169 uses real addresses while this uses virtual (effective)
1175 unsigned_cell align
;
1177 unsigned_cell baseaddr
;
1180 if (chirp_read_t2h_args(&args
, sizeof(args
),
1181 3 /*n_args*/, 1 /*n_returns*/,
1182 data
, processor
, cia
))
1184 TRACE(trace_os_emul
, ("claim - in - virt=0x%lx size=%ld align=%d\n",
1185 (unsigned long)args
.virt
,
1186 (long int)args
.size
,
1188 /* use the memory device to allocate (real) memory at the requested
1191 device_instance
*memory
= tree_find_ihandle_property(data
->root
, "/chosen/memory");
1192 unsigned_cell mem_in
[3];
1193 unsigned_cell mem_out
[1];
1194 mem_in
[0] = args
.align
; /*top-of-stack*/
1195 mem_in
[1] = args
.size
;
1196 mem_in
[2] = args
.virt
;
1197 if (device_instance_call_method(memory
, "claim",
1198 3, mem_in
, 1, mem_out
) < 0)
1199 error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d",
1200 (unsigned long)args
.virt
,
1201 (long int)args
.size
,
1203 args
.baseaddr
= mem_out
[0];
1205 /* if using virtual addresses, create a 1-1 map of this address space */
1206 if (!data
->real_mode
) {
1207 error("chirp: claim method does not support virtual mode");
1209 /* return the base address */
1210 TRACE(trace_os_emul
, ("claim - out - baseaddr=0x%lx\n",
1211 (unsigned long)args
.baseaddr
));
1212 chirp_write_h2t_args(&args
,
1220 chirp_emul_release(os_emul_data
*data
,
1224 /* NOTE: the client interface release routine is *very* different to
1225 the "claim" method described in IEEE-1275 appendix A. The latter
1226 uses real addresses while this uses virtual (effective)
1235 if (chirp_read_t2h_args(&args
, sizeof(args
),
1236 2 /*n_args*/, 0 /*n_returns*/,
1237 data
, processor
, cia
))
1239 TRACE(trace_os_emul
, ("release - in - virt=0x%lx size=%ld\n",
1240 (unsigned long)args
.virt
,
1241 (long int)args
.size
));
1242 /* use the memory device to release (real) memory at the requested
1245 device_instance
*memory
= tree_find_ihandle_property(data
->root
, "/chosen/memory");
1246 unsigned_cell mem_in
[2];
1247 mem_in
[0] = args
.size
;
1248 mem_in
[1] = args
.virt
;
1249 if (device_instance_call_method(memory
, "release",
1250 2, mem_in
, 0, NULL
) < 0)
1251 error("chirp: claim failed to release memory virt=0x%lx size=%ld",
1252 (unsigned long)args
.virt
,
1253 (long int)args
.size
);
1255 /* if using virtual addresses, remove the 1-1 map of this address space */
1256 if (!data
->real_mode
) {
1257 error("chirp: release method does not support virtual mode");
1259 /* return the base address */
1260 TRACE(trace_os_emul
, ("release - out\n"));
1261 chirp_write_h2t_args(&args
,
1269 /* Control transfer */
1272 chirp_emul_boot(os_emul_data
*data
,
1276 /* unlike OpenFirmware this one can take an argument */
1279 unsigned_cell bootspec
;
1282 char bootspec
[1024];
1283 /* read in the arguments */
1284 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, 0, data
, processor
, cia
))
1285 cpu_halt(processor
, cia
, was_exited
, -1);
1286 if (args
.bootspec
!= 0)
1287 emul_read_string(bootspec
, args
.bootspec
, sizeof(bootspec
),
1290 strcpy(bootspec
, "(null)");
1291 TRACE(trace_os_emul
, ("boot - in bootspec=`%s'\n", bootspec
));
1292 /* just report this and exit */
1293 printf_filtered("chrp: boot %s called, exiting.\n", bootspec
);
1294 cpu_halt(processor
, cia
, was_exited
, 0);
1299 chirp_emul_enter(os_emul_data
*data
,
1303 error("chirp: enter method not implemented\n");
1308 chirp_emul_exit(os_emul_data
*data
,
1312 /* unlike OpenBoot this one can take an argument */
1318 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, 0, data
, processor
, cia
))
1319 cpu_halt(processor
, cia
, was_exited
, -1);
1320 cpu_halt(processor
, cia
, was_exited
, args
.status
);
1325 chirp_emul_chain(os_emul_data
*data
,
1329 error("chirp: chain method not implemented\n");
1334 /* user interface */
1337 chirp_emul_interpret(os_emul_data
*data
,
1341 error("chirp: interpret method not implemented\n");
1346 chirp_emul_set_callback(os_emul_data
*data
,
1350 error("chirp: set_callback method not implemented\n");
1355 chirp_emul_set_symbol_lookup(os_emul_data
*data
,
1359 error("chirp: set_symbol_lookup method not implemented\n");
1367 chirp_emul_milliseconds(os_emul_data
*data
,
1377 /* read in the arguments */
1378 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
1380 /* make up a number */
1381 time
= event_queue_time(psim_event_queue(cpu_system(processor
))) / 1000000;
1383 /* write the arguments back out */
1384 TRACE(trace_os_emul
, ("milliseconds - out - ms=%ld\n",
1385 (unsigned long)args
.ms
));
1386 chirp_write_h2t_args(&args
,
1396 static chirp_services services
[] = {
1398 /* client interface */
1399 { "test", chirp_emul_test
},
1402 { "peer", chirp_emul_peer
},
1403 { "child", chirp_emul_child
},
1404 { "parent", chirp_emul_parent
},
1405 { "instance-to-package", chirp_emul_instance_to_package
},
1406 { "getproplen", chirp_emul_getproplen
},
1407 { "getprop", chirp_emul_getprop
},
1408 { "nextprop", chirp_emul_nextprop
},
1409 /* { "setprop", chirp_emul_setprop }, */
1410 { "canon", chirp_emul_canon
},
1411 { "finddevice", chirp_emul_finddevice
},
1412 { "instance-to-path", chirp_emul_instance_to_path
},
1413 { "package-to-path", chirp_emul_package_to_path
},
1414 { "call-method", chirp_emul_call_method
},
1417 { "open", chirp_emul_open
},
1418 { "close", chirp_emul_close
},
1419 { "read", chirp_emul_read
},
1420 { "write", chirp_emul_write
},
1421 { "seek", chirp_emul_seek
},
1422 { "write", chirp_emul_write
},
1425 { "claim", chirp_emul_claim
},
1426 { "release", chirp_emul_release
},
1428 /* control transfer */
1429 { "boot", chirp_emul_boot
},
1430 { "enter", chirp_emul_enter
},
1431 { "exit", chirp_emul_exit
},
1432 { "chain", chirp_emul_chain
},
1434 /* user interface */
1435 { "interpret", chirp_emul_interpret
},
1436 { "set_callback", chirp_emul_set_callback
},
1437 { "set_symbol_lookup", chirp_emul_set_symbol_lookup
},
1440 { "milliseconds", chirp_emul_milliseconds
},
1442 { 0, /* sentinal */ },
1448 /* Any starting address greater than this is assumed to be an Chirp
1451 #ifndef CHIRP_START_ADDRESS
1452 #define CHIRP_START_ADDRESS 0x80000000
1454 #ifndef CHIRP_LOAD_BASE
1455 #define CHIRP_LOAD_BASE -1
1459 typedef struct _chirp_note_desc
{
1472 } note_found_status
;
1473 typedef struct _chirp_note
{
1474 chirp_note_desc desc
;
1475 note_found_status found
;
1478 typedef struct _chirp_note_head
{
1485 map_over_chirp_note(bfd
*image
,
1489 chirp_note
*note
= (chirp_note
*)obj
;
1490 if (strcmp(sect
->name
, ".note") == 0) {
1491 chirp_note_head head
;
1493 /* check the head */
1494 if (!bfd_get_section_contents(image
, sect
,
1495 &head
, 0, sizeof(head
)))
1497 head
.namesz
= bfd_get_32(image
, (void*)&head
.namesz
);
1498 head
.descsz
= bfd_get_32(image
, (void*)&head
.descsz
);
1499 head
.type
= bfd_get_32(image
, (void*)&head
.type
);
1500 if (head
.type
!= 0x1275)
1502 /* check the name field */
1503 if (head
.namesz
> sizeof(name
)) {
1504 error("chirp: note name too long (%d > %d)\n", (int)head
.namesz
, sizeof(name
));
1506 if (!bfd_get_section_contents(image
, sect
,
1507 name
, sizeof(head
), head
.namesz
)) {
1508 error("chirp: note name unreadable\n");
1510 if (strcmp(name
, "PowerPC") != 0) {
1511 printf_filtered("chirp: note name (%s) not `PowerPC'\n", name
);
1513 /* check the size */
1514 if (head
.descsz
== sizeof(note
->desc
) - sizeof(signed32
)) {
1515 sim_io_printf_filtered("chirp: note descriptor missing load-base\n");
1517 else if (head
.descsz
!= sizeof(note
->desc
)) {
1518 sim_io_printf_filtered("chirp: note descriptor of wrong size\n");
1519 note
->found
= note_found
;
1522 note
->found
= note_correct
;
1523 /* get the contents */
1524 if (!bfd_get_section_contents(image
, sect
,
1525 ¬e
->desc
, /* page align start */
1526 ((sizeof(head
) + head
.namesz
) + 3) & ~3,
1528 error("chirp: note descriptor unreadable\n");
1530 note
->desc
.real_mode
= bfd_get_32(image
, (void*)¬e
->desc
.real_mode
);
1531 note
->desc
.real_base
= bfd_get_32(image
, (void*)¬e
->desc
.real_base
);
1532 note
->desc
.real_size
= bfd_get_32(image
, (void*)¬e
->desc
.real_size
);
1533 note
->desc
.virt_base
= bfd_get_32(image
, (void*)¬e
->desc
.virt_base
);
1534 note
->desc
.virt_size
= bfd_get_32(image
, (void*)¬e
->desc
.virt_size
);
1535 if (head
.descsz
== sizeof(note
->desc
))
1536 note
->desc
.load_base
= bfd_get_32(image
, (void*)¬e
->desc
.load_base
);
1538 note
->desc
.load_base
= CHIRP_LOAD_BASE
;
1543 static os_emul_data
*
1544 emul_chirp_create(device
*root
,
1548 os_emul_data
*chirp
;
1553 /* Sanity check that this really is the chosen emulation */
1554 if (name
== NULL
&& image
== NULL
)
1557 && strcmp(name
, "ob") != 0
1558 && strcmp(name
, "ieee1274") != 0
1559 && strcmp(name
, "chrp") != 0
1560 && strcmp(name
, "chirp") != 0
1561 && strcmp(name
, "openboot") != 0)
1564 /* look for an elf note section, enter its values into the device tree */
1565 memset(¬e
, 0, sizeof(note
));
1567 bfd_map_over_sections(image
, map_over_chirp_note
, ¬e
);
1568 if (name
== NULL
&& image
!= NULL
&& note
.found
== note_missing
)
1571 /* Assume that it is a chirp emulation */
1573 chirp
= ZALLOC(os_emul_data
);
1575 chirp
->services
= services
;
1578 tree_parse(root
, "/name \"gpl,clayton");
1580 /* default options */
1581 emul_add_tree_options(root
, image
, "chirp", "oea",
1582 0 /*oea-interrupt-prefix*/);
1585 emul_add_tree_hardware(root
);
1587 /* basic information */
1589 = tree_find_integer_property(root
, "/openprom/options/oea-memory-size");
1590 chirp
->little_endian
1591 = tree_find_boolean_property(root
, "/options/little-endian?");
1592 chirp
->floating_point_available
1593 = tree_find_boolean_property(root
, "/openprom/options/floating-point?");
1594 chirp
->interrupt_prefix
=
1595 tree_find_integer_property(root
, "/openprom/options/oea-interrupt-prefix");
1598 /* Perform an interum layout of the openboot firmware in memory */
1601 /* a page for firmware calls */
1602 chirp
->sizeof_code
= 4096;
1603 chirp
->code_offset
= 0x4000; /* possible space for interrupt table */
1606 chirp
->sizeof_stack
= 32 * 1024;
1607 chirp
->stack_offset
= chirp
->code_offset
+ chirp
->sizeof_code
;
1609 /* the hash table */
1610 if (!note
.desc
.real_mode
) {
1611 chirp
->nr_page_table_entry_groups
= (chirp
->memory_size
< 0x800000
1612 ? 1024 /* min allowed */
1613 : (chirp
->memory_size
/ 4096 / 2));
1614 chirp
->sizeof_htab
= chirp
->nr_page_table_entry_groups
* 64;
1616 chirp
->htab_offset
= chirp
->stack_offset
+ chirp
->sizeof_stack
;
1618 /* the actual amount of space needed */
1619 chirp
->real_size
= chirp
->htab_offset
+ chirp
->sizeof_htab
;
1622 /* now go through and see if it fits in what is available */
1625 /* resolve real-mode? */
1626 if (note
.found
== note_correct
)
1627 chirp
->real_mode
= note
.desc
.real_mode
;
1628 else if (tree_find_property(root
, "/options/real-mode?") != NULL
)
1629 chirp
->real_mode
= tree_find_boolean_property(root
, "/options/real-mode?");
1631 chirp
->real_mode
= 0;
1632 if (tree_find_property(root
, "/options/real-mode?") != NULL
) {
1633 if (!chirp
->real_mode
1634 != !tree_find_boolean_property(root
, "/options/real-mode?"))
1635 error("chirp: /options/real-mode? conflicts with note section\n");
1638 tree_parse(root
, "/options/real-mode? %s",
1639 chirp
->real_mode
? "true" : "false");
1641 /* resolve real-base */
1642 if (note
.found
== note_correct
1643 && note
.desc
.real_base
!= (signed32
)-1)
1644 chirp
->real_base
= note
.desc
.real_base
;
1645 else if (tree_find_property(root
, "/options/real-base") != NULL
)
1646 chirp
->real_base
= tree_find_integer_property(root
, "/options/real-base");
1648 chirp
->real_base
= chirp
->memory_size
- chirp
->real_size
;
1649 if (tree_find_property(root
, "/options/real-base") != NULL
) {
1650 if (chirp
->real_base
!= tree_find_integer_property(root
, "/options/real-base"))
1651 error("chirp: /options/real-base conflicts with note section\n");
1654 tree_parse(root
, "/options/real-base 0x%lx",
1655 (unsigned long)chirp
->real_base
);
1657 /* resolve real-size */
1658 if (note
.found
== note_correct
1659 && note
.desc
.real_size
!= (signed32
)-1
1660 && note
.desc
.real_size
!= 0
1661 && chirp
->real_size
> note
.desc
.real_size
)
1662 error("chirp: insufficient physical memory for firmware\n");
1663 if (tree_find_property(root
, "/options/real-size") != NULL
) {
1664 if (chirp
->real_size
> tree_find_integer_property(root
, "/options/real-size"))
1665 error("chirp: /options/real-size conflicts with note section\n");
1668 tree_parse(root
, "/options/real-size 0x%lx",
1669 (unsigned long)chirp
->real_size
);
1671 /* resolve virt-base */
1672 if (chirp
->real_mode
)
1673 chirp
->virt_base
= chirp
->real_base
;
1674 else if (note
.found
== note_correct
&& note
.desc
.virt_base
!= (signed32
)-1)
1675 chirp
->virt_base
= note
.desc
.virt_base
;
1676 else if (tree_find_property(root
, "/options/virt-base") != NULL
)
1677 chirp
->virt_base
= tree_find_integer_property(root
, "/options/virt-base");
1679 chirp
->virt_base
= CHIRP_START_ADDRESS
;
1680 if (tree_find_property(root
, "/options/virt-base") != NULL
) {
1681 if (chirp
->virt_base
!= tree_find_integer_property(root
, "/options/virt-base"))
1682 error("chirp: /options/virt-base conflicts with note section\n");
1685 tree_parse(root
, "/options/virt-base 0x%lx",
1686 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_base
);
1688 /* resolve virt-size */
1689 chirp
->virt_size
= chirp
->real_size
;
1690 if (note
.found
== note_correct
1691 && note
.desc
.virt_size
!= (signed32
)-1
1692 && note
.desc
.virt_size
!= 0
1693 && !chirp
->real_mode
1694 && chirp
->virt_size
> note
.desc
.virt_size
)
1695 error("chirp: insufficent virtual memory for firmware\n");
1696 if (tree_find_property(root
, "/options/virt-size") != NULL
) {
1697 if (chirp
->virt_size
> tree_find_integer_property(root
, "/options/virt-size"))
1698 error("chirp: /options/virt-size conflicts with note section\n");
1701 tree_parse(root
, "/options/virt-size 0x%lx",
1702 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_size
);
1704 /* resolve load-base */
1705 if (note
.found
== note_correct
1706 && note
.desc
.load_base
!= (signed32
)-1)
1707 chirp
->load_base
= note
.desc
.load_base
;
1708 else if (tree_find_property(root
, "/options/load-base") != NULL
)
1709 chirp
->load_base
= tree_find_integer_property(root
, "/options/load-base");
1711 chirp
->load_base
= CHIRP_LOAD_BASE
;
1712 if (tree_find_property(root
, "/options/load-base") != NULL
) {
1713 if (chirp
->load_base
!= tree_find_integer_property(root
, "/options/load-base"))
1714 error("chirp: /options/load-base conflicts with note section\n");
1717 tree_parse(root
, "/options/load-base 0x%lx",
1718 (unsigned long)chirp
->load_base
);
1720 /* now adjust the preliminary firmware addresses to final values */
1721 chirp
->code_ra
= chirp
->code_offset
+ chirp
->real_base
;
1722 chirp
->stack_ra
= chirp
->stack_offset
+ chirp
->real_base
;
1723 chirp
->htab_ra
= chirp
->htab_offset
+ chirp
->real_base
;
1725 /* the virtual addresses. In real mode these are real addresses. */
1727 chirp
->code_va
= chirp
->code_offset
+ chirp
->virt_base
;
1728 chirp
->stack_va
= chirp
->stack_offset
+ chirp
->virt_base
;
1729 chirp
->htab_va
= chirp
->htab_offset
+ chirp
->virt_base
;
1731 chirp
->code_client_va
= chirp
->code_va
;
1732 chirp
->code_client_ra
= chirp
->code_ra
;
1734 chirp
->code_callback_va
= chirp
->code_client_va
+ 16;
1735 chirp
->code_callback_ra
= chirp
->code_client_ra
+ 16;
1737 chirp
->code_loop_va
= chirp
->code_callback_va
+ 16;
1738 chirp
->code_loop_ra
= chirp
->code_callback_ra
+ 16;
1740 /* initialization */
1742 tree_parse(root
, "/openprom/init");
1743 tree_parse(root
, "/openprom/init/register");
1744 tree_parse(root
, "/openprom/init/register/0.pc 0x%lx",
1745 (unsigned long)bfd_get_start_address(image
));
1746 tree_parse(root
, "/openprom/init/register/pc 0x%lx",
1747 (unsigned long)chirp
->code_loop_va
);
1748 tree_parse(root
, "/openprom/init/register/msr 0x%x",
1749 (msr_machine_check_enable
1752 : (msr_instruction_relocate
1753 | msr_data_relocate
))
1754 | (chirp
->little_endian
1755 ? (msr_little_endian_mode
1756 | msr_interrupt_little_endian_mode
)
1758 | (chirp
->floating_point_available
1759 ? msr_floating_point_available
1761 | (chirp
->interrupt_prefix
1762 ? msr_interrupt_prefix
1765 tree_parse(root
, "/openprom/init/register/sdr1 0x%lx",
1766 (unsigned long)(chirp
->htab_ra
1768 | ((chirp
->sizeof_htab
- 1) >> 16)));
1769 /* make certain that the segment registers map straight through */
1770 for (i
= 0; i
< 16; i
++) {
1771 tree_parse(root
, "/openprom/init/register/sr%d 0x%lx",
1772 i
, (unsigned long)i
);
1775 /* establish an initial state for all processors */
1778 /* the client interface address */
1779 tree_parse(root
, "/openprom/init/register/r5 0x%lx",
1780 (unsigned long)chirp
->code_client_va
);
1782 tree_parse(root
, "/openprom/init/register/sp 0x%lx",
1783 (unsigned long)(chirp
->stack_va
+ chirp
->sizeof_stack
- 16));
1784 /* in chrp mode any arguments end up being concatinated */
1785 tree_parse(root
, "/openprom/init/stack/stack-type chirp");
1788 /* client interface - emul-call followed by return instruction */
1791 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1792 (unsigned long)chirp
->code_client_ra
);
1793 tree_parse(node
, "./psim,description \"client-interface instruction");
1794 tree_parse(node
, "./real-address 0x%lx",
1795 (unsigned long)chirp
->code_client_ra
);
1796 tree_parse(node
, "./data 0x%lx",
1797 (unsigned long)emul_call_instruction
);
1799 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1800 (unsigned long)(chirp
->code_client_ra
+ 4));
1801 tree_parse(node
, "./psim,description \"client-interface return instruction");
1802 tree_parse(node
, "./real-address 0x%lx",
1803 (unsigned long)(chirp
->code_client_ra
+ 4));
1804 tree_parse(node
, "./data 0x%lx",
1805 (unsigned long)emul_blr_instruction
);
1808 /* return address for client callbacks - an emul-call instruction
1809 that is again followed by a return instruction */
1812 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1813 (unsigned long)chirp
->code_callback_ra
);
1814 tree_parse(node
, "./psim,description \"client-callback instruction");
1815 tree_parse(node
, "./real-address 0x%lx",
1816 (unsigned long)chirp
->code_callback_ra
);
1817 tree_parse(node
, "./data 0x%lx",
1818 (unsigned long)emul_call_instruction
);
1820 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1821 (unsigned long)(chirp
->code_callback_ra
+ 4));
1822 tree_parse(node
, "./psim,description \"client-callback return instruction");
1823 tree_parse(node
, "./real-address 0x%lx",
1824 (unsigned long)(chirp
->code_callback_ra
+ 4));
1825 tree_parse(node
, "./data 0x%lx",
1826 (unsigned long)emul_blr_instruction
);
1828 /* loop to keep other processors busy */
1830 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1831 (unsigned long)chirp
->code_loop_ra
);
1832 tree_parse(node
, "./psim,description \"processor busy loop");
1833 tree_parse(node
, "./real-address 0x%lx",
1834 (unsigned long)chirp
->code_loop_ra
);
1835 tree_parse(node
, "./data 0x%lx",
1836 (unsigned long)emul_loop_instruction
);
1840 /* create a hash table */
1842 if (!chirp
->real_mode
) {
1843 node
= tree_parse(root
, "/openprom/init/htab@0x%lx",
1844 (unsigned long)chirp
->htab_ra
);
1845 tree_parse(node
, "./claim 0");
1846 tree_parse(node
, "./real-address 0x%lx",
1847 (unsigned long)chirp
->htab_ra
);
1848 tree_parse(node
, "./nr-bytes 0x%lx",
1849 (unsigned long)chirp
->sizeof_htab
);
1852 /* map in the stack */
1854 if (!chirp
->real_mode
) {
1855 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1856 (unsigned long)chirp
->stack_ra
);
1857 tree_parse(node
, "./psim,description \"map in the stack");
1858 tree_parse(node
, "./claim 1");
1859 tree_parse(node
, "./virtual-address 0x%lx",
1860 (unsigned long)chirp
->stack_va
);
1861 tree_parse(node
, "./real-address 0x%lx",
1862 (unsigned long)chirp
->stack_ra
);
1863 tree_parse(node
, "./nr-bytes 0x%lx",
1864 (unsigned long)chirp
->sizeof_stack
);
1865 tree_parse(node
, "./wimg %d", 0x7);
1866 tree_parse(node
, "./pp %d", 0x2);
1869 /* map in the chrp openboot callback code */
1871 if (!chirp
->real_mode
) {
1872 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1873 (unsigned long)chirp
->code_ra
);
1874 tree_parse(node
, "./psim,description \"map in chrp openboot callback code");
1875 tree_parse(node
, "./claim 1");
1876 tree_parse(node
, "./virtual-address 0x%lx",
1877 (unsigned long)chirp
->code_va
);
1878 tree_parse(node
, "./real-address 0x%lx",
1879 (unsigned long)chirp
->code_ra
);
1880 tree_parse(node
, "./nr-bytes 0x%lx",
1881 (unsigned long)chirp
->sizeof_code
);
1882 tree_parse(node
, "./wimg %d", 0x7);
1883 tree_parse(node
, "./pp %d", 0x2);
1886 /* map in the program to run */
1888 if (chirp
->real_mode
) {
1889 node
= tree_parse(node
, "/openprom/init/load-binary");
1890 tree_parse(node
, "./psim,description \"load the binary");
1891 tree_parse(node
, "./file-name %s", bfd_get_filename(image
));
1892 tree_parse(node
, "./claim 1");
1895 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1896 (unsigned long)chirp
->load_base
);
1897 tree_parse(node
, "./psim,description \"load & map the binary");
1898 tree_parse(node
, "./claim 1");
1899 tree_parse(node
, "./file-name \"%s", bfd_get_filename(image
));
1900 tree_parse(node
, "./wimg %d", 0x7);
1901 tree_parse(node
, "./pp %d", 0x2);
1908 emul_chirp_init(os_emul_data
*emul_data
,
1911 emul_data
->state
= serving
;
1915 emul_chirp_instruction_call(cpu
*processor
,
1918 os_emul_data
*emul_data
)
1920 unsigned_word service_name_addr
;
1921 unsigned_word result
;
1922 char service_buf
[32];
1924 chirp_services
*service
;
1926 switch (emul_data
->state
) {
1929 /* we are waiting on an OpenBoot request from the client program
1930 via the client interface */
1931 if (cia
!= emul_data
->code_client_va
)
1933 emul_data
->return_address
= LR
;
1934 emul_data
->arguments
= cpu_registers(processor
)->gpr
[3];
1935 /* try to determine what to do */
1936 service_name_addr
= emul_read_word(cpu_registers(processor
)->gpr
[3],
1938 service_name
= emul_read_string(service_buf
, service_name_addr
,
1939 sizeof(service_buf
), processor
, cia
);
1940 emul_data
->n_args
= emul_read_word(emul_data
->arguments
+ sizeof(unsigned_cell
),
1942 emul_data
->n_returns
= emul_read_word(emul_data
->arguments
+ 2 * sizeof(unsigned_cell
),
1944 /* verify what was passed */
1945 if (service_name_addr
== 0
1946 || service_name
== NULL
) {
1947 error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n",
1948 (unsigned long)emul_data
->return_address
,
1949 (unsigned long)emul_data
->arguments
);
1951 if (emul_data
->n_args
> 6) { /* See iee1275 requirements on nr returns */
1952 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n",
1953 (unsigned long)emul_data
->return_address
,
1954 (unsigned long)emul_data
->arguments
,
1955 emul_data
->n_returns
);
1957 if (emul_data
->n_returns
> 6) {
1958 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, with too many returns (%d)\n",
1959 (unsigned long)emul_data
->return_address
,
1960 (unsigned long)emul_data
->arguments
,
1964 TRACE(trace_os_emul
, ("%s called from 0x%lx with args 0x%lx\n",
1966 (unsigned long)emul_data
->return_address
,
1967 (unsigned long)emul_data
->arguments
));
1969 while (service
->name
!= NULL
&& strcmp(service
->name
, service_name
) != 0)
1972 if (service
->name
== NULL
) {
1973 error("OpenBoot service `%s' not found\n", service_name
);
1974 TRACE(trace_os_emul
, ("%s not found\n", service_name
));
1975 cpu_registers(processor
)->gpr
[3] = -1;
1978 emul_data
->service
= service
;
1980 result
= service
->handler(emul_data
, processor
, cia
);
1982 TRACE(trace_os_emul
, ("%s aborted with %ld\n", service_name
, (long)result
));
1983 cpu_registers(processor
)->gpr
[3] = result
;
1988 error("emul_chirp_instruction_call() unknown internal state\n");
1994 /* return to caller - instruction following this is a function return */
1998 const os_emul emul_chirp
= {
2002 NULL
, /*system_call*/
2003 emul_chirp_instruction_call
,