Add input support; at end of user writes, call fflush
[deliverable/binutils-gdb.git] / sim / ppc / emul_chirp.c
CommitLineData
93fac324
MM
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
979c3c25 50typedef int (chirp_handler)
93fac324
MM
51 (os_emul_data *data,
52 cpu *processor,
53 unsigned_word cia);
54typedef 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 */
62typedef enum {
63 serving,
979c3c25 64 faulting,
93fac324
MM
65 catching,
66} chirp_emul_state;
67
68struct _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;
52edddb9 77 chirp_services *services;
93fac324
MM
78};
79
80
52edddb9
MM
81/* Read in the argument list and make the most basic check that number
82 of argumnets are consistent with what was expected */
83
84static int
85chirp_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
93fac324
MM
112/* OpenBoot emulation functions */
113
52edddb9
MM
114/* client interface */
115
116static int
117chirp_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
158static int
159chirp_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
979c3c25
MM
206static int
207chirp_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;
52edddb9
MM
222 /* read the arguments in */
223 if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
979c3c25 224 return -1;
979c3c25
MM
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))));
52edddb9 230 /* find a child */
979c3c25
MM
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);
52edddb9 238 /* write the result out */
979c3c25
MM
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
249static int
52edddb9
MM
250chirp_emul_parent(os_emul_data *data,
251 cpu *processor,
252 unsigned_word cia)
979c3c25 253{
52edddb9
MM
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);
979c3c25
MM
289 return 0;
290}
291
292static int
52edddb9
MM
293chirp_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
301static int
302chirp_emul_getproplen(os_emul_data *data,
93fac324
MM
303 cpu *processor,
304 unsigned_word cia)
305{
52edddb9 306 struct getproplen_args {
93fac324
MM
307 unsigned32 service;
308 unsigned32 n_args;
309 unsigned32 n_returns;
310 /*in*/
93fac324 311 unsigned32 phandle;
52edddb9
MM
312 unsigned32 name;
313 /*out*/
314 unsigned32 proplen;
93fac324 315 } args;
52edddb9 316 char name[32];
93fac324 317 device *dev;
52edddb9
MM
318 const device_property *prop;
319 /* read the args in */
320 if (chirp_read_args(&args, sizeof(args), 2, 1, data, processor, cia))
93fac324 321 return -1;
52edddb9
MM
322 dev = cap_internal(data->phandles, args.phandle);
323 /* find our prop and get its length */
93fac324 324 if (dev == (device*)0)
52edddb9
MM
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",
979c3c25
MM
331 (unsigned long)T2H_4(args.phandle),
332 (unsigned long)dev,
52edddb9
MM
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)));
93fac324
MM
345 emul_write_buffer(&args, data->arguments,
346 sizeof(args),
347 processor, cia);
348 return 0;
349}
350
979c3c25 351static int
93fac324
MM
352chirp_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;
52edddb9
MM
371 /* read in the args */
372 if (chirp_read_args(&args, sizeof(args), 4, 1, data, processor, cia))
93fac324 373 return -1;
93fac324 374 dev = cap_internal(data->phandles, args.phandle);
93fac324
MM
375 emul_read_string(name,
376 T2H_4(args.name),
377 sizeof(name),
378 processor, cia);
979c3c25
MM
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)));
52edddb9 386 /* get the property */
979c3c25
MM
387 if (dev == (device*)0)
388 return -1;
93fac324
MM
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 }
979c3c25
MM
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 }
52edddb9 410 /* write back the result */
979c3c25
MM
411 TRACE(trace_os_emul, ("getprop - out - size=%ld\n",
412 (unsigned long)T2H_4(args.size)));
93fac324
MM
413 emul_write_buffer(&args, data->arguments,
414 sizeof(args),
415 processor, cia);
416 return 0;
417}
418
979c3c25 419static int
52edddb9
MM
420chirp_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
428static int
429chirp_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
437static int
438chirp_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
446static int
447chirp_emul_finddevice(os_emul_data *data,
979c3c25
MM
448 cpu *processor,
449 unsigned_word cia)
450{
52edddb9 451 struct finddevice_args {
979c3c25
MM
452 unsigned32 service;
453 unsigned32 n_args;
454 unsigned32 n_returns;
455 /*in*/
52edddb9 456 unsigned32 device_specifier;
979c3c25 457 /*out*/
52edddb9 458 unsigned32 phandle;
979c3c25 459 } args;
52edddb9 460 char device_specifier[1024];
979c3c25 461 device *dev;
52edddb9
MM
462 /* get the args */
463 if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
979c3c25 464 return -1;
52edddb9
MM
465 emul_read_string(device_specifier,
466 T2H_4(args.device_specifier),
467 sizeof(device_specifier),
979c3c25 468 processor, cia);
52edddb9
MM
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",
979c3c25
MM
480 (unsigned long)T2H_4(args.phandle),
481 (unsigned long)dev,
52edddb9 482 (dev == NULL ? "" : device_name(dev))));
979c3c25
MM
483 emul_write_buffer(&args, data->arguments,
484 sizeof(args),
485 processor, cia);
486 return 0;
487}
488
52edddb9
MM
489static int
490chirp_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
498static int
499chirp_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
507static int
508chirp_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
979c3c25
MM
519static int
520chirp_emul_open(os_emul_data *data,
93fac324
MM
521 cpu *processor,
522 unsigned_word cia)
523{
979c3c25
MM
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];
52edddb9
MM
534 /* read the args */
535 if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
979c3c25 536 return -1;
979c3c25
MM
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));
52edddb9 543 /* open the device */
979c3c25
MM
544 printf_filtered("OpenBoot - open unimplemented for %s\n", name);
545 args.ihandle = -1;
52edddb9 546 /* return the ihandle result */
979c3c25
MM
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
555static int
52edddb9
MM
556chirp_emul_close(os_emul_data *data,
557 cpu *processor,
558 unsigned_word cia)
979c3c25 559{
52edddb9 560 error("chirp: close not implemented\n");
979c3c25
MM
561 return 0;
562}
563
564static int
52edddb9 565chirp_emul_read(os_emul_data *data,
979c3c25
MM
566 cpu *processor,
567 unsigned_word cia)
568{
52edddb9 569 struct read_args {
979c3c25
MM
570 unsigned32 service;
571 unsigned32 n_args;
572 unsigned32 n_returns;
573 /*in*/
52edddb9
MM
574 unsigned32 ihandle;
575 unsigned32 addr;
576 unsigned32 len;
979c3c25 577 /*out*/
52edddb9 578 unsigned32 actual;
979c3c25 579 } args;
52edddb9
MM
580 char buf[1024];
581 int actual;
582 /* read the args */
583 if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
979c3c25 584 return -1;
52edddb9
MM
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';
979c3c25 601 }
52edddb9
MM
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 : "")));
979c3c25
MM
609 emul_write_buffer(&args, data->arguments,
610 sizeof(args),
611 processor, cia);
612 return 0;
613}
614
615static int
52edddb9 616chirp_emul_write(os_emul_data *data,
979c3c25
MM
617 cpu *processor,
618 unsigned_word cia)
619{
52edddb9 620 struct write_args {
93fac324
MM
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;
52edddb9
MM
633 /* get the args */
634 if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
93fac324 635 return -1;
93fac324 636 actual = T2H_4(args.len);
979c3c25
MM
637 if (actual >= sizeof(buf))
638 actual = sizeof(buf) - 1;
93fac324
MM
639 emul_read_buffer(buf,
640 T2H_4(args.addr),
641 actual,
642 processor, cia);
979c3c25 643 buf[actual] = '\0';
52edddb9 644 TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n",
979c3c25 645 (unsigned long)args.ihandle, buf, (long)actual));
52edddb9
MM
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",
979c3c25 654 (long)T2H_4(args.actual)));
93fac324
MM
655 emul_write_buffer(&args, data->arguments,
656 sizeof(args),
657 processor, cia);
658 return 0;
659}
660
979c3c25 661static int
52edddb9 662chirp_emul_seek(os_emul_data *data,
979c3c25
MM
663 cpu *processor,
664 unsigned_word cia)
93fac324 665{
52edddb9
MM
666 error("chirp: seek not implemented\n");
667 return 0;
668}
669
670
671/* memory */
672
673static int
674chirp_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
682static int
683chirp_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
694static int
695chirp_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
703static int
704chirp_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
712static int
713chirp_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
721static int
722chirp_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
733static int
734chirp_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
742static int
743chirp_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
751static int
752chirp_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
763static int
764chirp_emul_milliseconds(os_emul_data *data,
765 cpu *processor,
766 unsigned_word cia)
767{
768 struct test_args {
979c3c25
MM
769 unsigned32 service;
770 unsigned32 n_args;
771 unsigned32 n_returns;
772 /*in*/
979c3c25 773 /*out*/
52edddb9 774 unsigned32 ms;
979c3c25 775 } args;
52edddb9 776 unsigned64 time;
979c3c25 777 /* read in the arguments */
52edddb9
MM
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)));
979c3c25
MM
786 emul_write_buffer(&args, data->arguments,
787 sizeof(args),
788 processor, cia);
93fac324
MM
789 return 0;
790}
791
792
52edddb9
MM
793
794
795static chirp_services services[] = {
796
797 /* client interface */
798 { "test", chirp_emul_test },
799
800 /* device tree */
801 { "peer", chirp_emul_peer },
979c3c25 802 { "child", chirp_emul_child },
52edddb9
MM
803 { "parent", chirp_emul_parent },
804 { "instance-to-package", chirp_emul_instance_to_package },
979c3c25 805 { "getproplen", chirp_emul_getproplen },
52edddb9
MM
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 */
979c3c25 816 { "open", chirp_emul_open },
52edddb9 817 { "close", chirp_emul_close },
979c3c25 818 { "read", chirp_emul_read },
93fac324 819 { "write", chirp_emul_write },
52edddb9
MM
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
93fac324
MM
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
854typedef 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
862typedef struct _chirp_note {
863 chirp_note_desc desc;
864 int found;
865} chirp_note;
866
867typedef struct _chirp_note_head {
868 unsigned32 namesz;
869 unsigned32 descsz;
870 unsigned32 type;
871} chirp_note_head;
872
873static void
874map_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 */
52edddb9
MM
893 if (head.namesz > sizeof(name)) {
894 printf_filtered("open-boot warning: note name too long (%ld)\n",
895 (long)head.namesz);
93fac324 896 return;
52edddb9 897 }
93fac324 898 if (!bfd_get_section_contents(image, sect,
52edddb9
MM
899 name, sizeof(head), head.namesz)) {
900 printf_filtered("open-boot warning: note name unreadable\n");
93fac324 901 return;
52edddb9
MM
902 }
903 if (strcmp(name, "PowerPC") != 0) {
904 printf_filtered("open-boot warning: note name (%s) not `PowerPC'\n",
905 name);
93fac324 906 return;
52edddb9 907 }
93fac324 908 /* get the contents */
52edddb9
MM
909 if (head.descsz != sizeof(note->desc)) {
910 printf_filtered("open-boot warning: note descriptor of wrong size\n");
911 return;
912 }
93fac324 913 if (!bfd_get_section_contents(image, sect,
52edddb9
MM
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");
93fac324 918 return;
52edddb9 919 }
93fac324
MM
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
930static os_emul_data *
931emul_chirp_create(device *root,
932 bfd *image,
933 const char *name)
934{
935 os_emul_data *data;
936 chirp_note note;
979c3c25 937 int big_endian;
93fac324
MM
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
979c3c25
MM
957 /* the root node */
958 device_add_string_property(root,
959 "name",
960 "gpl,clayton");
961
93fac324
MM
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;
979c3c25 975
93fac324
MM
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;
979c3c25
MM
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;
93fac324 993 const unsigned_word htab_va = code_va + sizeof_code;
979c3c25
MM
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
93fac324
MM
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?",
979c3c25 1009 !big_endian);
93fac324
MM
1010 device_add_string_property(options,
1011 "env",
1012 "operating");
1013 device_add_boolean_property(options,
1014 "strict-alignment?",
1015 (WITH_ALIGNMENT == STRICT_ALIGNMENT
979c3c25 1016 || !big_endian));
93fac324
MM
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",
979c3c25
MM
1036 code_loop_va);
1037 device_add_integer_property(init_register,
1038 "0.pc",
93fac324
MM
1039 bfd_get_start_address(image));
1040 device_add_integer_property(init_register,
1041 "sp",
1042 stack_va + sizeof_stack - 16);
1043
979c3c25 1044 /* init the code callback along with a loop for the unused cpu's */
93fac324
MM
1045 device_add_integer_property(init_register,
1046 "r5",
979c3c25 1047 code_client_va);
52edddb9 1048 /* client interface */
979c3c25
MM
1049 device_tree_add_found_uw_u_u(init, "",
1050 "data",
1051 code_ra + (code_client_va - code_va),
52edddb9
MM
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 */
979c3c25
MM
1058 device_tree_add_found_uw_u_u(init, "",
1059 "data",
1060 code_ra + (code_callback_va - code_va),
52edddb9
MM
1061 4, emul_call_instruction);
1062 /* loop to keep other processors busy */
979c3c25
MM
1063 device_tree_add_found_uw_u_u(init, "",
1064 "data",
1065 code_ra + (code_loop_va - code_va),
52edddb9 1066 4, emul_loop_instruction);
93fac324
MM
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))
979c3c25 1074 | (big_endian
93fac324
MM
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");
979c3c25
MM
1114 device_add_string_property(chosen,
1115 "name",
1116 "chosen");
1117 device_add_integer_property(chosen,
1118 "stdin",
1119 0); /* FIXME: ihandle of stdin */
93fac324
MM
1120 device_add_integer_property(chosen,
1121 "stdout",
979c3c25
MM
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
93fac324
MM
1137 }
1138
1139 /* FIXME - should come from the device tree */
1140 data = ZALLOC(os_emul_data);
979c3c25
MM
1141 data->serving_instruction_ea = code_client_va;
1142 data->catching_instruction_ea = code_callback_va;
93fac324
MM
1143 data->phandles = cap_create("chirp");
1144 data->root = root;
52edddb9 1145 data->services = services;
93fac324
MM
1146 return data;
1147 }
1148}
1149
1150static void
1151emul_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
1158static int
1159emul_chirp_instruction_call(cpu *processor,
979c3c25
MM
1160 unsigned_word cia,
1161 unsigned_word ra,
1162 os_emul_data *emul_data)
93fac324
MM
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) {
979c3c25 1171
93fac324 1172 case serving:
979c3c25
MM
1173 /* we are waiting on an OpenBoot request from the client program
1174 via the client interface */
93fac324
MM
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);
979c3c25
MM
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));
93fac324
MM
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) {
979c3c25
MM
1193 error("OpenBoot service `%s' not found\n", service_name);
1194 TRACE(trace_os_emul, ("%s not found\n", service_name));
93fac324
MM
1195 cpu_registers(processor)->gpr[3] = 0;
1196 cpu_restart(processor, emul_data->return_address);
1197 }
1198 emul_data->service = service;
93fac324
MM
1199 /* call upon it */
1200 result = service->handler(emul_data, processor, cia);
1201 break;
979c3c25
MM
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
93fac324
MM
1219 default:
1220 error("emul_chirp_instruction_call() unknown internal state\n");
1221 result = -1;
1222 break;
979c3c25 1223
93fac324
MM
1224 }
1225
52edddb9 1226 /* return to caller - instruction following this is a function return */
93fac324
MM
1227 return 1;
1228}
1229
1230const 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.120663 seconds and 4 git commands to generate.