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