Latest changes from Andrew
[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 chirp_services *services;
78 };
79
80
81 /* Read in the argument list and make the most basic check that number
82 of argumnets are consistent with what was expected */
83
84 static int
85 chirp_read_args(void *args,
86 int sizeof_args,
87 int n_args,
88 int n_returns,
89 os_emul_data *data,
90 cpu *processor,
91 unsigned_word cia)
92 {
93 struct base_args {
94 unsigned32 service;
95 unsigned32 n_args;
96 unsigned32 n_returns;
97 } *base;
98 emul_read_buffer(args, data->arguments,
99 sizeof_args,
100 processor, cia);
101 base = (struct base_args*)args;
102 if (T2H_4(base->n_args) != n_args || T2H_4(base->n_returns) != n_returns) {
103 TRACE(trace_os_emul, ("invalid nr of args - n_args=%ld, n_returns=%ld\n",
104 (long)T2H_4(base->n_args),
105 (long)T2H_4(base->n_returns)));
106 return -1;
107 }
108 return 0;
109 }
110
111
112 /* OpenBoot emulation functions */
113
114 /* client interface */
115
116 static int
117 chirp_emul_test(os_emul_data *data,
118 cpu *processor,
119 unsigned_word cia)
120 {
121 struct test_args {
122 unsigned32 service;
123 unsigned32 n_args;
124 unsigned32 n_returns;
125 /*in*/
126 unsigned32 name; /*string*/
127 /*out*/
128 unsigned32 missing;
129 } args;
130 char name[32];
131 chirp_services *service = data->services;
132 /* read in the arguments */
133 if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
134 return -1;
135 emul_read_string(name, T2H_4(args.name), sizeof(name),
136 processor, cia);
137 TRACE(trace_os_emul, ("test - in - name=`%s'\n", name));
138 /* see if we know about the service */
139 while (service->name != NULL && strcmp(service->name, name) != 0) {
140 service++;
141 }
142 if (service->name == NULL)
143 args.missing = -1;
144 else
145 args.missing = 0;
146 /* write the arguments back out */
147 TRACE(trace_os_emul, ("test - out - missing=%ld\n",
148 (long)args.missing));
149 emul_write_buffer(&args, data->arguments,
150 sizeof(args),
151 processor, cia);
152 return 0;
153 }
154
155
156 /* Device tree */
157
158 static int
159 chirp_emul_peer(os_emul_data *data,
160 cpu *processor,
161 unsigned_word cia)
162 {
163 struct peer_args {
164 unsigned32 service;
165 unsigned32 n_args;
166 unsigned32 n_returns;
167 /*in*/
168 unsigned32 phandle;
169 /*out*/
170 unsigned32 sibling_phandle;
171 } args;
172 device *dev;
173 device *sibling_dev = NULL;
174 /* read in the arguments */
175 if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
176 return -1;
177 dev = cap_internal(data->phandles, args.phandle);
178 TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
179 (unsigned long)T2H_4(args.phandle),
180 (unsigned long)dev,
181 (dev == NULL ? "" : device_name(dev))));
182 /* find the peer */
183 if (dev == NULL && args.phandle != 0)
184 return -1;
185 if (args.phandle == 0)
186 sibling_dev = data->root;
187 else
188 sibling_dev = device_sibling(dev);
189 if (sibling_dev == NULL)
190 args.sibling_phandle = 0;
191 else
192 args.sibling_phandle = cap_external(data->phandles, sibling_dev);
193 /* write the arguments back out */
194 TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
195 (unsigned long)T2H_4(args.sibling_phandle),
196 (unsigned long)sibling_dev,
197 (sibling_dev == NULL
198 ? ""
199 : device_name(sibling_dev))));
200 emul_write_buffer(&args, data->arguments,
201 sizeof(args),
202 processor, cia);
203 return 0;
204 }
205
206 static int
207 chirp_emul_child(os_emul_data *data,
208 cpu *processor,
209 unsigned_word cia)
210 {
211 struct child_args {
212 unsigned32 service;
213 unsigned32 n_args;
214 unsigned32 n_returns;
215 /*in*/
216 unsigned32 phandle;
217 /*out*/
218 unsigned32 child_phandle;
219 } args;
220 device *dev;
221 device *child_dev;
222 /* read the arguments in */
223 if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
224 return -1;
225 dev = cap_internal(data->phandles, args.phandle);
226 TRACE(trace_os_emul, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
227 (unsigned long)T2H_4(args.phandle),
228 (unsigned long)dev,
229 (dev == NULL ? "" : device_name(dev))));
230 /* find a child */
231 if (dev == (device*)0)
232 return -1;
233 child_dev = device_child(dev);
234 if (child_dev == NULL)
235 args.child_phandle = 0;
236 else
237 args.child_phandle = cap_external(data->phandles, child_dev);
238 /* write the result out */
239 TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
240 (unsigned long)T2H_4(args.child_phandle),
241 (unsigned long)child_dev,
242 (child_dev == NULL ? "" : device_name(child_dev))));
243 emul_write_buffer(&args, data->arguments,
244 sizeof(args),
245 processor, cia);
246 return 0;
247 }
248
249 static int
250 chirp_emul_parent(os_emul_data *data,
251 cpu *processor,
252 unsigned_word cia)
253 {
254 struct parent_args {
255 unsigned32 service;
256 unsigned32 n_args;
257 unsigned32 n_returns;
258 /*in*/
259 unsigned32 phandle;
260 /*out*/
261 unsigned32 parent_phandle;
262 } args;
263 device *dev;
264 device *parent_dev;
265 /* read the args in */
266 if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
267 return -1;
268 dev = cap_internal(data->phandles, args.phandle);
269 TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
270 (unsigned long)T2H_4(args.phandle),
271 (unsigned long)dev,
272 (dev == NULL ? "" : device_name(dev))));
273 /* find a parent */
274 if (dev == (device*)0)
275 return -1;
276 parent_dev = device_parent(dev);
277 if (parent_dev == NULL)
278 args.parent_phandle = 0;
279 else
280 args.parent_phandle = cap_external(data->phandles, parent_dev);
281 /* return the result */
282 TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
283 (unsigned long)T2H_4(args.parent_phandle),
284 (unsigned long)parent_dev,
285 (parent_dev == NULL ? "" : device_name(parent_dev))));
286 emul_write_buffer(&args, data->arguments,
287 sizeof(args),
288 processor, cia);
289 return 0;
290 }
291
292 static int
293 chirp_emul_instance_to_package(os_emul_data *data,
294 cpu *processor,
295 unsigned_word cia)
296 {
297 error("chirp: instance-to-package unimplemented\n");
298 return 0;
299 }
300
301 static int
302 chirp_emul_getproplen(os_emul_data *data,
303 cpu *processor,
304 unsigned_word cia)
305 {
306 struct getproplen_args {
307 unsigned32 service;
308 unsigned32 n_args;
309 unsigned32 n_returns;
310 /*in*/
311 unsigned32 phandle;
312 unsigned32 name;
313 /*out*/
314 unsigned32 proplen;
315 } args;
316 char name[32];
317 device *dev;
318 const device_property *prop;
319 /* read the args in */
320 if (chirp_read_args(&args, sizeof(args), 2, 1, data, processor, cia))
321 return -1;
322 dev = cap_internal(data->phandles, args.phandle);
323 /* find our prop and get its length */
324 if (dev == (device*)0)
325 return -1;
326 emul_read_string(name,
327 T2H_4(args.name),
328 sizeof(name),
329 processor, cia);
330 TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
331 (unsigned long)T2H_4(args.phandle),
332 (unsigned long)dev,
333 (dev == NULL ? "" : device_name(dev)),
334 name));
335 prop = device_find_property(dev, name);
336 if (prop == (device_property*)0) {
337 args.proplen = -1;
338 }
339 else {
340 args.proplen = H2T_4(prop->sizeof_array);
341 }
342 /* return the result */
343 TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
344 (unsigned long)T2H_4(args.proplen)));
345 emul_write_buffer(&args, data->arguments,
346 sizeof(args),
347 processor, cia);
348 return 0;
349 }
350
351 static int
352 chirp_emul_getprop(os_emul_data *data,
353 cpu *processor,
354 unsigned_word cia)
355 {
356 struct getprop_args {
357 unsigned32 service;
358 unsigned32 n_args;
359 unsigned32 n_returns;
360 /*in*/
361 unsigned32 phandle;
362 unsigned32 name;
363 unsigned32 buf;
364 unsigned32 buflen;
365 /*out*/
366 unsigned32 size;
367 } args;
368 char name[32];
369 device *dev;
370 const device_property *prop;
371 /* read in the args */
372 if (chirp_read_args(&args, sizeof(args), 4, 1, data, processor, cia))
373 return -1;
374 dev = cap_internal(data->phandles, args.phandle);
375 emul_read_string(name,
376 T2H_4(args.name),
377 sizeof(name),
378 processor, cia);
379 TRACE(trace_os_emul, ("getprop - in - phandle=0x%lx(0x%lx`%s') name=`%s' buf=0x%lx buflen=%ld\n",
380 (unsigned long)T2H_4(args.phandle),
381 (unsigned long)dev,
382 (dev == NULL ? "" : device_name(dev)),
383 name,
384 (unsigned long)T2H_4(args.buf),
385 (unsigned long)T2H_4(args.buflen)));
386 /* get the property */
387 if (dev == (device*)0)
388 return -1;
389 prop = device_find_property(dev, name);
390 if (prop == (device_property*)0) {
391 args.size = -1;
392 }
393 else {
394 int size = T2H_4(args.buflen);
395 if (size > prop->sizeof_array)
396 size = prop->sizeof_array;
397 emul_write_buffer(prop->array, T2H_4(args.buf),
398 size,
399 processor, cia);
400 args.size = H2T_4(size);
401 }
402 switch (prop->type) {
403 case string_property:
404 TRACE(trace_os_emul, ("getprop - value=`%s' (string)\n",
405 (char*)prop->array));
406 break;
407 default:
408 break;
409 }
410 /* write back the result */
411 TRACE(trace_os_emul, ("getprop - out - size=%ld\n",
412 (unsigned long)T2H_4(args.size)));
413 emul_write_buffer(&args, data->arguments,
414 sizeof(args),
415 processor, cia);
416 return 0;
417 }
418
419 static int
420 chirp_emul_nextprop(os_emul_data *data,
421 cpu *processor,
422 unsigned_word cia)
423 {
424 error("chirp: nextprop not implemented\n");
425 return 0;
426 }
427
428 static int
429 chirp_emul_setprop(os_emul_data *data,
430 cpu *processor,
431 unsigned_word cia)
432 {
433 error("chirp: setprop not implemented\n");
434 return 0;
435 }
436
437 static int
438 chirp_emul_canon(os_emul_data *data,
439 cpu *processor,
440 unsigned_word cia)
441 {
442 error("chirp: canon not implemented\n");
443 return 0;
444 }
445
446 static int
447 chirp_emul_finddevice(os_emul_data *data,
448 cpu *processor,
449 unsigned_word cia)
450 {
451 struct finddevice_args {
452 unsigned32 service;
453 unsigned32 n_args;
454 unsigned32 n_returns;
455 /*in*/
456 unsigned32 device_specifier;
457 /*out*/
458 unsigned32 phandle;
459 } args;
460 char device_specifier[1024];
461 device *dev;
462 /* get the args */
463 if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
464 return -1;
465 emul_read_string(device_specifier,
466 T2H_4(args.device_specifier),
467 sizeof(device_specifier),
468 processor, cia);
469 TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
470 device_specifier));
471 /* find the device */
472 dev = device_tree_find_device(data->root,
473 device_specifier);
474 if (dev == (device*)0)
475 args.phandle = -1;
476 else
477 args.phandle = cap_external(data->phandles, dev);
478 /* return its phandle */
479 TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
480 (unsigned long)T2H_4(args.phandle),
481 (unsigned long)dev,
482 (dev == NULL ? "" : device_name(dev))));
483 emul_write_buffer(&args, data->arguments,
484 sizeof(args),
485 processor, cia);
486 return 0;
487 }
488
489 static int
490 chirp_emul_instance_to_path(os_emul_data *data,
491 cpu *processor,
492 unsigned_word cia)
493 {
494 error("chirp: instance_to_path not implemented\n");
495 return 0;
496 }
497
498 static int
499 chirp_emul_package_to_path(os_emul_data *data,
500 cpu *processor,
501 unsigned_word cia)
502 {
503 error("chirp: package_to_path not implemented\n");
504 return 0;
505 }
506
507 static int
508 chirp_emul_call_method(os_emul_data *data,
509 cpu *processor,
510 unsigned_word cia)
511 {
512 error("chirp: call-method implemented\n");
513 return 0;
514 }
515
516
517 /* Device I/O */
518
519 static int
520 chirp_emul_open(os_emul_data *data,
521 cpu *processor,
522 unsigned_word cia)
523 {
524 struct open_args {
525 unsigned32 service;
526 unsigned32 n_args;
527 unsigned32 n_returns;
528 /*in*/
529 unsigned32 device_specifier;
530 /*out*/
531 unsigned32 ihandle;
532 } args;
533 char name[1024];
534 /* read the args */
535 if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
536 return -1;
537 emul_read_string(name,
538 T2H_4(args.device_specifier),
539 sizeof(name),
540 processor, cia);
541 TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n",
542 name));
543 /* open the device */
544 printf_filtered("OpenBoot - open unimplemented for %s\n", name);
545 args.ihandle = -1;
546 /* return the ihandle result */
547 TRACE(trace_os_emul, ("open - out - ihandle=0x%lx\n",
548 (unsigned long)T2H_4(args.ihandle)));
549 emul_write_buffer(&args, data->arguments,
550 sizeof(args),
551 processor, cia);
552 return 0;
553 }
554
555 static int
556 chirp_emul_close(os_emul_data *data,
557 cpu *processor,
558 unsigned_word cia)
559 {
560 error("chirp: close not implemented\n");
561 return 0;
562 }
563
564 static int
565 chirp_emul_read(os_emul_data *data,
566 cpu *processor,
567 unsigned_word cia)
568 {
569 struct read_args {
570 unsigned32 service;
571 unsigned32 n_args;
572 unsigned32 n_returns;
573 /*in*/
574 unsigned32 ihandle;
575 unsigned32 addr;
576 unsigned32 len;
577 /*out*/
578 unsigned32 actual;
579 } args;
580 char buf[1024];
581 int actual;
582 /* read the args */
583 if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
584 return -1;
585 TRACE(trace_os_emul, ("read - in - ihandle=0x%lx addr=0x%lx len=%ld\n",
586 (unsigned long)args.ihandle,
587 (unsigned long)T2H_4(args.addr),
588 (unsigned long)T2H_4(args.len)));
589 /* do the read */
590 actual = T2H_4(args.len);
591 if (actual >= sizeof(buf))
592 actual = sizeof(buf) - 1;
593 actual = read(BE2H_4(args.ihandle), buf, actual);
594 if (actual >= 0) {
595 emul_write_buffer(buf,
596 T2H_4(args.addr),
597 actual,
598 processor, cia);
599 args.actual = H2T_4(actual);
600 buf[actual] = '\0';
601 }
602 else {
603 args.actual = 0;
604 }
605 /* return the result */
606 TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n",
607 (long)T2H_4(args.actual),
608 (actual >= 0 ? buf : "")));
609 emul_write_buffer(&args, data->arguments,
610 sizeof(args),
611 processor, cia);
612 return 0;
613 }
614
615 static int
616 chirp_emul_write(os_emul_data *data,
617 cpu *processor,
618 unsigned_word cia)
619 {
620 struct write_args {
621 unsigned32 service;
622 unsigned32 n_args;
623 unsigned32 n_returns;
624 /*in*/
625 unsigned32 ihandle;
626 unsigned32 addr;
627 unsigned32 len;
628 /*out*/
629 unsigned32 actual;
630 } args;
631 char buf[1024];
632 int actual;
633 /* get the args */
634 if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
635 return -1;
636 actual = T2H_4(args.len);
637 if (actual >= sizeof(buf))
638 actual = sizeof(buf) - 1;
639 emul_read_buffer(buf,
640 T2H_4(args.addr),
641 actual,
642 processor, cia);
643 buf[actual] = '\0';
644 TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n",
645 (unsigned long)args.ihandle, buf, (long)actual));
646 /* write it out */
647 actual = write(BE2H_4(args.ihandle), buf, actual);
648 if (actual < 0)
649 args.actual = 0;
650 else
651 args.actual = H2T_4(actual);
652 /* return the result */
653 TRACE(trace_os_emul, ("write - out - actual=%ld\n",
654 (long)T2H_4(args.actual)));
655 emul_write_buffer(&args, data->arguments,
656 sizeof(args),
657 processor, cia);
658 return 0;
659 }
660
661 static int
662 chirp_emul_seek(os_emul_data *data,
663 cpu *processor,
664 unsigned_word cia)
665 {
666 error("chirp: seek not implemented\n");
667 return 0;
668 }
669
670
671 /* memory */
672
673 static int
674 chirp_emul_claim(os_emul_data *data,
675 cpu *processor,
676 unsigned_word cia)
677 {
678 error("chirp: claim not implemented\n");
679 return 0;
680 }
681
682 static int
683 chirp_emul_release(os_emul_data *data,
684 cpu *processor,
685 unsigned_word cia)
686 {
687 error("chirp: release not implemented\n");
688 return 0;
689 }
690
691
692 /* Control transfer */
693
694 static int
695 chirp_emul_boot(os_emul_data *data,
696 cpu *processor,
697 unsigned_word cia)
698 {
699 error("chirp: boot not implemented\n");
700 return 0;
701 }
702
703 static int
704 chirp_emul_enter(os_emul_data *data,
705 cpu *processor,
706 unsigned_word cia)
707 {
708 error("chirp: enter not implemented\n");
709 return 0;
710 }
711
712 static int
713 chirp_emul_exit(os_emul_data *data,
714 cpu *processor,
715 unsigned_word cia)
716 {
717 cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
718 return 0;
719 }
720
721 static int
722 chirp_emul_chain(os_emul_data *data,
723 cpu *processor,
724 unsigned_word cia)
725 {
726 error("chirp: chain not implemented\n");
727 return 0;
728 }
729
730
731 /* user interface */
732
733 static int
734 chirp_emul_interpret(os_emul_data *data,
735 cpu *processor,
736 unsigned_word cia)
737 {
738 error("chirp: interpret not implemented\n");
739 return 0;
740 }
741
742 static int
743 chirp_emul_set_callback(os_emul_data *data,
744 cpu *processor,
745 unsigned_word cia)
746 {
747 error("chirp: set_callback not implemented\n");
748 return 0;
749 }
750
751 static int
752 chirp_emul_set_symbol_lookup(os_emul_data *data,
753 cpu *processor,
754 unsigned_word cia)
755 {
756 error("chirp: set_symbol_lookup not implemented\n");
757 return 0;
758 }
759
760
761 /* Time */
762
763 static int
764 chirp_emul_milliseconds(os_emul_data *data,
765 cpu *processor,
766 unsigned_word cia)
767 {
768 struct test_args {
769 unsigned32 service;
770 unsigned32 n_args;
771 unsigned32 n_returns;
772 /*in*/
773 /*out*/
774 unsigned32 ms;
775 } args;
776 unsigned64 time;
777 /* read in the arguments */
778 if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
779 return -1;
780 /* make up a number */
781 time = event_queue_time(cpu_event_queue(processor)) / 1000000;
782 args.ms = H2T_4(time);
783 /* write the arguments back out */
784 TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n",
785 (unsigned long)T2H_4(args.ms)));
786 emul_write_buffer(&args, data->arguments,
787 sizeof(args),
788 processor, cia);
789 return 0;
790 }
791
792
793
794
795 static chirp_services services[] = {
796
797 /* client interface */
798 { "test", chirp_emul_test },
799
800 /* device tree */
801 { "peer", chirp_emul_peer },
802 { "child", chirp_emul_child },
803 { "parent", chirp_emul_parent },
804 { "instance-to-package", chirp_emul_instance_to_package },
805 { "getproplen", chirp_emul_getproplen },
806 { "getprop", chirp_emul_getprop },
807 { "nextprop", chirp_emul_nextprop },
808 { "setprop", chirp_emul_setprop },
809 { "canon", chirp_emul_canon },
810 { "finddevice", chirp_emul_finddevice },
811 { "instance-to-path", chirp_emul_instance_to_path },
812 { "package-to-path", chirp_emul_package_to_path },
813 { "call-method", chirp_emul_call_method },
814
815 /* device I/O */
816 { "open", chirp_emul_open },
817 { "close", chirp_emul_close },
818 { "read", chirp_emul_read },
819 { "write", chirp_emul_write },
820 { "seek", chirp_emul_seek },
821 { "write", chirp_emul_write },
822
823 /* memory */
824 { "claim", chirp_emul_claim },
825 { "release", chirp_emul_release },
826
827 /* control transfer */
828 { "boot", chirp_emul_boot },
829 { "enter", chirp_emul_enter },
830 { "exit", chirp_emul_exit },
831 { "chain", chirp_emul_chain },
832
833 /* user interface */
834 { "interpret", chirp_emul_interpret },
835 { "set_callback", chirp_emul_set_callback },
836 { "set_symbol_lookup", chirp_emul_set_symbol_lookup },
837
838 /* time */
839 { "milliseconds", chirp_emul_milliseconds },
840
841 { 0, /* sentinal */ },
842 };
843
844
845 /* main handlers */
846
847 /* Any starting address greater than this is assumed to be an Chirp
848 rather than VEA */
849
850 #ifndef CHIRP_START_ADDRESS
851 #define CHIRP_START_ADDRESS 0x80000000
852 #endif
853
854 typedef struct _chirp_note_desc {
855 signed32 real_mode;
856 signed32 real_base;
857 signed32 real_size;
858 signed32 virt_base;
859 signed32 virt_size;
860 } chirp_note_desc;
861
862 typedef struct _chirp_note {
863 chirp_note_desc desc;
864 int found;
865 } chirp_note;
866
867 typedef struct _chirp_note_head {
868 unsigned32 namesz;
869 unsigned32 descsz;
870 unsigned32 type;
871 } chirp_note_head;
872
873 static void
874 map_over_chirp_note(bfd *image,
875 asection *sect,
876 PTR obj)
877 {
878 chirp_note *note = (chirp_note*)obj;
879 if (strcmp(sect->name, ".note") == 0) {
880 chirp_note_head head;
881 char name[16];
882 /* check the head */
883 if (!bfd_get_section_contents(image, sect,
884 &head, 0, sizeof(head)))
885 return;
886 head.namesz = bfd_get_32(image, (void*)&head.namesz);
887 head.descsz = bfd_get_32(image, (void*)&head.descsz);
888 head.type = bfd_get_32(image, (void*)&head.type);
889 if (head.type != 0x1275)
890 return;
891 note->found = 1;
892 /* check the name field */
893 if (head.namesz > sizeof(name)) {
894 printf_filtered("open-boot warning: note name too long (%ld)\n",
895 (long)head.namesz);
896 return;
897 }
898 if (!bfd_get_section_contents(image, sect,
899 name, sizeof(head), head.namesz)) {
900 printf_filtered("open-boot warning: note name unreadable\n");
901 return;
902 }
903 if (strcmp(name, "PowerPC") != 0) {
904 printf_filtered("open-boot warning: note name (%s) not `PowerPC'\n",
905 name);
906 return;
907 }
908 /* get the contents */
909 if (head.descsz != sizeof(note->desc)) {
910 printf_filtered("open-boot warning: note descriptor of wrong size\n");
911 return;
912 }
913 if (!bfd_get_section_contents(image, sect,
914 &note->desc, /* page align start */
915 ((sizeof(head) + head.namesz) + 3) & ~3,
916 head.descsz)) {
917 printf_filtered("open-boot warning: note descriptor unreadable\n");
918 return;
919 }
920 note->desc.real_mode = bfd_get_32(image, (void*)&note->desc.real_mode);
921 note->desc.real_base = bfd_get_32(image, (void*)&note->desc.real_base);
922 note->desc.real_size = bfd_get_32(image, (void*)&note->desc.real_size);
923 note->desc.virt_base = bfd_get_32(image, (void*)&note->desc.virt_base);
924 note->desc.virt_size = bfd_get_32(image, (void*)&note->desc.virt_size);
925 note->found = 2;
926 }
927 }
928
929
930 static os_emul_data *
931 emul_chirp_create(device *root,
932 bfd *image,
933 const char *name)
934 {
935 os_emul_data *data;
936 chirp_note note;
937 int big_endian;
938
939 /* Sanity check that this really is the chosen emulation */
940 if (name == NULL && image == NULL)
941 return NULL;
942 if (name != NULL
943 && strcmp(name, "ob") != 0
944 && strcmp(name, "ieee1274") != 0
945 && strcmp(name, "chrp") != 0
946 && strcmp(name, "chirp") != 0
947 && strcmp(name, "openboot") != 0)
948 return NULL;
949
950 /* look for an elf note section */
951 memset(&note, 0, sizeof(note));
952 if (image != NULL)
953 bfd_map_over_sections(image, map_over_chirp_note, &note);
954 if (name == NULL && image != NULL && !note.found)
955 return NULL;
956
957 /* the root node */
958 device_add_string_property(root,
959 "name",
960 "gpl,clayton");
961
962 {
963 const unsigned_word memory_size = 0x200000;
964
965 /* the hash table */
966 const unsigned nr_page_table_entry_groups = (memory_size < 0x800000
967 ? 1024 /* min allowed */
968 : (memory_size / 4096 / 2));
969 const unsigned sizeof_htab = nr_page_table_entry_groups * 64;
970 const unsigned_word htab_ra = memory_size - sizeof_htab;
971
972 /* a page for firmware calls */
973 const unsigned_word sizeof_code = 4096;
974 const unsigned_word code_ra = htab_ra - sizeof_code;
975
976 /* the stack */
977 const unsigned sizeof_stack = 32 * 1024;
978 const unsigned_word stack_ra = code_ra - sizeof_stack;
979
980 /* the firmware's home */
981 const int real_mode = 0;
982 /* const unsigned_word real_base = stack_ra; */
983 /* const unsigned real_size = memory_size - real_base; */
984 const unsigned_word virt_base = CHIRP_START_ADDRESS;
985 /* const unsigned virt_size = real_size;*/
986
987 /* the virtual addresses */
988 const unsigned_word stack_va = virt_base;
989 const unsigned_word code_va = stack_va + sizeof_stack;
990 const unsigned_word code_client_va = code_va;
991 const unsigned_word code_callback_va = code_client_va + 16;
992 const unsigned_word code_loop_va = code_callback_va + 16;
993 const unsigned_word htab_va = code_va + sizeof_code;
994
995 #ifdef bfd_big_endian /* new bfd */
996 big_endian = bfd_big_endian(image);
997 #else
998 big_endian = image->xvec->byteorder_big_p;
999 #endif
1000
1001 /* options */
1002 {
1003 device *options = device_tree_add_found(root, "/", "options");
1004 device_add_integer_property(options,
1005 "smp",
1006 MAX_NR_PROCESSORS);
1007 device_add_boolean_property(options,
1008 "little-endian?",
1009 !big_endian);
1010 device_add_string_property(options,
1011 "env",
1012 "operating");
1013 device_add_boolean_property(options,
1014 "strict-alignment?",
1015 (WITH_ALIGNMENT == STRICT_ALIGNMENT
1016 || !big_endian));
1017 device_add_boolean_property(options,
1018 "floating-point?",
1019 WITH_FLOATING_POINT);
1020 device_add_string_property(options,
1021 "os-emul",
1022 "chirp");
1023 }
1024
1025 /* hardware */
1026 device_tree_add_found_uw_u_u(root, "/", "memory",
1027 0, memory_size, access_read_write_exec);
1028
1029 /* initialization */
1030 {
1031 device *init = device_tree_add_found(root, "/", "init");
1032 {
1033 device *init_register = device_tree_add_found(init, "", "register");
1034 device_add_integer_property(init_register,
1035 "pc",
1036 code_loop_va);
1037 device_add_integer_property(init_register,
1038 "0.pc",
1039 bfd_get_start_address(image));
1040 device_add_integer_property(init_register,
1041 "sp",
1042 stack_va + sizeof_stack - 16);
1043
1044 /* init the code callback along with a loop for the unused cpu's */
1045 device_add_integer_property(init_register,
1046 "r5",
1047 code_client_va);
1048 /* client interface */
1049 device_tree_add_found_uw_u_u(init, "",
1050 "data",
1051 code_ra + (code_client_va - code_va),
1052 4, emul_call_instruction);
1053 device_tree_add_found_uw_u_u(init, "",
1054 "data",
1055 code_ra + (code_client_va - code_va) + 4,
1056 4, emul_blr_instruction);
1057 /* callback return address */
1058 device_tree_add_found_uw_u_u(init, "",
1059 "data",
1060 code_ra + (code_callback_va - code_va),
1061 4, emul_call_instruction);
1062 /* loop to keep other processors busy */
1063 device_tree_add_found_uw_u_u(init, "",
1064 "data",
1065 code_ra + (code_loop_va - code_va),
1066 4, emul_loop_instruction);
1067 device_add_integer_property(init_register,
1068 "msr",
1069 (msr_machine_check_enable
1070 | (real_mode
1071 ? 0
1072 : (msr_instruction_relocate
1073 | msr_data_relocate))
1074 | (big_endian
1075 ? 0
1076 : (msr_little_endian_mode
1077 | msr_interrupt_little_endian_mode
1078 ))));
1079 device_add_integer_property(init_register,
1080 "sdr1",
1081 (htab_ra
1082 | MASK32(16, 22)
1083 | ((sizeof_htab - 1) >> 16)));
1084 /* FIXME */
1085 device_add_integer_property(init_register,
1086 "sr8",
1087 0x00fffff8);
1088 device_add_integer_property(init_register,
1089 "sr9",
1090 0x00fffff9);
1091
1092 { /* hash table and vm */
1093 device *htab_root = device_tree_add_found_uw_u(init, "", "htab",
1094 htab_ra, sizeof_htab);
1095 device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte",
1096 stack_ra, stack_va, sizeof_stack,
1097 0x7/*wimg*/, 0x2/*pp*/);
1098 device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte",
1099 code_ra, code_va, sizeof_code,
1100 0x7/*wimg*/, 0x2/*pp*/);
1101 device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte",
1102 htab_ra, htab_va, sizeof_htab,
1103 0x7/*wimg*/, 0x2/*pp*/);
1104 device_tree_add_found_uw_u_u_c(htab_root, "", "pte",
1105 0x4000, /*magic*/
1106 0x7/*wimg*/, 0x2/*pp*/,
1107 bfd_get_filename (image));
1108 }
1109 }
1110 }
1111
1112 { /* chosen options */
1113 device *chosen = device_tree_add_found(root, "/", "chosen");
1114 device_add_string_property(chosen,
1115 "name",
1116 "chosen");
1117 device_add_integer_property(chosen,
1118 "stdin",
1119 0); /* FIXME: ihandle of stdin */
1120 device_add_integer_property(chosen,
1121 "stdout",
1122 1); /* FIXME: ihandle of stdout */
1123 device_add_string_property(chosen,
1124 "bootpath",
1125 "/disk@0:\\boot");
1126 device_add_string_property(chosen,
1127 "bootargs",
1128 "");
1129 #if 0
1130 device_add_integer_property(chosen,
1131 "memory",
1132 0); /* FIXME: ihandle of memory */
1133 device_add_integer_property(chosen,
1134 "mmu",
1135 0);
1136 #endif
1137 }
1138
1139 /* FIXME - should come from the device tree */
1140 data = ZALLOC(os_emul_data);
1141 data->serving_instruction_ea = code_client_va;
1142 data->catching_instruction_ea = code_callback_va;
1143 data->phandles = cap_create("chirp");
1144 data->root = root;
1145 data->services = services;
1146 return data;
1147 }
1148 }
1149
1150 static void
1151 emul_chirp_init(os_emul_data *emul_data,
1152 int nr_cpus)
1153 {
1154 emul_data->state = serving;
1155 cap_init(emul_data->phandles);
1156 }
1157
1158 static int
1159 emul_chirp_instruction_call(cpu *processor,
1160 unsigned_word cia,
1161 unsigned_word ra,
1162 os_emul_data *emul_data)
1163 {
1164 unsigned_word service_name_addr;
1165 unsigned_word result;
1166 char service_buf[32];
1167 char *service_name;
1168 chirp_services *service;
1169
1170 switch (emul_data->state) {
1171
1172 case serving:
1173 /* we are waiting on an OpenBoot request from the client program
1174 via the client interface */
1175 if (cia != emul_data->serving_instruction_ea)
1176 return 0;
1177 emul_data->return_address = LR;
1178 emul_data->arguments = cpu_registers(processor)->gpr[3];
1179 /* try to determine what to do */
1180 service_name_addr = emul_read_word(cpu_registers(processor)->gpr[3],
1181 processor, cia);
1182 service_name = emul_read_string(service_buf, service_name_addr,
1183 sizeof(service_buf), processor, cia);
1184 TRACE(trace_os_emul, ("%s called from 0x%lx with args 0x%lx\n",
1185 service_name,
1186 (unsigned long)emul_data->return_address,
1187 (unsigned long)emul_data->arguments));
1188 /* look it up */
1189 service = services;
1190 while (service->name != NULL && strcmp(service->name, service_name) != 0)
1191 service++;
1192 if (service->name == NULL) {
1193 error("OpenBoot service `%s' not found\n", service_name);
1194 TRACE(trace_os_emul, ("%s not found\n", service_name));
1195 cpu_registers(processor)->gpr[3] = 0;
1196 cpu_restart(processor, emul_data->return_address);
1197 }
1198 emul_data->service = service;
1199 /* call upon it */
1200 result = service->handler(emul_data, processor, cia);
1201 break;
1202
1203 case faulting:
1204 /* We were handling a client request but encountered a page fault
1205 (or other exception). The fault needs to be passed back to the
1206 client using the the client suplied call back interface */
1207 error("emul_chirp_instruction_call() faulting unimplemented\n");
1208 result = -1;
1209 break;
1210
1211 case catching:
1212 /* Have called the client (via the callback interface) because
1213 some fault (hash table miss) occured. The client has finished
1214 handling this and is now returning */
1215 error("emul_chirp_instruction_call() catching unimplemented\n");
1216 result = -1;
1217 break;
1218
1219 default:
1220 error("emul_chirp_instruction_call() unknown internal state\n");
1221 result = -1;
1222 break;
1223
1224 }
1225
1226 /* return to caller - instruction following this is a function return */
1227 return 1;
1228 }
1229
1230 const os_emul emul_chirp = {
1231 "chirp",
1232 emul_chirp_create,
1233 emul_chirp_init,
1234 NULL, /*system_call*/
1235 emul_chirp_instruction_call,
1236 0 /*data*/
1237 };
1238
1239 #endif
This page took 0.061642 seconds and 5 git commands to generate.