1 /* This file is part of the program psim.
3 Copyright (C) 1994-1997, 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"
43 #ifndef STATIC_INLINE_EMUL_CHIRP
44 #define STATIC_INLINE_EMUL_CHIRP STATIC_INLINE
51 OpenFirmware - IEEE Standard for Boot (Initialization
52 Configuration) Firmware.
61 This code assumes that the memory node has #address-cells and
62 #size-cells set to one. For future implementations, this may not
70 /* Descriptor of the open boot services being emulated */
72 typedef int (chirp_handler
)
77 typedef struct _chirp_services
{
79 chirp_handler
*handler
;
83 /* The OpenBoot emulation is, at any time either waiting for a client
84 request or waiting on a client callback */
91 struct _os_emul_data
{
92 chirp_emul_state state
;
93 unsigned_word return_address
;
94 unsigned_word arguments
;
96 unsigned_word n_returns
;
97 chirp_services
*service
;
99 chirp_services
*services
;
101 unsigned_word memory_size
;
102 unsigned_word real_base
;
103 unsigned_word real_size
;
104 unsigned_word virt_base
;
105 unsigned_word virt_size
;
108 int floating_point_available
;
109 int interrupt_prefix
;
110 unsigned_word load_base
;
112 unsigned_word nr_page_table_entry_groups
;
113 unsigned_word htab_offset
;
114 unsigned_word htab_ra
;
115 unsigned_word htab_va
;
116 unsigned_word sizeof_htab
;
117 /* virtual address of htab */
118 unsigned_word stack_offset
;
119 unsigned_word stack_ra
;
120 unsigned_word stack_va
;
121 unsigned_word sizeof_stack
;
122 /* addresses of emulation instructions virtual/real */
123 unsigned_word code_offset
;
124 unsigned_word code_va
;
125 unsigned_word code_ra
;
126 unsigned_word sizeof_code
;
127 unsigned_word code_client_va
;
128 unsigned_word code_client_ra
;
129 unsigned_word code_callback_va
;
130 unsigned_word code_callback_ra
;
131 unsigned_word code_loop_va
;
132 unsigned_word code_loop_ra
;
136 /* returns the name of the corresponding Ihandle */
138 ihandle_name(device_instance
*ihandle
)
143 return device_name(device_instance_device(ihandle
));
148 /* Read/write the argument list making certain that all values are
149 converted to/from host byte order.
151 In the below only n_args+n_returns is read/written */
154 chirp_read_t2h_args(void *args
,
162 unsigned_cell
*words
;
164 /* check against the number of arguments specified by the client
166 if ((n_args
>= 0 && data
->n_args
!= n_args
)
167 || (n_returns
>= 0 && data
->n_returns
!= n_returns
)) {
168 TRACE(trace_os_emul
, ("%s - invalid nr of args - n_args=%ld, n_returns=%ld\n",
171 (long)data
->n_returns
));
174 /* check that there is enough space */
175 if (sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
) > sizeof_args
)
177 /* bring in the data */
178 memset(args
, 0, sizeof_args
);
179 emul_read_buffer(args
, data
->arguments
+ 3 * sizeof(unsigned_cell
),
180 sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
),
182 /* convert all words to host format */
184 for (i
= 0; i
< (sizeof_args
/ sizeof(unsigned_cell
)); i
++)
185 words
[i
] = T2H_cell(words
[i
]);
190 chirp_write_h2t_args(void *args
,
197 unsigned_cell
*words
;
198 /* convert to target everything */
200 for (i
= 0; i
< (sizeof_args
/ sizeof(unsigned_cell
)); i
++)
201 words
[i
] = H2T_cell(words
[i
]);
202 /* bring in the data */
203 emul_write_buffer(args
, data
->arguments
+ 3 * sizeof(unsigned_cell
),
204 sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
),
209 /* OpenBoot emulation functions */
211 /* client interface */
214 chirp_emul_test(os_emul_data
*data
,
220 unsigned_cell name
; /*string*/
222 unsigned_cell missing
;
225 chirp_services
*service
= NULL
;
226 /* read in the arguments */
227 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
229 emul_read_string(name
, args
.name
, sizeof(name
),
231 TRACE(trace_os_emul
, ("test - in - name=`%s'\n", name
));
232 /* see if we know about the service */
233 service
= data
->services
;
234 while (service
->name
!= NULL
&& strcmp(service
->name
, name
) != 0) {
237 if (service
->name
== NULL
)
241 /* write the arguments back out */
242 TRACE(trace_os_emul
, ("test - out - missing=%ld\n",
243 (long)args
.missing
));
244 chirp_write_h2t_args(&args
,
255 chirp_emul_peer(os_emul_data
*data
,
261 unsigned_cell phandle
;
263 unsigned_cell sibling_phandle
;
266 device
*sibling_phandle
= NULL
;
267 /* read in the arguments */
268 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
270 phandle
= external_to_device(data
->root
, args
.phandle
);
271 TRACE(trace_os_emul
, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
272 (unsigned long)args
.phandle
,
273 (unsigned long)phandle
,
274 (phandle
== NULL
? "" : device_name(phandle
))));
276 if (args
.phandle
== 0) {
277 sibling_phandle
= data
->root
;
278 args
.sibling_phandle
= device_to_external(sibling_phandle
);
280 else if (phandle
== NULL
) {
281 sibling_phandle
= NULL
;
282 args
.sibling_phandle
= -1;
285 sibling_phandle
= device_sibling(phandle
);
286 if (sibling_phandle
== NULL
)
287 args
.sibling_phandle
= 0;
289 args
.sibling_phandle
= device_to_external(sibling_phandle
);
291 /* write the arguments back out */
292 TRACE(trace_os_emul
, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
293 (unsigned long)args
.sibling_phandle
,
294 (unsigned long)sibling_phandle
,
295 (sibling_phandle
== NULL
? "" : device_name(sibling_phandle
))));
296 chirp_write_h2t_args(&args
,
304 chirp_emul_child(os_emul_data
*data
,
310 unsigned_cell phandle
;
312 unsigned_cell child_phandle
;
315 device
*child_phandle
;
316 /* read the arguments in */
317 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
319 phandle
= external_to_device(data
->root
, args
.phandle
);
320 TRACE(trace_os_emul
, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
321 (unsigned long)args
.phandle
,
322 (unsigned long)phandle
,
323 (phandle
== NULL
? "" : device_name(phandle
))));
325 if (args
.phandle
== 0
326 || phandle
== NULL
) {
327 child_phandle
= NULL
;
328 args
.child_phandle
= -1;
331 child_phandle
= device_child(phandle
);
332 if (child_phandle
== NULL
)
333 args
.child_phandle
= 0;
335 args
.child_phandle
= device_to_external(child_phandle
);
337 /* write the result out */
338 TRACE(trace_os_emul
, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
339 (unsigned long)args
.child_phandle
,
340 (unsigned long)child_phandle
,
341 (child_phandle
== NULL
? "" : device_name(child_phandle
))));
342 chirp_write_h2t_args(&args
,
350 chirp_emul_parent(os_emul_data
*data
,
356 unsigned_cell phandle
;
358 unsigned_cell parent_phandle
;
361 device
*parent_phandle
;
362 /* read the args in */
363 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
365 phandle
= external_to_device(data
->root
, args
.phandle
);
366 TRACE(trace_os_emul
, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
367 (unsigned long)args
.phandle
,
368 (unsigned long)phandle
,
369 (phandle
== NULL
? "" : device_name(phandle
))));
371 if (args
.phandle
== 0
372 || phandle
== NULL
) {
373 parent_phandle
= NULL
;
374 args
.parent_phandle
= -1;
377 parent_phandle
= device_parent(phandle
);
378 if (parent_phandle
== NULL
)
379 args
.parent_phandle
= 0;
381 args
.parent_phandle
= device_to_external(parent_phandle
);
383 /* return the result */
384 TRACE(trace_os_emul
, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
385 (unsigned long)args
.parent_phandle
,
386 (unsigned long)parent_phandle
,
387 (parent_phandle
== NULL
? "" : device_name(parent_phandle
))));
388 chirp_write_h2t_args(&args
,
396 chirp_emul_instance_to_package(os_emul_data
*data
,
400 struct instance_to_package_args
{
402 unsigned_cell ihandle
;
404 unsigned_cell phandle
;
406 device_instance
*ihandle
;
407 device
*phandle
= NULL
;
408 /* read the args in */
409 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
411 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
412 TRACE(trace_os_emul
, ("instance-to-package - in - ihandle=0x%lx(0x%lx`%s')\n",
413 (unsigned long)args
.ihandle
,
414 (unsigned long)ihandle
,
415 ihandle_name(ihandle
)));
416 /* find the corresponding phandle */
417 if (ihandle
== NULL
) {
422 phandle
= device_instance_device(ihandle
);
423 args
.phandle
= device_to_external(phandle
);
425 /* return the result */
426 TRACE(trace_os_emul
, ("instance-to-package - out - phandle=0x%lx(0x%lx`%s')\n",
427 (unsigned long)args
.phandle
,
428 (unsigned long)phandle
,
429 (phandle
== NULL
? "" : device_name(phandle
))));
430 chirp_write_h2t_args(&args
,
438 chirp_emul_getproplen(os_emul_data
*data
,
442 struct getproplen_args
{
444 unsigned_cell phandle
;
447 unsigned_cell proplen
;
451 /* read the args in */
452 if (chirp_read_t2h_args(&args
, sizeof(args
), 2, 1, data
, processor
, cia
))
454 phandle
= external_to_device(data
->root
, args
.phandle
);
455 emul_read_string(name
,
459 TRACE(trace_os_emul
, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
460 (unsigned long)args
.phandle
,
461 (unsigned long)phandle
,
462 (phandle
== NULL
? "" : device_name(phandle
)),
464 /* find our prop and get its length */
465 if (args
.phandle
== 0
466 || phandle
== NULL
) {
470 const device_property
*prop
= device_find_property(phandle
, name
);
471 if (prop
== (device_property
*)0) {
475 args
.proplen
= prop
->sizeof_array
;
478 /* return the result */
479 TRACE(trace_os_emul
, ("getproplen - out - proplen=%ld\n",
480 (unsigned long)args
.proplen
));
481 chirp_write_h2t_args(&args
,
489 chirp_emul_getprop(os_emul_data
*data
,
493 struct getprop_args
{
495 unsigned_cell phandle
;
498 unsigned_cell buflen
;
504 /* read in the args, the return is optional */
505 if (chirp_read_t2h_args(&args
, sizeof(args
), 4, -1, data
, processor
, cia
))
507 phandle
= external_to_device(data
->root
, args
.phandle
);
508 emul_read_string(name
,
512 TRACE(trace_os_emul
, ("getprop - in - phandle=0x%lx(0x%lx`%s') name=`%s' buf=0x%lx buflen=%ld\n",
513 (unsigned long)args
.phandle
,
514 (unsigned long)phandle
,
515 (phandle
== NULL
? "" : device_name(phandle
)),
517 (unsigned long)args
.buf
,
518 (unsigned long)args
.buflen
));
519 /* get the property */
520 if (args
.phandle
== 0
521 || phandle
== NULL
) {
525 const device_property
*prop
= device_find_property(phandle
, name
);
530 int size
= args
.buflen
;
531 if (size
> prop
->sizeof_array
)
532 size
= prop
->sizeof_array
;
533 emul_write_buffer(prop
->array
, args
.buf
,
537 switch (prop
->type
) {
538 case string_property
:
539 TRACE(trace_os_emul
, ("getprop - string `%s'\n",
540 device_find_string_property(phandle
, name
)));
542 case ihandle_property
:
543 TRACE(trace_os_emul
, ("getprop - ihandle=0x%lx(0x%lx`%s')\n",
544 BE2H_cell(*(unsigned_cell
*)prop
->array
),
545 (unsigned long)device_find_ihandle_property(phandle
, name
),
546 ihandle_name(device_find_ihandle_property(phandle
, name
))));
553 /* write back the result */
554 if (data
->n_returns
== 0)
555 TRACE(trace_os_emul
, ("getprop - out - size=%ld (not returned)\n",
556 (unsigned long)args
.size
));
558 TRACE(trace_os_emul
, ("getprop - out - size=%ld\n",
559 (unsigned long)args
.size
));
560 chirp_write_h2t_args(&args
,
569 chirp_emul_nextprop(os_emul_data
*data
,
573 struct nextprop_args
{
575 unsigned_cell phandle
;
576 unsigned_cell previous
;
583 /* read in the args */
584 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
586 phandle
= external_to_device(data
->root
, args
.phandle
);
587 emul_read_string(previous
,
591 TRACE(trace_os_emul
, ("nextprop - in - phandle=0x%lx(0x%lx`%s') previous=`%s' buf=0x%lx\n",
592 (unsigned long)args
.phandle
,
593 (unsigned long)phandle
,
594 (phandle
== NULL
? "" : device_name(phandle
)),
596 (unsigned long)args
.buf
));
597 /* find the next property */
598 if (args
.phandle
== 0
599 || phandle
== NULL
) {
603 const device_property
*prev_prop
= device_find_property(phandle
, previous
);
604 if (prev_prop
== NULL
) {
605 args
.flag
= -1; /* name invalid */
608 const device_property
*next_prop
;
609 next_prop
= device_next_property(prev_prop
);
610 if (next_prop
== NULL
) {
611 args
.flag
= 0; /* last property */
614 emul_write_buffer(next_prop
->name
, args
.buf
, strlen(next_prop
->name
),
616 TRACE(trace_os_emul
, ("nextprop - name=`%s'\n", next_prop
->name
));
617 args
.flag
= 1; /* worked ok */
621 /* write back the result */
622 TRACE(trace_os_emul
, ("nextprop - out - flag=%ld\n",
623 (unsigned long)args
.flag
));
624 chirp_write_h2t_args(&args
,
633 chirp_emul_setprop(os_emul_data
*data
,
637 error("chirp: setprop method not implemented\n");
643 chirp_emul_canon(os_emul_data
*data
,
649 unsigned_cell device_specifier
;
651 unsigned_cell buflen
;
653 unsigned_cell length
;
655 char device_specifier
[1024];
659 /* read in the args */
660 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
662 emul_read_string(device_specifier
,
663 args
.device_specifier
,
664 sizeof(device_specifier
),
666 TRACE(trace_os_emul
, ("canon - in - device_specifier=`%s' buf=0x%lx buflen=%lx\n",
668 (unsigned long)args
.buf
,
669 (unsigned long)args
.buflen
));
671 phandle
= tree_find_device(data
->root
, device_specifier
);
672 if (phandle
== NULL
) {
678 path
= device_path(phandle
);
679 length
= strlen(path
);
680 if (length
>= args
.buflen
)
681 length
= args
.buflen
- 1;
682 emul_write_buffer(path
, args
.buf
, length
,
684 args
.length
= length
;
686 /* write back the result */
687 TRACE(trace_os_emul
, ("canon - out - length=%ld buf=`%s'\n",
688 (unsigned long)args
.length
,
690 chirp_write_h2t_args(&args
,
698 chirp_emul_finddevice(os_emul_data
*data
,
702 struct finddevice_args
{
704 unsigned_cell device_specifier
;
706 unsigned_cell phandle
;
708 char device_specifier
[1024];
711 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
713 emul_read_string(device_specifier
,
714 args
.device_specifier
,
715 sizeof(device_specifier
),
717 TRACE(trace_os_emul
, ("finddevice - in - device_specifier=`%s'\n",
719 /* find the device */
720 phandle
= tree_find_device(data
->root
, device_specifier
);
724 args
.phandle
= device_to_external(phandle
);
725 /* return its phandle */
726 TRACE(trace_os_emul
, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
727 (unsigned long)args
.phandle
,
728 (unsigned long)phandle
,
729 (phandle
== NULL
? "" : device_name(phandle
))));
730 chirp_write_h2t_args(&args
,
738 chirp_emul_instance_to_path(os_emul_data
*data
,
742 struct instance_to_path_args
{
744 unsigned_cell ihandle
;
746 unsigned_cell buflen
;
748 unsigned_cell length
;
750 device_instance
*ihandle
;
754 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
756 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
757 TRACE(trace_os_emul
, ("instance-to-path - in - ihandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
758 (unsigned long)args
.ihandle
,
759 (unsigned long)ihandle
,
760 ihandle_name(ihandle
),
761 (unsigned long)args
.buf
,
762 (unsigned long)args
.buflen
));
763 /* get the devices name */
764 if (ihandle
== NULL
) {
769 path
= device_instance_path(ihandle
);
770 length
= strlen(path
);
771 if (length
>= args
.buflen
)
772 length
= args
.buflen
- 1;
773 emul_write_buffer(path
, args
.buf
, length
,
775 args
.length
= length
;
777 /* return its phandle */
778 TRACE(trace_os_emul
, ("instance-to-path - out - length=%ld buf=`%s')\n",
779 (unsigned long)args
.length
,
781 chirp_write_h2t_args(&args
,
789 chirp_emul_package_to_path(os_emul_data
*data
,
793 struct package_to_path_args
{
795 unsigned_cell phandle
;
797 unsigned_cell buflen
;
799 unsigned_cell length
;
804 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
806 phandle
= external_to_device(data
->root
, args
.phandle
);
807 TRACE(trace_os_emul
, ("package-to-path - in - phandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
808 (unsigned long)args
.phandle
,
809 (unsigned long)phandle
,
810 (phandle
== NULL
? "" : device_name(phandle
)),
811 (unsigned long)args
.buf
,
812 (unsigned long)args
.buflen
));
813 /* get the devices name */
814 if (phandle
== NULL
) {
820 path
= device_path(phandle
);
821 length
= strlen(path
);
822 if (length
>= args
.buflen
)
823 length
= args
.buflen
- 1;
824 emul_write_buffer(path
, args
.buf
, length
,
826 args
.length
= length
;
828 /* return its phandle */
829 TRACE(trace_os_emul
, ("package-to-path - out - length=%ld buf=`%s')\n",
830 (unsigned long)args
.length
,
832 chirp_write_h2t_args(&args
,
840 chirp_emul_call_method(os_emul_data
*data
,
844 struct call_method_args
{
846 unsigned_cell method
;
847 unsigned_cell ihandle
;
849 unsigned_cell stack
[13]; /*6in + 6out + catch */
852 device_instance
*ihandle
;
853 /* some useful info about our mini stack */
856 int stack_catch_result
;
859 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, -1, data
, processor
, cia
))
861 emul_read_string(method
,
865 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
866 n_stack_args
= data
->n_args
- 2;
867 n_stack_returns
= data
->n_returns
- 1;
868 stack_catch_result
= n_stack_args
;
869 stack_returns
= stack_catch_result
+ 1;
870 TRACE(trace_os_emul
, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(0x%lx`%s')\n",
871 (unsigned long)data
->n_args
,
872 (unsigned long)data
->n_returns
,
874 (unsigned long)args
.ihandle
,
875 (unsigned long)ihandle
,
876 ihandle_name(ihandle
)));
877 /* see if we can emulate this method */
878 if (ihandle
== NULL
) {
879 /* OpenFirmware doesn't define this error */
880 error("chirp: invalid ihandle passed to call-method method");
883 args
.stack
[stack_catch_result
] =
884 device_instance_call_method(ihandle
,
889 &args
.stack
[stack_returns
]);
892 TRACE(trace_os_emul
, ("call-method - out - catch-result=%ld\n",
893 (unsigned long)args
.stack
[stack_catch_result
]));
894 chirp_write_h2t_args(&args
,
905 chirp_emul_open(os_emul_data
*data
,
911 unsigned_cell device_specifier
;
913 unsigned_cell ihandle
;
915 char device_specifier
[1024];
916 device_instance
*ihandle
;
918 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
920 emul_read_string(device_specifier
,
921 args
.device_specifier
,
922 sizeof(device_specifier
),
924 TRACE(trace_os_emul
, ("open - in - device_specifier=`%s'\n",
926 /* open the device */
927 ihandle
= tree_instance(data
->root
, device_specifier
);
931 args
.ihandle
= device_instance_to_external(ihandle
);
932 /* return the ihandle result */
933 TRACE(trace_os_emul
, ("open - out - ihandle=0x%lx(0x%lx`%s')\n",
934 (unsigned long)args
.ihandle
,
935 (unsigned long)ihandle
,
936 ihandle_name(ihandle
)));
937 chirp_write_h2t_args(&args
,
945 chirp_emul_close(os_emul_data
*data
,
951 unsigned_cell ihandle
;
954 device_instance
*ihandle
;
956 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 0, data
, processor
, cia
))
958 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
959 TRACE(trace_os_emul
, ("close - in - ihandle=0x%lx(0x%lx`%s')\n",
960 (unsigned long)args
.ihandle
,
961 (unsigned long)ihandle
,
962 ihandle_name(ihandle
)));
963 /* close the device */
964 if (ihandle
== NULL
) {
965 /* OpenFirmware doesn't define this error */
966 error("chirp: invalid ihandle passed to close method");
969 device_instance_delete(ihandle
);
971 /* return the ihandle result */
972 TRACE(trace_os_emul
, ("close - out\n"));
973 chirp_write_h2t_args(&args
,
981 chirp_emul_read(os_emul_data
*data
,
987 unsigned_cell ihandle
;
991 unsigned_cell actual
;
994 device_instance
*ihandle
;
996 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
998 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
999 TRACE(trace_os_emul
, ("read - in - ihandle=0x%lx(0x%lx`%s') addr=0x%lx len=%ld\n",
1000 (unsigned long)args
.ihandle
,
1001 (unsigned long)ihandle
,
1002 ihandle_name(ihandle
),
1003 (unsigned long)args
.addr
,
1004 (unsigned long)args
.len
));
1005 if (ihandle
== NULL
) {
1006 /* OpenFirmware doesn't define this error */
1007 error("chirp: invalid ihandle passed to read method");
1012 while (actual
< args
.len
) {
1013 int remaining
= args
.len
- actual
;
1014 int to_read
= (remaining
<= sizeof(buf
) ? remaining
: sizeof(buf
));
1015 int nr_read
= device_instance_read(ihandle
, buf
, to_read
);
1017 actual
= nr_read
; /* the error */
1020 else if (nr_read
== 0) {
1023 emul_write_buffer(buf
,
1030 args
.actual
= actual
;
1031 if (actual
< sizeof(buf
))
1034 buf
[sizeof(buf
) - 1] = '\0';
1041 case sim_io_not_ready
:
1042 ASSERT(sim_io_not_ready
== -2);
1043 args
.actual
= sim_io_not_ready
;
1046 error("Bad error value %ld", (long)actual
);
1051 /* return the result */
1052 TRACE(trace_os_emul
, ("read - out - actual=%ld `%s'\n",
1054 ((args
.actual
> 0 && args
.actual
< sizeof(buf
)) ? buf
: "")
1056 chirp_write_h2t_args(&args
,
1064 chirp_emul_write(os_emul_data
*data
,
1070 unsigned_cell ihandle
;
1074 unsigned_cell actual
;
1077 device_instance
*ihandle
;
1080 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1083 if (actual
>= sizeof(buf
))
1084 actual
= sizeof(buf
) - 1;
1085 emul_read_buffer(buf
,
1090 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1091 TRACE(trace_os_emul
, ("write - in - ihandle=0x%lx(0x%lx`%s') `%s' (%ld)\n",
1092 (unsigned long)args
.ihandle
,
1093 (unsigned long)ihandle
,
1094 ihandle_name(ihandle
),
1095 buf
, (long)actual
));
1096 if (ihandle
== NULL
) {
1097 /* OpenFirmware doesn't define this error */
1098 error("chirp: invalid ihandle passed to write method");
1102 actual
= device_instance_write(ihandle
, buf
, actual
);
1106 args
.actual
= actual
;
1108 /* return the result */
1109 TRACE(trace_os_emul
, ("write - out - actual=%ld\n",
1110 (long)args
.actual
));
1111 chirp_write_h2t_args(&args
,
1119 chirp_emul_seek(os_emul_data
*data
,
1125 unsigned_cell ihandle
;
1126 unsigned_cell pos_hi
;
1127 unsigned_cell pos_lo
;
1129 unsigned_cell status
;
1132 device_instance
*ihandle
;
1134 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1136 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1137 TRACE(trace_os_emul
, ("seek - in - ihandle=0x%lx(0x%lx`%s') pos.hi=0x%lx pos.lo=0x%lx\n",
1138 (unsigned long)args
.ihandle
,
1139 (unsigned long)ihandle
,
1140 ihandle_name(ihandle
),
1141 args
.pos_hi
, args
.pos_lo
));
1142 if (ihandle
== NULL
) {
1143 /* OpenFirmware doesn't define this error */
1144 error("chirp: invalid ihandle passed to seek method");
1148 status
= device_instance_seek(ihandle
, args
.pos_hi
, args
.pos_lo
);
1149 args
.status
= status
;
1151 /* return the result */
1152 TRACE(trace_os_emul
, ("seek - out - status=%ld\n",
1153 (long)args
.status
));
1154 chirp_write_h2t_args(&args
,
1165 chirp_emul_claim(os_emul_data
*data
,
1169 /* NOTE: the client interface claim routine is *very* different to
1170 the "claim" method described in IEEE-1275 appendix A. The latter
1171 uses real addresses while this uses virtual (effective)
1177 unsigned_cell align
;
1179 unsigned_cell baseaddr
;
1182 if (chirp_read_t2h_args(&args
, sizeof(args
),
1183 3 /*n_args*/, 1 /*n_returns*/,
1184 data
, processor
, cia
))
1186 TRACE(trace_os_emul
, ("claim - in - virt=0x%lx size=%ld align=%d\n",
1187 (unsigned long)args
.virt
,
1188 (long int)args
.size
,
1190 /* use the memory device to allocate (real) memory at the requested
1193 device_instance
*memory
= tree_find_ihandle_property(data
->root
, "/chosen/memory");
1194 unsigned_cell mem_in
[3];
1195 unsigned_cell mem_out
[1];
1196 mem_in
[0] = args
.align
; /*top-of-stack*/
1197 mem_in
[1] = args
.size
;
1198 mem_in
[2] = args
.virt
;
1199 if (device_instance_call_method(memory
, "claim",
1200 3, mem_in
, 1, mem_out
) < 0)
1201 error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d",
1202 (unsigned long)args
.virt
,
1203 (long int)args
.size
,
1205 args
.baseaddr
= mem_out
[0];
1207 /* if using virtual addresses, create a 1-1 map of this address space */
1208 if (!data
->real_mode
) {
1209 error("chirp: claim method does not support virtual mode");
1211 /* return the base address */
1212 TRACE(trace_os_emul
, ("claim - out - baseaddr=0x%lx\n",
1213 (unsigned long)args
.baseaddr
));
1214 chirp_write_h2t_args(&args
,
1222 chirp_emul_release(os_emul_data
*data
,
1226 /* NOTE: the client interface release routine is *very* different to
1227 the "claim" method described in IEEE-1275 appendix A. The latter
1228 uses real addresses while this uses virtual (effective)
1237 if (chirp_read_t2h_args(&args
, sizeof(args
),
1238 2 /*n_args*/, 0 /*n_returns*/,
1239 data
, processor
, cia
))
1241 TRACE(trace_os_emul
, ("release - in - virt=0x%lx size=%ld\n",
1242 (unsigned long)args
.virt
,
1243 (long int)args
.size
));
1244 /* use the memory device to release (real) memory at the requested
1247 device_instance
*memory
= tree_find_ihandle_property(data
->root
, "/chosen/memory");
1248 unsigned_cell mem_in
[2];
1249 mem_in
[0] = args
.size
;
1250 mem_in
[1] = args
.virt
;
1251 if (device_instance_call_method(memory
, "release",
1252 2, mem_in
, 0, NULL
) < 0)
1253 error("chirp: claim failed to release memory virt=0x%lx size=%ld",
1254 (unsigned long)args
.virt
,
1255 (long int)args
.size
);
1257 /* if using virtual addresses, remove the 1-1 map of this address space */
1258 if (!data
->real_mode
) {
1259 error("chirp: release method does not support virtual mode");
1261 /* return the base address */
1262 TRACE(trace_os_emul
, ("release - out\n"));
1263 chirp_write_h2t_args(&args
,
1271 /* Control transfer */
1274 chirp_emul_boot(os_emul_data
*data
,
1278 /* unlike OpenFirmware this one can take an argument */
1281 unsigned_cell bootspec
;
1284 char bootspec
[1024];
1285 /* read in the arguments */
1286 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, 0, data
, processor
, cia
))
1287 cpu_halt(processor
, cia
, was_exited
, -1);
1288 if (args
.bootspec
!= 0)
1289 emul_read_string(bootspec
, args
.bootspec
, sizeof(bootspec
),
1292 strcpy(bootspec
, "(null)");
1293 TRACE(trace_os_emul
, ("boot - in bootspec=`%s'\n", bootspec
));
1294 /* just report this and exit */
1295 printf_filtered("chrp: boot %s called, exiting.\n", bootspec
);
1296 cpu_halt(processor
, cia
, was_exited
, 0);
1301 chirp_emul_enter(os_emul_data
*data
,
1305 error("chirp: enter method not implemented\n");
1310 chirp_emul_exit(os_emul_data
*data
,
1314 /* unlike OpenBoot this one can take an argument */
1320 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, 0, data
, processor
, cia
))
1321 cpu_halt(processor
, cia
, was_exited
, -1);
1322 cpu_halt(processor
, cia
, was_exited
, args
.status
);
1327 chirp_emul_chain(os_emul_data
*data
,
1331 error("chirp: chain method not implemented\n");
1336 /* user interface */
1339 chirp_emul_interpret(os_emul_data
*data
,
1343 error("chirp: interpret method not implemented\n");
1348 chirp_emul_set_callback(os_emul_data
*data
,
1352 error("chirp: set_callback method not implemented\n");
1357 chirp_emul_set_symbol_lookup(os_emul_data
*data
,
1361 error("chirp: set_symbol_lookup method not implemented\n");
1369 chirp_emul_milliseconds(os_emul_data
*data
,
1379 /* read in the arguments */
1380 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
1382 /* make up a number */
1383 time
= event_queue_time(psim_event_queue(cpu_system(processor
))) / 1000000;
1385 /* write the arguments back out */
1386 TRACE(trace_os_emul
, ("milliseconds - out - ms=%ld\n",
1387 (unsigned long)args
.ms
));
1388 chirp_write_h2t_args(&args
,
1398 static chirp_services services
[] = {
1400 /* client interface */
1401 { "test", chirp_emul_test
},
1404 { "peer", chirp_emul_peer
},
1405 { "child", chirp_emul_child
},
1406 { "parent", chirp_emul_parent
},
1407 { "instance-to-package", chirp_emul_instance_to_package
},
1408 { "getproplen", chirp_emul_getproplen
},
1409 { "getprop", chirp_emul_getprop
},
1410 { "nextprop", chirp_emul_nextprop
},
1411 /* { "setprop", chirp_emul_setprop }, */
1412 { "canon", chirp_emul_canon
},
1413 { "finddevice", chirp_emul_finddevice
},
1414 { "instance-to-path", chirp_emul_instance_to_path
},
1415 { "package-to-path", chirp_emul_package_to_path
},
1416 { "call-method", chirp_emul_call_method
},
1419 { "open", chirp_emul_open
},
1420 { "close", chirp_emul_close
},
1421 { "read", chirp_emul_read
},
1422 { "write", chirp_emul_write
},
1423 { "seek", chirp_emul_seek
},
1424 { "write", chirp_emul_write
},
1427 { "claim", chirp_emul_claim
},
1428 { "release", chirp_emul_release
},
1430 /* control transfer */
1431 { "boot", chirp_emul_boot
},
1432 { "enter", chirp_emul_enter
},
1433 { "exit", chirp_emul_exit
},
1434 { "chain", chirp_emul_chain
},
1436 /* user interface */
1437 { "interpret", chirp_emul_interpret
},
1438 { "set_callback", chirp_emul_set_callback
},
1439 { "set_symbol_lookup", chirp_emul_set_symbol_lookup
},
1442 { "milliseconds", chirp_emul_milliseconds
},
1444 { 0, /* sentinal */ },
1450 /* Any starting address greater than this is assumed to be an Chirp
1453 #ifndef CHIRP_START_ADDRESS
1454 #define CHIRP_START_ADDRESS 0x80000000
1456 #ifndef CHIRP_LOAD_BASE
1457 #define CHIRP_LOAD_BASE -1
1461 typedef struct _chirp_note_desc
{
1474 } note_found_status
;
1475 typedef struct _chirp_note
{
1476 chirp_note_desc desc
;
1477 note_found_status found
;
1480 typedef struct _chirp_note_head
{
1487 map_over_chirp_note(bfd
*image
,
1491 chirp_note
*note
= (chirp_note
*)obj
;
1492 if (strcmp(sect
->name
, ".note") == 0) {
1493 chirp_note_head head
;
1495 /* check the head */
1496 if (!bfd_get_section_contents(image
, sect
,
1497 &head
, 0, sizeof(head
)))
1499 head
.namesz
= bfd_get_32(image
, (void*)&head
.namesz
);
1500 head
.descsz
= bfd_get_32(image
, (void*)&head
.descsz
);
1501 head
.type
= bfd_get_32(image
, (void*)&head
.type
);
1502 if (head
.type
!= 0x1275)
1504 /* check the name field */
1505 if (head
.namesz
> sizeof(name
)) {
1506 error("chirp: note name too long (%d > %d)\n", (int)head
.namesz
, sizeof(name
));
1508 if (!bfd_get_section_contents(image
, sect
,
1509 name
, sizeof(head
), head
.namesz
)) {
1510 error("chirp: note name unreadable\n");
1512 if (strcmp(name
, "PowerPC") != 0) {
1513 printf_filtered("chirp: note name (%s) not `PowerPC'\n", name
);
1515 /* check the size */
1516 if (head
.descsz
== sizeof(note
->desc
) - sizeof(signed32
)) {
1517 sim_io_printf_filtered("chirp: note descriptor missing load-base\n");
1519 else if (head
.descsz
!= sizeof(note
->desc
)) {
1520 sim_io_printf_filtered("chirp: note descriptor of wrong size\n");
1521 note
->found
= note_found
;
1524 note
->found
= note_correct
;
1525 /* get the contents */
1526 if (!bfd_get_section_contents(image
, sect
,
1527 ¬e
->desc
, /* page align start */
1528 ((sizeof(head
) + head
.namesz
) + 3) & ~3,
1530 error("chirp: note descriptor unreadable\n");
1532 note
->desc
.real_mode
= bfd_get_32(image
, (void*)¬e
->desc
.real_mode
);
1533 note
->desc
.real_base
= bfd_get_32(image
, (void*)¬e
->desc
.real_base
);
1534 note
->desc
.real_size
= bfd_get_32(image
, (void*)¬e
->desc
.real_size
);
1535 note
->desc
.virt_base
= bfd_get_32(image
, (void*)¬e
->desc
.virt_base
);
1536 note
->desc
.virt_size
= bfd_get_32(image
, (void*)¬e
->desc
.virt_size
);
1537 if (head
.descsz
== sizeof(note
->desc
))
1538 note
->desc
.load_base
= bfd_get_32(image
, (void*)¬e
->desc
.load_base
);
1540 note
->desc
.load_base
= CHIRP_LOAD_BASE
;
1545 static os_emul_data
*
1546 emul_chirp_create(device
*root
,
1550 os_emul_data
*chirp
;
1555 /* Sanity check that this really is the chosen emulation */
1556 if (name
== NULL
&& image
== NULL
)
1559 && strcmp(name
, "ob") != 0
1560 && strcmp(name
, "ieee1274") != 0
1561 && strcmp(name
, "chrp") != 0
1562 && strcmp(name
, "chirp") != 0
1563 && strcmp(name
, "openboot") != 0)
1566 /* look for an elf note section, enter its values into the device tree */
1567 memset(¬e
, 0, sizeof(note
));
1569 bfd_map_over_sections(image
, map_over_chirp_note
, ¬e
);
1570 if (name
== NULL
&& image
!= NULL
&& note
.found
== note_missing
)
1573 /* Assume that it is a chirp emulation */
1575 chirp
= ZALLOC(os_emul_data
);
1577 chirp
->services
= services
;
1580 tree_parse(root
, "/name \"gpl,clayton");
1582 /* default options */
1583 emul_add_tree_options(root
, image
, "chirp", "oea",
1584 0 /*oea-interrupt-prefix*/);
1587 emul_add_tree_hardware(root
);
1589 /* basic information */
1591 = tree_find_integer_property(root
, "/openprom/options/oea-memory-size");
1592 chirp
->little_endian
1593 = tree_find_boolean_property(root
, "/options/little-endian?");
1594 chirp
->floating_point_available
1595 = tree_find_boolean_property(root
, "/openprom/options/floating-point?");
1596 chirp
->interrupt_prefix
=
1597 tree_find_integer_property(root
, "/openprom/options/oea-interrupt-prefix");
1600 /* Perform an interum layout of the openboot firmware in memory */
1603 /* a page for firmware calls */
1604 chirp
->sizeof_code
= 4096;
1605 chirp
->code_offset
= 0x4000; /* possible space for interrupt table */
1608 chirp
->sizeof_stack
= 32 * 1024;
1609 chirp
->stack_offset
= chirp
->code_offset
+ chirp
->sizeof_code
;
1611 /* the hash table */
1612 if (!note
.desc
.real_mode
) {
1613 chirp
->nr_page_table_entry_groups
= (chirp
->memory_size
< 0x800000
1614 ? 1024 /* min allowed */
1615 : (chirp
->memory_size
/ 4096 / 2));
1616 chirp
->sizeof_htab
= chirp
->nr_page_table_entry_groups
* 64;
1618 chirp
->htab_offset
= chirp
->stack_offset
+ chirp
->sizeof_stack
;
1620 /* the actual amount of space needed */
1621 chirp
->real_size
= chirp
->htab_offset
+ chirp
->sizeof_htab
;
1624 /* now go through and see if it fits in what is available */
1627 /* resolve real-mode? */
1628 if (note
.found
== note_correct
)
1629 chirp
->real_mode
= note
.desc
.real_mode
;
1630 else if (tree_find_property(root
, "/options/real-mode?") != NULL
)
1631 chirp
->real_mode
= tree_find_boolean_property(root
, "/options/real-mode?");
1633 chirp
->real_mode
= 0;
1634 if (tree_find_property(root
, "/options/real-mode?") != NULL
) {
1635 if (!chirp
->real_mode
1636 != !tree_find_boolean_property(root
, "/options/real-mode?"))
1637 error("chirp: /options/real-mode? conflicts with note section\n");
1640 tree_parse(root
, "/options/real-mode? %s",
1641 chirp
->real_mode
? "true" : "false");
1643 /* resolve real-base */
1644 if (note
.found
== note_correct
1645 && note
.desc
.real_base
!= (signed32
)-1)
1646 chirp
->real_base
= note
.desc
.real_base
;
1647 else if (tree_find_property(root
, "/options/real-base") != NULL
)
1648 chirp
->real_base
= tree_find_integer_property(root
, "/options/real-base");
1650 chirp
->real_base
= chirp
->memory_size
- chirp
->real_size
;
1651 if (tree_find_property(root
, "/options/real-base") != NULL
) {
1652 if (chirp
->real_base
!= tree_find_integer_property(root
, "/options/real-base"))
1653 error("chirp: /options/real-base conflicts with note section\n");
1656 tree_parse(root
, "/options/real-base 0x%lx",
1657 (unsigned long)chirp
->real_base
);
1659 /* resolve real-size */
1660 if (note
.found
== note_correct
1661 && note
.desc
.real_size
!= (signed32
)-1
1662 && note
.desc
.real_size
!= 0
1663 && chirp
->real_size
> note
.desc
.real_size
)
1664 error("chirp: insufficient physical memory for firmware\n");
1665 if (tree_find_property(root
, "/options/real-size") != NULL
) {
1666 if (chirp
->real_size
> tree_find_integer_property(root
, "/options/real-size"))
1667 error("chirp: /options/real-size conflicts with note section\n");
1670 tree_parse(root
, "/options/real-size 0x%lx",
1671 (unsigned long)chirp
->real_size
);
1673 /* resolve virt-base */
1674 if (chirp
->real_mode
)
1675 chirp
->virt_base
= chirp
->real_base
;
1676 else if (note
.found
== note_correct
&& note
.desc
.virt_base
!= -1)
1677 chirp
->virt_base
= note
.desc
.virt_base
;
1678 else if (tree_find_property(root
, "/options/virt-base") != NULL
)
1679 chirp
->virt_base
= tree_find_integer_property(root
, "/options/virt-base");
1681 chirp
->virt_base
= CHIRP_START_ADDRESS
;
1682 if (tree_find_property(root
, "/options/virt-base") != NULL
) {
1683 unsigned_word virt_base
= tree_find_integer_property(root
, "/options/virt-base");
1684 if (virt_base
!= -1 && chirp
->virt_base
!= virt_base
)
1685 error("chirp: /options/virt-base conflicts with note section\n");
1688 tree_parse(root
, "/options/virt-base 0x%lx",
1689 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_base
);
1691 /* resolve virt-size */
1692 chirp
->virt_size
= chirp
->real_size
;
1693 if (note
.found
== note_correct
1694 && note
.desc
.virt_size
!= (signed32
)-1
1695 && note
.desc
.virt_size
!= 0
1696 && !chirp
->real_mode
1697 && chirp
->virt_size
> note
.desc
.virt_size
)
1698 error("chirp: insufficent virtual memory for firmware\n");
1699 if (tree_find_property(root
, "/options/virt-size") != NULL
) {
1700 if (chirp
->virt_size
> tree_find_integer_property(root
, "/options/virt-size"))
1701 error("chirp: /options/virt-size conflicts with note section\n");
1704 tree_parse(root
, "/options/virt-size 0x%lx",
1705 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_size
);
1707 /* resolve load-base */
1708 if (note
.found
== note_correct
1709 && note
.desc
.load_base
!= (signed32
)-1)
1710 chirp
->load_base
= note
.desc
.load_base
;
1711 else if (tree_find_property(root
, "/options/load-base") != NULL
)
1712 chirp
->load_base
= tree_find_integer_property(root
, "/options/load-base");
1714 chirp
->load_base
= CHIRP_LOAD_BASE
;
1715 if (tree_find_property(root
, "/options/load-base") != NULL
) {
1716 if (chirp
->load_base
!= tree_find_integer_property(root
, "/options/load-base"))
1717 error("chirp: /options/load-base conflicts with note section\n");
1720 tree_parse(root
, "/options/load-base 0x%lx",
1721 (unsigned long)chirp
->load_base
);
1723 /* now adjust the preliminary firmware addresses to final values */
1724 chirp
->code_ra
= chirp
->code_offset
+ chirp
->real_base
;
1725 chirp
->stack_ra
= chirp
->stack_offset
+ chirp
->real_base
;
1726 chirp
->htab_ra
= chirp
->htab_offset
+ chirp
->real_base
;
1728 /* the virtual addresses. In real mode these are real addresses. */
1730 chirp
->code_va
= chirp
->code_offset
+ chirp
->virt_base
;
1731 chirp
->stack_va
= chirp
->stack_offset
+ chirp
->virt_base
;
1732 chirp
->htab_va
= chirp
->htab_offset
+ chirp
->virt_base
;
1734 chirp
->code_client_va
= chirp
->code_va
;
1735 chirp
->code_client_ra
= chirp
->code_ra
;
1737 chirp
->code_callback_va
= chirp
->code_client_va
+ 16;
1738 chirp
->code_callback_ra
= chirp
->code_client_ra
+ 16;
1740 chirp
->code_loop_va
= chirp
->code_callback_va
+ 16;
1741 chirp
->code_loop_ra
= chirp
->code_callback_ra
+ 16;
1743 /* initialization */
1745 tree_parse(root
, "/openprom/init");
1746 tree_parse(root
, "/openprom/init/register");
1747 tree_parse(root
, "/openprom/init/register/0.pc 0x%lx",
1748 (unsigned long)bfd_get_start_address(image
));
1749 tree_parse(root
, "/openprom/init/register/pc 0x%lx",
1750 (unsigned long)chirp
->code_loop_va
);
1751 tree_parse(root
, "/openprom/init/register/msr 0x%x",
1752 (msr_machine_check_enable
1755 : (msr_instruction_relocate
1756 | msr_data_relocate
))
1757 | (chirp
->little_endian
1758 ? (msr_little_endian_mode
1759 | msr_interrupt_little_endian_mode
)
1761 | (chirp
->floating_point_available
1762 ? msr_floating_point_available
1764 | (chirp
->interrupt_prefix
1765 ? msr_interrupt_prefix
1768 tree_parse(root
, "/openprom/init/register/sdr1 0x%lx",
1769 (unsigned long)(chirp
->htab_ra
1771 | ((chirp
->sizeof_htab
- 1) >> 16)));
1772 /* make certain that the segment registers map straight through */
1773 for (i
= 0; i
< 16; i
++) {
1774 tree_parse(root
, "/openprom/init/register/sr%d 0x%lx",
1775 i
, (unsigned long)i
);
1778 /* establish an initial state for all processors */
1781 /* the client interface address */
1782 tree_parse(root
, "/openprom/init/register/r5 0x%lx",
1783 (unsigned long)chirp
->code_client_va
);
1785 tree_parse(root
, "/openprom/init/register/sp 0x%lx",
1786 (unsigned long)(chirp
->stack_va
+ chirp
->sizeof_stack
- 16));
1787 /* in chrp mode any arguments end up being concatinated */
1788 tree_parse(root
, "/openprom/init/stack/stack-type chirp");
1791 /* client interface - emul-call followed by return instruction */
1794 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1795 (unsigned long)chirp
->code_client_ra
);
1796 tree_parse(node
, "./psim,description \"client-interface instruction");
1797 tree_parse(node
, "./real-address 0x%lx",
1798 (unsigned long)chirp
->code_client_ra
);
1799 tree_parse(node
, "./data 0x%lx",
1800 (unsigned long)emul_call_instruction
);
1802 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1803 (unsigned long)(chirp
->code_client_ra
+ 4));
1804 tree_parse(node
, "./psim,description \"client-interface return instruction");
1805 tree_parse(node
, "./real-address 0x%lx",
1806 (unsigned long)(chirp
->code_client_ra
+ 4));
1807 tree_parse(node
, "./data 0x%lx",
1808 (unsigned long)emul_blr_instruction
);
1811 /* return address for client callbacks - an emul-call instruction
1812 that is again followed by a return instruction */
1815 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1816 (unsigned long)chirp
->code_callback_ra
);
1817 tree_parse(node
, "./psim,description \"client-callback instruction");
1818 tree_parse(node
, "./real-address 0x%lx",
1819 (unsigned long)chirp
->code_callback_ra
);
1820 tree_parse(node
, "./data 0x%lx",
1821 (unsigned long)emul_call_instruction
);
1823 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1824 (unsigned long)(chirp
->code_callback_ra
+ 4));
1825 tree_parse(node
, "./psim,description \"client-callback return instruction");
1826 tree_parse(node
, "./real-address 0x%lx",
1827 (unsigned long)(chirp
->code_callback_ra
+ 4));
1828 tree_parse(node
, "./data 0x%lx",
1829 (unsigned long)emul_blr_instruction
);
1831 /* loop to keep other processors busy */
1833 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1834 (unsigned long)chirp
->code_loop_ra
);
1835 tree_parse(node
, "./psim,description \"processor busy loop");
1836 tree_parse(node
, "./real-address 0x%lx",
1837 (unsigned long)chirp
->code_loop_ra
);
1838 tree_parse(node
, "./data 0x%lx",
1839 (unsigned long)emul_loop_instruction
);
1843 /* create a hash table */
1845 if (!chirp
->real_mode
) {
1846 node
= tree_parse(root
, "/openprom/init/htab@0x%lx",
1847 (unsigned long)chirp
->htab_ra
);
1848 tree_parse(node
, "./claim 0");
1849 tree_parse(node
, "./real-address 0x%lx",
1850 (unsigned long)chirp
->htab_ra
);
1851 tree_parse(node
, "./nr-bytes 0x%lx",
1852 (unsigned long)chirp
->sizeof_htab
);
1855 /* map in the stack */
1857 if (!chirp
->real_mode
) {
1858 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1859 (unsigned long)chirp
->stack_ra
);
1860 tree_parse(node
, "./psim,description \"map in the stack");
1861 tree_parse(node
, "./claim 1");
1862 tree_parse(node
, "./virtual-address 0x%lx",
1863 (unsigned long)chirp
->stack_va
);
1864 tree_parse(node
, "./real-address 0x%lx",
1865 (unsigned long)chirp
->stack_ra
);
1866 tree_parse(node
, "./nr-bytes 0x%lx",
1867 (unsigned long)chirp
->sizeof_stack
);
1868 tree_parse(node
, "./wimg %d", 0x7);
1869 tree_parse(node
, "./pp %d", 0x2);
1872 /* map in the chrp openboot callback code */
1874 if (!chirp
->real_mode
) {
1875 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1876 (unsigned long)chirp
->code_ra
);
1877 tree_parse(node
, "./psim,description \"map in chrp openboot callback code");
1878 tree_parse(node
, "./claim 1");
1879 tree_parse(node
, "./virtual-address 0x%lx",
1880 (unsigned long)chirp
->code_va
);
1881 tree_parse(node
, "./real-address 0x%lx",
1882 (unsigned long)chirp
->code_ra
);
1883 tree_parse(node
, "./nr-bytes 0x%lx",
1884 (unsigned long)chirp
->sizeof_code
);
1885 tree_parse(node
, "./wimg %d", 0x7);
1886 tree_parse(node
, "./pp %d", 0x2);
1889 /* map in the program to run */
1891 if (chirp
->real_mode
) {
1892 node
= tree_parse(node
, "/openprom/init/load-binary");
1893 tree_parse(node
, "./psim,description \"load the binary");
1894 tree_parse(node
, "./file-name %s", bfd_get_filename(image
));
1895 tree_parse(node
, "./claim 1");
1898 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1899 (unsigned long)chirp
->load_base
);
1900 tree_parse(node
, "./psim,description \"load & map the binary");
1901 tree_parse(node
, "./claim 1");
1902 tree_parse(node
, "./file-name \"%s", bfd_get_filename(image
));
1903 tree_parse(node
, "./wimg %d", 0x7);
1904 tree_parse(node
, "./pp %d", 0x2);
1911 emul_chirp_init(os_emul_data
*emul_data
,
1914 emul_data
->state
= serving
;
1918 emul_chirp_instruction_call(cpu
*processor
,
1921 os_emul_data
*emul_data
)
1923 unsigned_word service_name_addr
;
1924 unsigned_word result
;
1925 char service_buf
[32];
1927 chirp_services
*service
;
1929 switch (emul_data
->state
) {
1932 /* we are waiting on an OpenBoot request from the client program
1933 via the client interface */
1934 if (cia
!= emul_data
->code_client_va
)
1936 emul_data
->return_address
= LR
;
1937 emul_data
->arguments
= cpu_registers(processor
)->gpr
[3];
1938 /* try to determine what to do */
1939 service_name_addr
= emul_read_word(cpu_registers(processor
)->gpr
[3],
1941 service_name
= emul_read_string(service_buf
, service_name_addr
,
1942 sizeof(service_buf
), processor
, cia
);
1943 emul_data
->n_args
= emul_read_word(emul_data
->arguments
+ sizeof(unsigned_cell
),
1945 emul_data
->n_returns
= emul_read_word(emul_data
->arguments
+ 2 * sizeof(unsigned_cell
),
1947 /* verify what was passed */
1948 if (service_name_addr
== 0
1949 || service_name
== NULL
) {
1950 error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n",
1951 (unsigned long)emul_data
->return_address
,
1952 (unsigned long)emul_data
->arguments
);
1954 if (emul_data
->n_args
> 6) { /* See iee1275 requirements on nr returns */
1955 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n",
1956 (unsigned long)emul_data
->return_address
,
1957 (unsigned long)emul_data
->arguments
,
1958 emul_data
->n_returns
);
1960 if (emul_data
->n_returns
> 6) {
1961 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, with too many returns (%d)\n",
1962 (unsigned long)emul_data
->return_address
,
1963 (unsigned long)emul_data
->arguments
,
1967 TRACE(trace_os_emul
, ("%s called from 0x%lx with args 0x%lx\n",
1969 (unsigned long)emul_data
->return_address
,
1970 (unsigned long)emul_data
->arguments
));
1972 while (service
->name
!= NULL
&& strcmp(service
->name
, service_name
) != 0)
1975 if (service
->name
== NULL
) {
1976 error("OpenBoot service `%s' not found\n", service_name
);
1977 TRACE(trace_os_emul
, ("%s not found\n", service_name
));
1978 cpu_registers(processor
)->gpr
[3] = -1;
1981 emul_data
->service
= service
;
1983 result
= service
->handler(emul_data
, processor
, cia
);
1985 TRACE(trace_os_emul
, ("%s aborted with %ld\n", service_name
, (long)result
));
1986 cpu_registers(processor
)->gpr
[3] = result
;
1991 error("emul_chirp_instruction_call() unknown internal state\n");
1997 /* return to caller - instruction following this is a function return */
2001 const os_emul emul_chirp
= {
2005 NULL
, /*system_call*/
2006 emul_chirp_instruction_call
,