1 /* This file is part of the program psim.
3 Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #ifndef _EMUL_CHIRP_C_
22 #define _EMUL_CHIRP_C_
24 /* Note: this module is called via a table. There is no benefit in
27 #include "emul_generic.h"
28 #include "emul_chirp.h"
33 #ifndef STATIC_INLINE_EMUL_CHIRP
34 #define STATIC_INLINE_EMUL_CHIRP STATIC_INLINE
41 OpenFirmware - IEEE Standard for Boot (Initialization
42 Configuration) Firmware.
51 This code assumes that the memory node has #address-cells and
52 #size-cells set to one. For future implementations, this may not
60 /* Descriptor of the open boot services being emulated */
62 typedef int (chirp_handler
)
67 typedef struct _chirp_services
{
69 chirp_handler
*handler
;
73 /* The OpenBoot emulation is, at any time either waiting for a client
74 request or waiting on a client callback */
81 struct _os_emul_data
{
82 chirp_emul_state state
;
83 unsigned_word return_address
;
84 unsigned_word arguments
;
86 unsigned_word n_returns
;
87 chirp_services
*service
;
89 chirp_services
*services
;
91 unsigned_word memory_size
;
92 unsigned_word real_base
;
93 unsigned_word real_size
;
94 unsigned_word virt_base
;
95 unsigned_word virt_size
;
98 int floating_point_available
;
100 unsigned_word load_base
;
102 unsigned_word nr_page_table_entry_groups
;
103 unsigned_word htab_offset
;
104 unsigned_word htab_ra
;
105 unsigned_word htab_va
;
106 unsigned_word sizeof_htab
;
107 /* virtual address of htab */
108 unsigned_word stack_offset
;
109 unsigned_word stack_ra
;
110 unsigned_word stack_va
;
111 unsigned_word sizeof_stack
;
112 /* addresses of emulation instructions virtual/real */
113 unsigned_word code_offset
;
114 unsigned_word code_va
;
115 unsigned_word code_ra
;
116 unsigned_word sizeof_code
;
117 unsigned_word code_client_va
;
118 unsigned_word code_client_ra
;
119 unsigned_word code_callback_va
;
120 unsigned_word code_callback_ra
;
121 unsigned_word code_loop_va
;
122 unsigned_word code_loop_ra
;
126 /* returns the name of the corresponding Ihandle */
128 ihandle_name(device_instance
*ihandle
)
133 return device_name(device_instance_device(ihandle
));
138 /* Read/write the argument list making certain that all values are
139 converted to/from host byte order.
141 In the below only n_args+n_returns is read/written */
144 chirp_read_t2h_args(void *args
,
152 unsigned_cell
*words
;
154 /* check against the number of arguments specified by the client
156 if ((n_args
>= 0 && data
->n_args
!= n_args
)
157 || (n_returns
>= 0 && data
->n_returns
!= n_returns
)) {
158 TRACE(trace_os_emul
, ("%s - invalid nr of args - n_args=%ld, n_returns=%ld\n",
161 (long)data
->n_returns
));
164 /* check that there is enough space */
165 if (sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
) > sizeof_args
)
167 /* bring in the data */
168 memset(args
, 0, sizeof_args
);
169 emul_read_buffer(args
, data
->arguments
+ 3 * sizeof(unsigned_cell
),
170 sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
),
172 /* convert all words to host format */
174 for (i
= 0; i
< (sizeof_args
/ sizeof(unsigned_cell
)); i
++)
175 words
[i
] = T2H_cell(words
[i
]);
180 chirp_write_h2t_args(void *args
,
187 unsigned_cell
*words
;
188 /* convert to target everything */
190 for (i
= 0; i
< (sizeof_args
/ sizeof(unsigned_cell
)); i
++)
191 words
[i
] = H2T_cell(words
[i
]);
192 /* bring in the data */
193 emul_write_buffer(args
, data
->arguments
+ 3 * sizeof(unsigned_cell
),
194 sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
),
199 /* OpenBoot emulation functions */
201 /* client interface */
204 chirp_emul_test(os_emul_data
*data
,
210 unsigned_cell name
; /*string*/
212 unsigned_cell missing
;
215 chirp_services
*service
= NULL
;
216 /* read in the arguments */
217 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
219 emul_read_string(name
, args
.name
, sizeof(name
),
221 TRACE(trace_os_emul
, ("test - in - name=`%s'\n", name
));
222 /* see if we know about the service */
223 service
= data
->services
;
224 while (service
->name
!= NULL
&& strcmp(service
->name
, name
) != 0) {
227 if (service
->name
== NULL
)
231 /* write the arguments back out */
232 TRACE(trace_os_emul
, ("test - out - missing=%ld\n",
233 (long)args
.missing
));
234 chirp_write_h2t_args(&args
,
245 chirp_emul_peer(os_emul_data
*data
,
251 unsigned_cell phandle
;
253 unsigned_cell sibling_phandle
;
256 device
*sibling_phandle
= NULL
;
257 /* read in the arguments */
258 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
260 phandle
= external_to_device(data
->root
, args
.phandle
);
261 TRACE(trace_os_emul
, ("peer - in - phandle=0x%lx(%p`%s')\n",
262 (unsigned long)args
.phandle
,
264 (phandle
== NULL
? "" : device_name(phandle
))));
266 if (args
.phandle
== 0) {
267 sibling_phandle
= data
->root
;
268 args
.sibling_phandle
= device_to_external(sibling_phandle
);
270 else if (phandle
== NULL
) {
271 sibling_phandle
= NULL
;
272 args
.sibling_phandle
= -1;
275 sibling_phandle
= device_sibling(phandle
);
276 if (sibling_phandle
== NULL
)
277 args
.sibling_phandle
= 0;
279 args
.sibling_phandle
= device_to_external(sibling_phandle
);
281 /* write the arguments back out */
282 TRACE(trace_os_emul
, ("peer - out - sibling_phandle=0x%lx(%p`%s')\n",
283 (unsigned long)args
.sibling_phandle
,
285 (sibling_phandle
== NULL
? "" : device_name(sibling_phandle
))));
286 chirp_write_h2t_args(&args
,
294 chirp_emul_child(os_emul_data
*data
,
300 unsigned_cell phandle
;
302 unsigned_cell child_phandle
;
305 device
*child_phandle
;
306 /* read the arguments in */
307 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
309 phandle
= external_to_device(data
->root
, args
.phandle
);
310 TRACE(trace_os_emul
, ("child - in - phandle=0x%lx(%p`%s')\n",
311 (unsigned long)args
.phandle
,
313 (phandle
== NULL
? "" : device_name(phandle
))));
315 if (args
.phandle
== 0
316 || phandle
== NULL
) {
317 child_phandle
= NULL
;
318 args
.child_phandle
= -1;
321 child_phandle
= device_child(phandle
);
322 if (child_phandle
== NULL
)
323 args
.child_phandle
= 0;
325 args
.child_phandle
= device_to_external(child_phandle
);
327 /* write the result out */
328 TRACE(trace_os_emul
, ("child - out - child_phandle=0x%lx(%p`%s')\n",
329 (unsigned long)args
.child_phandle
,
331 (child_phandle
== NULL
? "" : device_name(child_phandle
))));
332 chirp_write_h2t_args(&args
,
340 chirp_emul_parent(os_emul_data
*data
,
346 unsigned_cell phandle
;
348 unsigned_cell parent_phandle
;
351 device
*parent_phandle
;
352 /* read the args in */
353 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
355 phandle
= external_to_device(data
->root
, args
.phandle
);
356 TRACE(trace_os_emul
, ("parent - in - phandle=0x%lx(%p`%s')\n",
357 (unsigned long)args
.phandle
,
359 (phandle
== NULL
? "" : device_name(phandle
))));
361 if (args
.phandle
== 0
362 || phandle
== NULL
) {
363 parent_phandle
= NULL
;
364 args
.parent_phandle
= -1;
367 parent_phandle
= device_parent(phandle
);
368 if (parent_phandle
== NULL
)
369 args
.parent_phandle
= 0;
371 args
.parent_phandle
= device_to_external(parent_phandle
);
373 /* return the result */
374 TRACE(trace_os_emul
, ("parent - out - parent_phandle=0x%lx(%p`%s')\n",
375 (unsigned long)args
.parent_phandle
,
377 (parent_phandle
== NULL
? "" : device_name(parent_phandle
))));
378 chirp_write_h2t_args(&args
,
386 chirp_emul_instance_to_package(os_emul_data
*data
,
390 struct instance_to_package_args
{
392 unsigned_cell ihandle
;
394 unsigned_cell phandle
;
396 device_instance
*ihandle
;
397 device
*phandle
= NULL
;
398 /* read the args in */
399 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
401 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
402 TRACE(trace_os_emul
, ("instance-to-package - in - ihandle=0x%lx(%p`%s')\n",
403 (unsigned long)args
.ihandle
,
405 ihandle_name(ihandle
)));
406 /* find the corresponding phandle */
407 if (ihandle
== NULL
) {
412 phandle
= device_instance_device(ihandle
);
413 args
.phandle
= device_to_external(phandle
);
415 /* return the result */
416 TRACE(trace_os_emul
, ("instance-to-package - out - phandle=0x%lx(%p`%s')\n",
417 (unsigned long)args
.phandle
,
419 (phandle
== NULL
? "" : device_name(phandle
))));
420 chirp_write_h2t_args(&args
,
428 chirp_emul_getproplen(os_emul_data
*data
,
432 struct getproplen_args
{
434 unsigned_cell phandle
;
437 unsigned_cell proplen
;
441 /* read the args in */
442 if (chirp_read_t2h_args(&args
, sizeof(args
), 2, 1, data
, processor
, cia
))
444 phandle
= external_to_device(data
->root
, args
.phandle
);
445 emul_read_string(name
,
449 TRACE(trace_os_emul
, ("getproplen - in - phandle=0x%lx(%p`%s') name=`%s'\n",
450 (unsigned long)args
.phandle
,
452 (phandle
== NULL
? "" : device_name(phandle
)),
454 /* find our prop and get its length */
455 if (args
.phandle
== 0
456 || phandle
== NULL
) {
460 const device_property
*prop
= device_find_property(phandle
, name
);
461 if (prop
== (device_property
*)0) {
465 args
.proplen
= prop
->sizeof_array
;
468 /* return the result */
469 TRACE(trace_os_emul
, ("getproplen - out - proplen=%ld\n",
470 (unsigned long)args
.proplen
));
471 chirp_write_h2t_args(&args
,
479 chirp_emul_getprop(os_emul_data
*data
,
483 struct getprop_args
{
485 unsigned_cell phandle
;
488 unsigned_cell buflen
;
494 /* read in the args, the return is optional */
495 if (chirp_read_t2h_args(&args
, sizeof(args
), 4, -1, data
, processor
, cia
))
497 phandle
= external_to_device(data
->root
, args
.phandle
);
498 emul_read_string(name
,
502 TRACE(trace_os_emul
, ("getprop - in - phandle=0x%lx(%p`%s') name=`%s' buf=0x%lx buflen=%ld\n",
503 (unsigned long)args
.phandle
,
505 (phandle
== NULL
? "" : device_name(phandle
)),
507 (unsigned long)args
.buf
,
508 (unsigned long)args
.buflen
));
509 /* get the property */
510 if (args
.phandle
== 0
511 || phandle
== NULL
) {
515 const device_property
*prop
= device_find_property(phandle
, name
);
520 int size
= args
.buflen
;
521 if (size
> prop
->sizeof_array
)
522 size
= prop
->sizeof_array
;
523 emul_write_buffer(prop
->array
, args
.buf
,
527 switch (prop
->type
) {
528 case string_property
:
529 TRACE(trace_os_emul
, ("getprop - string `%s'\n",
530 device_find_string_property(phandle
, name
)));
532 case ihandle_property
:
533 TRACE(trace_os_emul
, ("getprop - ihandle=0x%lx(%p`%s')\n",
534 (unsigned long)BE2H_cell(*(unsigned_cell
*)prop
->array
),
535 device_find_ihandle_property(phandle
, name
),
536 ihandle_name(device_find_ihandle_property(phandle
, name
))));
543 /* write back the result */
544 if (data
->n_returns
== 0)
545 TRACE(trace_os_emul
, ("getprop - out - size=%ld (not returned)\n",
546 (unsigned long)args
.size
));
548 TRACE(trace_os_emul
, ("getprop - out - size=%ld\n",
549 (unsigned long)args
.size
));
550 chirp_write_h2t_args(&args
,
559 chirp_emul_nextprop(os_emul_data
*data
,
563 struct nextprop_args
{
565 unsigned_cell phandle
;
566 unsigned_cell previous
;
573 /* read in the args */
574 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
576 phandle
= external_to_device(data
->root
, args
.phandle
);
577 if (args
.previous
!= 0)
578 emul_read_string(previous
,
583 /* If previous is NULL, make it look like the empty string. The
584 next property after the empty string is the first property. */
585 strcpy (previous
, "");
586 TRACE(trace_os_emul
, ("nextprop - in - phandle=0x%lx(%p`%s') previous=`%s' buf=0x%lx\n",
587 (unsigned long)args
.phandle
,
589 (phandle
== NULL
? "" : device_name(phandle
)),
591 (unsigned long)args
.buf
));
592 /* find the next property */
593 if (args
.phandle
== 0
594 || phandle
== NULL
) {
598 const device_property
*prev_prop
= device_find_property(phandle
, previous
);
599 if (prev_prop
== NULL
) {
600 if (strcmp (previous
, "") == 0)
601 args
.flag
= 0; /* No properties */
603 args
.flag
= -1; /* name invalid */
606 const device_property
*next_prop
;
607 if (strcmp (previous
, "") == 0) {
608 next_prop
= prev_prop
; /* The first property. */
611 next_prop
= device_next_property(prev_prop
);
613 if (next_prop
== NULL
) {
614 args
.flag
= 0; /* last property */
617 emul_write_buffer(next_prop
->name
, args
.buf
, strlen(next_prop
->name
),
619 TRACE(trace_os_emul
, ("nextprop - name=`%s'\n", next_prop
->name
));
620 args
.flag
= 1; /* worked ok */
624 /* write back the result */
625 TRACE(trace_os_emul
, ("nextprop - out - flag=%ld\n",
626 (unsigned long)args
.flag
));
627 chirp_write_h2t_args(&args
,
636 chirp_emul_setprop(os_emul_data
*data
,
640 error("chirp: setprop method not implemented\n");
646 chirp_emul_canon(os_emul_data
*data
,
652 unsigned_cell device_specifier
;
654 unsigned_cell buflen
;
656 unsigned_cell length
;
658 char device_specifier
[1024];
662 /* read in the args */
663 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
665 emul_read_string(device_specifier
,
666 args
.device_specifier
,
667 sizeof(device_specifier
),
669 TRACE(trace_os_emul
, ("canon - in - device_specifier=`%s' buf=0x%lx buflen=%lx\n",
671 (unsigned long)args
.buf
,
672 (unsigned long)args
.buflen
));
674 phandle
= tree_find_device(data
->root
, device_specifier
);
675 if (phandle
== NULL
) {
681 path
= device_path(phandle
);
682 length
= strlen(path
);
683 if (length
>= args
.buflen
)
684 length
= args
.buflen
- 1;
685 emul_write_buffer(path
, args
.buf
, length
,
687 args
.length
= length
;
689 /* write back the result */
690 TRACE(trace_os_emul
, ("canon - out - length=%ld buf=`%s'\n",
691 (unsigned long)args
.length
,
693 chirp_write_h2t_args(&args
,
701 chirp_emul_finddevice(os_emul_data
*data
,
705 struct finddevice_args
{
707 unsigned_cell device_specifier
;
709 unsigned_cell phandle
;
711 char device_specifier
[1024];
714 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
716 emul_read_string(device_specifier
,
717 args
.device_specifier
,
718 sizeof(device_specifier
),
720 TRACE(trace_os_emul
, ("finddevice - in - device_specifier=`%s'\n",
722 /* find the device */
723 phandle
= tree_find_device(data
->root
, device_specifier
);
727 args
.phandle
= device_to_external(phandle
);
728 /* return its phandle */
729 TRACE(trace_os_emul
, ("finddevice - out - phandle=0x%lx(%p`%s')\n",
730 (unsigned long)args
.phandle
,
732 (phandle
== NULL
? "" : device_name(phandle
))));
733 chirp_write_h2t_args(&args
,
741 chirp_emul_instance_to_path(os_emul_data
*data
,
745 struct instance_to_path_args
{
747 unsigned_cell ihandle
;
749 unsigned_cell buflen
;
751 unsigned_cell length
;
753 device_instance
*ihandle
;
757 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
759 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
760 TRACE(trace_os_emul
, ("instance-to-path - in - ihandle=0x%lx(%p`%s') buf=0x%lx buflen=%ld\n",
761 (unsigned long)args
.ihandle
,
763 ihandle_name(ihandle
),
764 (unsigned long)args
.buf
,
765 (unsigned long)args
.buflen
));
766 /* get the devices name */
767 if (ihandle
== NULL
) {
772 path
= device_instance_path(ihandle
);
773 length
= strlen(path
);
774 if (length
>= args
.buflen
)
775 length
= args
.buflen
- 1;
776 emul_write_buffer(path
, args
.buf
, length
,
778 args
.length
= length
;
780 /* return its phandle */
781 TRACE(trace_os_emul
, ("instance-to-path - out - length=%ld buf=`%s')\n",
782 (unsigned long)args
.length
,
784 chirp_write_h2t_args(&args
,
792 chirp_emul_package_to_path(os_emul_data
*data
,
796 struct package_to_path_args
{
798 unsigned_cell phandle
;
800 unsigned_cell buflen
;
802 unsigned_cell length
;
807 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
809 phandle
= external_to_device(data
->root
, args
.phandle
);
810 TRACE(trace_os_emul
, ("package-to-path - in - phandle=0x%lx(%p`%s') buf=0x%lx buflen=%ld\n",
811 (unsigned long)args
.phandle
,
813 (phandle
== NULL
? "" : device_name(phandle
)),
814 (unsigned long)args
.buf
,
815 (unsigned long)args
.buflen
));
816 /* get the devices name */
817 if (phandle
== NULL
) {
823 path
= device_path(phandle
);
824 length
= strlen(path
);
825 if (length
>= args
.buflen
)
826 length
= args
.buflen
- 1;
827 emul_write_buffer(path
, args
.buf
, length
,
829 args
.length
= length
;
831 /* return its phandle */
832 TRACE(trace_os_emul
, ("package-to-path - out - length=%ld buf=`%s')\n",
833 (unsigned long)args
.length
,
835 chirp_write_h2t_args(&args
,
843 chirp_emul_call_method(os_emul_data
*data
,
847 struct call_method_args
{
849 unsigned_cell method
;
850 unsigned_cell ihandle
;
852 unsigned_cell stack
[13]; /*6in + 6out + catch */
855 device_instance
*ihandle
;
856 /* some useful info about our mini stack */
859 int stack_catch_result
;
862 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, -1, data
, processor
, cia
))
864 emul_read_string(method
,
868 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
869 n_stack_args
= data
->n_args
- 2;
870 n_stack_returns
= data
->n_returns
- 1;
871 stack_catch_result
= n_stack_args
;
872 stack_returns
= stack_catch_result
+ 1;
873 TRACE(trace_os_emul
, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(%p`%s')\n",
874 (unsigned long)data
->n_args
,
875 (unsigned long)data
->n_returns
,
877 (unsigned long)args
.ihandle
,
879 ihandle_name(ihandle
)));
880 /* see if we can emulate this method */
881 if (ihandle
== NULL
) {
882 /* OpenFirmware doesn't define this error */
883 error("chirp: invalid ihandle passed to call-method method");
886 args
.stack
[stack_catch_result
] =
887 device_instance_call_method(ihandle
,
892 &args
.stack
[stack_returns
]);
895 TRACE(trace_os_emul
, ("call-method - out - catch-result=%ld\n",
896 (unsigned long)args
.stack
[stack_catch_result
]));
897 chirp_write_h2t_args(&args
,
908 chirp_emul_open(os_emul_data
*data
,
914 unsigned_cell device_specifier
;
916 unsigned_cell ihandle
;
918 char device_specifier
[1024];
919 device_instance
*ihandle
;
921 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
923 emul_read_string(device_specifier
,
924 args
.device_specifier
,
925 sizeof(device_specifier
),
927 TRACE(trace_os_emul
, ("open - in - device_specifier=`%s'\n",
929 /* open the device */
930 ihandle
= tree_instance(data
->root
, device_specifier
);
934 args
.ihandle
= device_instance_to_external(ihandle
);
935 /* return the ihandle result */
936 TRACE(trace_os_emul
, ("open - out - ihandle=0x%lx(%p`%s')\n",
937 (unsigned long)args
.ihandle
,
939 ihandle_name(ihandle
)));
940 chirp_write_h2t_args(&args
,
948 chirp_emul_close(os_emul_data
*data
,
954 unsigned_cell ihandle
;
957 device_instance
*ihandle
;
959 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 0, data
, processor
, cia
))
961 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
962 TRACE(trace_os_emul
, ("close - in - ihandle=0x%lx(%p`%s')\n",
963 (unsigned long)args
.ihandle
,
965 ihandle_name(ihandle
)));
966 /* close the device */
967 if (ihandle
== NULL
) {
968 /* OpenFirmware doesn't define this error */
969 error("chirp: invalid ihandle passed to close method");
972 device_instance_delete(ihandle
);
974 /* return the ihandle result */
975 TRACE(trace_os_emul
, ("close - out\n"));
976 chirp_write_h2t_args(&args
,
984 chirp_emul_read(os_emul_data
*data
,
990 unsigned_cell ihandle
;
994 unsigned_cell actual
;
997 device_instance
*ihandle
;
999 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1001 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1002 TRACE(trace_os_emul
, ("read - in - ihandle=0x%lx(%p`%s') addr=0x%lx len=%ld\n",
1003 (unsigned long)args
.ihandle
,
1005 ihandle_name(ihandle
),
1006 (unsigned long)args
.addr
,
1007 (unsigned long)args
.len
));
1008 if (ihandle
== NULL
) {
1009 /* OpenFirmware doesn't define this error */
1010 error("chirp: invalid ihandle passed to read method");
1015 while (actual
< args
.len
) {
1016 int remaining
= args
.len
- actual
;
1017 int to_read
= (remaining
<= sizeof(buf
) ? remaining
: sizeof(buf
));
1018 int nr_read
= device_instance_read(ihandle
, buf
, to_read
);
1020 actual
= nr_read
; /* the error */
1023 else if (nr_read
== 0) {
1026 emul_write_buffer(buf
,
1033 args
.actual
= actual
;
1034 if (actual
< sizeof(buf
))
1037 buf
[sizeof(buf
) - 1] = '\0';
1044 case sim_io_not_ready
:
1045 ASSERT(sim_io_not_ready
== -2);
1046 args
.actual
= sim_io_not_ready
;
1049 error("Bad error value %ld", (long)actual
);
1054 /* return the result */
1055 TRACE(trace_os_emul
, ("read - out - actual=%ld `%s'\n",
1057 ((args
.actual
> 0 && args
.actual
< sizeof(buf
)) ? buf
: "")
1059 chirp_write_h2t_args(&args
,
1067 chirp_emul_write(os_emul_data
*data
,
1073 unsigned_cell ihandle
;
1077 unsigned_cell actual
;
1080 device_instance
*ihandle
;
1083 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1086 if (actual
>= sizeof(buf
))
1087 actual
= sizeof(buf
) - 1;
1088 emul_read_buffer(buf
,
1093 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1094 TRACE(trace_os_emul
, ("write - in - ihandle=0x%lx(%p`%s') `%s' (%ld)\n",
1095 (unsigned long)args
.ihandle
,
1097 ihandle_name(ihandle
),
1098 buf
, (long)actual
));
1099 if (ihandle
== NULL
) {
1100 /* OpenFirmware doesn't define this error */
1101 error("chirp: invalid ihandle passed to write method");
1105 actual
= device_instance_write(ihandle
, buf
, actual
);
1109 args
.actual
= actual
;
1111 /* return the result */
1112 TRACE(trace_os_emul
, ("write - out - actual=%ld\n",
1113 (long)args
.actual
));
1114 chirp_write_h2t_args(&args
,
1122 chirp_emul_seek(os_emul_data
*data
,
1128 unsigned_cell ihandle
;
1129 unsigned_cell pos_hi
;
1130 unsigned_cell pos_lo
;
1132 unsigned_cell status
;
1135 device_instance
*ihandle
;
1137 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1139 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1140 TRACE(trace_os_emul
, ("seek - in - ihandle=0x%lx(%p`%s') pos.hi=0x%lx pos.lo=0x%lx\n",
1141 (unsigned long)args
.ihandle
,
1143 ihandle_name(ihandle
),
1144 (unsigned long)args
.pos_hi
,
1145 (unsigned long)args
.pos_lo
));
1146 if (ihandle
== NULL
) {
1147 /* OpenFirmware doesn't define this error */
1148 error("chirp: invalid ihandle passed to seek method");
1152 status
= device_instance_seek(ihandle
, args
.pos_hi
, args
.pos_lo
);
1153 args
.status
= status
;
1155 /* return the result */
1156 TRACE(trace_os_emul
, ("seek - out - status=%ld\n",
1157 (long)args
.status
));
1158 chirp_write_h2t_args(&args
,
1169 chirp_emul_claim(os_emul_data
*data
,
1173 /* NOTE: the client interface claim routine is *very* different to
1174 the "claim" method described in IEEE-1275 appendix A. The latter
1175 uses real addresses while this uses virtual (effective)
1181 unsigned_cell align
;
1183 unsigned_cell baseaddr
;
1186 if (chirp_read_t2h_args(&args
, sizeof(args
),
1187 3 /*n_args*/, 1 /*n_returns*/,
1188 data
, processor
, cia
))
1190 TRACE(trace_os_emul
, ("claim - in - virt=0x%lx size=%ld align=%d\n",
1191 (unsigned long)args
.virt
,
1192 (long int)args
.size
,
1194 /* use the memory device to allocate (real) memory at the requested
1197 device_instance
*memory
= tree_find_ihandle_property(data
->root
, "/chosen/memory");
1198 unsigned_cell mem_in
[3];
1199 unsigned_cell mem_out
[1];
1200 mem_in
[0] = args
.align
; /*top-of-stack*/
1201 mem_in
[1] = args
.size
;
1202 mem_in
[2] = args
.virt
;
1203 if (device_instance_call_method(memory
, "claim",
1204 3, mem_in
, 1, mem_out
) < 0)
1205 error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d",
1206 (unsigned long)args
.virt
,
1207 (long int)args
.size
,
1209 args
.baseaddr
= mem_out
[0];
1211 /* if using virtual addresses, create a 1-1 map of this address space */
1212 if (!data
->real_mode
) {
1213 error("chirp: claim method does not support virtual mode");
1215 /* return the base address */
1216 TRACE(trace_os_emul
, ("claim - out - baseaddr=0x%lx\n",
1217 (unsigned long)args
.baseaddr
));
1218 chirp_write_h2t_args(&args
,
1226 chirp_emul_release(os_emul_data
*data
,
1230 /* NOTE: the client interface release routine is *very* different to
1231 the "claim" method described in IEEE-1275 appendix A. The latter
1232 uses real addresses while this uses virtual (effective)
1241 if (chirp_read_t2h_args(&args
, sizeof(args
),
1242 2 /*n_args*/, 0 /*n_returns*/,
1243 data
, processor
, cia
))
1245 TRACE(trace_os_emul
, ("release - in - virt=0x%lx size=%ld\n",
1246 (unsigned long)args
.virt
,
1247 (long int)args
.size
));
1248 /* use the memory device to release (real) memory at the requested
1251 device_instance
*memory
= tree_find_ihandle_property(data
->root
, "/chosen/memory");
1252 unsigned_cell mem_in
[2];
1253 mem_in
[0] = args
.size
;
1254 mem_in
[1] = args
.virt
;
1255 if (device_instance_call_method(memory
, "release",
1256 2, mem_in
, 0, NULL
) < 0)
1257 error("chirp: claim failed to release memory virt=0x%lx size=%ld",
1258 (unsigned long)args
.virt
,
1259 (long int)args
.size
);
1261 /* if using virtual addresses, remove the 1-1 map of this address space */
1262 if (!data
->real_mode
) {
1263 error("chirp: release method does not support virtual mode");
1265 /* return the base address */
1266 TRACE(trace_os_emul
, ("release - out\n"));
1267 chirp_write_h2t_args(&args
,
1275 /* Control transfer */
1278 chirp_emul_boot(os_emul_data
*data
,
1282 /* unlike OpenFirmware this one can take an argument */
1285 unsigned_cell bootspec
;
1288 char bootspec
[1024];
1289 /* read in the arguments */
1290 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, 0, data
, processor
, cia
))
1291 cpu_halt(processor
, cia
, was_exited
, -1);
1292 if (args
.bootspec
!= 0)
1293 emul_read_string(bootspec
, args
.bootspec
, sizeof(bootspec
),
1296 strcpy(bootspec
, "(null)");
1297 TRACE(trace_os_emul
, ("boot - in bootspec=`%s'\n", bootspec
));
1298 /* just report this and exit */
1299 printf_filtered("chrp: boot %s called, exiting.\n", bootspec
);
1300 cpu_halt(processor
, cia
, was_exited
, 0);
1305 chirp_emul_enter(os_emul_data
*data
,
1309 error("chirp: enter method not implemented\n");
1314 chirp_emul_exit(os_emul_data
*data
,
1318 /* unlike OpenBoot this one can take an argument */
1324 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, 0, data
, processor
, cia
))
1325 cpu_halt(processor
, cia
, was_exited
, -1);
1326 cpu_halt(processor
, cia
, was_exited
, args
.status
);
1331 chirp_emul_chain(os_emul_data
*data
,
1335 error("chirp: chain method not implemented\n");
1340 /* user interface */
1343 chirp_emul_interpret(os_emul_data
*data
,
1347 error("chirp: interpret method not implemented\n");
1352 chirp_emul_set_callback(os_emul_data
*data
,
1356 error("chirp: set_callback method not implemented\n");
1361 chirp_emul_set_symbol_lookup(os_emul_data
*data
,
1365 error("chirp: set_symbol_lookup method not implemented\n");
1373 chirp_emul_milliseconds(os_emul_data
*data
,
1383 /* read in the arguments */
1384 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
1386 /* make up a number */
1387 time
= event_queue_time(psim_event_queue(cpu_system(processor
))) / 1000000;
1389 /* write the arguments back out */
1390 TRACE(trace_os_emul
, ("milliseconds - out - ms=%ld\n",
1391 (unsigned long)args
.ms
));
1392 chirp_write_h2t_args(&args
,
1402 static chirp_services services
[] = {
1404 /* client interface */
1405 { "test", chirp_emul_test
},
1408 { "peer", chirp_emul_peer
},
1409 { "child", chirp_emul_child
},
1410 { "parent", chirp_emul_parent
},
1411 { "instance-to-package", chirp_emul_instance_to_package
},
1412 { "getproplen", chirp_emul_getproplen
},
1413 { "getprop", chirp_emul_getprop
},
1414 { "nextprop", chirp_emul_nextprop
},
1415 /* { "setprop", chirp_emul_setprop }, */
1416 { "canon", chirp_emul_canon
},
1417 { "finddevice", chirp_emul_finddevice
},
1418 { "instance-to-path", chirp_emul_instance_to_path
},
1419 { "package-to-path", chirp_emul_package_to_path
},
1420 { "call-method", chirp_emul_call_method
},
1423 { "open", chirp_emul_open
},
1424 { "close", chirp_emul_close
},
1425 { "read", chirp_emul_read
},
1426 { "write", chirp_emul_write
},
1427 { "seek", chirp_emul_seek
},
1428 { "write", chirp_emul_write
},
1431 { "claim", chirp_emul_claim
},
1432 { "release", chirp_emul_release
},
1434 /* control transfer */
1435 { "boot", chirp_emul_boot
},
1436 { "enter", chirp_emul_enter
},
1437 { "exit", chirp_emul_exit
},
1438 { "chain", chirp_emul_chain
},
1440 /* user interface */
1441 { "interpret", chirp_emul_interpret
},
1442 { "set_callback", chirp_emul_set_callback
},
1443 { "set_symbol_lookup", chirp_emul_set_symbol_lookup
},
1446 { "milliseconds", chirp_emul_milliseconds
},
1448 { 0, /* sentinal */ },
1454 /* Any starting address greater than this is assumed to be an Chirp
1457 #ifndef CHIRP_START_ADDRESS
1458 #define CHIRP_START_ADDRESS 0x80000000
1460 #ifndef CHIRP_LOAD_BASE
1461 #define CHIRP_LOAD_BASE -1
1465 typedef struct _chirp_note_desc
{
1478 } note_found_status
;
1479 typedef struct _chirp_note
{
1480 chirp_note_desc desc
;
1481 note_found_status found
;
1484 typedef struct _chirp_note_head
{
1491 map_over_chirp_note(bfd
*image
,
1495 chirp_note
*note
= (chirp_note
*)obj
;
1496 if (strcmp(sect
->name
, ".note") == 0) {
1497 chirp_note_head head
;
1499 /* check the head */
1500 if (!bfd_get_section_contents(image
, sect
,
1501 &head
, 0, sizeof(head
)))
1503 head
.namesz
= bfd_get_32(image
, (void*)&head
.namesz
);
1504 head
.descsz
= bfd_get_32(image
, (void*)&head
.descsz
);
1505 head
.type
= bfd_get_32(image
, (void*)&head
.type
);
1506 if (head
.type
!= 0x1275)
1508 /* check the name field */
1509 if (head
.namesz
> sizeof(name
)) {
1510 error("chirp: note name too long (%d > %d)\n", (int)head
.namesz
, (int)sizeof(name
));
1512 if (!bfd_get_section_contents(image
, sect
,
1513 name
, sizeof(head
), head
.namesz
)) {
1514 error("chirp: note name unreadable\n");
1516 if (strcmp(name
, "PowerPC") != 0) {
1517 printf_filtered("chirp: note name (%s) not `PowerPC'\n", name
);
1519 /* check the size */
1520 if (head
.descsz
== sizeof(note
->desc
) - sizeof(int32_t)) {
1521 sim_io_printf_filtered("chirp: note descriptor missing load-base\n");
1523 else if (head
.descsz
!= sizeof(note
->desc
)) {
1524 sim_io_printf_filtered("chirp: note descriptor of wrong size\n");
1525 note
->found
= note_found
;
1528 note
->found
= note_correct
;
1529 /* get the contents */
1530 if (!bfd_get_section_contents(image
, sect
,
1531 ¬e
->desc
, /* page align start */
1532 ((sizeof(head
) + head
.namesz
) + 3) & ~3,
1534 error("chirp: note descriptor unreadable\n");
1536 note
->desc
.real_mode
= bfd_get_32(image
, (void*)¬e
->desc
.real_mode
);
1537 note
->desc
.real_base
= bfd_get_32(image
, (void*)¬e
->desc
.real_base
);
1538 note
->desc
.real_size
= bfd_get_32(image
, (void*)¬e
->desc
.real_size
);
1539 note
->desc
.virt_base
= bfd_get_32(image
, (void*)¬e
->desc
.virt_base
);
1540 note
->desc
.virt_size
= bfd_get_32(image
, (void*)¬e
->desc
.virt_size
);
1541 if (head
.descsz
== sizeof(note
->desc
))
1542 note
->desc
.load_base
= bfd_get_32(image
, (void*)¬e
->desc
.load_base
);
1544 note
->desc
.load_base
= (int32_t)-1;
1549 static os_emul_data
*
1550 emul_chirp_create(device
*root
,
1554 os_emul_data
*chirp
;
1559 /* Sanity check that this really is the chosen emulation */
1560 if (name
== NULL
&& image
== NULL
)
1563 && strcmp(name
, "ob") != 0
1564 && strcmp(name
, "ieee1274") != 0
1565 && strcmp(name
, "chrp") != 0
1566 && strcmp(name
, "chirp") != 0
1567 && strcmp(name
, "openboot") != 0)
1570 /* look for an elf note section, enter its values into the device tree */
1571 memset(¬e
, 0, sizeof(note
));
1573 bfd_map_over_sections(image
, map_over_chirp_note
, ¬e
);
1574 if (name
== NULL
&& image
!= NULL
&& note
.found
== note_missing
)
1577 /* Assume that it is a chirp emulation */
1579 chirp
= ZALLOC(os_emul_data
);
1581 chirp
->services
= services
;
1584 tree_parse(root
, "/name \"gpl,clayton");
1586 /* default options */
1587 emul_add_tree_options(root
, image
, "chirp", "oea",
1588 0 /*oea-interrupt-prefix*/);
1591 emul_add_tree_hardware(root
);
1593 /* basic information */
1595 = tree_find_integer_property(root
, "/openprom/options/oea-memory-size");
1596 chirp
->little_endian
1597 = tree_find_boolean_property(root
, "/options/little-endian?");
1598 chirp
->floating_point_available
1599 = tree_find_boolean_property(root
, "/openprom/options/floating-point?");
1600 chirp
->interrupt_prefix
=
1601 tree_find_integer_property(root
, "/openprom/options/oea-interrupt-prefix");
1604 /* Perform an interum layout of the openboot firmware in memory */
1607 /* a page for firmware calls */
1608 chirp
->sizeof_code
= 4096;
1609 chirp
->code_offset
= 0x4000; /* possible space for interrupt table */
1612 chirp
->sizeof_stack
= 32 * 1024;
1613 chirp
->stack_offset
= chirp
->code_offset
+ chirp
->sizeof_code
;
1615 /* the hash table */
1616 if (!note
.desc
.real_mode
) {
1617 chirp
->nr_page_table_entry_groups
= (chirp
->memory_size
< 0x800000
1618 ? 1024 /* min allowed */
1619 : (chirp
->memory_size
/ 4096 / 2));
1620 chirp
->sizeof_htab
= chirp
->nr_page_table_entry_groups
* 64;
1622 chirp
->htab_offset
= chirp
->stack_offset
+ chirp
->sizeof_stack
;
1624 /* the actual amount of space needed */
1625 chirp
->real_size
= chirp
->htab_offset
+ chirp
->sizeof_htab
;
1628 /* now go through and see if it fits in what is available */
1631 /* resolve real-mode? */
1632 if (note
.found
== note_correct
)
1633 chirp
->real_mode
= note
.desc
.real_mode
;
1634 else if (tree_find_property(root
, "/options/real-mode?") != NULL
)
1635 chirp
->real_mode
= tree_find_boolean_property(root
, "/options/real-mode?");
1637 chirp
->real_mode
= 0;
1638 if (tree_find_property(root
, "/options/real-mode?") != NULL
) {
1639 if (!chirp
->real_mode
1640 != !tree_find_boolean_property(root
, "/options/real-mode?"))
1641 error("chirp: /options/real-mode? conflicts with note section\n");
1644 tree_parse(root
, "/options/real-mode? %s",
1645 chirp
->real_mode
? "true" : "false");
1647 /* resolve real-base */
1648 if (note
.found
== note_correct
1649 && note
.desc
.real_base
!= (int32_t)-1)
1650 chirp
->real_base
= note
.desc
.real_base
;
1651 else if (tree_find_property(root
, "/options/real-base") != NULL
)
1652 chirp
->real_base
= tree_find_integer_property(root
, "/options/real-base");
1654 chirp
->real_base
= chirp
->memory_size
- chirp
->real_size
;
1655 if (tree_find_property(root
, "/options/real-base") != NULL
) {
1656 if (chirp
->real_base
!= tree_find_integer_property(root
, "/options/real-base"))
1657 error("chirp: /options/real-base conflicts with note section\n");
1660 tree_parse(root
, "/options/real-base 0x%lx",
1661 (unsigned long)chirp
->real_base
);
1663 /* resolve real-size */
1664 if (note
.found
== note_correct
1665 && note
.desc
.real_size
!= (int32_t)-1
1666 && note
.desc
.real_size
!= 0
1667 && chirp
->real_size
> note
.desc
.real_size
)
1668 error("chirp: insufficient physical memory for firmware\n");
1669 if (tree_find_property(root
, "/options/real-size") != NULL
) {
1670 if (chirp
->real_size
> tree_find_integer_property(root
, "/options/real-size"))
1671 error("chirp: /options/real-size conflicts with note section\n");
1674 tree_parse(root
, "/options/real-size 0x%lx",
1675 (unsigned long)chirp
->real_size
);
1677 /* resolve virt-base */
1678 if (chirp
->real_mode
)
1679 chirp
->virt_base
= chirp
->real_base
;
1680 else if (note
.found
== note_correct
&& note
.desc
.virt_base
!= -1)
1681 chirp
->virt_base
= note
.desc
.virt_base
;
1682 else if (tree_find_property(root
, "/options/virt-base") != NULL
)
1683 chirp
->virt_base
= tree_find_integer_property(root
, "/options/virt-base");
1685 chirp
->virt_base
= CHIRP_START_ADDRESS
;
1686 if (tree_find_property(root
, "/options/virt-base") != NULL
) {
1687 unsigned_word virt_base
= tree_find_integer_property(root
, "/options/virt-base");
1688 if (virt_base
!= -1 && chirp
->virt_base
!= virt_base
)
1689 error("chirp: /options/virt-base conflicts with note section\n");
1692 tree_parse(root
, "/options/virt-base 0x%lx",
1693 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_base
);
1695 /* resolve virt-size */
1696 chirp
->virt_size
= chirp
->real_size
;
1697 if (note
.found
== note_correct
1698 && note
.desc
.virt_size
!= (int32_t)-1
1699 && note
.desc
.virt_size
!= 0
1700 && !chirp
->real_mode
1701 && chirp
->virt_size
> note
.desc
.virt_size
)
1702 error("chirp: insufficent virtual memory for firmware\n");
1703 if (tree_find_property(root
, "/options/virt-size") != NULL
) {
1704 if (chirp
->virt_size
> tree_find_integer_property(root
, "/options/virt-size"))
1705 error("chirp: /options/virt-size conflicts with note section\n");
1708 tree_parse(root
, "/options/virt-size 0x%lx",
1709 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_size
);
1711 /* resolve load-base */
1712 if (note
.found
== note_correct
1713 && note
.desc
.load_base
!= (int32_t)-1)
1714 chirp
->load_base
= note
.desc
.load_base
;
1715 else if (tree_find_property(root
, "/options/load-base") != NULL
)
1716 chirp
->load_base
= tree_find_integer_property(root
, "/options/load-base");
1718 chirp
->load_base
= CHIRP_LOAD_BASE
;
1719 if (tree_find_property(root
, "/options/load-base") != NULL
) {
1720 if (chirp
->load_base
!= tree_find_integer_property(root
, "/options/load-base"))
1721 error("chirp: /options/load-base conflicts with note section\n");
1724 tree_parse(root
, "/options/load-base 0x%lx",
1725 (unsigned long)chirp
->load_base
);
1727 /* now adjust the preliminary firmware addresses to final values */
1728 chirp
->code_ra
= chirp
->code_offset
+ chirp
->real_base
;
1729 chirp
->stack_ra
= chirp
->stack_offset
+ chirp
->real_base
;
1730 chirp
->htab_ra
= chirp
->htab_offset
+ chirp
->real_base
;
1732 /* the virtual addresses. In real mode these are real addresses. */
1734 chirp
->code_va
= chirp
->code_offset
+ chirp
->virt_base
;
1735 chirp
->stack_va
= chirp
->stack_offset
+ chirp
->virt_base
;
1736 chirp
->htab_va
= chirp
->htab_offset
+ chirp
->virt_base
;
1738 chirp
->code_client_va
= chirp
->code_va
;
1739 chirp
->code_client_ra
= chirp
->code_ra
;
1741 chirp
->code_callback_va
= chirp
->code_client_va
+ 16;
1742 chirp
->code_callback_ra
= chirp
->code_client_ra
+ 16;
1744 chirp
->code_loop_va
= chirp
->code_callback_va
+ 16;
1745 chirp
->code_loop_ra
= chirp
->code_callback_ra
+ 16;
1747 /* initialization */
1749 tree_parse(root
, "/openprom/init");
1750 tree_parse(root
, "/openprom/init/register");
1751 tree_parse(root
, "/openprom/init/register/0.pc 0x%lx",
1752 (unsigned long)bfd_get_start_address(image
));
1753 tree_parse(root
, "/openprom/init/register/pc 0x%lx",
1754 (unsigned long)chirp
->code_loop_va
);
1755 tree_parse(root
, "/openprom/init/register/msr 0x%x",
1756 (msr_machine_check_enable
1759 : (msr_instruction_relocate
1760 | msr_data_relocate
))
1761 | (chirp
->little_endian
1762 ? (msr_little_endian_mode
1763 | msr_interrupt_little_endian_mode
)
1765 | (chirp
->floating_point_available
1766 ? msr_floating_point_available
1768 | (chirp
->interrupt_prefix
1769 ? msr_interrupt_prefix
1772 tree_parse(root
, "/openprom/init/register/sdr1 0x%lx",
1773 (unsigned long)(chirp
->htab_ra
1775 | ((chirp
->sizeof_htab
- 1) >> 16)));
1776 /* make certain that the segment registers map straight through */
1777 for (i
= 0; i
< 16; i
++) {
1778 tree_parse(root
, "/openprom/init/register/sr%d 0x%lx",
1779 i
, (unsigned long)i
);
1782 /* establish an initial state for all processors */
1785 /* the client interface address */
1786 tree_parse(root
, "/openprom/init/register/r5 0x%lx",
1787 (unsigned long)chirp
->code_client_va
);
1789 tree_parse(root
, "/openprom/init/register/sp 0x%lx",
1790 (unsigned long)(chirp
->stack_va
+ chirp
->sizeof_stack
- 16));
1791 /* in chrp mode any arguments end up being concatinated */
1792 tree_parse(root
, "/openprom/init/stack/stack-type chirp");
1795 /* client interface - emul-call followed by return instruction */
1798 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1799 (unsigned long)chirp
->code_client_ra
);
1800 tree_parse(node
, "./psim,description \"client-interface instruction");
1801 tree_parse(node
, "./real-address 0x%lx",
1802 (unsigned long)chirp
->code_client_ra
);
1803 tree_parse(node
, "./data 0x%lx",
1804 (unsigned long)emul_call_instruction
);
1806 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1807 (unsigned long)(chirp
->code_client_ra
+ 4));
1808 tree_parse(node
, "./psim,description \"client-interface return instruction");
1809 tree_parse(node
, "./real-address 0x%lx",
1810 (unsigned long)(chirp
->code_client_ra
+ 4));
1811 tree_parse(node
, "./data 0x%lx",
1812 (unsigned long)emul_blr_instruction
);
1815 /* return address for client callbacks - an emul-call instruction
1816 that is again followed by a return instruction */
1819 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1820 (unsigned long)chirp
->code_callback_ra
);
1821 tree_parse(node
, "./psim,description \"client-callback instruction");
1822 tree_parse(node
, "./real-address 0x%lx",
1823 (unsigned long)chirp
->code_callback_ra
);
1824 tree_parse(node
, "./data 0x%lx",
1825 (unsigned long)emul_call_instruction
);
1827 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1828 (unsigned long)(chirp
->code_callback_ra
+ 4));
1829 tree_parse(node
, "./psim,description \"client-callback return instruction");
1830 tree_parse(node
, "./real-address 0x%lx",
1831 (unsigned long)(chirp
->code_callback_ra
+ 4));
1832 tree_parse(node
, "./data 0x%lx",
1833 (unsigned long)emul_blr_instruction
);
1835 /* loop to keep other processors busy */
1837 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1838 (unsigned long)chirp
->code_loop_ra
);
1839 tree_parse(node
, "./psim,description \"processor busy loop");
1840 tree_parse(node
, "./real-address 0x%lx",
1841 (unsigned long)chirp
->code_loop_ra
);
1842 tree_parse(node
, "./data 0x%lx",
1843 (unsigned long)emul_loop_instruction
);
1847 /* create a hash table */
1849 if (!chirp
->real_mode
) {
1850 node
= tree_parse(root
, "/openprom/init/htab@0x%lx",
1851 (unsigned long)chirp
->htab_ra
);
1852 tree_parse(node
, "./claim 0");
1853 tree_parse(node
, "./real-address 0x%lx",
1854 (unsigned long)chirp
->htab_ra
);
1855 tree_parse(node
, "./nr-bytes 0x%lx",
1856 (unsigned long)chirp
->sizeof_htab
);
1859 /* map in the stack */
1861 if (!chirp
->real_mode
) {
1862 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1863 (unsigned long)chirp
->stack_ra
);
1864 tree_parse(node
, "./psim,description \"map in the stack");
1865 tree_parse(node
, "./claim 1");
1866 tree_parse(node
, "./virtual-address 0x%lx",
1867 (unsigned long)chirp
->stack_va
);
1868 tree_parse(node
, "./real-address 0x%lx",
1869 (unsigned long)chirp
->stack_ra
);
1870 tree_parse(node
, "./nr-bytes 0x%lx",
1871 (unsigned long)chirp
->sizeof_stack
);
1872 tree_parse(node
, "./wimg %d", 0x7);
1873 tree_parse(node
, "./pp %d", 0x2);
1876 /* map in the chrp openboot callback code */
1878 if (!chirp
->real_mode
) {
1879 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1880 (unsigned long)chirp
->code_ra
);
1881 tree_parse(node
, "./psim,description \"map in chrp openboot callback code");
1882 tree_parse(node
, "./claim 1");
1883 tree_parse(node
, "./virtual-address 0x%lx",
1884 (unsigned long)chirp
->code_va
);
1885 tree_parse(node
, "./real-address 0x%lx",
1886 (unsigned long)chirp
->code_ra
);
1887 tree_parse(node
, "./nr-bytes 0x%lx",
1888 (unsigned long)chirp
->sizeof_code
);
1889 tree_parse(node
, "./wimg %d", 0x7);
1890 tree_parse(node
, "./pp %d", 0x2);
1893 /* map in the program to run */
1895 if (chirp
->real_mode
) {
1896 node
= tree_parse(node
, "/openprom/init/load-binary");
1897 tree_parse(node
, "./psim,description \"load the binary");
1898 tree_parse(node
, "./file-name %s", bfd_get_filename(image
));
1899 tree_parse(node
, "./claim 1");
1902 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1903 (unsigned long)chirp
->load_base
);
1904 tree_parse(node
, "./psim,description \"load & map the binary");
1905 tree_parse(node
, "./claim 1");
1906 tree_parse(node
, "./file-name \"%s", bfd_get_filename(image
));
1907 tree_parse(node
, "./wimg %d", 0x7);
1908 tree_parse(node
, "./pp %d", 0x2);
1911 /* map in the interrupt vectors */
1913 if (!chirp
->real_mode
) {
1914 node
= tree_parse(root
, "/openprom/init/htab/pte@0x0");
1915 tree_parse(node
, "./psim,description \"map in interrupt vectors");
1916 tree_parse(node
, "./virtual-address 0x0");
1917 tree_parse(node
, "./real-address 0x0");
1918 tree_parse(node
, "./nr-bytes 0x3000");
1919 tree_parse(node
, "./wimg %d", 0x7);
1920 tree_parse(node
, "./pp %d", 0x2);
1927 emul_chirp_init(os_emul_data
*emul_data
,
1930 emul_data
->state
= serving
;
1934 emul_chirp_instruction_call(cpu
*processor
,
1937 os_emul_data
*emul_data
)
1939 unsigned_word service_name_addr
;
1940 unsigned_word result
;
1941 char service_buf
[32];
1943 chirp_services
*service
;
1945 switch (emul_data
->state
) {
1948 /* we are waiting on an OpenBoot request from the client program
1949 via the client interface */
1950 if (cia
!= emul_data
->code_client_va
)
1952 emul_data
->return_address
= LR
;
1953 emul_data
->arguments
= cpu_registers(processor
)->gpr
[3];
1954 /* try to determine what to do */
1955 service_name_addr
= emul_read_word(cpu_registers(processor
)->gpr
[3],
1957 service_name
= emul_read_string(service_buf
, service_name_addr
,
1958 sizeof(service_buf
), processor
, cia
);
1959 emul_data
->n_args
= emul_read_word(emul_data
->arguments
+ sizeof(unsigned_cell
),
1961 emul_data
->n_returns
= emul_read_word(emul_data
->arguments
+ 2 * sizeof(unsigned_cell
),
1963 /* verify what was passed */
1964 if (service_name_addr
== 0
1965 || service_name
== NULL
) {
1966 error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n",
1967 (unsigned long)emul_data
->return_address
,
1968 (unsigned long)emul_data
->arguments
);
1970 if (emul_data
->n_args
> 6) { /* See iee1275 requirements on nr returns */
1971 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n",
1973 (unsigned long)emul_data
->return_address
,
1974 (unsigned long)emul_data
->arguments
,
1975 emul_data
->n_returns
);
1977 if (emul_data
->n_returns
> 6) {
1978 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, with too many returns (%d)\n",
1980 (unsigned long)emul_data
->return_address
,
1981 (unsigned long)emul_data
->arguments
,
1985 TRACE(trace_os_emul
, ("%s called from 0x%lx with args 0x%lx\n",
1987 (unsigned long)emul_data
->return_address
,
1988 (unsigned long)emul_data
->arguments
));
1990 while (service
->name
!= NULL
&& strcmp(service
->name
, service_name
) != 0)
1993 if (service
->name
== NULL
) {
1994 error("OpenBoot service `%s' not found\n", service_name
);
1995 TRACE(trace_os_emul
, ("%s not found\n", service_name
));
1996 cpu_registers(processor
)->gpr
[3] = -1;
1999 emul_data
->service
= service
;
2001 result
= service
->handler(emul_data
, processor
, cia
);
2003 TRACE(trace_os_emul
, ("%s aborted with %ld\n", service_name
, (long)result
));
2004 cpu_registers(processor
)->gpr
[3] = result
;
2009 error("emul_chirp_instruction_call() unknown internal state\n");
2015 /* return to caller - instruction following this is a function return */
2019 const os_emul emul_chirp
= {
2023 NULL
, /*system_call*/
2024 emul_chirp_instruction_call
,