1 /*  This file is part of the program psim.
2 
3     Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
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.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19     */
20 
21 
22 #ifndef _EMUL_CHIRP_C_
23 #define _EMUL_CHIRP_C_
24 
25 /* Note: this module is called via a table.  There is no benefit in
26    making it inline */
27 
28 #include "emul_generic.h"
29 #include "emul_chirp.h"
30 
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #else
34 #ifdef HAVE_STRINGS_H
35 #include <strings.h>
36 #endif
37 #endif
38 
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42 
43 #ifndef STATIC_INLINE_EMUL_CHIRP
44 #define STATIC_INLINE_EMUL_CHIRP STATIC_INLINE
45 #endif
46 
47 
48 /* EMULATION
49 
50 
51    OpenFirmware - IEEE Standard for Boot (Initialization
52    Configuration) Firmware.
53 
54 
55    DESCRIPTION
56 
57 
58    BUGS
59 
60 
61    This code assumes that the memory node has #address-cells and
62    #size-cells set to one.  For future implementations, this may not
63    be the case.
64 
65    */
66 
67 
68 
69 
70 /* Descriptor of the open boot services being emulated */
71 
72 typedef int (chirp_handler)
73      (os_emul_data *data,
74       cpu *processor,
75       unsigned_word cia);
76 
77 typedef struct _chirp_services {
78   const char *name;
79   chirp_handler *handler;
80 } chirp_services;
81 
82 
83 /* The OpenBoot emulation is, at any time either waiting for a client
84    request or waiting on a client callback */
85 typedef enum {
86   serving,
87   emulating,
88   faulting,
89 } chirp_emul_state;
90 
91 struct _os_emul_data {
92   chirp_emul_state state;
93   unsigned_word return_address;
94   unsigned_word arguments;
95   unsigned_word n_args;
96   unsigned_word n_returns;
97   chirp_services *service;
98   device *root;
99   chirp_services *services;
100   /* configuration */
101   unsigned_word memory_size;
102   unsigned_word real_base;
103   unsigned_word real_size;
104   unsigned_word virt_base;
105   unsigned_word virt_size;
106   int real_mode;
107   int little_endian;
108   int floating_point_available;
109   int interrupt_prefix;
110   unsigned_word load_base;
111   /* hash table */
112   unsigned_word nr_page_table_entry_groups;
113   unsigned_word htab_offset;
114   unsigned_word htab_ra;
115   unsigned_word htab_va;
116   unsigned_word sizeof_htab;
117   /* virtual address of htab */
118   unsigned_word stack_offset;
119   unsigned_word stack_ra;
120   unsigned_word stack_va;
121   unsigned_word sizeof_stack;
122   /* addresses of emulation instructions virtual/real */
123   unsigned_word code_offset;
124   unsigned_word code_va;
125   unsigned_word code_ra;
126   unsigned_word sizeof_code;
127   unsigned_word code_client_va;
128   unsigned_word code_client_ra;
129   unsigned_word code_callback_va;
130   unsigned_word code_callback_ra;
131   unsigned_word code_loop_va;
132   unsigned_word code_loop_ra;
133 };
134 
135 
136 /* returns the name of the corresponding Ihandle */
137 static const char *
ihandle_name(device_instance * ihandle)138 ihandle_name(device_instance *ihandle)
139 {
140   if (ihandle == NULL)
141     return "";
142   else
143     return device_name(device_instance_device(ihandle));
144 }
145 
146 
147 
148 /* Read/write the argument list making certain that all values are
149    converted to/from host byte order.
150 
151    In the below only n_args+n_returns is read/written */
152 
153 static int
chirp_read_t2h_args(void * args,int sizeof_args,int n_args,int n_returns,os_emul_data * data,cpu * processor,unsigned_word cia)154 chirp_read_t2h_args(void *args,
155 		    int sizeof_args,
156 		    int n_args,
157 		    int n_returns,
158 		    os_emul_data *data,
159 		    cpu *processor,
160 		    unsigned_word cia)
161 {
162   unsigned_cell *words;
163   int i;
164   /* check against the number of arguments specified by the client
165      program */
166   if ((n_args >= 0 && data->n_args != n_args)
167       || (n_returns >= 0 && data->n_returns != n_returns)) {
168     TRACE(trace_os_emul, ("%s - invalid nr of args - n_args=%ld, n_returns=%ld\n",
169 			  data->service->name,
170 			  (long)data->n_args,
171 			  (long)data->n_returns));
172     return -1;
173   }
174   /* check that there is enough space */
175   if (sizeof(unsigned_cell) * (data->n_args + data->n_returns) > sizeof_args)
176     return -1;
177   /* bring in the data */
178   memset(args, 0, sizeof_args);
179   emul_read_buffer(args, data->arguments + 3 * sizeof(unsigned_cell),
180 		   sizeof(unsigned_cell) * (data->n_args + data->n_returns),
181 		   processor, cia);
182   /* convert all words to host format */
183   words = args;
184   for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++)
185     words[i] = T2H_cell(words[i]);
186   return 0;
187 }
188 
189 static void
chirp_write_h2t_args(void * args,int sizeof_args,os_emul_data * data,cpu * processor,unsigned_word cia)190 chirp_write_h2t_args(void *args,
191 		     int sizeof_args,
192 		     os_emul_data *data,
193 		     cpu *processor,
194 		     unsigned_word cia)
195 {
196   int i;
197   unsigned_cell *words;
198   /* convert to target everything */
199   words = args;
200   for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++)
201     words[i] = H2T_cell(words[i]);
202   /* bring in the data */
203   emul_write_buffer(args, data->arguments + 3 * sizeof(unsigned_cell),
204 		    sizeof(unsigned_cell) * (data->n_args + data->n_returns),
205 		    processor, cia);
206 }
207 
208 
209 /* OpenBoot emulation functions */
210 
211 /* client interface */
212 
213 static int
chirp_emul_test(os_emul_data * data,cpu * processor,unsigned_word cia)214 chirp_emul_test(os_emul_data *data,
215 		cpu *processor,
216 		unsigned_word cia)
217 {
218   struct test_args {
219     /*in*/
220     unsigned_cell name; /*string*/
221     /*out*/
222     unsigned_cell missing;
223   } args;
224   char name[32];
225   chirp_services *service = NULL;
226   /* read in the arguments */
227   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
228     return -1;
229   emul_read_string(name, args.name, sizeof(name),
230 		   processor, cia);
231   TRACE(trace_os_emul, ("test - in - name=`%s'\n", name));
232   /* see if we know about the service */
233   service = data->services;
234   while (service->name != NULL && strcmp(service->name, name) != 0) {
235     service++;
236   }
237   if (service->name == NULL)
238     args.missing = -1;
239   else
240     args.missing = 0;
241   /* write the arguments back out */
242   TRACE(trace_os_emul, ("test - out - missing=%ld\n",
243 			(long)args.missing));
244   chirp_write_h2t_args(&args,
245 		       sizeof(args),
246 		       data,
247 		       processor, cia);
248   return 0;
249 }
250 
251 
252 /* Device tree */
253 
254 static int
chirp_emul_peer(os_emul_data * data,cpu * processor,unsigned_word cia)255 chirp_emul_peer(os_emul_data *data,
256 		cpu *processor,
257 		unsigned_word cia)
258 {
259   struct peer_args {
260     /*in*/
261     unsigned_cell phandle;
262     /*out*/
263     unsigned_cell sibling_phandle;
264   } args;
265   device *phandle;
266   device *sibling_phandle = NULL;
267   /* read in the arguments */
268   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
269     return -1;
270   phandle = external_to_device(data->root, args.phandle);
271   TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
272 			(unsigned long)args.phandle,
273 			(unsigned long)phandle,
274 			(phandle == NULL ? "" : device_name(phandle))));
275   /* find the peer */
276   if (args.phandle == 0) {
277     sibling_phandle = data->root;
278     args.sibling_phandle = device_to_external(sibling_phandle);
279   }
280   else if (phandle == NULL) {
281     sibling_phandle = NULL;
282     args.sibling_phandle = -1;
283   }
284   else {
285     sibling_phandle = device_sibling(phandle);
286     if (sibling_phandle == NULL)
287       args.sibling_phandle = 0;
288     else
289       args.sibling_phandle = device_to_external(sibling_phandle);
290   }
291   /* write the arguments back out */
292   TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
293 			(unsigned long)args.sibling_phandle,
294 			(unsigned long)sibling_phandle,
295 			(sibling_phandle == NULL ? "" : device_name(sibling_phandle))));
296   chirp_write_h2t_args(&args,
297 		       sizeof(args),
298 		       data,
299 		       processor, cia);
300   return 0;
301 }
302 
303 static int
chirp_emul_child(os_emul_data * data,cpu * processor,unsigned_word cia)304 chirp_emul_child(os_emul_data *data,
305 		 cpu *processor,
306 		 unsigned_word cia)
307 {
308   struct child_args {
309     /*in*/
310     unsigned_cell phandle;
311     /*out*/
312     unsigned_cell child_phandle;
313   } args;
314   device *phandle;
315   device *child_phandle;
316   /* read the arguments in */
317   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
318     return -1;
319   phandle = external_to_device(data->root, args.phandle);
320   TRACE(trace_os_emul, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
321 			(unsigned long)args.phandle,
322 			(unsigned long)phandle,
323 			(phandle == NULL ? "" : device_name(phandle))));
324   /* find a child */
325   if (args.phandle == 0
326       || phandle == NULL) {
327     child_phandle = NULL;
328     args.child_phandle = -1;
329   }
330   else {
331     child_phandle = device_child(phandle);
332     if (child_phandle == NULL)
333       args.child_phandle = 0;
334     else
335       args.child_phandle = device_to_external(child_phandle);
336   }
337   /* write the result out */
338   TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
339 			(unsigned long)args.child_phandle,
340 			(unsigned long)child_phandle,
341 			(child_phandle == NULL ? "" : device_name(child_phandle))));
342   chirp_write_h2t_args(&args,
343 		       sizeof(args),
344 		       data,
345 		       processor, cia);
346   return 0;
347 }
348 
349 static int
chirp_emul_parent(os_emul_data * data,cpu * processor,unsigned_word cia)350 chirp_emul_parent(os_emul_data *data,
351 		  cpu *processor,
352 		  unsigned_word cia)
353 {
354   struct parent_args {
355     /*in*/
356     unsigned_cell phandle;
357     /*out*/
358     unsigned_cell parent_phandle;
359   } args;
360   device *phandle;
361   device *parent_phandle;
362   /* read the args in */
363   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
364     return -1;
365   phandle = external_to_device(data->root, args.phandle);
366   TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
367 			(unsigned long)args.phandle,
368 			(unsigned long)phandle,
369 			(phandle == NULL ? "" : device_name(phandle))));
370   /* find a parent */
371   if (args.phandle == 0
372       || phandle == NULL) {
373     parent_phandle = NULL;
374     args.parent_phandle = -1;
375   }
376   else {
377     parent_phandle = device_parent(phandle);
378     if (parent_phandle == NULL)
379       args.parent_phandle = 0;
380     else
381       args.parent_phandle = device_to_external(parent_phandle);
382   }
383   /* return the result */
384   TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
385 			(unsigned long)args.parent_phandle,
386 			(unsigned long)parent_phandle,
387 			(parent_phandle == NULL ? "" : device_name(parent_phandle))));
388   chirp_write_h2t_args(&args,
389 		       sizeof(args),
390 		       data,
391 		       processor, cia);
392   return 0;
393 }
394 
395 static int
chirp_emul_instance_to_package(os_emul_data * data,cpu * processor,unsigned_word cia)396 chirp_emul_instance_to_package(os_emul_data *data,
397 			       cpu *processor,
398 			       unsigned_word cia)
399 {
400   struct instance_to_package_args {
401     /*in*/
402     unsigned_cell ihandle;
403     /*out*/
404     unsigned_cell phandle;
405   } args;
406   device_instance *ihandle;
407   device *phandle = NULL;
408   /* read the args in */
409   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
410     return -1;
411   ihandle = external_to_device_instance(data->root, args.ihandle);
412   TRACE(trace_os_emul, ("instance-to-package - in - ihandle=0x%lx(0x%lx`%s')\n",
413 			(unsigned long)args.ihandle,
414 			(unsigned long)ihandle,
415 			ihandle_name(ihandle)));
416   /* find the corresponding phandle */
417   if (ihandle == NULL) {
418     phandle = NULL;
419     args.phandle = -1;
420   }
421   else {
422     phandle = device_instance_device(ihandle);
423     args.phandle = device_to_external(phandle);
424   }
425   /* return the result */
426   TRACE(trace_os_emul, ("instance-to-package - out - phandle=0x%lx(0x%lx`%s')\n",
427 			(unsigned long)args.phandle,
428 			(unsigned long)phandle,
429 			(phandle == NULL ? "" : device_name(phandle))));
430   chirp_write_h2t_args(&args,
431 		       sizeof(args),
432 		       data,
433 		       processor, cia);
434   return 0;
435 }
436 
437 static int
chirp_emul_getproplen(os_emul_data * data,cpu * processor,unsigned_word cia)438 chirp_emul_getproplen(os_emul_data *data,
439 		      cpu *processor,
440 		      unsigned_word cia)
441 {
442   struct getproplen_args {
443     /*in*/
444     unsigned_cell phandle;
445     unsigned_cell name;
446     /*out*/
447     unsigned_cell proplen;
448   } args;
449   char name[32];
450   device *phandle;
451   /* read the args in */
452   if (chirp_read_t2h_args(&args, sizeof(args), 2, 1, data, processor, cia))
453     return -1;
454   phandle = external_to_device(data->root, args.phandle);
455   emul_read_string(name,
456 		   args.name,
457 		   sizeof(name),
458 		   processor, cia);
459   TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
460 			(unsigned long)args.phandle,
461 			(unsigned long)phandle,
462 			(phandle == NULL ? "" : device_name(phandle)),
463 			name));
464   /* find our prop and get its length */
465   if (args.phandle == 0
466       || phandle == NULL) {
467     args.proplen = -1;
468   }
469   else {
470     const device_property *prop = device_find_property(phandle, name);
471     if (prop == (device_property*)0) {
472       args.proplen = -1;
473     }
474     else {
475       args.proplen = prop->sizeof_array;
476     }
477   }
478   /* return the result */
479   TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
480 			(unsigned long)args.proplen));
481   chirp_write_h2t_args(&args,
482 		       sizeof(args),
483 		       data,
484 		       processor, cia);
485   return 0;
486 }
487 
488 static int
chirp_emul_getprop(os_emul_data * data,cpu * processor,unsigned_word cia)489 chirp_emul_getprop(os_emul_data *data,
490 		   cpu *processor,
491 		   unsigned_word cia)
492 {
493   struct getprop_args {
494     /*in*/
495     unsigned_cell phandle;
496     unsigned_cell name;
497     unsigned_cell buf;
498     unsigned_cell buflen;
499     /*out*/
500     unsigned_cell size;
501   } args;
502   char name[32];
503   device *phandle;
504   /* read in the args, the return is optional */
505   if (chirp_read_t2h_args(&args, sizeof(args), 4, -1, data, processor, cia))
506     return -1;
507   phandle = external_to_device(data->root, args.phandle);
508   emul_read_string(name,
509 		   args.name,
510 		   sizeof(name),
511 		   processor, cia);
512   TRACE(trace_os_emul, ("getprop - in - phandle=0x%lx(0x%lx`%s') name=`%s' buf=0x%lx buflen=%ld\n",
513 			(unsigned long)args.phandle,
514 			(unsigned long)phandle,
515 			(phandle == NULL ? "" : device_name(phandle)),
516 			name,
517 			(unsigned long)args.buf,
518 			(unsigned long)args.buflen));
519   /* get the property */
520   if (args.phandle == 0
521       || phandle == NULL) {
522     args.size = -1;
523   }
524   else {
525     const device_property *prop = device_find_property(phandle, name);
526     if (prop == NULL) {
527       args.size = -1;
528     }
529     else {
530       int size = args.buflen;
531       if (size > prop->sizeof_array)
532 	size = prop->sizeof_array;
533       emul_write_buffer(prop->array, args.buf,
534 			size,
535 			processor, cia);
536       args.size = size;
537       switch (prop->type) {
538       case string_property:
539 	TRACE(trace_os_emul, ("getprop - string `%s'\n",
540 			      device_find_string_property(phandle, name)));
541 	break;
542       case ihandle_property:
543 	TRACE(trace_os_emul, ("getprop - ihandle=0x%lx(0x%lx`%s')\n",
544 			      BE2H_cell(*(unsigned_cell*)prop->array),
545 			      (unsigned long)device_find_ihandle_property(phandle, name),
546 			      ihandle_name(device_find_ihandle_property(phandle, name))));
547 	break;
548       default:
549 	break;
550       }
551     }
552   }
553   /* write back the result */
554   if (data->n_returns == 0)
555     TRACE(trace_os_emul, ("getprop - out - size=%ld (not returned)\n",
556 			  (unsigned long)args.size));
557   else {
558     TRACE(trace_os_emul, ("getprop - out - size=%ld\n",
559 			  (unsigned long)args.size));
560     chirp_write_h2t_args(&args,
561 			 sizeof(args),
562 			 data,
563 			 processor, cia);
564   }
565   return 0;
566 }
567 
568 static int
chirp_emul_nextprop(os_emul_data * data,cpu * processor,unsigned_word cia)569 chirp_emul_nextprop(os_emul_data *data,
570 		    cpu *processor,
571 		    unsigned_word cia)
572 {
573   struct nextprop_args {
574     /*in*/
575     unsigned_cell phandle;
576     unsigned_cell previous;
577     unsigned_cell buf;
578     /*out*/
579     unsigned_cell flag;
580   } args;
581   char previous[32];
582   device *phandle;
583   /* read in the args */
584   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
585     return -1;
586   phandle = external_to_device(data->root, args.phandle);
587   if (args.previous != 0)
588     emul_read_string(previous,
589 		     args.previous,
590 		     sizeof(previous),
591 		     processor, cia);
592   else
593     /* If previous is NULL, make it look like the empty string.  The
594        next property after the empty string is the first property.  */
595     strcpy (previous, "");
596   TRACE(trace_os_emul, ("nextprop - in - phandle=0x%lx(0x%lx`%s') previous=`%s' buf=0x%lx\n",
597 			(unsigned long)args.phandle,
598 			(unsigned long)phandle,
599 			(phandle == NULL ? "" : device_name(phandle)),
600 			previous,
601 			(unsigned long)args.buf));
602   /* find the next property */
603   if (args.phandle == 0
604       || phandle == NULL) {
605     args.flag = -1;
606   }
607   else {
608     const device_property *prev_prop = device_find_property(phandle, previous);
609     if (prev_prop == NULL) {
610       if (strcmp (previous, "") == 0)
611 	args.flag = 0; /* No properties */
612       else
613 	args.flag = -1; /* name invalid */
614     }
615     else {
616       const device_property *next_prop;
617       if (strcmp (previous, "") == 0) {
618 	next_prop = prev_prop;	/* The first property.  */
619       }
620       else {
621 	next_prop = device_next_property(prev_prop);
622       }
623       if (next_prop == NULL) {
624 	args.flag = 0; /* last property */
625       }
626       else {
627 	emul_write_buffer(next_prop->name, args.buf, strlen(next_prop->name),
628 			  processor, cia);
629 	TRACE(trace_os_emul, ("nextprop - name=`%s'\n", next_prop->name));
630 	args.flag = 1; /* worked ok */
631       }
632     }
633   }
634   /* write back the result */
635   TRACE(trace_os_emul, ("nextprop - out - flag=%ld\n",
636 			(unsigned long)args.flag));
637   chirp_write_h2t_args(&args,
638 		       sizeof(args),
639 		       data,
640 		       processor, cia);
641   return 0;
642 }
643 
644 #if 0
645 static int
646 chirp_emul_setprop(os_emul_data *data,
647 		   cpu *processor,
648 		   unsigned_word cia)
649 {
650   error("chirp: setprop method not implemented\n");
651   return 0;
652 }
653 #endif
654 
655 static int
chirp_emul_canon(os_emul_data * data,cpu * processor,unsigned_word cia)656 chirp_emul_canon(os_emul_data *data,
657 		 cpu *processor,
658 		 unsigned_word cia)
659 {
660   struct canon_args {
661     /*in*/
662     unsigned_cell device_specifier;
663     unsigned_cell buf;
664     unsigned_cell buflen;
665     /*out*/
666     unsigned_cell length;
667   } args;
668   char device_specifier[1024];
669   device *phandle;
670   const char *path;
671   int length;
672   /* read in the args */
673   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
674     return -1;
675   emul_read_string(device_specifier,
676 		   args.device_specifier,
677 		   sizeof(device_specifier),
678 		   processor, cia);
679   TRACE(trace_os_emul, ("canon - in - device_specifier=`%s' buf=0x%lx buflen=%lx\n",
680 			device_specifier,
681 			(unsigned long)args.buf,
682 			(unsigned long)args.buflen));
683   /* canon the name */
684   phandle = tree_find_device(data->root, device_specifier);
685   if (phandle == NULL) {
686     length = -1;
687     path = "";
688     args.length = -1;
689   }
690   else {
691     path = device_path(phandle);
692     length = strlen(path);
693     if (length >= args.buflen)
694       length = args.buflen - 1;
695     emul_write_buffer(path, args.buf, length,
696 		      processor, cia);
697     args.length = length;
698   }
699   /* write back the result */
700   TRACE(trace_os_emul, ("canon - out - length=%ld buf=`%s'\n",
701 			(unsigned long)args.length,
702 			path));
703   chirp_write_h2t_args(&args,
704 		       sizeof(args),
705 		       data,
706 		       processor, cia);
707   return 0;
708 }
709 
710 static int
chirp_emul_finddevice(os_emul_data * data,cpu * processor,unsigned_word cia)711 chirp_emul_finddevice(os_emul_data *data,
712 		      cpu *processor,
713 		      unsigned_word cia)
714 {
715   struct finddevice_args {
716     /*in*/
717     unsigned_cell device_specifier;
718     /*out*/
719     unsigned_cell phandle;
720   } args;
721   char device_specifier[1024];
722   device *phandle;
723   /* get the args */
724   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
725     return -1;
726   emul_read_string(device_specifier,
727 		   args.device_specifier,
728 		   sizeof(device_specifier),
729 		   processor, cia);
730   TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
731 			device_specifier));
732   /* find the device */
733   phandle = tree_find_device(data->root, device_specifier);
734   if (phandle == NULL)
735     args.phandle = -1;
736   else
737     args.phandle = device_to_external(phandle);
738   /* return its phandle */
739   TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
740 			(unsigned long)args.phandle,
741 			(unsigned long)phandle,
742 			(phandle == NULL ? "" : device_name(phandle))));
743   chirp_write_h2t_args(&args,
744 		       sizeof(args),
745 		       data,
746 		       processor, cia);
747   return 0;
748 }
749 
750 static int
chirp_emul_instance_to_path(os_emul_data * data,cpu * processor,unsigned_word cia)751 chirp_emul_instance_to_path(os_emul_data *data,
752 			    cpu *processor,
753 			    unsigned_word cia)
754 {
755   struct instance_to_path_args {
756     /*in*/
757     unsigned_cell ihandle;
758     unsigned_cell buf;
759     unsigned_cell buflen;
760     /*out*/
761     unsigned_cell length;
762   } args;
763   device_instance *ihandle;
764   const char *path;
765   int length;
766   /* get the args */
767   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
768     return -1;
769   ihandle = external_to_device_instance(data->root, args.ihandle);
770   TRACE(trace_os_emul, ("instance-to-path - in - ihandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
771 			(unsigned long)args.ihandle,
772 			(unsigned long)ihandle,
773 			ihandle_name(ihandle),
774 			(unsigned long)args.buf,
775 			(unsigned long)args.buflen));
776   /* get the devices name */
777   if (ihandle == NULL) {
778     args.length = -1;
779     path = "(null)";
780   }
781   else {
782     path = device_instance_path(ihandle);
783     length = strlen(path);
784     if (length >= args.buflen)
785       length = args.buflen - 1;
786     emul_write_buffer(path, args.buf, length,
787 		      processor, cia);
788     args.length = length;
789   }
790   /* return its phandle */
791   TRACE(trace_os_emul, ("instance-to-path - out - length=%ld buf=`%s')\n",
792 			(unsigned long)args.length,
793 			path));
794   chirp_write_h2t_args(&args,
795 		       sizeof(args),
796 		       data,
797 		       processor, cia);
798   return 0;
799 }
800 
801 static int
chirp_emul_package_to_path(os_emul_data * data,cpu * processor,unsigned_word cia)802 chirp_emul_package_to_path(os_emul_data *data,
803 			   cpu *processor,
804 			   unsigned_word cia)
805 {
806   struct package_to_path_args {
807     /*in*/
808     unsigned_cell phandle;
809     unsigned_cell buf;
810     unsigned_cell buflen;
811     /*out*/
812     unsigned_cell length;
813   } args;
814   device *phandle;
815   const char *path;
816   /* get the args */
817   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
818     return -1;
819   phandle = external_to_device(data->root, args.phandle);
820   TRACE(trace_os_emul, ("package-to-path - in - phandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
821 			(unsigned long)args.phandle,
822 			(unsigned long)phandle,
823 			(phandle == NULL ? "" : device_name(phandle)),
824 			(unsigned long)args.buf,
825 			(unsigned long)args.buflen));
826   /* get the devices name */
827   if (phandle == NULL) {
828     args.length = -1;
829     path = "(null)";
830   }
831   else {
832     int length;
833     path = device_path(phandle);
834     length = strlen(path);
835     if (length >= args.buflen)
836       length = args.buflen - 1;
837     emul_write_buffer(path, args.buf, length,
838 		      processor, cia);
839     args.length = length;
840   }
841   /* return its phandle */
842   TRACE(trace_os_emul, ("package-to-path - out - length=%ld buf=`%s')\n",
843 			(unsigned long)args.length,
844 			path));
845   chirp_write_h2t_args(&args,
846 		       sizeof(args),
847 		       data,
848 		       processor, cia);
849   return 0;
850 }
851 
852 static int
chirp_emul_call_method(os_emul_data * data,cpu * processor,unsigned_word cia)853 chirp_emul_call_method(os_emul_data *data,
854 		       cpu *processor,
855 		       unsigned_word cia)
856 {
857   struct call_method_args {
858     /*in*/
859     unsigned_cell method;
860     unsigned_cell ihandle;
861     /*in/out*/
862     unsigned_cell stack[13]; /*6in + 6out + catch */
863   } args;
864   char method[32];
865   device_instance *ihandle;
866   /* some useful info about our mini stack */
867   int n_stack_args;
868   int n_stack_returns;
869   int stack_catch_result;
870   int stack_returns;
871   /* read the args */
872   if (chirp_read_t2h_args(&args, sizeof(args), -1, -1, data, processor, cia))
873     return -1;
874   emul_read_string(method,
875 		   args.method,
876 		   sizeof(method),
877 		   processor, cia);
878   ihandle = external_to_device_instance(data->root, args.ihandle);
879   n_stack_args = data->n_args - 2;
880   n_stack_returns = data->n_returns - 1;
881   stack_catch_result = n_stack_args;
882   stack_returns = stack_catch_result + 1;
883   TRACE(trace_os_emul, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(0x%lx`%s')\n",
884 			(unsigned long)data->n_args,
885 			(unsigned long)data->n_returns,
886 			method,
887 			(unsigned long)args.ihandle,
888 			(unsigned long)ihandle,
889 			ihandle_name(ihandle)));
890   /* see if we can emulate this method */
891   if (ihandle == NULL) {
892     /* OpenFirmware doesn't define this error */
893     error("chirp: invalid ihandle passed to call-method method");
894   }
895   else {
896     args.stack[stack_catch_result] =
897       device_instance_call_method(ihandle,
898 				  method,
899 				  n_stack_args,
900 				  &args.stack[0],
901 				  n_stack_returns,
902 				  &args.stack[stack_returns]);
903   }
904   /* finished */
905   TRACE(trace_os_emul, ("call-method - out - catch-result=%ld\n",
906 			(unsigned long)args.stack[stack_catch_result]));
907   chirp_write_h2t_args(&args,
908 		       sizeof(args),
909 		       data,
910 		       processor, cia);
911   return 0;
912 }
913 
914 
915 /* Device I/O */
916 
917 static int
chirp_emul_open(os_emul_data * data,cpu * processor,unsigned_word cia)918 chirp_emul_open(os_emul_data *data,
919 		cpu *processor,
920 		unsigned_word cia)
921 {
922   struct open_args {
923     /*in*/
924     unsigned_cell device_specifier;
925     /*out*/
926     unsigned_cell ihandle;
927   } args;
928   char device_specifier[1024];
929   device_instance *ihandle;
930   /* read the args */
931   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
932     return -1;
933   emul_read_string(device_specifier,
934 		   args.device_specifier,
935 		   sizeof(device_specifier),
936 		   processor, cia);
937   TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n",
938 			device_specifier));
939   /* open the device */
940   ihandle = tree_instance(data->root, device_specifier);
941   if (ihandle == NULL)
942     args.ihandle = -1;
943   else
944     args.ihandle = device_instance_to_external(ihandle);
945   /* return the ihandle result */
946   TRACE(trace_os_emul, ("open - out - ihandle=0x%lx(0x%lx`%s')\n",
947 			(unsigned long)args.ihandle,
948 			(unsigned long)ihandle,
949 			ihandle_name(ihandle)));
950   chirp_write_h2t_args(&args,
951 		       sizeof(args),
952 		       data,
953 		       processor, cia);
954   return 0;
955 }
956 
957 static int
chirp_emul_close(os_emul_data * data,cpu * processor,unsigned_word cia)958 chirp_emul_close(os_emul_data *data,
959 		 cpu *processor,
960 		 unsigned_word cia)
961 {
962   struct close_args {
963     /*in*/
964     unsigned_cell ihandle;
965     /*out*/
966   } args;
967   device_instance *ihandle;
968   /* read the args */
969   if (chirp_read_t2h_args(&args, sizeof(args), 1, 0, data, processor, cia))
970     return -1;
971   ihandle = external_to_device_instance(data->root, args.ihandle);
972   TRACE(trace_os_emul, ("close - in - ihandle=0x%lx(0x%lx`%s')\n",
973 			(unsigned long)args.ihandle,
974 			(unsigned long)ihandle,
975 			ihandle_name(ihandle)));
976   /* close the device */
977   if (ihandle == NULL) {
978     /* OpenFirmware doesn't define this error */
979     error("chirp: invalid ihandle passed to close method");
980   }
981   else {
982     device_instance_delete(ihandle);
983   }
984   /* return the ihandle result */
985   TRACE(trace_os_emul, ("close - out\n"));
986   chirp_write_h2t_args(&args,
987 		       sizeof(args),
988 		       data,
989 		       processor, cia);
990   return 0;
991 }
992 
993 static int
chirp_emul_read(os_emul_data * data,cpu * processor,unsigned_word cia)994 chirp_emul_read(os_emul_data *data,
995 		cpu *processor,
996 		unsigned_word cia)
997 {
998   struct read_args {
999     /*in*/
1000     unsigned_cell ihandle;
1001     unsigned_cell addr;
1002     unsigned_cell len;
1003     /*out*/
1004     unsigned_cell actual;
1005   } args;
1006   char buf[1024];
1007   device_instance *ihandle;
1008   /* read the args */
1009   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
1010     return -1;
1011   ihandle = external_to_device_instance(data->root, args.ihandle);
1012   TRACE(trace_os_emul, ("read - in - ihandle=0x%lx(0x%lx`%s') addr=0x%lx len=%ld\n",
1013 			(unsigned long)args.ihandle,
1014 			(unsigned long)ihandle,
1015 			ihandle_name(ihandle),
1016 			(unsigned long)args.addr,
1017 			(unsigned long)args.len));
1018   if (ihandle == NULL) {
1019     /* OpenFirmware doesn't define this error */
1020     error("chirp: invalid ihandle passed to read method");
1021   }
1022   else {
1023     /* do the reads */
1024     int actual = 0;
1025     while (actual < args.len) {
1026       int remaining = args.len - actual;
1027       int to_read = (remaining <= sizeof(buf) ? remaining : sizeof(buf));
1028       int nr_read = device_instance_read(ihandle, buf, to_read);
1029       if (nr_read < 0) {
1030 	actual = nr_read; /* the error */
1031 	break;
1032       }
1033       else if (nr_read == 0) {
1034 	break;
1035       }
1036       emul_write_buffer(buf,
1037 			args.addr + actual,
1038 			nr_read,
1039 			processor, cia);
1040       actual += nr_read;
1041     }
1042     if (actual >= 0) {
1043       args.actual = actual;
1044       if (actual < sizeof(buf))
1045 	buf[actual] = '\0';
1046       else
1047 	buf[sizeof(buf) - 1] = '\0';
1048     }
1049     else {
1050       switch (actual) {
1051       case sim_io_eof:
1052 	args.actual = 0;
1053 	break;
1054       case sim_io_not_ready:
1055 	ASSERT(sim_io_not_ready == -2);
1056 	args.actual = sim_io_not_ready;
1057 	break;
1058       default:
1059 	error("Bad error value %ld", (long)actual);
1060 	break;
1061       }
1062     }
1063   }
1064   /* return the result */
1065   TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n",
1066 			(long)args.actual,
1067 			((args.actual > 0 && args.actual < sizeof(buf)) ? buf : "")
1068 			));
1069   chirp_write_h2t_args(&args,
1070 		       sizeof(args),
1071 		       data,
1072 		       processor, cia);
1073   return 0;
1074 }
1075 
1076 static int
chirp_emul_write(os_emul_data * data,cpu * processor,unsigned_word cia)1077 chirp_emul_write(os_emul_data *data,
1078 		 cpu *processor,
1079 		 unsigned_word cia)
1080 {
1081   struct write_args {
1082     /*in*/
1083     unsigned_cell ihandle;
1084     unsigned_cell addr;
1085     unsigned_cell len;
1086     /*out*/
1087     unsigned_cell actual;
1088   } args;
1089   char buf[1024];
1090   device_instance *ihandle;
1091   int actual;
1092   /* get the args */
1093   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
1094     return -1;
1095   actual = args.len;
1096   if (actual >= sizeof(buf))
1097     actual = sizeof(buf) - 1;
1098   emul_read_buffer(buf,
1099 		   args.addr,
1100 		   actual,
1101 		   processor, cia);
1102   buf[actual] = '\0';
1103   ihandle = external_to_device_instance(data->root, args.ihandle);
1104   TRACE(trace_os_emul, ("write - in - ihandle=0x%lx(0x%lx`%s') `%s' (%ld)\n",
1105 			(unsigned long)args.ihandle,
1106 			(unsigned long)ihandle,
1107 			ihandle_name(ihandle),
1108 			buf, (long)actual));
1109   if (ihandle == NULL) {
1110     /* OpenFirmware doesn't define this error */
1111     error("chirp: invalid ihandle passed to write method");
1112   }
1113   else {
1114     /* write it out */
1115     actual = device_instance_write(ihandle, buf, actual);
1116     if (actual < 0)
1117       args.actual = 0;
1118     else
1119       args.actual = actual;
1120   }
1121   /* return the result */
1122   TRACE(trace_os_emul, ("write - out - actual=%ld\n",
1123 			(long)args.actual));
1124   chirp_write_h2t_args(&args,
1125 		       sizeof(args),
1126 		       data,
1127 		       processor, cia);
1128   return 0;
1129 }
1130 
1131 static int
chirp_emul_seek(os_emul_data * data,cpu * processor,unsigned_word cia)1132 chirp_emul_seek(os_emul_data *data,
1133 		cpu *processor,
1134 		unsigned_word cia)
1135 {
1136   struct seek_args {
1137     /*in*/
1138     unsigned_cell ihandle;
1139     unsigned_cell pos_hi;
1140     unsigned_cell pos_lo;
1141     /*out*/
1142     unsigned_cell status;
1143   } args;
1144   int status;
1145   device_instance *ihandle;
1146   /* get the args */
1147   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
1148     return -1;
1149   ihandle = external_to_device_instance(data->root, args.ihandle);
1150   TRACE(trace_os_emul, ("seek - in - ihandle=0x%lx(0x%lx`%s') pos.hi=0x%lx pos.lo=0x%lx\n",
1151 			(unsigned long)args.ihandle,
1152 			(unsigned long)ihandle,
1153 			ihandle_name(ihandle),
1154 			args.pos_hi, args.pos_lo));
1155   if (ihandle == NULL) {
1156     /* OpenFirmware doesn't define this error */
1157     error("chirp: invalid ihandle passed to seek method");
1158   }
1159   else {
1160     /* seek it out */
1161     status = device_instance_seek(ihandle, args.pos_hi, args.pos_lo);
1162     args.status = status;
1163   }
1164   /* return the result */
1165   TRACE(trace_os_emul, ("seek - out - status=%ld\n",
1166 			(long)args.status));
1167   chirp_write_h2t_args(&args,
1168 		       sizeof(args),
1169 		       data,
1170 		       processor, cia);
1171   return 0;
1172 }
1173 
1174 
1175 /* memory */
1176 
1177 static int
chirp_emul_claim(os_emul_data * data,cpu * processor,unsigned_word cia)1178 chirp_emul_claim(os_emul_data *data,
1179 		 cpu *processor,
1180 		 unsigned_word cia)
1181 {
1182   /* NOTE: the client interface claim routine is *very* different to
1183      the "claim" method described in IEEE-1275 appendix A.  The latter
1184      uses real addresses while this uses virtual (effective)
1185      addresses. */
1186   struct claim_args {
1187     /* in */
1188     unsigned_cell virt;
1189     unsigned_cell size;
1190     unsigned_cell align;
1191     /* out */
1192     unsigned_cell baseaddr;
1193   } args;
1194   /* read the args */
1195   if (chirp_read_t2h_args(&args, sizeof(args),
1196 			  3 /*n_args*/, 1 /*n_returns*/,
1197 			  data, processor, cia))
1198     return -1;
1199   TRACE(trace_os_emul, ("claim - in - virt=0x%lx size=%ld align=%d\n",
1200 			(unsigned long)args.virt,
1201 			(long int)args.size,
1202 			(int)args.align));
1203   /* use the memory device to allocate (real) memory at the requested
1204      address */
1205   {
1206     device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory");
1207     unsigned_cell mem_in[3];
1208     unsigned_cell mem_out[1];
1209     mem_in[0] = args.align; /*top-of-stack*/
1210     mem_in[1] = args.size;
1211     mem_in[2] = args.virt;
1212     if (device_instance_call_method(memory, "claim",
1213 				    3, mem_in, 1, mem_out) < 0)
1214       error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d",
1215 	    (unsigned long)args.virt,
1216 	    (long int)args.size,
1217 	    (int)args.align);
1218     args.baseaddr = mem_out[0];
1219   }
1220   /* if using virtual addresses, create a 1-1 map of this address space */
1221   if (!data->real_mode) {
1222     error("chirp: claim method does not support virtual mode");
1223   }
1224   /* return the base address */
1225   TRACE(trace_os_emul, ("claim - out - baseaddr=0x%lx\n",
1226 			(unsigned long)args.baseaddr));
1227   chirp_write_h2t_args(&args,
1228 		       sizeof(args),
1229 		       data,
1230 		       processor, cia);
1231   return 0;
1232 }
1233 
1234 static int
chirp_emul_release(os_emul_data * data,cpu * processor,unsigned_word cia)1235 chirp_emul_release(os_emul_data *data,
1236 		   cpu *processor,
1237 		   unsigned_word cia)
1238 {
1239   /* NOTE: the client interface release routine is *very* different to
1240      the "claim" method described in IEEE-1275 appendix A.  The latter
1241      uses real addresses while this uses virtual (effective)
1242      addresses. */
1243   struct claim_args {
1244     /* in */
1245     unsigned_cell virt;
1246     unsigned_cell size;
1247     /* out */
1248   } args;
1249   /* read the args */
1250   if (chirp_read_t2h_args(&args, sizeof(args),
1251 			  2 /*n_args*/, 0 /*n_returns*/,
1252 			  data, processor, cia))
1253     return -1;
1254   TRACE(trace_os_emul, ("release - in - virt=0x%lx size=%ld\n",
1255 			(unsigned long)args.virt,
1256 			(long int)args.size));
1257   /* use the memory device to release (real) memory at the requested
1258      address */
1259   {
1260     device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory");
1261     unsigned_cell mem_in[2];
1262     mem_in[0] = args.size;
1263     mem_in[1] = args.virt;
1264     if (device_instance_call_method(memory, "release",
1265 				    2, mem_in, 0, NULL) < 0)
1266       error("chirp: claim failed to release memory virt=0x%lx size=%ld",
1267 	    (unsigned long)args.virt,
1268 	    (long int)args.size);
1269   }
1270   /* if using virtual addresses, remove the 1-1 map of this address space */
1271   if (!data->real_mode) {
1272     error("chirp: release method does not support virtual mode");
1273   }
1274   /* return the base address */
1275   TRACE(trace_os_emul, ("release - out\n"));
1276   chirp_write_h2t_args(&args,
1277 		       sizeof(args),
1278 		       data,
1279 		       processor, cia);
1280   return 0;
1281 }
1282 
1283 
1284 /* Control transfer */
1285 
1286 static int
chirp_emul_boot(os_emul_data * data,cpu * processor,unsigned_word cia)1287 chirp_emul_boot(os_emul_data *data,
1288 		cpu *processor,
1289 		unsigned_word cia)
1290 {
1291   /* unlike OpenFirmware this one can take an argument */
1292   struct boot_args {
1293     /*in*/
1294     unsigned_cell bootspec;
1295     /*out*/
1296   } args;
1297   char bootspec[1024];
1298   /* read in the arguments */
1299   if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia))
1300     cpu_halt(processor, cia, was_exited, -1);
1301   if (args.bootspec != 0)
1302     emul_read_string(bootspec, args.bootspec, sizeof(bootspec),
1303 		     processor, cia);
1304   else
1305     strcpy(bootspec, "(null)");
1306   TRACE(trace_os_emul, ("boot - in bootspec=`%s'\n", bootspec));
1307   /* just report this and exit */
1308   printf_filtered("chrp: boot %s called, exiting.\n", bootspec);
1309   cpu_halt(processor, cia, was_exited, 0);
1310   return 0;
1311 }
1312 
1313 static int
chirp_emul_enter(os_emul_data * data,cpu * processor,unsigned_word cia)1314 chirp_emul_enter(os_emul_data *data,
1315 		 cpu *processor,
1316 		 unsigned_word cia)
1317 {
1318   error("chirp: enter method not implemented\n");
1319   return 0;
1320 }
1321 
1322 static int
chirp_emul_exit(os_emul_data * data,cpu * processor,unsigned_word cia)1323 chirp_emul_exit(os_emul_data *data,
1324 		cpu *processor,
1325 		unsigned_word cia)
1326 {
1327   /* unlike OpenBoot this one can take an argument */
1328   struct exit_args {
1329     /*in*/
1330     signed_cell status;
1331     /*out*/
1332   } args;
1333   if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia))
1334     cpu_halt(processor, cia, was_exited, -1);
1335   cpu_halt(processor, cia, was_exited, args.status);
1336   return 0;
1337 }
1338 
1339 static int
chirp_emul_chain(os_emul_data * data,cpu * processor,unsigned_word cia)1340 chirp_emul_chain(os_emul_data *data,
1341 		 cpu *processor,
1342 		 unsigned_word cia)
1343 {
1344   error("chirp: chain method not implemented\n");
1345   return 0;
1346 }
1347 
1348 
1349 /* user interface */
1350 
1351 static int
chirp_emul_interpret(os_emul_data * data,cpu * processor,unsigned_word cia)1352 chirp_emul_interpret(os_emul_data *data,
1353 		     cpu *processor,
1354 		     unsigned_word cia)
1355 {
1356   error("chirp: interpret method not implemented\n");
1357   return 0;
1358 }
1359 
1360 static int
chirp_emul_set_callback(os_emul_data * data,cpu * processor,unsigned_word cia)1361 chirp_emul_set_callback(os_emul_data *data,
1362 			cpu *processor,
1363 			unsigned_word cia)
1364 {
1365   error("chirp: set_callback method not implemented\n");
1366   return 0;
1367 }
1368 
1369 static int
chirp_emul_set_symbol_lookup(os_emul_data * data,cpu * processor,unsigned_word cia)1370 chirp_emul_set_symbol_lookup(os_emul_data *data,
1371 			     cpu *processor,
1372 			     unsigned_word cia)
1373 {
1374   error("chirp: set_symbol_lookup method not implemented\n");
1375   return 0;
1376 }
1377 
1378 
1379 /* Time */
1380 
1381 static int
chirp_emul_milliseconds(os_emul_data * data,cpu * processor,unsigned_word cia)1382 chirp_emul_milliseconds(os_emul_data *data,
1383 			cpu *processor,
1384 			unsigned_word cia)
1385 {
1386   struct test_args {
1387     /*in*/
1388     /*out*/
1389     unsigned_cell ms;
1390   } args;
1391   unsigned64 time;
1392   /* read in the arguments */
1393   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
1394     return -1;
1395   /* make up a number */
1396   time = event_queue_time(psim_event_queue(cpu_system(processor))) / 1000000;
1397   args.ms = time;
1398   /* write the arguments back out */
1399   TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n",
1400 			(unsigned long)args.ms));
1401   chirp_write_h2t_args(&args,
1402 		       sizeof(args),
1403 		       data,
1404 		       processor, cia);
1405   return 0;
1406 }
1407 
1408 
1409 
1410 
1411 static chirp_services services[] = {
1412 
1413   /* client interface */
1414   { "test", chirp_emul_test },
1415 
1416   /* device tree */
1417   { "peer", chirp_emul_peer },
1418   { "child", chirp_emul_child },
1419   { "parent", chirp_emul_parent },
1420   { "instance-to-package", chirp_emul_instance_to_package },
1421   { "getproplen", chirp_emul_getproplen },
1422   { "getprop", chirp_emul_getprop },
1423   { "nextprop", chirp_emul_nextprop },
1424   /* { "setprop", chirp_emul_setprop }, */
1425   { "canon", chirp_emul_canon },
1426   { "finddevice", chirp_emul_finddevice },
1427   { "instance-to-path", chirp_emul_instance_to_path },
1428   { "package-to-path", chirp_emul_package_to_path },
1429   { "call-method", chirp_emul_call_method },
1430 
1431   /* device I/O */
1432   { "open", chirp_emul_open },
1433   { "close", chirp_emul_close },
1434   { "read", chirp_emul_read },
1435   { "write", chirp_emul_write },
1436   { "seek", chirp_emul_seek },
1437   { "write", chirp_emul_write },
1438 
1439   /* memory */
1440   { "claim", chirp_emul_claim },
1441   { "release", chirp_emul_release },
1442 
1443   /* control transfer */
1444   { "boot", chirp_emul_boot },
1445   { "enter", chirp_emul_enter },
1446   { "exit", chirp_emul_exit },
1447   { "chain", chirp_emul_chain },
1448 
1449   /* user interface */
1450   { "interpret", chirp_emul_interpret },
1451   { "set_callback", chirp_emul_set_callback },
1452   { "set_symbol_lookup", chirp_emul_set_symbol_lookup },
1453 
1454   /* time */
1455   { "milliseconds", chirp_emul_milliseconds },
1456 
1457   { 0, /* sentinal */ },
1458 };
1459 
1460 
1461 /* main handlers */
1462 
1463 /* Any starting address greater than this is assumed to be an Chirp
1464    rather than VEA */
1465 
1466 #ifndef CHIRP_START_ADDRESS
1467 #define CHIRP_START_ADDRESS 0x80000000
1468 #endif
1469 #ifndef CHIRP_LOAD_BASE
1470 #define CHIRP_LOAD_BASE -1
1471 #endif
1472 
1473 
1474 typedef struct _chirp_note_desc {
1475   signed32 real_mode;
1476   signed32 real_base;
1477   signed32 real_size;
1478   signed32 virt_base;
1479   signed32 virt_size;
1480   signed32 load_base;
1481 } chirp_note_desc;
1482 
1483 typedef enum {
1484   note_missing,
1485   note_found,
1486   note_correct,
1487 } note_found_status;
1488 typedef struct _chirp_note {
1489   chirp_note_desc desc;
1490   note_found_status found;
1491 } chirp_note;
1492 
1493 typedef struct _chirp_note_head {
1494   unsigned32 namesz;
1495   unsigned32 descsz;
1496   unsigned32 type;
1497 } chirp_note_head;
1498 
1499 static void
map_over_chirp_note(bfd * image,asection * sect,PTR obj)1500 map_over_chirp_note(bfd *image,
1501 		    asection *sect,
1502 		    PTR obj)
1503 {
1504   chirp_note *note = (chirp_note*)obj;
1505   if (strcmp(sect->name, ".note") == 0) {
1506     chirp_note_head head;
1507     char name[16];
1508     /* check the head */
1509     if (!bfd_get_section_contents(image, sect,
1510 				  &head, 0, sizeof(head)))
1511       return;
1512     head.namesz = bfd_get_32(image, (void*)&head.namesz);
1513     head.descsz = bfd_get_32(image, (void*)&head.descsz);
1514     head.type = bfd_get_32(image, (void*)&head.type);
1515     if (head.type != 0x1275)
1516       return;
1517     /* check the name field */
1518     if (head.namesz > sizeof(name)) {
1519       error("chirp: note name too long (%d > %d)\n", (int)head.namesz, sizeof(name));
1520     }
1521     if (!bfd_get_section_contents(image, sect,
1522 				  name, sizeof(head), head.namesz)) {
1523       error("chirp: note name unreadable\n");
1524     }
1525     if (strcmp(name, "PowerPC") != 0) {
1526       printf_filtered("chirp: note name (%s) not `PowerPC'\n", name);
1527     }
1528     /* check the size */
1529     if (head.descsz == sizeof(note->desc) - sizeof(signed32)) {
1530       sim_io_printf_filtered("chirp: note descriptor missing load-base\n");
1531     }
1532     else if (head.descsz != sizeof(note->desc)) {
1533       sim_io_printf_filtered("chirp: note descriptor of wrong size\n");
1534       note->found = note_found;
1535       return;
1536     }
1537     note->found = note_correct;
1538     /* get the contents */
1539     if (!bfd_get_section_contents(image, sect,
1540 				  &note->desc, /* page align start */
1541 				  ((sizeof(head) + head.namesz) + 3) & ~3,
1542 				  head.descsz)) {
1543       error("chirp: note descriptor unreadable\n");
1544     }
1545     note->desc.real_mode = bfd_get_32(image, (void*)&note->desc.real_mode);
1546     note->desc.real_base = bfd_get_32(image, (void*)&note->desc.real_base);
1547     note->desc.real_size = bfd_get_32(image, (void*)&note->desc.real_size);
1548     note->desc.virt_base = bfd_get_32(image, (void*)&note->desc.virt_base);
1549     note->desc.virt_size = bfd_get_32(image, (void*)&note->desc.virt_size);
1550     if (head.descsz == sizeof(note->desc))
1551       note->desc.load_base = bfd_get_32(image, (void*)&note->desc.load_base);
1552     else
1553       note->desc.load_base = (signed32)-1;
1554   }
1555 }
1556 
1557 
1558 static os_emul_data *
emul_chirp_create(device * root,bfd * image,const char * name)1559 emul_chirp_create(device *root,
1560 		  bfd *image,
1561 		  const char *name)
1562 {
1563   os_emul_data *chirp;
1564   device *node;
1565   chirp_note note;
1566   int i;
1567 
1568   /* Sanity check that this really is the chosen emulation */
1569   if (name == NULL && image == NULL)
1570     return NULL;
1571   if (name != NULL
1572       && strcmp(name, "ob") != 0
1573       && strcmp(name, "ieee1274") != 0
1574       && strcmp(name, "chrp") != 0
1575       && strcmp(name, "chirp") != 0
1576       && strcmp(name, "openboot") != 0)
1577     return NULL;
1578 
1579   /* look for an elf note section, enter its values into the device tree */
1580   memset(&note, 0, sizeof(note));
1581   if (image != NULL)
1582     bfd_map_over_sections(image, map_over_chirp_note, &note);
1583   if (name == NULL && image != NULL && note.found == note_missing)
1584     return NULL;
1585 
1586   /* Assume that it is a chirp emulation */
1587 
1588   chirp = ZALLOC(os_emul_data);
1589   chirp->root = root;
1590   chirp->services = services;
1591 
1592   /* the root node */
1593   tree_parse(root, "/name \"gpl,clayton");
1594 
1595   /* default options */
1596   emul_add_tree_options(root, image, "chirp", "oea",
1597 			0 /*oea-interrupt-prefix*/);
1598 
1599   /* hardware */
1600   emul_add_tree_hardware(root);
1601 
1602   /* basic information */
1603   chirp->memory_size
1604     = tree_find_integer_property(root, "/openprom/options/oea-memory-size");
1605   chirp->little_endian
1606     = tree_find_boolean_property(root, "/options/little-endian?");
1607   chirp->floating_point_available
1608     = tree_find_boolean_property(root, "/openprom/options/floating-point?");
1609   chirp->interrupt_prefix =
1610     tree_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
1611 
1612 
1613   /* Perform an interum layout of the openboot firmware in memory */
1614 
1615 
1616   /* a page for firmware calls */
1617   chirp->sizeof_code = 4096;
1618   chirp->code_offset = 0x4000; /* possible space for interrupt table */
1619 
1620   /* the stack */
1621   chirp->sizeof_stack = 32 * 1024;
1622   chirp->stack_offset = chirp->code_offset + chirp->sizeof_code;
1623 
1624   /* the hash table */
1625   if (!note.desc.real_mode) {
1626     chirp->nr_page_table_entry_groups = (chirp->memory_size < 0x800000
1627 					 ? 1024 /* min allowed */
1628 					 : (chirp->memory_size / 4096 / 2));
1629     chirp->sizeof_htab = chirp->nr_page_table_entry_groups * 64;
1630   }
1631   chirp->htab_offset = chirp->stack_offset + chirp->sizeof_stack;
1632 
1633   /* the actual amount of space needed */
1634   chirp->real_size = chirp->htab_offset + chirp->sizeof_htab;
1635 
1636 
1637   /* now go through and see if it fits in what is available */
1638 
1639 
1640   /* resolve real-mode? */
1641   if (note.found == note_correct)
1642     chirp->real_mode = note.desc.real_mode;
1643   else if (tree_find_property(root, "/options/real-mode?") != NULL)
1644     chirp->real_mode = tree_find_boolean_property(root, "/options/real-mode?");
1645   else
1646     chirp->real_mode = 0;
1647   if (tree_find_property(root, "/options/real-mode?") != NULL) {
1648     if (!chirp->real_mode
1649 	!= !tree_find_boolean_property(root, "/options/real-mode?"))
1650       error("chirp: /options/real-mode? conflicts with note section\n");
1651   }
1652   else
1653     tree_parse(root, "/options/real-mode? %s",
1654 	       chirp->real_mode ? "true" : "false");
1655 
1656   /* resolve real-base */
1657   if (note.found == note_correct
1658       && note.desc.real_base != (signed32)-1)
1659     chirp->real_base = note.desc.real_base;
1660   else if (tree_find_property(root, "/options/real-base") != NULL)
1661     chirp->real_base = tree_find_integer_property(root, "/options/real-base");
1662   else
1663     chirp->real_base = chirp->memory_size - chirp->real_size;
1664   if (tree_find_property(root, "/options/real-base") != NULL) {
1665     if (chirp->real_base != tree_find_integer_property(root, "/options/real-base"))
1666       error("chirp: /options/real-base conflicts with note section\n");
1667   }
1668   else
1669     tree_parse(root, "/options/real-base 0x%lx",
1670 	       (unsigned long)chirp->real_base);
1671 
1672   /* resolve real-size */
1673   if (note.found == note_correct
1674       && note.desc.real_size != (signed32)-1
1675       && note.desc.real_size != 0
1676       && chirp->real_size > note.desc.real_size)
1677     error("chirp: insufficient physical memory for firmware\n");
1678   if (tree_find_property(root, "/options/real-size") != NULL) {
1679     if (chirp->real_size > tree_find_integer_property(root, "/options/real-size"))
1680       error("chirp: /options/real-size conflicts with note section\n");
1681   }
1682   else
1683     tree_parse(root, "/options/real-size 0x%lx",
1684 	       (unsigned long)chirp->real_size);
1685 
1686   /* resolve virt-base */
1687   if (chirp->real_mode)
1688     chirp->virt_base = chirp->real_base;
1689   else if (note.found == note_correct && note.desc.virt_base != -1)
1690     chirp->virt_base = note.desc.virt_base;
1691   else if (tree_find_property(root, "/options/virt-base") != NULL)
1692     chirp->virt_base = tree_find_integer_property(root, "/options/virt-base");
1693   else
1694     chirp->virt_base = CHIRP_START_ADDRESS;
1695   if (tree_find_property(root, "/options/virt-base") != NULL) {
1696     unsigned_word virt_base = tree_find_integer_property(root, "/options/virt-base");
1697     if (virt_base != -1 && chirp->virt_base != virt_base)
1698       error("chirp: /options/virt-base conflicts with note section\n");
1699   }
1700   else
1701     tree_parse(root, "/options/virt-base 0x%lx",
1702 	       chirp->real_mode ? -1 : (unsigned long)chirp->virt_base);
1703 
1704   /* resolve virt-size */
1705   chirp->virt_size = chirp->real_size;
1706   if (note.found == note_correct
1707      && note.desc.virt_size != (signed32)-1
1708       && note.desc.virt_size != 0
1709       && !chirp->real_mode
1710       && chirp->virt_size > note.desc.virt_size)
1711     error("chirp: insufficent virtual memory for firmware\n");
1712   if (tree_find_property(root, "/options/virt-size") != NULL) {
1713     if (chirp->virt_size > tree_find_integer_property(root, "/options/virt-size"))
1714       error("chirp: /options/virt-size conflicts with note section\n");
1715   }
1716   else
1717     tree_parse(root, "/options/virt-size 0x%lx",
1718 	       chirp->real_mode ? -1 : (unsigned long)chirp->virt_size);
1719 
1720   /* resolve load-base */
1721   if (note.found == note_correct
1722       && note.desc.load_base != (signed32)-1)
1723     chirp->load_base = note.desc.load_base;
1724   else if (tree_find_property(root, "/options/load-base") != NULL)
1725     chirp->load_base = tree_find_integer_property(root, "/options/load-base");
1726   else
1727     chirp->load_base = CHIRP_LOAD_BASE;
1728   if (tree_find_property(root, "/options/load-base") != NULL) {
1729     if (chirp->load_base != tree_find_integer_property(root, "/options/load-base"))
1730       error("chirp: /options/load-base conflicts with note section\n");
1731   }
1732   else
1733     tree_parse(root, "/options/load-base 0x%lx",
1734 	       (unsigned long)chirp->load_base);
1735 
1736   /* now adjust the preliminary firmware addresses to final values */
1737   chirp->code_ra = chirp->code_offset + chirp->real_base;
1738   chirp->stack_ra = chirp->stack_offset + chirp->real_base;
1739   chirp->htab_ra = chirp->htab_offset + chirp->real_base;
1740 
1741   /* the virtual addresses.  In real mode these are real addresses. */
1742 
1743   chirp->code_va = chirp->code_offset + chirp->virt_base;
1744   chirp->stack_va = chirp->stack_offset + chirp->virt_base;
1745   chirp->htab_va = chirp->htab_offset + chirp->virt_base;
1746 
1747   chirp->code_client_va = chirp->code_va;
1748   chirp->code_client_ra = chirp->code_ra;
1749 
1750   chirp->code_callback_va = chirp->code_client_va + 16;
1751   chirp->code_callback_ra = chirp->code_client_ra + 16;
1752 
1753   chirp->code_loop_va = chirp->code_callback_va + 16;
1754   chirp->code_loop_ra = chirp->code_callback_ra + 16;
1755 
1756   /* initialization */
1757 
1758   tree_parse(root, "/openprom/init");
1759   tree_parse(root, "/openprom/init/register");
1760   tree_parse(root, "/openprom/init/register/0.pc 0x%lx",
1761 	     (unsigned long)bfd_get_start_address(image));
1762   tree_parse(root, "/openprom/init/register/pc 0x%lx",
1763 	     (unsigned long)chirp->code_loop_va);
1764   tree_parse(root, "/openprom/init/register/msr 0x%x",
1765 	     (msr_machine_check_enable
1766 	      | (chirp->real_mode
1767 		 ? 0
1768 		 : (msr_instruction_relocate
1769 		    | msr_data_relocate))
1770 	      | (chirp->little_endian
1771 		 ? (msr_little_endian_mode
1772 		    | msr_interrupt_little_endian_mode)
1773 		 : 0)
1774 	      | (chirp->floating_point_available
1775 		 ? msr_floating_point_available
1776 		 : 0)
1777 	      | (chirp->interrupt_prefix
1778 		 ? msr_interrupt_prefix
1779 		 : 0)
1780 	      ));
1781   tree_parse(root, "/openprom/init/register/sdr1 0x%lx",
1782 	     (unsigned long)(chirp->htab_ra
1783 			     | MASK32(16, 22)
1784 			     | ((chirp->sizeof_htab - 1) >> 16)));
1785   /* make certain that the segment registers map straight through */
1786   for (i = 0; i < 16; i++) {
1787     tree_parse(root, "/openprom/init/register/sr%d 0x%lx",
1788 	       i, (unsigned long)i);
1789   }
1790 
1791   /* establish an initial state for all processors */
1792 
1793 
1794   /* the client interface address */
1795   tree_parse(root, "/openprom/init/register/r5 0x%lx",
1796 	     (unsigned long)chirp->code_client_va);
1797   /* a stack */
1798   tree_parse(root, "/openprom/init/register/sp 0x%lx",
1799 	     (unsigned long)(chirp->stack_va + chirp->sizeof_stack - 16));
1800   /* in chrp mode any arguments end up being concatinated */
1801   tree_parse(root, "/openprom/init/stack/stack-type chirp");
1802 
1803 
1804   /* client interface - emul-call followed by return instruction */
1805 
1806 
1807   node = tree_parse(root, "/openprom/init/data@0x%lx",
1808 		    (unsigned long)chirp->code_client_ra);
1809   tree_parse(node, "./psim,description \"client-interface instruction");
1810   tree_parse(node, "./real-address 0x%lx",
1811 	     (unsigned long)chirp->code_client_ra);
1812   tree_parse(node, "./data 0x%lx",
1813 	     (unsigned long)emul_call_instruction);
1814 
1815   node = tree_parse(root, "/openprom/init/data@0x%lx",
1816 		    (unsigned long)(chirp->code_client_ra + 4));
1817   tree_parse(node, "./psim,description \"client-interface return instruction");
1818   tree_parse(node, "./real-address 0x%lx",
1819 	     (unsigned long)(chirp->code_client_ra + 4));
1820   tree_parse(node, "./data 0x%lx",
1821 	     (unsigned long)emul_blr_instruction);
1822 
1823 
1824   /* return address for client callbacks - an emul-call instruction
1825      that is again followed by a return instruction */
1826 
1827 
1828   node = tree_parse(root, "/openprom/init/data@0x%lx",
1829 		    (unsigned long)chirp->code_callback_ra);
1830   tree_parse(node, "./psim,description \"client-callback instruction");
1831   tree_parse(node, "./real-address 0x%lx",
1832 	     (unsigned long)chirp->code_callback_ra);
1833   tree_parse(node, "./data 0x%lx",
1834 	     (unsigned long)emul_call_instruction);
1835 
1836   node = tree_parse(root, "/openprom/init/data@0x%lx",
1837 		    (unsigned long)(chirp->code_callback_ra + 4));
1838   tree_parse(node, "./psim,description \"client-callback return instruction");
1839   tree_parse(node, "./real-address 0x%lx",
1840 	     (unsigned long)(chirp->code_callback_ra + 4));
1841   tree_parse(node, "./data 0x%lx",
1842 	     (unsigned long)emul_blr_instruction);
1843 
1844   /* loop to keep other processors busy */
1845 
1846   node = tree_parse(root, "/openprom/init/data@0x%lx",
1847 		    (unsigned long)chirp->code_loop_ra);
1848   tree_parse(node, "./psim,description \"processor busy loop");
1849   tree_parse(node, "./real-address 0x%lx",
1850 	     (unsigned long)chirp->code_loop_ra);
1851   tree_parse(node, "./data 0x%lx",
1852 	     (unsigned long)emul_loop_instruction);
1853 
1854   /* hash table */
1855 
1856   /* create a hash table */
1857 
1858   if (!chirp->real_mode) {
1859     node = tree_parse(root, "/openprom/init/htab@0x%lx",
1860 		      (unsigned long)chirp->htab_ra);
1861     tree_parse(node, "./claim 0");
1862     tree_parse(node, "./real-address 0x%lx",
1863 	       (unsigned long)chirp->htab_ra);
1864     tree_parse(node, "./nr-bytes 0x%lx",
1865 	       (unsigned long)chirp->sizeof_htab);
1866   }
1867 
1868   /* map in the stack */
1869 
1870   if (!chirp->real_mode) {
1871     node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
1872 		      (unsigned long)chirp->stack_ra);
1873     tree_parse(node, "./psim,description \"map in the stack");
1874     tree_parse(node, "./claim 1");
1875     tree_parse(node, "./virtual-address 0x%lx",
1876 	       (unsigned long)chirp->stack_va);
1877     tree_parse(node, "./real-address 0x%lx",
1878 	       (unsigned long)chirp->stack_ra);
1879     tree_parse(node, "./nr-bytes 0x%lx",
1880 	       (unsigned long)chirp->sizeof_stack);
1881     tree_parse(node, "./wimg %d", 0x7);
1882     tree_parse(node, "./pp %d", 0x2);
1883   }
1884 
1885   /* map in the chrp openboot callback code */
1886 
1887   if (!chirp->real_mode) {
1888     node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
1889 		      (unsigned long)chirp->code_ra);
1890     tree_parse(node, "./psim,description \"map in chrp openboot callback code");
1891     tree_parse(node, "./claim 1");
1892     tree_parse(node, "./virtual-address 0x%lx",
1893 	       (unsigned long)chirp->code_va);
1894     tree_parse(node, "./real-address 0x%lx",
1895 	       (unsigned long)chirp->code_ra);
1896     tree_parse(node, "./nr-bytes 0x%lx",
1897 	       (unsigned long)chirp->sizeof_code);
1898     tree_parse(node, "./wimg %d", 0x7);
1899     tree_parse(node, "./pp %d", 0x2);
1900   }
1901 
1902   /* map in the program to run */
1903 
1904   if (chirp->real_mode) {
1905     node = tree_parse(node, "/openprom/init/load-binary");
1906     tree_parse(node, "./psim,description \"load the binary");
1907     tree_parse(node, "./file-name %s", bfd_get_filename(image));
1908     tree_parse(node, "./claim 1");
1909   }
1910   else {
1911     node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
1912 		      (unsigned long)chirp->load_base);
1913     tree_parse(node, "./psim,description \"load & map the binary");
1914     tree_parse(node, "./claim 1");
1915     tree_parse(node, "./file-name \"%s", bfd_get_filename(image));
1916     tree_parse(node, "./wimg %d", 0x7);
1917     tree_parse(node, "./pp %d", 0x2);
1918   }
1919 
1920   /* map in the interrupt vectors */
1921 
1922   if (!chirp->real_mode) {
1923     node = tree_parse(root, "/openprom/init/htab/pte@0x0");
1924     tree_parse(node, "./psim,description \"map in interrupt vectors");
1925     tree_parse(node, "./virtual-address 0x0");
1926     tree_parse(node, "./real-address 0x0");
1927     tree_parse(node, "./nr-bytes 0x3000");
1928     tree_parse(node, "./wimg %d", 0x7);
1929     tree_parse(node, "./pp %d", 0x2);
1930   }
1931 
1932   return chirp;
1933 }
1934 
1935 static void
emul_chirp_init(os_emul_data * emul_data,int nr_cpus)1936 emul_chirp_init(os_emul_data *emul_data,
1937 		int nr_cpus)
1938 {
1939   emul_data->state = serving;
1940 }
1941 
1942 static int
emul_chirp_instruction_call(cpu * processor,unsigned_word cia,unsigned_word ra,os_emul_data * emul_data)1943 emul_chirp_instruction_call(cpu *processor,
1944 			    unsigned_word cia,
1945 			    unsigned_word ra,
1946 			    os_emul_data *emul_data)
1947 {
1948   unsigned_word service_name_addr;
1949   unsigned_word result;
1950   char service_buf[32];
1951   char *service_name;
1952   chirp_services *service;
1953 
1954   switch (emul_data->state) {
1955 
1956   case serving:
1957     /* we are waiting on an OpenBoot request from the client program
1958        via the client interface */
1959     if (cia != emul_data->code_client_va)
1960       return 0;
1961     emul_data->return_address = LR;
1962     emul_data->arguments = cpu_registers(processor)->gpr[3];
1963     /* try to determine what to do */
1964     service_name_addr = emul_read_word(cpu_registers(processor)->gpr[3],
1965 				       processor, cia);
1966     service_name = emul_read_string(service_buf, service_name_addr,
1967 				    sizeof(service_buf), processor, cia);
1968     emul_data->n_args = emul_read_word(emul_data->arguments + sizeof(unsigned_cell),
1969 				       processor, cia);
1970     emul_data->n_returns = emul_read_word(emul_data->arguments + 2 * sizeof(unsigned_cell),
1971 					  processor, cia);
1972     /* verify what was passed */
1973     if (service_name_addr == 0
1974 	|| service_name == NULL) {
1975       error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n",
1976 	    (unsigned long)emul_data->return_address,
1977 	    (unsigned long)emul_data->arguments);
1978     }
1979     if (emul_data->n_args > 6) { /* See iee1275 requirements on nr returns */
1980       error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n",
1981 	    (unsigned long)emul_data->return_address,
1982 	    (unsigned long)emul_data->arguments,
1983 	    emul_data->n_returns);
1984     }
1985     if (emul_data->n_returns > 6) {
1986       error("OpenFirmware service %s called from 0x%lx with args 0x%lx,  with too many returns (%d)\n",
1987 	    (unsigned long)emul_data->return_address,
1988 	    (unsigned long)emul_data->arguments,
1989 	    emul_data->n_args);
1990     }
1991     /* look it up */
1992     TRACE(trace_os_emul, ("%s called from 0x%lx with args 0x%lx\n",
1993 			  service_name,
1994 			  (unsigned long)emul_data->return_address,
1995 			  (unsigned long)emul_data->arguments));
1996     service = services;
1997     while (service->name != NULL && strcmp(service->name, service_name) != 0)
1998       service++;
1999     /* found or not? */
2000     if (service->name == NULL) {
2001       error("OpenBoot service `%s' not found\n", service_name);
2002       TRACE(trace_os_emul, ("%s not found\n", service_name));
2003       cpu_registers(processor)->gpr[3] = -1;
2004     }
2005     else {
2006       emul_data->service = service;
2007       /* call upon it */
2008       result = service->handler(emul_data, processor, cia);
2009       if (result != 0)
2010 	TRACE(trace_os_emul, ("%s aborted with %ld\n", service_name, (long)result));
2011       cpu_registers(processor)->gpr[3] = result;
2012     }
2013     break;
2014 
2015   default:
2016     error("emul_chirp_instruction_call() unknown internal state\n");
2017     result = -1;
2018     break;
2019 
2020   }
2021 
2022   /* return to caller - instruction following this is a function return */
2023   return 1;
2024 }
2025 
2026 const os_emul emul_chirp = {
2027   "chirp",
2028   emul_chirp_create,
2029   emul_chirp_init,
2030   NULL, /*system_call*/
2031   emul_chirp_instruction_call,
2032   0 /*data*/
2033 };
2034 
2035 #endif
2036