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"
42 #ifndef STATIC_INLINE_EMUL_CHIRP
43 #define STATIC_INLINE_EMUL_CHIRP STATIC_INLINE
50 OpenFirmware - IEEE Standard for Boot (Initialization
51 Configuration) Firmware.
60 This code assumes that the memory node has #address-cells and
61 #size-cells set to one. For future implementations, this may not
69 /* Descriptor of the open boot services being emulated */
71 typedef int (chirp_handler
)
76 typedef struct _chirp_services
{
78 chirp_handler
*handler
;
82 /* The OpenBoot emulation is, at any time either waiting for a client
83 request or waiting on a client callback */
90 struct _os_emul_data
{
91 chirp_emul_state state
;
92 unsigned_word return_address
;
93 unsigned_word arguments
;
95 unsigned_word n_returns
;
96 chirp_services
*service
;
98 chirp_services
*services
;
100 unsigned_word memory_size
;
101 unsigned_word real_base
;
102 unsigned_word real_size
;
103 unsigned_word virt_base
;
104 unsigned_word virt_size
;
107 int floating_point_available
;
108 int interrupt_prefix
;
109 unsigned_word load_base
;
111 unsigned_word nr_page_table_entry_groups
;
112 unsigned_word htab_offset
;
113 unsigned_word htab_ra
;
114 unsigned_word htab_va
;
115 unsigned_word sizeof_htab
;
116 /* virtual address of htab */
117 unsigned_word stack_offset
;
118 unsigned_word stack_ra
;
119 unsigned_word stack_va
;
120 unsigned_word sizeof_stack
;
121 /* addresses of emulation instructions virtual/real */
122 unsigned_word code_offset
;
123 unsigned_word code_va
;
124 unsigned_word code_ra
;
125 unsigned_word sizeof_code
;
126 unsigned_word code_client_va
;
127 unsigned_word code_client_ra
;
128 unsigned_word code_callback_va
;
129 unsigned_word code_callback_ra
;
130 unsigned_word code_loop_va
;
131 unsigned_word code_loop_ra
;
135 /* returns the name of the corresponding Ihandle */
137 ihandle_name(device_instance
*ihandle
)
142 return device_name(device_instance_device(ihandle
));
147 /* Read/write the argument list making certain that all values are
148 converted to/from host byte order.
150 In the below only n_args+n_returns is read/written */
153 chirp_read_t2h_args(void *args
,
161 unsigned_cell
*words
;
163 /* check against the number of arguments specified by the client
165 if ((n_args
>= 0 && data
->n_args
!= n_args
)
166 || (n_returns
>= 0 && data
->n_returns
!= n_returns
)) {
167 TRACE(trace_os_emul
, ("%s - invalid nr of args - n_args=%ld, n_returns=%ld\n",
170 (long)data
->n_returns
));
173 /* check that there is enough space */
174 if (sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
) > sizeof_args
)
176 /* bring in the data */
177 memset(args
, 0, sizeof_args
);
178 emul_read_buffer(args
, data
->arguments
+ 3 * sizeof(unsigned_cell
),
179 sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
),
181 /* convert all words to host format */
183 for (i
= 0; i
< (sizeof_args
/ sizeof(unsigned_cell
)); i
++)
184 words
[i
] = T2H_cell(words
[i
]);
189 chirp_write_h2t_args(void *args
,
196 unsigned_cell
*words
;
197 /* convert to target everything */
199 for (i
= 0; i
< (sizeof_args
/ sizeof(unsigned_cell
)); i
++)
200 words
[i
] = H2T_cell(words
[i
]);
201 /* bring in the data */
202 emul_write_buffer(args
, data
->arguments
+ 3 * sizeof(unsigned_cell
),
203 sizeof(unsigned_cell
) * (data
->n_args
+ data
->n_returns
),
208 /* OpenBoot emulation functions */
210 /* client interface */
213 chirp_emul_test(os_emul_data
*data
,
219 unsigned_cell name
; /*string*/
221 unsigned_cell missing
;
224 chirp_services
*service
= NULL
;
225 /* read in the arguments */
226 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
228 emul_read_string(name
, args
.name
, sizeof(name
),
230 TRACE(trace_os_emul
, ("test - in - name=`%s'\n", name
));
231 /* see if we know about the service */
232 service
= data
->services
;
233 while (service
->name
!= NULL
&& strcmp(service
->name
, name
) != 0) {
236 if (service
->name
== NULL
)
240 /* write the arguments back out */
241 TRACE(trace_os_emul
, ("test - out - missing=%ld\n",
242 (long)args
.missing
));
243 chirp_write_h2t_args(&args
,
254 chirp_emul_peer(os_emul_data
*data
,
260 unsigned_cell phandle
;
262 unsigned_cell sibling_phandle
;
265 device
*sibling_phandle
= NULL
;
266 /* read in the arguments */
267 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
269 phandle
= external_to_device(data
->root
, args
.phandle
);
270 TRACE(trace_os_emul
, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
271 (unsigned long)args
.phandle
,
272 (unsigned long)phandle
,
273 (phandle
== NULL
? "" : device_name(phandle
))));
275 if (args
.phandle
== 0) {
276 sibling_phandle
= data
->root
;
277 args
.sibling_phandle
= device_to_external(sibling_phandle
);
279 else if (phandle
== NULL
) {
280 sibling_phandle
= NULL
;
281 args
.sibling_phandle
= -1;
284 sibling_phandle
= device_sibling(phandle
);
285 if (sibling_phandle
== NULL
)
286 args
.sibling_phandle
= 0;
288 args
.sibling_phandle
= device_to_external(sibling_phandle
);
290 /* write the arguments back out */
291 TRACE(trace_os_emul
, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
292 (unsigned long)args
.sibling_phandle
,
293 (unsigned long)sibling_phandle
,
294 (sibling_phandle
== NULL
? "" : device_name(sibling_phandle
))));
295 chirp_write_h2t_args(&args
,
303 chirp_emul_child(os_emul_data
*data
,
309 unsigned_cell phandle
;
311 unsigned_cell child_phandle
;
314 device
*child_phandle
;
315 /* read the arguments in */
316 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
318 phandle
= external_to_device(data
->root
, args
.phandle
);
319 TRACE(trace_os_emul
, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
320 (unsigned long)args
.phandle
,
321 (unsigned long)phandle
,
322 (phandle
== NULL
? "" : device_name(phandle
))));
324 if (args
.phandle
== 0
325 || phandle
== NULL
) {
326 child_phandle
= NULL
;
327 args
.child_phandle
= -1;
330 child_phandle
= device_child(phandle
);
331 if (child_phandle
== NULL
)
332 args
.child_phandle
= 0;
334 args
.child_phandle
= device_to_external(child_phandle
);
336 /* write the result out */
337 TRACE(trace_os_emul
, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
338 (unsigned long)args
.child_phandle
,
339 (unsigned long)child_phandle
,
340 (child_phandle
== NULL
? "" : device_name(child_phandle
))));
341 chirp_write_h2t_args(&args
,
349 chirp_emul_parent(os_emul_data
*data
,
355 unsigned_cell phandle
;
357 unsigned_cell parent_phandle
;
360 device
*parent_phandle
;
361 /* read the args in */
362 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
364 phandle
= external_to_device(data
->root
, args
.phandle
);
365 TRACE(trace_os_emul
, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
366 (unsigned long)args
.phandle
,
367 (unsigned long)phandle
,
368 (phandle
== NULL
? "" : device_name(phandle
))));
370 if (args
.phandle
== 0
371 || phandle
== NULL
) {
372 parent_phandle
= NULL
;
373 args
.parent_phandle
= -1;
376 parent_phandle
= device_parent(phandle
);
377 if (parent_phandle
== NULL
)
378 args
.parent_phandle
= 0;
380 args
.parent_phandle
= device_to_external(parent_phandle
);
382 /* return the result */
383 TRACE(trace_os_emul
, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
384 (unsigned long)args
.parent_phandle
,
385 (unsigned long)parent_phandle
,
386 (parent_phandle
== NULL
? "" : device_name(parent_phandle
))));
387 chirp_write_h2t_args(&args
,
395 chirp_emul_instance_to_package(os_emul_data
*data
,
399 struct instance_to_package_args
{
401 unsigned_cell ihandle
;
403 unsigned_cell phandle
;
405 device_instance
*ihandle
;
406 device
*phandle
= NULL
;
407 /* read the args in */
408 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
410 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
411 TRACE(trace_os_emul
, ("instance-to-package - in - ihandle=0x%lx(0x%lx`%s')\n",
412 (unsigned long)args
.ihandle
,
413 (unsigned long)ihandle
,
414 ihandle_name(ihandle
)));
415 /* find the corresponding phandle */
416 if (ihandle
== NULL
) {
421 phandle
= device_instance_device(ihandle
);
422 args
.phandle
= device_to_external(phandle
);
424 /* return the result */
425 TRACE(trace_os_emul
, ("instance-to-package - out - phandle=0x%lx(0x%lx`%s')\n",
426 (unsigned long)args
.phandle
,
427 (unsigned long)phandle
,
428 (phandle
== NULL
? "" : device_name(phandle
))));
429 chirp_write_h2t_args(&args
,
437 chirp_emul_getproplen(os_emul_data
*data
,
441 struct getproplen_args
{
443 unsigned_cell phandle
;
446 unsigned_cell proplen
;
450 /* read the args in */
451 if (chirp_read_t2h_args(&args
, sizeof(args
), 2, 1, data
, processor
, cia
))
453 phandle
= external_to_device(data
->root
, args
.phandle
);
454 emul_read_string(name
,
458 TRACE(trace_os_emul
, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
459 (unsigned long)args
.phandle
,
460 (unsigned long)phandle
,
461 (phandle
== NULL
? "" : device_name(phandle
)),
463 /* find our prop and get its length */
464 if (args
.phandle
== 0
465 || phandle
== NULL
) {
469 const device_property
*prop
= device_find_property(phandle
, name
);
470 if (prop
== (device_property
*)0) {
474 args
.proplen
= prop
->sizeof_array
;
477 /* return the result */
478 TRACE(trace_os_emul
, ("getproplen - out - proplen=%ld\n",
479 (unsigned long)args
.proplen
));
480 chirp_write_h2t_args(&args
,
488 chirp_emul_getprop(os_emul_data
*data
,
492 struct getprop_args
{
494 unsigned_cell phandle
;
497 unsigned_cell buflen
;
503 /* read in the args, the return is optional */
504 if (chirp_read_t2h_args(&args
, sizeof(args
), 4, -1, data
, processor
, cia
))
506 phandle
= external_to_device(data
->root
, args
.phandle
);
507 emul_read_string(name
,
511 TRACE(trace_os_emul
, ("getprop - in - phandle=0x%lx(0x%lx`%s') name=`%s' buf=0x%lx buflen=%ld\n",
512 (unsigned long)args
.phandle
,
513 (unsigned long)phandle
,
514 (phandle
== NULL
? "" : device_name(phandle
)),
516 (unsigned long)args
.buf
,
517 (unsigned long)args
.buflen
));
518 /* get the property */
519 if (args
.phandle
== 0
520 || phandle
== NULL
) {
524 const device_property
*prop
= device_find_property(phandle
, name
);
529 int size
= args
.buflen
;
530 if (size
> prop
->sizeof_array
)
531 size
= prop
->sizeof_array
;
532 emul_write_buffer(prop
->array
, args
.buf
,
536 switch (prop
->type
) {
537 case string_property
:
538 TRACE(trace_os_emul
, ("getprop - string `%s'\n",
539 device_find_string_property(phandle
, name
)));
541 case ihandle_property
:
542 TRACE(trace_os_emul
, ("getprop - ihandle=0x%lx(0x%lx`%s')\n",
543 BE2H_cell(*(unsigned_cell
*)prop
->array
),
544 (unsigned long)device_find_ihandle_property(phandle
, name
),
545 ihandle_name(device_find_ihandle_property(phandle
, name
))));
552 /* write back the result */
553 if (data
->n_returns
== 0)
554 TRACE(trace_os_emul
, ("getprop - out - size=%ld (not returned)\n",
555 (unsigned long)args
.size
));
557 TRACE(trace_os_emul
, ("getprop - out - size=%ld\n",
558 (unsigned long)args
.size
));
559 chirp_write_h2t_args(&args
,
568 chirp_emul_nextprop(os_emul_data
*data
,
572 struct nextprop_args
{
574 unsigned_cell phandle
;
575 unsigned_cell previous
;
582 /* read in the args */
583 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
585 phandle
= external_to_device(data
->root
, args
.phandle
);
586 if (args
.previous
!= 0)
587 emul_read_string(previous
,
592 /* If previous is NULL, make it look like the empty string. The
593 next property after the empty string is the first property. */
594 strcpy (previous
, "");
595 TRACE(trace_os_emul
, ("nextprop - in - phandle=0x%lx(0x%lx`%s') previous=`%s' buf=0x%lx\n",
596 (unsigned long)args
.phandle
,
597 (unsigned long)phandle
,
598 (phandle
== NULL
? "" : device_name(phandle
)),
600 (unsigned long)args
.buf
));
601 /* find the next property */
602 if (args
.phandle
== 0
603 || phandle
== NULL
) {
607 const device_property
*prev_prop
= device_find_property(phandle
, previous
);
608 if (prev_prop
== NULL
) {
609 if (strcmp (previous
, "") == 0)
610 args
.flag
= 0; /* No properties */
612 args
.flag
= -1; /* name invalid */
615 const device_property
*next_prop
;
616 if (strcmp (previous
, "") == 0) {
617 next_prop
= prev_prop
; /* The first property. */
620 next_prop
= device_next_property(prev_prop
);
622 if (next_prop
== NULL
) {
623 args
.flag
= 0; /* last property */
626 emul_write_buffer(next_prop
->name
, args
.buf
, strlen(next_prop
->name
),
628 TRACE(trace_os_emul
, ("nextprop - name=`%s'\n", next_prop
->name
));
629 args
.flag
= 1; /* worked ok */
633 /* write back the result */
634 TRACE(trace_os_emul
, ("nextprop - out - flag=%ld\n",
635 (unsigned long)args
.flag
));
636 chirp_write_h2t_args(&args
,
645 chirp_emul_setprop(os_emul_data
*data
,
649 error("chirp: setprop method not implemented\n");
655 chirp_emul_canon(os_emul_data
*data
,
661 unsigned_cell device_specifier
;
663 unsigned_cell buflen
;
665 unsigned_cell length
;
667 char device_specifier
[1024];
671 /* read in the args */
672 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
674 emul_read_string(device_specifier
,
675 args
.device_specifier
,
676 sizeof(device_specifier
),
678 TRACE(trace_os_emul
, ("canon - in - device_specifier=`%s' buf=0x%lx buflen=%lx\n",
680 (unsigned long)args
.buf
,
681 (unsigned long)args
.buflen
));
683 phandle
= tree_find_device(data
->root
, device_specifier
);
684 if (phandle
== NULL
) {
690 path
= device_path(phandle
);
691 length
= strlen(path
);
692 if (length
>= args
.buflen
)
693 length
= args
.buflen
- 1;
694 emul_write_buffer(path
, args
.buf
, length
,
696 args
.length
= length
;
698 /* write back the result */
699 TRACE(trace_os_emul
, ("canon - out - length=%ld buf=`%s'\n",
700 (unsigned long)args
.length
,
702 chirp_write_h2t_args(&args
,
710 chirp_emul_finddevice(os_emul_data
*data
,
714 struct finddevice_args
{
716 unsigned_cell device_specifier
;
718 unsigned_cell phandle
;
720 char device_specifier
[1024];
723 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
725 emul_read_string(device_specifier
,
726 args
.device_specifier
,
727 sizeof(device_specifier
),
729 TRACE(trace_os_emul
, ("finddevice - in - device_specifier=`%s'\n",
731 /* find the device */
732 phandle
= tree_find_device(data
->root
, device_specifier
);
736 args
.phandle
= device_to_external(phandle
);
737 /* return its phandle */
738 TRACE(trace_os_emul
, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
739 (unsigned long)args
.phandle
,
740 (unsigned long)phandle
,
741 (phandle
== NULL
? "" : device_name(phandle
))));
742 chirp_write_h2t_args(&args
,
750 chirp_emul_instance_to_path(os_emul_data
*data
,
754 struct instance_to_path_args
{
756 unsigned_cell ihandle
;
758 unsigned_cell buflen
;
760 unsigned_cell length
;
762 device_instance
*ihandle
;
766 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
768 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
769 TRACE(trace_os_emul
, ("instance-to-path - in - ihandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
770 (unsigned long)args
.ihandle
,
771 (unsigned long)ihandle
,
772 ihandle_name(ihandle
),
773 (unsigned long)args
.buf
,
774 (unsigned long)args
.buflen
));
775 /* get the devices name */
776 if (ihandle
== NULL
) {
781 path
= device_instance_path(ihandle
);
782 length
= strlen(path
);
783 if (length
>= args
.buflen
)
784 length
= args
.buflen
- 1;
785 emul_write_buffer(path
, args
.buf
, length
,
787 args
.length
= length
;
789 /* return its phandle */
790 TRACE(trace_os_emul
, ("instance-to-path - out - length=%ld buf=`%s')\n",
791 (unsigned long)args
.length
,
793 chirp_write_h2t_args(&args
,
801 chirp_emul_package_to_path(os_emul_data
*data
,
805 struct package_to_path_args
{
807 unsigned_cell phandle
;
809 unsigned_cell buflen
;
811 unsigned_cell length
;
816 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
818 phandle
= external_to_device(data
->root
, args
.phandle
);
819 TRACE(trace_os_emul
, ("package-to-path - in - phandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
820 (unsigned long)args
.phandle
,
821 (unsigned long)phandle
,
822 (phandle
== NULL
? "" : device_name(phandle
)),
823 (unsigned long)args
.buf
,
824 (unsigned long)args
.buflen
));
825 /* get the devices name */
826 if (phandle
== NULL
) {
832 path
= device_path(phandle
);
833 length
= strlen(path
);
834 if (length
>= args
.buflen
)
835 length
= args
.buflen
- 1;
836 emul_write_buffer(path
, args
.buf
, length
,
838 args
.length
= length
;
840 /* return its phandle */
841 TRACE(trace_os_emul
, ("package-to-path - out - length=%ld buf=`%s')\n",
842 (unsigned long)args
.length
,
844 chirp_write_h2t_args(&args
,
852 chirp_emul_call_method(os_emul_data
*data
,
856 struct call_method_args
{
858 unsigned_cell method
;
859 unsigned_cell ihandle
;
861 unsigned_cell stack
[13]; /*6in + 6out + catch */
864 device_instance
*ihandle
;
865 /* some useful info about our mini stack */
868 int stack_catch_result
;
871 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, -1, data
, processor
, cia
))
873 emul_read_string(method
,
877 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
878 n_stack_args
= data
->n_args
- 2;
879 n_stack_returns
= data
->n_returns
- 1;
880 stack_catch_result
= n_stack_args
;
881 stack_returns
= stack_catch_result
+ 1;
882 TRACE(trace_os_emul
, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(0x%lx`%s')\n",
883 (unsigned long)data
->n_args
,
884 (unsigned long)data
->n_returns
,
886 (unsigned long)args
.ihandle
,
887 (unsigned long)ihandle
,
888 ihandle_name(ihandle
)));
889 /* see if we can emulate this method */
890 if (ihandle
== NULL
) {
891 /* OpenFirmware doesn't define this error */
892 error("chirp: invalid ihandle passed to call-method method");
895 args
.stack
[stack_catch_result
] =
896 device_instance_call_method(ihandle
,
901 &args
.stack
[stack_returns
]);
904 TRACE(trace_os_emul
, ("call-method - out - catch-result=%ld\n",
905 (unsigned long)args
.stack
[stack_catch_result
]));
906 chirp_write_h2t_args(&args
,
917 chirp_emul_open(os_emul_data
*data
,
923 unsigned_cell device_specifier
;
925 unsigned_cell ihandle
;
927 char device_specifier
[1024];
928 device_instance
*ihandle
;
930 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
932 emul_read_string(device_specifier
,
933 args
.device_specifier
,
934 sizeof(device_specifier
),
936 TRACE(trace_os_emul
, ("open - in - device_specifier=`%s'\n",
938 /* open the device */
939 ihandle
= tree_instance(data
->root
, device_specifier
);
943 args
.ihandle
= device_instance_to_external(ihandle
);
944 /* return the ihandle result */
945 TRACE(trace_os_emul
, ("open - out - ihandle=0x%lx(0x%lx`%s')\n",
946 (unsigned long)args
.ihandle
,
947 (unsigned long)ihandle
,
948 ihandle_name(ihandle
)));
949 chirp_write_h2t_args(&args
,
957 chirp_emul_close(os_emul_data
*data
,
963 unsigned_cell ihandle
;
966 device_instance
*ihandle
;
968 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 0, data
, processor
, cia
))
970 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
971 TRACE(trace_os_emul
, ("close - in - ihandle=0x%lx(0x%lx`%s')\n",
972 (unsigned long)args
.ihandle
,
973 (unsigned long)ihandle
,
974 ihandle_name(ihandle
)));
975 /* close the device */
976 if (ihandle
== NULL
) {
977 /* OpenFirmware doesn't define this error */
978 error("chirp: invalid ihandle passed to close method");
981 device_instance_delete(ihandle
);
983 /* return the ihandle result */
984 TRACE(trace_os_emul
, ("close - out\n"));
985 chirp_write_h2t_args(&args
,
993 chirp_emul_read(os_emul_data
*data
,
999 unsigned_cell ihandle
;
1003 unsigned_cell actual
;
1006 device_instance
*ihandle
;
1008 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1010 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1011 TRACE(trace_os_emul
, ("read - in - ihandle=0x%lx(0x%lx`%s') addr=0x%lx len=%ld\n",
1012 (unsigned long)args
.ihandle
,
1013 (unsigned long)ihandle
,
1014 ihandle_name(ihandle
),
1015 (unsigned long)args
.addr
,
1016 (unsigned long)args
.len
));
1017 if (ihandle
== NULL
) {
1018 /* OpenFirmware doesn't define this error */
1019 error("chirp: invalid ihandle passed to read method");
1024 while (actual
< args
.len
) {
1025 int remaining
= args
.len
- actual
;
1026 int to_read
= (remaining
<= sizeof(buf
) ? remaining
: sizeof(buf
));
1027 int nr_read
= device_instance_read(ihandle
, buf
, to_read
);
1029 actual
= nr_read
; /* the error */
1032 else if (nr_read
== 0) {
1035 emul_write_buffer(buf
,
1042 args
.actual
= actual
;
1043 if (actual
< sizeof(buf
))
1046 buf
[sizeof(buf
) - 1] = '\0';
1053 case sim_io_not_ready
:
1054 ASSERT(sim_io_not_ready
== -2);
1055 args
.actual
= sim_io_not_ready
;
1058 error("Bad error value %ld", (long)actual
);
1063 /* return the result */
1064 TRACE(trace_os_emul
, ("read - out - actual=%ld `%s'\n",
1066 ((args
.actual
> 0 && args
.actual
< sizeof(buf
)) ? buf
: "")
1068 chirp_write_h2t_args(&args
,
1076 chirp_emul_write(os_emul_data
*data
,
1082 unsigned_cell ihandle
;
1086 unsigned_cell actual
;
1089 device_instance
*ihandle
;
1092 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1095 if (actual
>= sizeof(buf
))
1096 actual
= sizeof(buf
) - 1;
1097 emul_read_buffer(buf
,
1102 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1103 TRACE(trace_os_emul
, ("write - in - ihandle=0x%lx(0x%lx`%s') `%s' (%ld)\n",
1104 (unsigned long)args
.ihandle
,
1105 (unsigned long)ihandle
,
1106 ihandle_name(ihandle
),
1107 buf
, (long)actual
));
1108 if (ihandle
== NULL
) {
1109 /* OpenFirmware doesn't define this error */
1110 error("chirp: invalid ihandle passed to write method");
1114 actual
= device_instance_write(ihandle
, buf
, actual
);
1118 args
.actual
= actual
;
1120 /* return the result */
1121 TRACE(trace_os_emul
, ("write - out - actual=%ld\n",
1122 (long)args
.actual
));
1123 chirp_write_h2t_args(&args
,
1131 chirp_emul_seek(os_emul_data
*data
,
1137 unsigned_cell ihandle
;
1138 unsigned_cell pos_hi
;
1139 unsigned_cell pos_lo
;
1141 unsigned_cell status
;
1144 device_instance
*ihandle
;
1146 if (chirp_read_t2h_args(&args
, sizeof(args
), 3, 1, data
, processor
, cia
))
1148 ihandle
= external_to_device_instance(data
->root
, args
.ihandle
);
1149 TRACE(trace_os_emul
, ("seek - in - ihandle=0x%lx(0x%lx`%s') pos.hi=0x%lx pos.lo=0x%lx\n",
1150 (unsigned long)args
.ihandle
,
1151 (unsigned long)ihandle
,
1152 ihandle_name(ihandle
),
1153 args
.pos_hi
, args
.pos_lo
));
1154 if (ihandle
== NULL
) {
1155 /* OpenFirmware doesn't define this error */
1156 error("chirp: invalid ihandle passed to seek method");
1160 status
= device_instance_seek(ihandle
, args
.pos_hi
, args
.pos_lo
);
1161 args
.status
= status
;
1163 /* return the result */
1164 TRACE(trace_os_emul
, ("seek - out - status=%ld\n",
1165 (long)args
.status
));
1166 chirp_write_h2t_args(&args
,
1177 chirp_emul_claim(os_emul_data
*data
,
1181 /* NOTE: the client interface claim routine is *very* different to
1182 the "claim" method described in IEEE-1275 appendix A. The latter
1183 uses real addresses while this uses virtual (effective)
1189 unsigned_cell align
;
1191 unsigned_cell baseaddr
;
1194 if (chirp_read_t2h_args(&args
, sizeof(args
),
1195 3 /*n_args*/, 1 /*n_returns*/,
1196 data
, processor
, cia
))
1198 TRACE(trace_os_emul
, ("claim - in - virt=0x%lx size=%ld align=%d\n",
1199 (unsigned long)args
.virt
,
1200 (long int)args
.size
,
1202 /* use the memory device to allocate (real) memory at the requested
1205 device_instance
*memory
= tree_find_ihandle_property(data
->root
, "/chosen/memory");
1206 unsigned_cell mem_in
[3];
1207 unsigned_cell mem_out
[1];
1208 mem_in
[0] = args
.align
; /*top-of-stack*/
1209 mem_in
[1] = args
.size
;
1210 mem_in
[2] = args
.virt
;
1211 if (device_instance_call_method(memory
, "claim",
1212 3, mem_in
, 1, mem_out
) < 0)
1213 error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d",
1214 (unsigned long)args
.virt
,
1215 (long int)args
.size
,
1217 args
.baseaddr
= mem_out
[0];
1219 /* if using virtual addresses, create a 1-1 map of this address space */
1220 if (!data
->real_mode
) {
1221 error("chirp: claim method does not support virtual mode");
1223 /* return the base address */
1224 TRACE(trace_os_emul
, ("claim - out - baseaddr=0x%lx\n",
1225 (unsigned long)args
.baseaddr
));
1226 chirp_write_h2t_args(&args
,
1234 chirp_emul_release(os_emul_data
*data
,
1238 /* NOTE: the client interface release routine is *very* different to
1239 the "claim" method described in IEEE-1275 appendix A. The latter
1240 uses real addresses while this uses virtual (effective)
1249 if (chirp_read_t2h_args(&args
, sizeof(args
),
1250 2 /*n_args*/, 0 /*n_returns*/,
1251 data
, processor
, cia
))
1253 TRACE(trace_os_emul
, ("release - in - virt=0x%lx size=%ld\n",
1254 (unsigned long)args
.virt
,
1255 (long int)args
.size
));
1256 /* use the memory device to release (real) memory at the requested
1259 device_instance
*memory
= tree_find_ihandle_property(data
->root
, "/chosen/memory");
1260 unsigned_cell mem_in
[2];
1261 mem_in
[0] = args
.size
;
1262 mem_in
[1] = args
.virt
;
1263 if (device_instance_call_method(memory
, "release",
1264 2, mem_in
, 0, NULL
) < 0)
1265 error("chirp: claim failed to release memory virt=0x%lx size=%ld",
1266 (unsigned long)args
.virt
,
1267 (long int)args
.size
);
1269 /* if using virtual addresses, remove the 1-1 map of this address space */
1270 if (!data
->real_mode
) {
1271 error("chirp: release method does not support virtual mode");
1273 /* return the base address */
1274 TRACE(trace_os_emul
, ("release - out\n"));
1275 chirp_write_h2t_args(&args
,
1283 /* Control transfer */
1286 chirp_emul_boot(os_emul_data
*data
,
1290 /* unlike OpenFirmware this one can take an argument */
1293 unsigned_cell bootspec
;
1296 char bootspec
[1024];
1297 /* read in the arguments */
1298 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, 0, data
, processor
, cia
))
1299 cpu_halt(processor
, cia
, was_exited
, -1);
1300 if (args
.bootspec
!= 0)
1301 emul_read_string(bootspec
, args
.bootspec
, sizeof(bootspec
),
1304 strcpy(bootspec
, "(null)");
1305 TRACE(trace_os_emul
, ("boot - in bootspec=`%s'\n", bootspec
));
1306 /* just report this and exit */
1307 printf_filtered("chrp: boot %s called, exiting.\n", bootspec
);
1308 cpu_halt(processor
, cia
, was_exited
, 0);
1313 chirp_emul_enter(os_emul_data
*data
,
1317 error("chirp: enter method not implemented\n");
1322 chirp_emul_exit(os_emul_data
*data
,
1326 /* unlike OpenBoot this one can take an argument */
1332 if (chirp_read_t2h_args(&args
, sizeof(args
), -1, 0, data
, processor
, cia
))
1333 cpu_halt(processor
, cia
, was_exited
, -1);
1334 cpu_halt(processor
, cia
, was_exited
, args
.status
);
1339 chirp_emul_chain(os_emul_data
*data
,
1343 error("chirp: chain method not implemented\n");
1348 /* user interface */
1351 chirp_emul_interpret(os_emul_data
*data
,
1355 error("chirp: interpret method not implemented\n");
1360 chirp_emul_set_callback(os_emul_data
*data
,
1364 error("chirp: set_callback method not implemented\n");
1369 chirp_emul_set_symbol_lookup(os_emul_data
*data
,
1373 error("chirp: set_symbol_lookup method not implemented\n");
1381 chirp_emul_milliseconds(os_emul_data
*data
,
1391 /* read in the arguments */
1392 if (chirp_read_t2h_args(&args
, sizeof(args
), 1, 1, data
, processor
, cia
))
1394 /* make up a number */
1395 time
= event_queue_time(psim_event_queue(cpu_system(processor
))) / 1000000;
1397 /* write the arguments back out */
1398 TRACE(trace_os_emul
, ("milliseconds - out - ms=%ld\n",
1399 (unsigned long)args
.ms
));
1400 chirp_write_h2t_args(&args
,
1410 static chirp_services services
[] = {
1412 /* client interface */
1413 { "test", chirp_emul_test
},
1416 { "peer", chirp_emul_peer
},
1417 { "child", chirp_emul_child
},
1418 { "parent", chirp_emul_parent
},
1419 { "instance-to-package", chirp_emul_instance_to_package
},
1420 { "getproplen", chirp_emul_getproplen
},
1421 { "getprop", chirp_emul_getprop
},
1422 { "nextprop", chirp_emul_nextprop
},
1423 /* { "setprop", chirp_emul_setprop }, */
1424 { "canon", chirp_emul_canon
},
1425 { "finddevice", chirp_emul_finddevice
},
1426 { "instance-to-path", chirp_emul_instance_to_path
},
1427 { "package-to-path", chirp_emul_package_to_path
},
1428 { "call-method", chirp_emul_call_method
},
1431 { "open", chirp_emul_open
},
1432 { "close", chirp_emul_close
},
1433 { "read", chirp_emul_read
},
1434 { "write", chirp_emul_write
},
1435 { "seek", chirp_emul_seek
},
1436 { "write", chirp_emul_write
},
1439 { "claim", chirp_emul_claim
},
1440 { "release", chirp_emul_release
},
1442 /* control transfer */
1443 { "boot", chirp_emul_boot
},
1444 { "enter", chirp_emul_enter
},
1445 { "exit", chirp_emul_exit
},
1446 { "chain", chirp_emul_chain
},
1448 /* user interface */
1449 { "interpret", chirp_emul_interpret
},
1450 { "set_callback", chirp_emul_set_callback
},
1451 { "set_symbol_lookup", chirp_emul_set_symbol_lookup
},
1454 { "milliseconds", chirp_emul_milliseconds
},
1456 { 0, /* sentinal */ },
1462 /* Any starting address greater than this is assumed to be an Chirp
1465 #ifndef CHIRP_START_ADDRESS
1466 #define CHIRP_START_ADDRESS 0x80000000
1468 #ifndef CHIRP_LOAD_BASE
1469 #define CHIRP_LOAD_BASE -1
1473 typedef struct _chirp_note_desc
{
1486 } note_found_status
;
1487 typedef struct _chirp_note
{
1488 chirp_note_desc desc
;
1489 note_found_status found
;
1492 typedef struct _chirp_note_head
{
1499 map_over_chirp_note(bfd
*image
,
1503 chirp_note
*note
= (chirp_note
*)obj
;
1504 if (strcmp(sect
->name
, ".note") == 0) {
1505 chirp_note_head head
;
1507 /* check the head */
1508 if (!bfd_get_section_contents(image
, sect
,
1509 &head
, 0, sizeof(head
)))
1511 head
.namesz
= bfd_get_32(image
, (void*)&head
.namesz
);
1512 head
.descsz
= bfd_get_32(image
, (void*)&head
.descsz
);
1513 head
.type
= bfd_get_32(image
, (void*)&head
.type
);
1514 if (head
.type
!= 0x1275)
1516 /* check the name field */
1517 if (head
.namesz
> sizeof(name
)) {
1518 error("chirp: note name too long (%d > %d)\n", (int)head
.namesz
, sizeof(name
));
1520 if (!bfd_get_section_contents(image
, sect
,
1521 name
, sizeof(head
), head
.namesz
)) {
1522 error("chirp: note name unreadable\n");
1524 if (strcmp(name
, "PowerPC") != 0) {
1525 printf_filtered("chirp: note name (%s) not `PowerPC'\n", name
);
1527 /* check the size */
1528 if (head
.descsz
== sizeof(note
->desc
) - sizeof(signed32
)) {
1529 sim_io_printf_filtered("chirp: note descriptor missing load-base\n");
1531 else if (head
.descsz
!= sizeof(note
->desc
)) {
1532 sim_io_printf_filtered("chirp: note descriptor of wrong size\n");
1533 note
->found
= note_found
;
1536 note
->found
= note_correct
;
1537 /* get the contents */
1538 if (!bfd_get_section_contents(image
, sect
,
1539 ¬e
->desc
, /* page align start */
1540 ((sizeof(head
) + head
.namesz
) + 3) & ~3,
1542 error("chirp: note descriptor unreadable\n");
1544 note
->desc
.real_mode
= bfd_get_32(image
, (void*)¬e
->desc
.real_mode
);
1545 note
->desc
.real_base
= bfd_get_32(image
, (void*)¬e
->desc
.real_base
);
1546 note
->desc
.real_size
= bfd_get_32(image
, (void*)¬e
->desc
.real_size
);
1547 note
->desc
.virt_base
= bfd_get_32(image
, (void*)¬e
->desc
.virt_base
);
1548 note
->desc
.virt_size
= bfd_get_32(image
, (void*)¬e
->desc
.virt_size
);
1549 if (head
.descsz
== sizeof(note
->desc
))
1550 note
->desc
.load_base
= bfd_get_32(image
, (void*)¬e
->desc
.load_base
);
1552 note
->desc
.load_base
= (signed32
)-1;
1557 static os_emul_data
*
1558 emul_chirp_create(device
*root
,
1562 os_emul_data
*chirp
;
1567 /* Sanity check that this really is the chosen emulation */
1568 if (name
== NULL
&& image
== NULL
)
1571 && strcmp(name
, "ob") != 0
1572 && strcmp(name
, "ieee1274") != 0
1573 && strcmp(name
, "chrp") != 0
1574 && strcmp(name
, "chirp") != 0
1575 && strcmp(name
, "openboot") != 0)
1578 /* look for an elf note section, enter its values into the device tree */
1579 memset(¬e
, 0, sizeof(note
));
1581 bfd_map_over_sections(image
, map_over_chirp_note
, ¬e
);
1582 if (name
== NULL
&& image
!= NULL
&& note
.found
== note_missing
)
1585 /* Assume that it is a chirp emulation */
1587 chirp
= ZALLOC(os_emul_data
);
1589 chirp
->services
= services
;
1592 tree_parse(root
, "/name \"gpl,clayton");
1594 /* default options */
1595 emul_add_tree_options(root
, image
, "chirp", "oea",
1596 0 /*oea-interrupt-prefix*/);
1599 emul_add_tree_hardware(root
);
1601 /* basic information */
1603 = tree_find_integer_property(root
, "/openprom/options/oea-memory-size");
1604 chirp
->little_endian
1605 = tree_find_boolean_property(root
, "/options/little-endian?");
1606 chirp
->floating_point_available
1607 = tree_find_boolean_property(root
, "/openprom/options/floating-point?");
1608 chirp
->interrupt_prefix
=
1609 tree_find_integer_property(root
, "/openprom/options/oea-interrupt-prefix");
1612 /* Perform an interum layout of the openboot firmware in memory */
1615 /* a page for firmware calls */
1616 chirp
->sizeof_code
= 4096;
1617 chirp
->code_offset
= 0x4000; /* possible space for interrupt table */
1620 chirp
->sizeof_stack
= 32 * 1024;
1621 chirp
->stack_offset
= chirp
->code_offset
+ chirp
->sizeof_code
;
1623 /* the hash table */
1624 if (!note
.desc
.real_mode
) {
1625 chirp
->nr_page_table_entry_groups
= (chirp
->memory_size
< 0x800000
1626 ? 1024 /* min allowed */
1627 : (chirp
->memory_size
/ 4096 / 2));
1628 chirp
->sizeof_htab
= chirp
->nr_page_table_entry_groups
* 64;
1630 chirp
->htab_offset
= chirp
->stack_offset
+ chirp
->sizeof_stack
;
1632 /* the actual amount of space needed */
1633 chirp
->real_size
= chirp
->htab_offset
+ chirp
->sizeof_htab
;
1636 /* now go through and see if it fits in what is available */
1639 /* resolve real-mode? */
1640 if (note
.found
== note_correct
)
1641 chirp
->real_mode
= note
.desc
.real_mode
;
1642 else if (tree_find_property(root
, "/options/real-mode?") != NULL
)
1643 chirp
->real_mode
= tree_find_boolean_property(root
, "/options/real-mode?");
1645 chirp
->real_mode
= 0;
1646 if (tree_find_property(root
, "/options/real-mode?") != NULL
) {
1647 if (!chirp
->real_mode
1648 != !tree_find_boolean_property(root
, "/options/real-mode?"))
1649 error("chirp: /options/real-mode? conflicts with note section\n");
1652 tree_parse(root
, "/options/real-mode? %s",
1653 chirp
->real_mode
? "true" : "false");
1655 /* resolve real-base */
1656 if (note
.found
== note_correct
1657 && note
.desc
.real_base
!= (signed32
)-1)
1658 chirp
->real_base
= note
.desc
.real_base
;
1659 else if (tree_find_property(root
, "/options/real-base") != NULL
)
1660 chirp
->real_base
= tree_find_integer_property(root
, "/options/real-base");
1662 chirp
->real_base
= chirp
->memory_size
- chirp
->real_size
;
1663 if (tree_find_property(root
, "/options/real-base") != NULL
) {
1664 if (chirp
->real_base
!= tree_find_integer_property(root
, "/options/real-base"))
1665 error("chirp: /options/real-base conflicts with note section\n");
1668 tree_parse(root
, "/options/real-base 0x%lx",
1669 (unsigned long)chirp
->real_base
);
1671 /* resolve real-size */
1672 if (note
.found
== note_correct
1673 && note
.desc
.real_size
!= (signed32
)-1
1674 && note
.desc
.real_size
!= 0
1675 && chirp
->real_size
> note
.desc
.real_size
)
1676 error("chirp: insufficient physical memory for firmware\n");
1677 if (tree_find_property(root
, "/options/real-size") != NULL
) {
1678 if (chirp
->real_size
> tree_find_integer_property(root
, "/options/real-size"))
1679 error("chirp: /options/real-size conflicts with note section\n");
1682 tree_parse(root
, "/options/real-size 0x%lx",
1683 (unsigned long)chirp
->real_size
);
1685 /* resolve virt-base */
1686 if (chirp
->real_mode
)
1687 chirp
->virt_base
= chirp
->real_base
;
1688 else if (note
.found
== note_correct
&& note
.desc
.virt_base
!= -1)
1689 chirp
->virt_base
= note
.desc
.virt_base
;
1690 else if (tree_find_property(root
, "/options/virt-base") != NULL
)
1691 chirp
->virt_base
= tree_find_integer_property(root
, "/options/virt-base");
1693 chirp
->virt_base
= CHIRP_START_ADDRESS
;
1694 if (tree_find_property(root
, "/options/virt-base") != NULL
) {
1695 unsigned_word virt_base
= tree_find_integer_property(root
, "/options/virt-base");
1696 if (virt_base
!= -1 && chirp
->virt_base
!= virt_base
)
1697 error("chirp: /options/virt-base conflicts with note section\n");
1700 tree_parse(root
, "/options/virt-base 0x%lx",
1701 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_base
);
1703 /* resolve virt-size */
1704 chirp
->virt_size
= chirp
->real_size
;
1705 if (note
.found
== note_correct
1706 && note
.desc
.virt_size
!= (signed32
)-1
1707 && note
.desc
.virt_size
!= 0
1708 && !chirp
->real_mode
1709 && chirp
->virt_size
> note
.desc
.virt_size
)
1710 error("chirp: insufficent virtual memory for firmware\n");
1711 if (tree_find_property(root
, "/options/virt-size") != NULL
) {
1712 if (chirp
->virt_size
> tree_find_integer_property(root
, "/options/virt-size"))
1713 error("chirp: /options/virt-size conflicts with note section\n");
1716 tree_parse(root
, "/options/virt-size 0x%lx",
1717 chirp
->real_mode
? -1 : (unsigned long)chirp
->virt_size
);
1719 /* resolve load-base */
1720 if (note
.found
== note_correct
1721 && note
.desc
.load_base
!= (signed32
)-1)
1722 chirp
->load_base
= note
.desc
.load_base
;
1723 else if (tree_find_property(root
, "/options/load-base") != NULL
)
1724 chirp
->load_base
= tree_find_integer_property(root
, "/options/load-base");
1726 chirp
->load_base
= CHIRP_LOAD_BASE
;
1727 if (tree_find_property(root
, "/options/load-base") != NULL
) {
1728 if (chirp
->load_base
!= tree_find_integer_property(root
, "/options/load-base"))
1729 error("chirp: /options/load-base conflicts with note section\n");
1732 tree_parse(root
, "/options/load-base 0x%lx",
1733 (unsigned long)chirp
->load_base
);
1735 /* now adjust the preliminary firmware addresses to final values */
1736 chirp
->code_ra
= chirp
->code_offset
+ chirp
->real_base
;
1737 chirp
->stack_ra
= chirp
->stack_offset
+ chirp
->real_base
;
1738 chirp
->htab_ra
= chirp
->htab_offset
+ chirp
->real_base
;
1740 /* the virtual addresses. In real mode these are real addresses. */
1742 chirp
->code_va
= chirp
->code_offset
+ chirp
->virt_base
;
1743 chirp
->stack_va
= chirp
->stack_offset
+ chirp
->virt_base
;
1744 chirp
->htab_va
= chirp
->htab_offset
+ chirp
->virt_base
;
1746 chirp
->code_client_va
= chirp
->code_va
;
1747 chirp
->code_client_ra
= chirp
->code_ra
;
1749 chirp
->code_callback_va
= chirp
->code_client_va
+ 16;
1750 chirp
->code_callback_ra
= chirp
->code_client_ra
+ 16;
1752 chirp
->code_loop_va
= chirp
->code_callback_va
+ 16;
1753 chirp
->code_loop_ra
= chirp
->code_callback_ra
+ 16;
1755 /* initialization */
1757 tree_parse(root
, "/openprom/init");
1758 tree_parse(root
, "/openprom/init/register");
1759 tree_parse(root
, "/openprom/init/register/0.pc 0x%lx",
1760 (unsigned long)bfd_get_start_address(image
));
1761 tree_parse(root
, "/openprom/init/register/pc 0x%lx",
1762 (unsigned long)chirp
->code_loop_va
);
1763 tree_parse(root
, "/openprom/init/register/msr 0x%x",
1764 (msr_machine_check_enable
1767 : (msr_instruction_relocate
1768 | msr_data_relocate
))
1769 | (chirp
->little_endian
1770 ? (msr_little_endian_mode
1771 | msr_interrupt_little_endian_mode
)
1773 | (chirp
->floating_point_available
1774 ? msr_floating_point_available
1776 | (chirp
->interrupt_prefix
1777 ? msr_interrupt_prefix
1780 tree_parse(root
, "/openprom/init/register/sdr1 0x%lx",
1781 (unsigned long)(chirp
->htab_ra
1783 | ((chirp
->sizeof_htab
- 1) >> 16)));
1784 /* make certain that the segment registers map straight through */
1785 for (i
= 0; i
< 16; i
++) {
1786 tree_parse(root
, "/openprom/init/register/sr%d 0x%lx",
1787 i
, (unsigned long)i
);
1790 /* establish an initial state for all processors */
1793 /* the client interface address */
1794 tree_parse(root
, "/openprom/init/register/r5 0x%lx",
1795 (unsigned long)chirp
->code_client_va
);
1797 tree_parse(root
, "/openprom/init/register/sp 0x%lx",
1798 (unsigned long)(chirp
->stack_va
+ chirp
->sizeof_stack
- 16));
1799 /* in chrp mode any arguments end up being concatinated */
1800 tree_parse(root
, "/openprom/init/stack/stack-type chirp");
1803 /* client interface - emul-call followed by return instruction */
1806 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1807 (unsigned long)chirp
->code_client_ra
);
1808 tree_parse(node
, "./psim,description \"client-interface instruction");
1809 tree_parse(node
, "./real-address 0x%lx",
1810 (unsigned long)chirp
->code_client_ra
);
1811 tree_parse(node
, "./data 0x%lx",
1812 (unsigned long)emul_call_instruction
);
1814 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1815 (unsigned long)(chirp
->code_client_ra
+ 4));
1816 tree_parse(node
, "./psim,description \"client-interface return instruction");
1817 tree_parse(node
, "./real-address 0x%lx",
1818 (unsigned long)(chirp
->code_client_ra
+ 4));
1819 tree_parse(node
, "./data 0x%lx",
1820 (unsigned long)emul_blr_instruction
);
1823 /* return address for client callbacks - an emul-call instruction
1824 that is again followed by a return instruction */
1827 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1828 (unsigned long)chirp
->code_callback_ra
);
1829 tree_parse(node
, "./psim,description \"client-callback instruction");
1830 tree_parse(node
, "./real-address 0x%lx",
1831 (unsigned long)chirp
->code_callback_ra
);
1832 tree_parse(node
, "./data 0x%lx",
1833 (unsigned long)emul_call_instruction
);
1835 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1836 (unsigned long)(chirp
->code_callback_ra
+ 4));
1837 tree_parse(node
, "./psim,description \"client-callback return instruction");
1838 tree_parse(node
, "./real-address 0x%lx",
1839 (unsigned long)(chirp
->code_callback_ra
+ 4));
1840 tree_parse(node
, "./data 0x%lx",
1841 (unsigned long)emul_blr_instruction
);
1843 /* loop to keep other processors busy */
1845 node
= tree_parse(root
, "/openprom/init/data@0x%lx",
1846 (unsigned long)chirp
->code_loop_ra
);
1847 tree_parse(node
, "./psim,description \"processor busy loop");
1848 tree_parse(node
, "./real-address 0x%lx",
1849 (unsigned long)chirp
->code_loop_ra
);
1850 tree_parse(node
, "./data 0x%lx",
1851 (unsigned long)emul_loop_instruction
);
1855 /* create a hash table */
1857 if (!chirp
->real_mode
) {
1858 node
= tree_parse(root
, "/openprom/init/htab@0x%lx",
1859 (unsigned long)chirp
->htab_ra
);
1860 tree_parse(node
, "./claim 0");
1861 tree_parse(node
, "./real-address 0x%lx",
1862 (unsigned long)chirp
->htab_ra
);
1863 tree_parse(node
, "./nr-bytes 0x%lx",
1864 (unsigned long)chirp
->sizeof_htab
);
1867 /* map in the stack */
1869 if (!chirp
->real_mode
) {
1870 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1871 (unsigned long)chirp
->stack_ra
);
1872 tree_parse(node
, "./psim,description \"map in the stack");
1873 tree_parse(node
, "./claim 1");
1874 tree_parse(node
, "./virtual-address 0x%lx",
1875 (unsigned long)chirp
->stack_va
);
1876 tree_parse(node
, "./real-address 0x%lx",
1877 (unsigned long)chirp
->stack_ra
);
1878 tree_parse(node
, "./nr-bytes 0x%lx",
1879 (unsigned long)chirp
->sizeof_stack
);
1880 tree_parse(node
, "./wimg %d", 0x7);
1881 tree_parse(node
, "./pp %d", 0x2);
1884 /* map in the chrp openboot callback code */
1886 if (!chirp
->real_mode
) {
1887 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1888 (unsigned long)chirp
->code_ra
);
1889 tree_parse(node
, "./psim,description \"map in chrp openboot callback code");
1890 tree_parse(node
, "./claim 1");
1891 tree_parse(node
, "./virtual-address 0x%lx",
1892 (unsigned long)chirp
->code_va
);
1893 tree_parse(node
, "./real-address 0x%lx",
1894 (unsigned long)chirp
->code_ra
);
1895 tree_parse(node
, "./nr-bytes 0x%lx",
1896 (unsigned long)chirp
->sizeof_code
);
1897 tree_parse(node
, "./wimg %d", 0x7);
1898 tree_parse(node
, "./pp %d", 0x2);
1901 /* map in the program to run */
1903 if (chirp
->real_mode
) {
1904 node
= tree_parse(node
, "/openprom/init/load-binary");
1905 tree_parse(node
, "./psim,description \"load the binary");
1906 tree_parse(node
, "./file-name %s", bfd_get_filename(image
));
1907 tree_parse(node
, "./claim 1");
1910 node
= tree_parse(root
, "/openprom/init/htab/pte@0x%lx",
1911 (unsigned long)chirp
->load_base
);
1912 tree_parse(node
, "./psim,description \"load & map the binary");
1913 tree_parse(node
, "./claim 1");
1914 tree_parse(node
, "./file-name \"%s", bfd_get_filename(image
));
1915 tree_parse(node
, "./wimg %d", 0x7);
1916 tree_parse(node
, "./pp %d", 0x2);
1919 /* map in the interrupt vectors */
1921 if (!chirp
->real_mode
) {
1922 node
= tree_parse(root
, "/openprom/init/htab/pte@0x0");
1923 tree_parse(node
, "./psim,description \"map in interrupt vectors");
1924 tree_parse(node
, "./virtual-address 0x0");
1925 tree_parse(node
, "./real-address 0x0");
1926 tree_parse(node
, "./nr-bytes 0x3000");
1927 tree_parse(node
, "./wimg %d", 0x7);
1928 tree_parse(node
, "./pp %d", 0x2);
1935 emul_chirp_init(os_emul_data
*emul_data
,
1938 emul_data
->state
= serving
;
1942 emul_chirp_instruction_call(cpu
*processor
,
1945 os_emul_data
*emul_data
)
1947 unsigned_word service_name_addr
;
1948 unsigned_word result
;
1949 char service_buf
[32];
1951 chirp_services
*service
;
1953 switch (emul_data
->state
) {
1956 /* we are waiting on an OpenBoot request from the client program
1957 via the client interface */
1958 if (cia
!= emul_data
->code_client_va
)
1960 emul_data
->return_address
= LR
;
1961 emul_data
->arguments
= cpu_registers(processor
)->gpr
[3];
1962 /* try to determine what to do */
1963 service_name_addr
= emul_read_word(cpu_registers(processor
)->gpr
[3],
1965 service_name
= emul_read_string(service_buf
, service_name_addr
,
1966 sizeof(service_buf
), processor
, cia
);
1967 emul_data
->n_args
= emul_read_word(emul_data
->arguments
+ sizeof(unsigned_cell
),
1969 emul_data
->n_returns
= emul_read_word(emul_data
->arguments
+ 2 * sizeof(unsigned_cell
),
1971 /* verify what was passed */
1972 if (service_name_addr
== 0
1973 || service_name
== NULL
) {
1974 error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n",
1975 (unsigned long)emul_data
->return_address
,
1976 (unsigned long)emul_data
->arguments
);
1978 if (emul_data
->n_args
> 6) { /* See iee1275 requirements on nr returns */
1979 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n",
1980 (unsigned long)emul_data
->return_address
,
1981 (unsigned long)emul_data
->arguments
,
1982 emul_data
->n_returns
);
1984 if (emul_data
->n_returns
> 6) {
1985 error("OpenFirmware service %s called from 0x%lx with args 0x%lx, with too many returns (%d)\n",
1986 (unsigned long)emul_data
->return_address
,
1987 (unsigned long)emul_data
->arguments
,
1991 TRACE(trace_os_emul
, ("%s called from 0x%lx with args 0x%lx\n",
1993 (unsigned long)emul_data
->return_address
,
1994 (unsigned long)emul_data
->arguments
));
1996 while (service
->name
!= NULL
&& strcmp(service
->name
, service_name
) != 0)
1999 if (service
->name
== NULL
) {
2000 error("OpenBoot service `%s' not found\n", service_name
);
2001 TRACE(trace_os_emul
, ("%s not found\n", service_name
));
2002 cpu_registers(processor
)->gpr
[3] = -1;
2005 emul_data
->service
= service
;
2007 result
= service
->handler(emul_data
, processor
, cia
);
2009 TRACE(trace_os_emul
, ("%s aborted with %ld\n", service_name
, (long)result
));
2010 cpu_registers(processor
)->gpr
[3] = result
;
2015 error("emul_chirp_instruction_call() unknown internal state\n");
2021 /* return to caller - instruction following this is a function return */
2025 const os_emul emul_chirp
= {
2029 NULL
, /*system_call*/
2030 emul_chirp_instruction_call
,