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