Latest cagney update
[deliverable/binutils-gdb.git] / sim / ppc / emul_chirp.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, 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 #include "cap.h"
32
33 #ifdef HAVE_STRING_H
34 #include <string.h>
35 #else
36 #ifdef HAVE_STRINGS_H
37 #include <strings.h>
38 #endif
39 #endif
40
41 #include <unistd.h>
42
43 #ifndef STATIC_INLINE_EMUL_CHIRP
44 #define STATIC_INLINE_EMUL_CHIRP STATIC_INLINE
45 #endif
46
47
48 /* Descriptor of the open boot services being emulated */
49
50 typedef int (chirp_handler)
51 (os_emul_data *data,
52 cpu *processor,
53 unsigned_word cia);
54 typedef struct _chirp_services {
55 const char *name;
56 chirp_handler *handler;
57 } chirp_services;
58
59
60 /* The OpenBoot emulation is, at any time either waiting for a client
61 request or waiting on a client callback */
62 typedef enum {
63 serving,
64 faulting,
65 catching,
66 } chirp_emul_state;
67
68 struct _os_emul_data {
69 chirp_emul_state state;
70 unsigned_word return_address;
71 unsigned_word arguments;
72 chirp_services *service;
73 unsigned_word serving_instruction_ea;
74 unsigned_word catching_instruction_ea;
75 cap *phandles;
76 device *root;
77 };
78
79
80 /* OpenBoot emulation functions */
81
82 static int
83 chirp_emul_child(os_emul_data *data,
84 cpu *processor,
85 unsigned_word cia)
86 {
87 struct child_args {
88 unsigned32 service;
89 unsigned32 n_args;
90 unsigned32 n_returns;
91 /*in*/
92 unsigned32 phandle;
93 /*out*/
94 unsigned32 child_phandle;
95 } args;
96 device *dev;
97 device *child_dev;
98 emul_read_buffer(&args, data->arguments,
99 sizeof(args),
100 processor, cia);
101 if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
102 TRACE(trace_os_emul, ("child - invalid nr - n_args=%ld, n_returns=%ld\n",
103 (long)T2H_4(args.n_args),
104 (long)T2H_4(args.n_returns)));
105 return -1;
106 }
107 /* read in the arguments */
108 dev = cap_internal(data->phandles, args.phandle);
109 TRACE(trace_os_emul, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
110 (unsigned long)T2H_4(args.phandle),
111 (unsigned long)dev,
112 (dev == NULL ? "" : device_name(dev))));
113 if (dev == (device*)0)
114 return -1;
115 child_dev = device_child(dev);
116 if (child_dev == NULL)
117 args.child_phandle = 0;
118 else
119 args.child_phandle = cap_external(data->phandles, child_dev);
120 TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
121 (unsigned long)T2H_4(args.child_phandle),
122 (unsigned long)child_dev,
123 (child_dev == NULL ? "" : device_name(child_dev))));
124 emul_write_buffer(&args, data->arguments,
125 sizeof(args),
126 processor, cia);
127 return 0;
128 }
129
130 static int
131 chirp_emul_exit(os_emul_data *data,
132 cpu *processor,
133 unsigned_word cia)
134 {
135 cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
136 return 0;
137 }
138
139 static int
140 chirp_emul_finddevice(os_emul_data *data,
141 cpu *processor,
142 unsigned_word cia)
143 {
144 struct finddevice_args {
145 unsigned32 service;
146 unsigned32 n_args;
147 unsigned32 n_returns;
148 /*in*/
149 unsigned32 device_specifier;
150 /*out*/
151 unsigned32 phandle;
152 } args;
153 char device_specifier[1024];
154 device *dev;
155 emul_read_buffer(&args, data->arguments,
156 sizeof(args),
157 processor, cia);
158 if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
159 TRACE(trace_os_emul, ("finddevice - invalid nr - n_args=%ld, n_returns=%ld\n",
160 (long)T2H_4(args.n_args),
161 (long)T2H_4(args.n_returns)));
162 return -1;
163 }
164 emul_read_string(device_specifier,
165 T2H_4(args.device_specifier),
166 sizeof(device_specifier),
167 processor, cia);
168 TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
169 device_specifier));
170 dev = device_tree_find_device(data->root,
171 device_specifier);
172 if (dev == (device*)0)
173 args.phandle = -1;
174 else
175 args.phandle = cap_external(data->phandles, dev);
176 TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
177 (unsigned long)T2H_4(args.phandle),
178 (unsigned long)dev,
179 (dev == NULL ? "" : device_name(dev))));
180 emul_write_buffer(&args, data->arguments,
181 sizeof(args),
182 processor, cia);
183 return 0;
184 }
185
186 static int
187 chirp_emul_getprop(os_emul_data *data,
188 cpu *processor,
189 unsigned_word cia)
190 {
191 struct getprop_args {
192 unsigned32 service;
193 unsigned32 n_args;
194 unsigned32 n_returns;
195 /*in*/
196 unsigned32 phandle;
197 unsigned32 name;
198 unsigned32 buf;
199 unsigned32 buflen;
200 /*out*/
201 unsigned32 size;
202 } args;
203 char name[32];
204 device *dev;
205 const device_property *prop;
206 emul_read_buffer(&args, data->arguments,
207 sizeof(args),
208 processor, cia);
209 if (T2H_4(args.n_args) != 4 || T2H_4(args.n_returns) != 1) {
210 TRACE(trace_os_emul, ("getprop - invalid nr - n_args=%ld, n_returns=%ld\n",
211 (long)T2H_4(args.n_args),
212 (long)T2H_4(args.n_returns)));
213 return -1;
214 }
215 /* read in the arguments */
216 dev = cap_internal(data->phandles, args.phandle);
217 emul_read_string(name,
218 T2H_4(args.name),
219 sizeof(name),
220 processor, cia);
221 TRACE(trace_os_emul, ("getprop - in - phandle=0x%lx(0x%lx`%s') name=`%s' buf=0x%lx buflen=%ld\n",
222 (unsigned long)T2H_4(args.phandle),
223 (unsigned long)dev,
224 (dev == NULL ? "" : device_name(dev)),
225 name,
226 (unsigned long)T2H_4(args.buf),
227 (unsigned long)T2H_4(args.buflen)));
228 if (dev == (device*)0)
229 return -1;
230 prop = device_find_property(dev, name);
231 if (prop == (device_property*)0) {
232 args.size = -1;
233 }
234 else {
235 int size = T2H_4(args.buflen);
236 if (size > prop->sizeof_array)
237 size = prop->sizeof_array;
238 emul_write_buffer(prop->array, T2H_4(args.buf),
239 size,
240 processor, cia);
241 args.size = H2T_4(size);
242 }
243 switch (prop->type) {
244 case string_property:
245 TRACE(trace_os_emul, ("getprop - value=`%s' (string)\n",
246 (char*)prop->array));
247 break;
248 default:
249 break;
250 }
251 TRACE(trace_os_emul, ("getprop - out - size=%ld\n",
252 (unsigned long)T2H_4(args.size)));
253 emul_write_buffer(&args, data->arguments,
254 sizeof(args),
255 processor, cia);
256 return 0;
257 }
258
259 static int
260 chirp_emul_getproplen(os_emul_data *data,
261 cpu *processor,
262 unsigned_word cia)
263 {
264 struct getproplen_args {
265 unsigned32 service;
266 unsigned32 n_args;
267 unsigned32 n_returns;
268 /*in*/
269 unsigned32 phandle;
270 unsigned32 name;
271 /*out*/
272 unsigned32 proplen;
273 } args;
274 char name[32];
275 device *dev;
276 const device_property *prop;
277 emul_read_buffer(&args, data->arguments,
278 sizeof(args),
279 processor, cia);
280 if (T2H_4(args.n_args) != 2 || T2H_4(args.n_returns) != 1) {
281 TRACE(trace_os_emul, ("getproplen - invalid nr - n_args=%ld, n_returns=%ld\n",
282 (long)T2H_4(args.n_args),
283 (long)T2H_4(args.n_returns)));
284 return -1;
285 }
286 /* read in the arguments */
287 dev = cap_internal(data->phandles, args.phandle);
288 if (dev == (device*)0)
289 return -1;
290 emul_read_string(name,
291 T2H_4(args.name),
292 sizeof(name),
293 processor, cia);
294 TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
295 (unsigned long)T2H_4(args.phandle),
296 (unsigned long)dev,
297 (dev == NULL ? "" : device_name(dev)),
298 name));
299 prop = device_find_property(dev, name);
300 if (prop == (device_property*)0) {
301 args.proplen = -1;
302 }
303 else {
304 args.proplen = H2T_4(prop->sizeof_array);
305 }
306 TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
307 (unsigned long)T2H_4(args.proplen)));
308 emul_write_buffer(&args, data->arguments,
309 sizeof(args),
310 processor, cia);
311 return 0;
312 }
313
314 static int
315 chirp_emul_open(os_emul_data *data,
316 cpu *processor,
317 unsigned_word cia)
318 {
319 struct open_args {
320 unsigned32 service;
321 unsigned32 n_args;
322 unsigned32 n_returns;
323 /*in*/
324 unsigned32 device_specifier;
325 /*out*/
326 unsigned32 ihandle;
327 } args;
328 char name[1024];
329 emul_read_buffer(&args, data->arguments,
330 sizeof(args),
331 processor, cia);
332 if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
333 TRACE(trace_os_emul, ("open - invalid nr - n_args=%ld, n_returns=%ld\n",
334 (long)T2H_4(args.n_args),
335 (long)T2H_4(args.n_returns)));
336 return -1;
337 }
338 /* read in the arguments */
339 emul_read_string(name,
340 T2H_4(args.device_specifier),
341 sizeof(name),
342 processor, cia);
343 TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n",
344 name));
345 printf_filtered("OpenBoot - open unimplemented for %s\n", name);
346 args.ihandle = -1;
347 TRACE(trace_os_emul, ("open - out - ihandle=0x%lx\n",
348 (unsigned long)T2H_4(args.ihandle)));
349 emul_write_buffer(&args, data->arguments,
350 sizeof(args),
351 processor, cia);
352 return 0;
353 }
354
355 static int
356 chirp_emul_parent(os_emul_data *data,
357 cpu *processor,
358 unsigned_word cia)
359 {
360 struct parent_args {
361 unsigned32 service;
362 unsigned32 n_args;
363 unsigned32 n_returns;
364 /*in*/
365 unsigned32 phandle;
366 /*out*/
367 unsigned32 parent_phandle;
368 } args;
369 device *dev;
370 device *parent_dev;
371 emul_read_buffer(&args, data->arguments,
372 sizeof(args),
373 processor, cia);
374 if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
375 TRACE(trace_os_emul, ("parent - invalid nr - n_args=%ld, n_returns=%ld\n",
376 (long)T2H_4(args.n_args),
377 (long)T2H_4(args.n_returns)));
378 return -1;
379 }
380 /* read in the arguments */
381 dev = cap_internal(data->phandles, args.phandle);
382 TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
383 (unsigned long)T2H_4(args.phandle),
384 (unsigned long)dev,
385 (dev == NULL ? "" : device_name(dev))));
386 if (dev == (device*)0)
387 return -1;
388 parent_dev = device_parent(dev);
389 if (parent_dev == NULL)
390 args.parent_phandle = 0;
391 else
392 args.parent_phandle = cap_external(data->phandles, parent_dev);
393 TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
394 (unsigned long)T2H_4(args.parent_phandle),
395 (unsigned long)parent_dev,
396 (parent_dev == NULL ? "" : device_name(parent_dev))));
397 emul_write_buffer(&args, data->arguments,
398 sizeof(args),
399 processor, cia);
400 return 0;
401 }
402
403 static int
404 chirp_emul_peer(os_emul_data *data,
405 cpu *processor,
406 unsigned_word cia)
407 {
408 struct peer_args {
409 unsigned32 service;
410 unsigned32 n_args;
411 unsigned32 n_returns;
412 /*in*/
413 unsigned32 phandle;
414 /*out*/
415 unsigned32 sibling_phandle;
416 } args;
417 device *dev;
418 device *sibling_dev = NULL;
419 emul_read_buffer(&args, data->arguments,
420 sizeof(args),
421 processor, cia);
422 if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
423 TRACE(trace_os_emul, ("peer - invalid nr - n_args=%ld, n_returns=%ld\n",
424 (long)T2H_4(args.n_args),
425 (long)T2H_4(args.n_returns)));
426 return -1;
427 }
428 /* read in the arguments */
429 dev = cap_internal(data->phandles, args.phandle);
430 TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
431 (unsigned long)T2H_4(args.phandle),
432 (unsigned long)dev,
433 (dev == NULL ? "" : device_name(dev))));
434 if (dev == NULL && args.phandle != 0)
435 return -1;
436 if (args.phandle == 0)
437 sibling_dev = data->root;
438 else
439 sibling_dev = device_sibling(dev);
440 if (sibling_dev == NULL)
441 args.sibling_phandle = 0;
442 else
443 args.sibling_phandle = cap_external(data->phandles, sibling_dev);
444 TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
445 (unsigned long)T2H_4(args.sibling_phandle),
446 (unsigned long)sibling_dev,
447 (sibling_dev == NULL ? "" : device_name(sibling_dev))));
448 emul_write_buffer(&args, data->arguments,
449 sizeof(args),
450 processor, cia);
451 return 0;
452 }
453
454 static int
455 chirp_emul_read(os_emul_data *data,
456 cpu *processor,
457 unsigned_word cia)
458 {
459 struct read_args {
460 unsigned32 service;
461 unsigned32 n_args;
462 unsigned32 n_returns;
463 /*in*/
464 unsigned32 ihandle;
465 unsigned32 addr;
466 unsigned32 len;
467 /*out*/
468 unsigned32 actual;
469 } args;
470 char buf[1024];
471 int actual;
472 emul_read_buffer(&args, data->arguments,
473 sizeof(args),
474 processor, cia);
475 if (T2H_4(args.n_args) != 3 || T2H_4(args.n_returns) != 1) {
476 TRACE(trace_os_emul, ("read - invalid nr - n_args=%ld, n_returns=%ld\n",
477 (long)T2H_4(args.n_args),
478 (long)T2H_4(args.n_returns)));
479 return -1;
480 }
481 /* read in the arguments */
482 actual = T2H_4(args.len);
483 if (actual >= sizeof(buf))
484 actual = sizeof(buf) - 1;
485 emul_read_buffer(buf,
486 T2H_4(args.addr),
487 actual,
488 processor, cia);
489 buf[actual] = '\0';
490 /* read it in */
491 TRACE(trace_os_emul, ("read - in - ihandle=0x%lx `%s' (%ld)\n",
492 (unsigned long)args.ihandle, buf, (long)actual));
493 read(BE2H_4(args.ihandle), buf, actual);
494 args.actual = H2T_4(actual);
495 TRACE(trace_os_emul, ("read - out - actual=%ld\n",
496 (long)T2H_4(args.actual)));
497 emul_write_buffer(&args, data->arguments,
498 sizeof(args),
499 processor, cia);
500 return 0;
501 }
502
503 static int
504 chirp_emul_write(os_emul_data *data,
505 cpu *processor,
506 unsigned_word cia)
507 {
508 struct write_args {
509 unsigned32 service;
510 unsigned32 n_args;
511 unsigned32 n_returns;
512 /*in*/
513 unsigned32 ihandle;
514 unsigned32 addr;
515 unsigned32 len;
516 /*out*/
517 unsigned32 actual;
518 } args;
519 char buf[1024];
520 int actual;
521 emul_read_buffer(&args, data->arguments,
522 sizeof(args),
523 processor, cia);
524 if (T2H_4(args.n_args) != 3 || T2H_4(args.n_returns) != 1) {
525 TRACE(trace_os_emul, ("write - invalid nr - n_args=%ld, n_returns=%ld\n",
526 (long)T2H_4(args.n_args),
527 (long)T2H_4(args.n_returns)));
528 return -1;
529 }
530 /* read in the arguments */
531 actual = T2H_4(args.len);
532 if (actual >= sizeof(buf))
533 actual = sizeof(buf) - 1;
534 emul_read_buffer(buf,
535 T2H_4(args.addr),
536 actual,
537 processor, cia);
538 buf[actual] = '\0';
539 /* write it out */
540 TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n",
541 (unsigned long)args.ihandle, buf, (long)actual));
542 write(BE2H_4(args.ihandle), buf, actual);
543 args.actual = H2T_4(actual);
544 TRACE(trace_os_emul, ("write - out - actual=%ld\n",
545 (long)T2H_4(args.actual)));
546 emul_write_buffer(&args, data->arguments,
547 sizeof(args),
548 processor, cia);
549 return 0;
550 }
551
552
553 chirp_services services[] = {
554 { "child", chirp_emul_child },
555 { "exit", chirp_emul_exit },
556 { "finddevice", chirp_emul_finddevice },
557 { "getprop", chirp_emul_getprop },
558 { "getproplen", chirp_emul_getproplen },
559 { "open", chirp_emul_open },
560 { "parent", chirp_emul_parent },
561 { "peer", chirp_emul_peer },
562 { "read", chirp_emul_read },
563 { "write", chirp_emul_write },
564 { 0, /* sentinal */ },
565 };
566
567
568 /* main handlers */
569
570 /* Any starting address greater than this is assumed to be an Chirp
571 rather than VEA */
572
573 #ifndef CHIRP_START_ADDRESS
574 #define CHIRP_START_ADDRESS 0x80000000
575 #endif
576
577 typedef struct _chirp_note_desc {
578 signed32 real_mode;
579 signed32 real_base;
580 signed32 real_size;
581 signed32 virt_base;
582 signed32 virt_size;
583 } chirp_note_desc;
584
585 typedef struct _chirp_note {
586 chirp_note_desc desc;
587 int found;
588 } chirp_note;
589
590 typedef struct _chirp_note_head {
591 unsigned32 namesz;
592 unsigned32 descsz;
593 unsigned32 type;
594 } chirp_note_head;
595
596 static void
597 map_over_chirp_note(bfd *image,
598 asection *sect,
599 PTR obj)
600 {
601 chirp_note *note = (chirp_note*)obj;
602 if (strcmp(sect->name, ".note") == 0) {
603 chirp_note_head head;
604 char name[16];
605 /* check the head */
606 if (!bfd_get_section_contents(image, sect,
607 &head, 0, sizeof(head)))
608 return;
609 head.namesz = bfd_get_32(image, (void*)&head.namesz);
610 head.descsz = bfd_get_32(image, (void*)&head.descsz);
611 head.type = bfd_get_32(image, (void*)&head.type);
612 if (head.type != 0x1275)
613 return;
614 note->found = 1;
615 /* check the name field */
616 if (head.namesz > sizeof(name))
617 return;
618 if (!bfd_get_section_contents(image, sect,
619 name, sizeof(head), head.namesz))
620 return;
621 if (strcmp(name, "PowerPC") != 0)
622 return;
623 /* get the contents */
624 if (!bfd_get_section_contents(image, sect,
625 &note->desc, sizeof(head) + head.namesz,
626 head.descsz))
627 return;
628 note->desc.real_mode = bfd_get_32(image, (void*)&note->desc.real_mode);
629 note->desc.real_base = bfd_get_32(image, (void*)&note->desc.real_base);
630 note->desc.real_size = bfd_get_32(image, (void*)&note->desc.real_size);
631 note->desc.virt_base = bfd_get_32(image, (void*)&note->desc.virt_base);
632 note->desc.virt_size = bfd_get_32(image, (void*)&note->desc.virt_size);
633 note->found = 2;
634 }
635 }
636
637
638 static os_emul_data *
639 emul_chirp_create(device *root,
640 bfd *image,
641 const char *name)
642 {
643 os_emul_data *data;
644 chirp_note note;
645 int big_endian;
646
647 /* Sanity check that this really is the chosen emulation */
648 if (name == NULL && image == NULL)
649 return NULL;
650 if (name != NULL
651 && strcmp(name, "ob") != 0
652 && strcmp(name, "ieee1274") != 0
653 && strcmp(name, "chrp") != 0
654 && strcmp(name, "chirp") != 0
655 && strcmp(name, "openboot") != 0)
656 return NULL;
657
658 /* look for an elf note section */
659 memset(&note, 0, sizeof(note));
660 if (image != NULL)
661 bfd_map_over_sections(image, map_over_chirp_note, &note);
662 if (name == NULL && image != NULL && !note.found)
663 return NULL;
664
665 /* the root node */
666 device_add_string_property(root,
667 "name",
668 "gpl,clayton");
669
670 {
671 const unsigned_word memory_size = 0x200000;
672
673 /* the hash table */
674 const unsigned nr_page_table_entry_groups = (memory_size < 0x800000
675 ? 1024 /* min allowed */
676 : (memory_size / 4096 / 2));
677 const unsigned sizeof_htab = nr_page_table_entry_groups * 64;
678 const unsigned_word htab_ra = memory_size - sizeof_htab;
679
680 /* a page for firmware calls */
681 const unsigned_word sizeof_code = 4096;
682 const unsigned_word code_ra = htab_ra - sizeof_code;
683
684 /* the stack */
685 const unsigned sizeof_stack = 32 * 1024;
686 const unsigned_word stack_ra = code_ra - sizeof_stack;
687
688 /* the firmware's home */
689 const int real_mode = 0;
690 /* const unsigned_word real_base = stack_ra; */
691 /* const unsigned real_size = memory_size - real_base; */
692 const unsigned_word virt_base = CHIRP_START_ADDRESS;
693 /* const unsigned virt_size = real_size;*/
694
695 /* the virtual addresses */
696 const unsigned_word stack_va = virt_base;
697 const unsigned_word code_va = stack_va + sizeof_stack;
698 const unsigned_word code_client_va = code_va;
699 const unsigned_word code_callback_va = code_client_va + 16;
700 const unsigned_word code_loop_va = code_callback_va + 16;
701 const unsigned_word htab_va = code_va + sizeof_code;
702
703 #ifdef bfd_big_endian /* new bfd */
704 big_endian = bfd_big_endian(image);
705 #else
706 big_endian = image->xvec->byteorder_big_p;
707 #endif
708
709 /* options */
710 {
711 device *options = device_tree_add_found(root, "/", "options");
712 device_add_integer_property(options,
713 "smp",
714 MAX_NR_PROCESSORS);
715 device_add_boolean_property(options,
716 "little-endian?",
717 !big_endian);
718 device_add_string_property(options,
719 "env",
720 "operating");
721 device_add_boolean_property(options,
722 "strict-alignment?",
723 (WITH_ALIGNMENT == STRICT_ALIGNMENT
724 || !big_endian));
725 device_add_boolean_property(options,
726 "floating-point?",
727 WITH_FLOATING_POINT);
728 device_add_string_property(options,
729 "os-emul",
730 "chirp");
731 }
732
733 /* hardware */
734 device_tree_add_found_uw_u_u(root, "/", "memory",
735 0, memory_size, access_read_write_exec);
736
737 /* initialization */
738 {
739 device *init = device_tree_add_found(root, "/", "init");
740 {
741 device *init_register = device_tree_add_found(init, "", "register");
742 device_add_integer_property(init_register,
743 "pc",
744 code_loop_va);
745 device_add_integer_property(init_register,
746 "0.pc",
747 bfd_get_start_address(image));
748 device_add_integer_property(init_register,
749 "sp",
750 stack_va + sizeof_stack - 16);
751
752 /* init the code callback along with a loop for the unused cpu's */
753 device_add_integer_property(init_register,
754 "r5",
755 code_client_va);
756 device_tree_add_found_uw_u_u(init, "",
757 "data",
758 code_ra + (code_client_va - code_va),
759 4, 0x1); /*emul-call*/
760 device_tree_add_found_uw_u_u(init, "",
761 "data",
762 code_ra + (code_callback_va - code_va),
763 4, 0x1); /*emul-call*/
764 device_tree_add_found_uw_u_u(init, "",
765 "data",
766 code_ra + (code_loop_va - code_va),
767 4, 0x48000000); /*b .*/
768 device_add_integer_property(init_register,
769 "msr",
770 (msr_machine_check_enable
771 | (real_mode
772 ? 0
773 : (msr_instruction_relocate
774 | msr_data_relocate))
775 | (big_endian
776 ? 0
777 : (msr_little_endian_mode
778 | msr_interrupt_little_endian_mode
779 ))));
780 device_add_integer_property(init_register,
781 "sdr1",
782 (htab_ra
783 | MASK32(16, 22)
784 | ((sizeof_htab - 1) >> 16)));
785 /* FIXME */
786 device_add_integer_property(init_register,
787 "sr8",
788 0x00fffff8);
789 device_add_integer_property(init_register,
790 "sr9",
791 0x00fffff9);
792
793 { /* hash table and vm */
794 device *htab_root = device_tree_add_found_uw_u(init, "", "htab",
795 htab_ra, sizeof_htab);
796 device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte",
797 stack_ra, stack_va, sizeof_stack,
798 0x7/*wimg*/, 0x2/*pp*/);
799 device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte",
800 code_ra, code_va, sizeof_code,
801 0x7/*wimg*/, 0x2/*pp*/);
802 device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte",
803 htab_ra, htab_va, sizeof_htab,
804 0x7/*wimg*/, 0x2/*pp*/);
805 device_tree_add_found_uw_u_u_c(htab_root, "", "pte",
806 0x4000, /*magic*/
807 0x7/*wimg*/, 0x2/*pp*/,
808 bfd_get_filename (image));
809 }
810 }
811 }
812
813 { /* chosen options */
814 device *chosen = device_tree_add_found(root, "/", "chosen");
815 device_add_string_property(chosen,
816 "name",
817 "chosen");
818 device_add_integer_property(chosen,
819 "stdin",
820 0); /* FIXME: ihandle of stdin */
821 device_add_integer_property(chosen,
822 "stdout",
823 1); /* FIXME: ihandle of stdout */
824 device_add_string_property(chosen,
825 "bootpath",
826 "/disk@0:\\boot");
827 device_add_string_property(chosen,
828 "bootargs",
829 "");
830 #if 0
831 device_add_integer_property(chosen,
832 "memory",
833 0); /* FIXME: ihandle of memory */
834 device_add_integer_property(chosen,
835 "mmu",
836 0);
837 #endif
838 }
839
840 /* FIXME - should come from the device tree */
841 data = ZALLOC(os_emul_data);
842 data->serving_instruction_ea = code_client_va;
843 data->catching_instruction_ea = code_callback_va;
844 data->phandles = cap_create("chirp");
845 data->root = root;
846 return data;
847 }
848 }
849
850 static void
851 emul_chirp_init(os_emul_data *emul_data,
852 int nr_cpus)
853 {
854 emul_data->state = serving;
855 cap_init(emul_data->phandles);
856 }
857
858 static int
859 emul_chirp_instruction_call(cpu *processor,
860 unsigned_word cia,
861 unsigned_word ra,
862 os_emul_data *emul_data)
863 {
864 unsigned_word service_name_addr;
865 unsigned_word result;
866 char service_buf[32];
867 char *service_name;
868 chirp_services *service;
869
870 switch (emul_data->state) {
871
872 case serving:
873 /* we are waiting on an OpenBoot request from the client program
874 via the client interface */
875 if (cia != emul_data->serving_instruction_ea)
876 return 0;
877 emul_data->return_address = LR;
878 emul_data->arguments = cpu_registers(processor)->gpr[3];
879 /* try to determine what to do */
880 service_name_addr = emul_read_word(cpu_registers(processor)->gpr[3],
881 processor, cia);
882 service_name = emul_read_string(service_buf, service_name_addr,
883 sizeof(service_buf), processor, cia);
884 TRACE(trace_os_emul, ("%s called from 0x%lx with args 0x%lx\n",
885 service_name,
886 (unsigned long)emul_data->return_address,
887 (unsigned long)emul_data->arguments));
888 /* look it up */
889 service = services;
890 while (service->name != NULL && strcmp(service->name, service_name) != 0)
891 service++;
892 if (service->name == NULL) {
893 error("OpenBoot service `%s' not found\n", service_name);
894 TRACE(trace_os_emul, ("%s not found\n", service_name));
895 cpu_registers(processor)->gpr[3] = 0;
896 cpu_restart(processor, emul_data->return_address);
897 }
898 emul_data->service = service;
899 /* call upon it */
900 result = service->handler(emul_data, processor, cia);
901 break;
902
903 case faulting:
904 /* We were handling a client request but encountered a page fault
905 (or other exception). The fault needs to be passed back to the
906 client using the the client suplied call back interface */
907 error("emul_chirp_instruction_call() faulting unimplemented\n");
908 result = -1;
909 break;
910
911 case catching:
912 /* Have called the client (via the callback interface) because
913 some fault (hash table miss) occured. The client has finished
914 handling this and is now returning */
915 error("emul_chirp_instruction_call() catching unimplemented\n");
916 result = -1;
917 break;
918
919 default:
920 error("emul_chirp_instruction_call() unknown internal state\n");
921 result = -1;
922 break;
923
924 }
925
926 /* return to caller */
927 cpu_registers(processor)->gpr[3] = result;
928 cpu_restart(processor, emul_data->return_address);
929 return 1;
930 }
931
932 const os_emul emul_chirp = {
933 "chirp",
934 emul_chirp_create,
935 emul_chirp_init,
936 NULL, /*system_call*/
937 emul_chirp_instruction_call,
938 0 /*data*/
939 };
940
941 #endif
This page took 0.059102 seconds and 5 git commands to generate.