Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/libofw/openfirm.c
34677 views
1
/* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
2
3
/*-
4
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
5
* Copyright (C) 1995, 1996 TooLs GmbH.
6
* All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
* 3. All advertising materials mentioning features or use of this software
17
* must display the following acknowledgement:
18
* This product includes software developed by TooLs GmbH.
19
* 4. The name of TooLs GmbH may not be used to endorse or promote products
20
* derived from this software without specific prior written permission.
21
*
22
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
*/
33
/*-
34
* Copyright (C) 2000 Benno Rice.
35
* All rights reserved.
36
*
37
* Redistribution and use in source and binary forms, with or without
38
* modification, are permitted provided that the following conditions
39
* are met:
40
* 1. Redistributions of source code must retain the above copyright
41
* notice, this list of conditions and the following disclaimer.
42
* 2. Redistributions in binary form must reproduce the above copyright
43
* notice, this list of conditions and the following disclaimer in the
44
* documentation and/or other materials provided with the distribution.
45
*
46
* THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
47
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
52
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
55
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56
*/
57
58
#include <sys/endian.h>
59
#include <sys/stdarg.h>
60
61
#include <stand.h>
62
63
#include "openfirm.h"
64
65
int (*openfirmware)(void *);
66
67
phandle_t chosen;
68
ihandle_t mmu;
69
ihandle_t memory;
70
int real_mode = 0;
71
72
#define IN(x) htobe32((cell_t)x)
73
#define OUT(x) be32toh(x)
74
#define SETUP(a, b, c, d) \
75
a.name = IN( (b) ); \
76
a.nargs = IN( (c) ); \
77
a.nreturns = IN( (d) );
78
79
/* Initialiser */
80
81
void
82
OF_init(int (*openfirm)(void *))
83
{
84
phandle_t options;
85
char mode[sizeof("true")];
86
87
openfirmware = openfirm;
88
89
if ((chosen = OF_finddevice("/chosen")) == -1)
90
OF_exit();
91
if (OF_getprop(chosen, "memory", &memory, sizeof(memory)) == -1) {
92
memory = OF_open("/memory");
93
if (memory == -1)
94
memory = OF_open("/memory@0");
95
if (memory == -1)
96
OF_exit();
97
}
98
if (OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)) == -1)
99
OF_exit();
100
101
/*
102
* Check if we run in real mode. If so, we do not need to map
103
* memory later on.
104
*/
105
options = OF_finddevice("/options");
106
if (OF_getprop(options, "real-mode?", mode, sizeof(mode)) > 0 &&
107
strcmp(mode, "true") == 0)
108
real_mode = 1;
109
}
110
111
/*
112
* Generic functions
113
*/
114
115
/* Test to see if a service exists. */
116
int
117
OF_test(char *name)
118
{
119
static struct {
120
cell_t name;
121
cell_t nargs;
122
cell_t nreturns;
123
cell_t service;
124
cell_t missing;
125
} args = {};
126
SETUP(args, "test", 1, 1);
127
128
args.service = IN(name);
129
if (openfirmware(&args) == -1)
130
return (-1);
131
return (OUT(args.missing));
132
}
133
134
/* Return firmware millisecond count. */
135
int
136
OF_milliseconds(void)
137
{
138
static struct {
139
cell_t name;
140
cell_t nargs;
141
cell_t nreturns;
142
cell_t ms;
143
} args = {};
144
SETUP(args, "milliseconds", 0, 1);
145
146
openfirmware(&args);
147
return (OUT(args.ms));
148
}
149
150
/*
151
* Device tree functions
152
*/
153
154
/* Return the next sibling of this node or 0. */
155
phandle_t
156
OF_peer(phandle_t node)
157
{
158
static struct {
159
cell_t name;
160
cell_t nargs;
161
cell_t nreturns;
162
cell_t node;
163
cell_t next;
164
} args = {};
165
SETUP(args, "peer", 1, 1);
166
167
args.node = node;
168
if (openfirmware(&args) == -1)
169
return (-1);
170
return (args.next);
171
}
172
173
/* Return the first child of this node or 0. */
174
phandle_t
175
OF_child(phandle_t node)
176
{
177
static struct {
178
cell_t name;
179
cell_t nargs;
180
cell_t nreturns;
181
cell_t node;
182
cell_t child;
183
} args = {};
184
SETUP(args, "child", 1, 1);
185
186
args.node = node;
187
if (openfirmware(&args) == -1)
188
return (-1);
189
return (args.child);
190
}
191
192
/* Return the parent of this node or 0. */
193
phandle_t
194
OF_parent(phandle_t node)
195
{
196
static struct {
197
cell_t name;
198
cell_t nargs;
199
cell_t nreturns;
200
cell_t node;
201
cell_t parent;
202
} args = {};
203
SETUP(args, "parent", 1, 1);
204
205
args.node = node;
206
if (openfirmware(&args) == -1)
207
return (-1);
208
return (args.parent);
209
}
210
211
/* Return the package handle that corresponds to an instance handle. */
212
phandle_t
213
OF_instance_to_package(ihandle_t instance)
214
{
215
static struct {
216
cell_t name;
217
cell_t nargs;
218
cell_t nreturns;
219
cell_t instance;
220
cell_t package;
221
} args = {};
222
SETUP(args, "instance-to-package", 1, 1);
223
224
args.instance = instance;
225
if (openfirmware(&args) == -1)
226
return (-1);
227
return (args.package);
228
}
229
230
/* Get the length of a property of a package. */
231
int
232
OF_getproplen(phandle_t package, const char *propname)
233
{
234
static struct {
235
cell_t name;
236
cell_t nargs;
237
cell_t nreturns;
238
cell_t package;
239
cell_t propname;
240
cell_t proplen;
241
} args = {};
242
SETUP(args, "getproplen", 2, 1);
243
244
args.package = package;
245
args.propname = IN(propname);
246
if (openfirmware(&args) == -1)
247
return (-1);
248
return (OUT(args.proplen));
249
}
250
251
/* Get the value of a property of a package. */
252
int
253
OF_getprop(phandle_t package, const char *propname, void *buf, int buflen)
254
{
255
static struct {
256
cell_t name;
257
cell_t nargs;
258
cell_t nreturns;
259
cell_t package;
260
cell_t propname;
261
cell_t buf;
262
cell_t buflen;
263
cell_t size;
264
} args = {};
265
SETUP(args, "getprop", 4, 1);
266
267
args.package = package;
268
args.propname = IN(propname);
269
args.buf = IN(buf);
270
args.buflen = IN(buflen);
271
if (openfirmware(&args) == -1)
272
return (-1);
273
return (OUT(args.size));
274
}
275
276
/* Decode a binary property from a package. */
277
int
278
OF_getencprop(phandle_t package, const char *propname, cell_t *buf, int buflen)
279
{
280
int retval, i;
281
retval = OF_getprop(package, propname, buf, buflen);
282
if (retval == -1)
283
return (retval);
284
285
for (i = 0; i < buflen/4; i++)
286
buf[i] = be32toh((uint32_t)buf[i]);
287
288
return (retval);
289
}
290
291
/* Get the next property of a package. */
292
int
293
OF_nextprop(phandle_t package, const char *previous, char *buf)
294
{
295
static struct {
296
cell_t name;
297
cell_t nargs;
298
cell_t nreturns;
299
cell_t package;
300
cell_t previous;
301
cell_t buf;
302
cell_t flag;
303
} args = {};
304
SETUP(args, "nextprop", 3, 1);
305
306
args.package = package;
307
args.previous = IN(previous);
308
args.buf = IN(buf);
309
if (openfirmware(&args) == -1)
310
return (-1);
311
return (OUT(args.flag));
312
}
313
314
/* Set the value of a property of a package. */
315
/* XXX Has a bug on FirePower */
316
int
317
OF_setprop(phandle_t package, const char *propname, void *buf, int len)
318
{
319
static struct {
320
cell_t name;
321
cell_t nargs;
322
cell_t nreturns;
323
cell_t package;
324
cell_t propname;
325
cell_t buf;
326
cell_t len;
327
cell_t size;
328
} args = {};
329
SETUP(args, "setprop", 4, 1);
330
331
args.package = package;
332
args.propname = IN(propname);
333
args.buf = IN(buf);
334
args.len = IN(len);
335
if (openfirmware(&args) == -1)
336
return (-1);
337
return (OUT(args.size));
338
}
339
340
/* Convert a device specifier to a fully qualified pathname. */
341
int
342
OF_canon(const char *device, char *buf, int len)
343
{
344
static struct {
345
cell_t name;
346
cell_t nargs;
347
cell_t nreturns;
348
cell_t device;
349
cell_t buf;
350
cell_t len;
351
cell_t size;
352
} args = {};
353
SETUP(args, "canon", 3, 1);
354
355
args.device = IN(device);
356
args.buf = IN(buf);
357
args.len = IN(len);
358
if (openfirmware(&args) == -1)
359
return (-1);
360
return (OUT(args.size));
361
}
362
363
/* Return a package handle for the specified device. */
364
phandle_t
365
OF_finddevice(const char *device)
366
{
367
static struct {
368
cell_t name;
369
cell_t nargs;
370
cell_t nreturns;
371
cell_t device;
372
cell_t package;
373
} args = {};
374
SETUP(args, "finddevice", 1, 1);
375
376
args.device = IN(device);
377
if (openfirmware(&args) == -1)
378
return (-1);
379
return (args.package);
380
}
381
382
/* Return the fully qualified pathname corresponding to an instance. */
383
int
384
OF_instance_to_path(ihandle_t instance, char *buf, int len)
385
{
386
static struct {
387
cell_t name;
388
cell_t nargs;
389
cell_t nreturns;
390
cell_t instance;
391
cell_t buf;
392
cell_t len;
393
cell_t size;
394
} args = {};
395
SETUP(args, "instance-to-path", 3, 1);
396
397
args.instance = instance;
398
args.buf = IN(buf);
399
args.len = IN(len);
400
if (openfirmware(&args) == -1)
401
return (-1);
402
return (OUT(args.size));
403
}
404
405
/* Return the fully qualified pathname corresponding to a package. */
406
int
407
OF_package_to_path(phandle_t package, char *buf, int len)
408
{
409
static struct {
410
cell_t name;
411
cell_t nargs;
412
cell_t nreturns;
413
cell_t package;
414
cell_t buf;
415
cell_t len;
416
cell_t size;
417
} args = {};
418
SETUP(args, "package-to-path", 3, 1);
419
420
args.package = package;
421
args.buf = IN(buf);
422
args.len = IN(len);
423
if (openfirmware(&args) == -1)
424
return (-1);
425
return (OUT(args.size));
426
}
427
428
/* Call the method in the scope of a given instance. */
429
int
430
OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
431
{
432
va_list ap;
433
static struct {
434
cell_t name;
435
cell_t nargs;
436
cell_t nreturns;
437
cell_t method;
438
cell_t instance;
439
cell_t args_n_results[12];
440
} args = {};
441
SETUP(args, "call-method", nargs + 2, nreturns + 1);
442
cell_t *cp;
443
int n;
444
445
if (nargs > 6)
446
return (-1);
447
args.method = IN(method);
448
args.instance = instance;
449
va_start(ap, nreturns);
450
for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;)
451
*--cp = IN(va_arg(ap, cell_t));
452
if (openfirmware(&args) == -1)
453
return (-1);
454
if (args.args_n_results[nargs])
455
return (OUT(args.args_n_results[nargs]));
456
/* XXX what if ihandles or phandles are returned */
457
for (cp = (cell_t *)(args.args_n_results + nargs +
458
(n = be32toh(args.nreturns))); --n > 0;)
459
*va_arg(ap, cell_t *) = OUT(*--cp);
460
va_end(ap);
461
return (0);
462
}
463
464
/*
465
* Device I/O functions
466
*/
467
468
/* Open an instance for a device. */
469
ihandle_t
470
OF_open(char *device)
471
{
472
static struct {
473
cell_t name;
474
cell_t nargs;
475
cell_t nreturns;
476
cell_t device;
477
cell_t instance;
478
} args = {};
479
SETUP(args, "open", 1, 1);
480
481
args.device = IN(device);
482
if (openfirmware(&args) == -1 || args.instance == 0) {
483
return (-1);
484
}
485
return (args.instance);
486
}
487
488
/* Close an instance. */
489
void
490
OF_close(ihandle_t instance)
491
{
492
static struct {
493
cell_t name;
494
cell_t nargs;
495
cell_t nreturns;
496
cell_t instance;
497
} args = {};
498
SETUP(args, "close", 1, 0);
499
500
args.instance = instance;
501
openfirmware(&args);
502
}
503
504
/* Read from an instance. */
505
int
506
OF_read(ihandle_t instance, void *addr, int len)
507
{
508
static struct {
509
cell_t name;
510
cell_t nargs;
511
cell_t nreturns;
512
cell_t instance;
513
cell_t addr;
514
cell_t len;
515
cell_t actual;
516
} args = {};
517
SETUP(args, "read", 3, 1);
518
519
args.instance = instance;
520
args.addr = IN(addr);
521
args.len = IN(len);
522
523
#if defined(OPENFIRM_DEBUG)
524
printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
525
instance, addr, len);
526
#endif
527
528
if (openfirmware(&args) == -1)
529
return (-1);
530
531
#if defined(OPENFIRM_DEBUG)
532
printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
533
args.instance, OUT(args.addr), OUT(args.len), OUT(args.actual));
534
#endif
535
536
return (OUT(args.actual));
537
}
538
539
/* Write to an instance. */
540
int
541
OF_write(ihandle_t instance, void *addr, int len)
542
{
543
static struct {
544
cell_t name;
545
cell_t nargs;
546
cell_t nreturns;
547
cell_t instance;
548
cell_t addr;
549
cell_t len;
550
cell_t actual;
551
} args = {};
552
SETUP(args, "write", 3, 1);
553
554
args.instance = instance;
555
args.addr = IN(addr);
556
args.len = IN(len);
557
if (openfirmware(&args) == -1)
558
return (-1);
559
return (OUT(args.actual));
560
}
561
562
/* Seek to a position. */
563
int
564
OF_seek(ihandle_t instance, uint64_t pos)
565
{
566
static struct {
567
cell_t name;
568
cell_t nargs;
569
cell_t nreturns;
570
cell_t instance;
571
cell_t poshi;
572
cell_t poslo;
573
cell_t status;
574
} args = {};
575
SETUP(args, "seek", 3, 1);
576
577
args.instance = instance;
578
args.poshi = IN(((uint64_t)pos >> 32));
579
args.poslo = IN(pos);
580
if (openfirmware(&args) == -1)
581
return (-1);
582
return (OUT(args.status));
583
}
584
585
/* Blocks. */
586
unsigned int
587
OF_blocks(ihandle_t instance)
588
{
589
static struct {
590
cell_t name;
591
cell_t nargs;
592
cell_t nreturns;
593
cell_t instance;
594
cell_t result;
595
cell_t blocks;
596
} args = {};
597
SETUP(args, "#blocks", 2, 1);
598
599
args.instance = instance;
600
if (openfirmware(&args) == -1)
601
return ((unsigned int)-1);
602
return (OUT(args.blocks));
603
}
604
605
/* Block size. */
606
int
607
OF_block_size(ihandle_t instance)
608
{
609
static struct {
610
cell_t name;
611
cell_t nargs;
612
cell_t nreturns;
613
cell_t instance;
614
cell_t result;
615
cell_t size;
616
} args = {};
617
SETUP(args, "block-size", 2, 1);
618
619
args.instance = instance;
620
if (openfirmware(&args) == -1)
621
return (512);
622
return (OUT(args.size));
623
}
624
625
/*
626
* Memory functions
627
*/
628
629
/* Claim an area of memory. */
630
void *
631
OF_claim(void *virt, u_int size, u_int align)
632
{
633
static struct {
634
cell_t name;
635
cell_t nargs;
636
cell_t nreturns;
637
cell_t virt;
638
cell_t size;
639
cell_t align;
640
cell_t baseaddr;
641
} args = {};
642
SETUP(args, "claim", 3, 1);
643
644
args.virt = IN(virt);
645
args.size = IN(size);
646
args.align = IN(align);
647
if (openfirmware(&args) == -1)
648
return ((void *)-1);
649
return ((void *)OUT(args.baseaddr));
650
}
651
652
/* Release an area of memory. */
653
void
654
OF_release(void *virt, u_int size)
655
{
656
static struct {
657
cell_t name;
658
cell_t nargs;
659
cell_t nreturns;
660
cell_t virt;
661
cell_t size;
662
} args = {};
663
SETUP(args, "release", 2, 0);
664
665
args.virt = IN(virt);
666
args.size = IN(size);
667
openfirmware(&args);
668
}
669
670
/*
671
* Control transfer functions
672
*/
673
674
/* Reset the system and call "boot <bootspec>". */
675
void
676
OF_boot(char *bootspec)
677
{
678
static struct {
679
cell_t name;
680
cell_t nargs;
681
cell_t nreturns;
682
cell_t bootspec;
683
} args = {};
684
SETUP(args, "boot", 1, 0);
685
686
args.bootspec = IN(bootspec);
687
openfirmware(&args);
688
for (;;) /* just in case */
689
;
690
}
691
692
/* Suspend and drop back to the Open Firmware interface. */
693
void
694
OF_enter(void)
695
{
696
static struct {
697
cell_t name;
698
cell_t nargs;
699
cell_t nreturns;
700
} args = {};
701
SETUP(args, "enter", 0, 0);
702
703
openfirmware(&args);
704
/* We may come back. */
705
}
706
707
/* Shut down and drop back to the Open Firmware interface. */
708
void
709
OF_exit(void)
710
{
711
static struct {
712
cell_t name;
713
cell_t nargs;
714
cell_t nreturns;
715
} args = {};
716
SETUP(args, "exit", 0, 0);
717
718
openfirmware(&args);
719
for (;;) /* just in case */
720
;
721
}
722
723
void
724
OF_quiesce(void)
725
{
726
static struct {
727
cell_t name;
728
cell_t nargs;
729
cell_t nreturns;
730
} args = {};
731
SETUP(args, "quiesce", 0, 0);
732
733
openfirmware(&args);
734
}
735
736
/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
737
#if 0
738
void
739
OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
740
{
741
static struct {
742
cell_t name;
743
cell_t nargs;
744
cell_t nreturns;
745
cell_t virt;
746
cell_t size;
747
cell_t entry;
748
cell_t arg;
749
cell_t len;
750
} args = {};
751
SETUP(args, "chain", 5, 0);
752
753
args.virt = IN(virt);
754
args.size = IN(size);
755
args.entry = IN(entry);
756
args.arg = IN(arg);
757
args.len = IN(len);
758
openfirmware(&args);
759
}
760
#else
761
void
762
OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
763
{
764
/*
765
* This is a REALLY dirty hack till the firmware gets this going
766
*/
767
#if 0
768
if (size > 0)
769
OF_release(virt, size);
770
#endif
771
((int (*)(u_long, u_long, u_long, void *, u_long))entry)
772
(0, 0, (u_long)openfirmware, arg, len);
773
}
774
#endif
775
776