OSDN Git Service

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