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