1 /* Open firmware emulation.
2 *
3 * This is really simplistic. The first goal is to implement all stuff
4 * needed to boot Linux. Then, I'll try Darwin.
5 * Note that this emulation run in the host environment.
6 * There is no Forth interpreter, so standard bootloader cannot be launched.
7 * In the future, it will be nice to get a complete OpenFirmware implementation
8 * so that OSes can be launched exactly the way they are in the real world...
9 *
10 * Copyright (c) 2003-2005 Jocelyn Mayer
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License V2
14 * as published by the Free Software Foundation
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include "bios.h"
29
30 //#define DEBUG_OF 1
31
32 #if defined (DEBUG_OF)
33 #define OF_DPRINTF(fmt, args...) \
34 do { dprintf("%s: " fmt, __func__ , ##args); } while (0)
35 #else
36 #define OF_DPRINTF(fmt, args...) \
37 do { } while (0)
38 #endif
39
40 #define PROT_READ 1
41 #define PROT_WRITE 2
42
43 typedef struct OF_transl_t OF_transl_t;
44 struct OF_transl_t {
45 uint32_t virt;
46 uint32_t size;
47 uint32_t phys;
48 uint32_t mode;
49 };
50
51 typedef struct OF_env_t OF_env_t;
52 struct OF_env_t {
53 uint32_t *stackp; /* Stack pointer */
54 uint32_t *stackb; /* Stack base */
55 uint32_t *funcp; /* Function stack pointer */
56 uint32_t *funcb; /* Function stack base */
57 };
58
59 typedef struct OF_bustyp_t OF_bustyp_t;
60 struct OF_bustyp_t {
61 const char *name;
62 int type;
63 };
64
65 typedef struct pci_address_t pci_address_t;
66 struct pci_address_t {
67 uint32_t hi;
68 uint32_t mid;
69 uint32_t lo;
70 };
71
72 typedef struct pci_reg_prop_t pci_reg_prop_t;
73 struct pci_reg_prop_t {
74 pci_address_t addr;
75 uint32_t size_hi;
76 uint32_t size_lo;
77 };
78
79 typedef struct pci_range_t pci_range_t;
80 struct pci_range_t {
81 pci_address_t addr;
82 uint32_t phys;
83 uint32_t size_hi;
84 uint32_t size_lo;
85 };
86
87 /*****************************************************************************/
88 __attribute__ (( section (".OpenFirmware") ))
OF_lds(uint8_t * dst,const void * address)89 static void OF_lds (uint8_t *dst, const void *address)
90 {
91 const uint8_t *p;
92 uint8_t *_d = dst;
93
94 for (p = address; *p != '\0'; p++) {
95 *_d++ = *p;
96 }
97 *_d = '\0';
98 OF_DPRINTF("Loaded string %s\n", dst);
99 }
100
101 __attribute__ (( section (".OpenFirmware") ))
OF_sts(void * address,const uint8_t * src)102 static void OF_sts (void *address, const uint8_t *src)
103 {
104 const uint8_t *_s;
105 uint8_t *p = address;
106
107 OF_DPRINTF("Store string %s\n", src);
108 for (_s = src; *_s != '\0'; _s++) {
109 *p++ = *_s;
110 }
111 *p = '\0';
112 }
113
114 #define OF_DUMP_STRING(env, buffer) \
115 do { \
116 unsigned char tmp[OF_NAMELEN_MAX]; \
117 OF_lds(tmp, buffer); \
118 OF_DPRINTF("[%s]\n", tmp); \
119 } while (0)
120
121 /*****************************************************************************/
122 /* Forth like environmnent */
123 #define OF_CHECK_NBARGS(env, nb) \
124 do { \
125 int nb_args; \
126 nb_args = stackd_depth((env)); \
127 if (nb_args != (nb)) { \
128 printf("%s: Bad number of arguments (%d - %d)\n", \
129 __func__, nb_args, (nb)); \
130 bug(); \
131 popd_all((env), nb_args); \
132 pushd((env), -1); \
133 return; \
134 } \
135 } while (0)
136
137 #define OF_STACK_SIZE 0x1000
138 #define OF_FSTACK_SIZE 0x100
139 __attribute__ (( section (".OpenFirmware_vars") ))
140 uint8_t OF_stack[OF_STACK_SIZE];
141 __attribute__ (( section (".OpenFirmware_vars") ))
142 uint8_t OF_fstack[OF_FSTACK_SIZE];
143
144 typedef void (*OF_cb_t)(OF_env_t *OF_env);
145
_push(uint32_t ** stackp,uint32_t data)146 static inline void _push (uint32_t **stackp, uint32_t data)
147 {
148 // OF_DPRINTF("%p 0x%0x\n", *stackp, data);
149 **stackp = data;
150 (*stackp)--;
151 }
152
_pop(uint32_t ** stackp)153 static inline uint32_t _pop (uint32_t **stackp)
154 {
155 (*stackp)++;
156 // OF_DPRINTF("%p 0x%0x\n", *stackp, **stackp);
157 return **stackp;
158 }
159
_pop_all(uint32_t ** stackp,int nb)160 static inline void _pop_all (uint32_t **stackp, int nb)
161 {
162 int i;
163
164 for (i = 0; i < nb; i++)
165 (*stackp)++;
166 }
167
_stack_depth(uint32_t * stackp,uint32_t * basep)168 static inline int _stack_depth (uint32_t *stackp, uint32_t *basep)
169 {
170 return basep - stackp;
171 }
172
pushd(OF_env_t * OF_env,uint32_t data)173 static inline void pushd (OF_env_t *OF_env, uint32_t data)
174 {
175 _push(&OF_env->stackp, data);
176 }
177
popd(OF_env_t * OF_env)178 static inline uint32_t popd (OF_env_t *OF_env)
179 {
180 return _pop(&OF_env->stackp);
181 }
182
popd_all(OF_env_t * OF_env,int nb)183 static inline void popd_all (OF_env_t *OF_env, int nb)
184 {
185 _pop_all(&OF_env->stackp, nb);
186 }
187
stackd_depth(OF_env_t * OF_env)188 static inline int stackd_depth (OF_env_t *OF_env)
189 {
190 return _stack_depth(OF_env->stackp, OF_env->stackb);
191 }
192
pushf(OF_env_t * OF_env,OF_cb_t * func)193 static inline void pushf (OF_env_t *OF_env, OF_cb_t *func)
194 {
195 _push(&OF_env->funcp, (uint32_t)func);
196 }
197
popf(OF_env_t * OF_env)198 static inline OF_cb_t *popf (OF_env_t *OF_env)
199 {
200 return (OF_cb_t *)_pop(&OF_env->funcp);
201 }
202
popf_all(OF_env_t * OF_env,int nb)203 static inline void popf_all (OF_env_t *OF_env, int nb)
204 {
205 _pop_all(&OF_env->funcp, nb);
206 }
207
stackf_depth(OF_env_t * OF_env)208 static inline int stackf_depth (OF_env_t *OF_env)
209 {
210 return _stack_depth(OF_env->funcp, OF_env->funcb);
211 }
212
OF_env_init(OF_env_t * OF_env)213 static inline void OF_env_init (OF_env_t *OF_env)
214 {
215 OF_env->stackb = (uint32_t *)(OF_stack + OF_STACK_SIZE - 4);
216 OF_env->stackp = OF_env->stackb;
217 OF_env->funcb = (uint32_t *)(OF_fstack + OF_FSTACK_SIZE - 4);
218 OF_env->funcp = OF_env->funcb;
219 }
220
221 /* Forth run-time */
222 __attribute__ (( section (".OpenFirmware") ))
C_to_Forth(OF_env_t * env,void * p,OF_cb_t * cb)223 static void C_to_Forth (OF_env_t *env, void *p, OF_cb_t *cb)
224 {
225 OF_cb_t *_cb;
226 uint32_t *u, *rets;
227 uint32_t i, n_args, n_rets, tmp;
228
229 // OF_DPRINTF("enter\n");
230 /* Fill argument structure */
231 u = p;
232 n_args = *u++;
233 n_rets = *u++;
234 u += n_args;
235 rets = u;
236 // OF_DPRINTF("n_args=%d n_rets=%d\n", n_args, n_rets);
237 /* Load arguments */
238 for (i = 0; i < n_args; i++)
239 pushd(env, *(--u));
240 pushf(env, cb);
241 while (stackf_depth(env) != 0) {
242 // OF_DPRINTF("func stack: %p %p\n", env->funcb, env->funcp);
243 _cb = popf(env);
244 // OF_DPRINTF("Next func: %p %d\n", cb, stackf_depth(env));
245 (*_cb)(env);
246 }
247 // OF_DPRINTF("Back to C: n_args=%d n_rets=%d\n", n_args, n_rets);
248 /* Copy returned values */
249 for (i = 0; stackd_depth(env) != 0; i++) {
250 tmp = popd(env);
251 // OF_DPRINTF("Store 0x%0x (%d)\n", tmp, tmp);
252 *rets++ = tmp;
253 }
254 for (; i < n_rets; i++)
255 *rets++ = 0;
256 OF_CHECK_NBARGS(env, 0);
257 // OF_DPRINTF("done\n");
258 }
259
260 /*****************************************************************************/
261 /* Memory pool (will be needed when it'll become native) */
262 #if 0
263 #define OF_INTBITS_LEN 128
264 #define OF_INTPOOL_LEN (OF_INTBITS_LEN * 8)
265 __attribute__ (( section (".OpenFirmware_vars") ))
266 static uint32_t OF_int_pool[OF_INTPOOL_LEN];
267 __attribute__ (( section (".OpenFirmware_vars") ))
268 static uint8_t OF_int_bits[OF_INTBITS_LEN];
269
270 __attribute__ (( section (".OpenFirmware") ))
271 static uint32_t *OF_int_alloc (unused OF_env_t *env)
272 {
273 uint8_t tmp;
274 int i, j;
275
276 for (i = 0; i < OF_INTBITS_LEN; i++) {
277 tmp = OF_int_bits[i];
278 if (tmp == 0xFF)
279 continue;
280 for (j = 0; j < 7; j++) {
281 if ((tmp & 1) == 0) {
282 OF_int_bits[i] |= 1 << j;
283 return &OF_int_pool[(i << 3) | j];
284 }
285 tmp = tmp >> 1;
286 }
287 }
288 printf("ALERT: unable to \"allocate\" new integer\n");
289
290 return NULL;
291 }
292
293 __attribute__ (( section (".OpenFirmware") ))
294 static void OF_int_free (unused OF_env_t *env,
295 uint32_t *area)
296 {
297 int i, j;
298
299 i = area - OF_int_pool;
300 j = i & 7;
301 i = i >> 3;
302 OF_int_bits[i] &= ~(1 << j);
303 }
304
305 __attribute__ (( section (".OpenFirmware") ))
306 static void OF_free (unused OF_env_t *env, void *area)
307 {
308 uint32_t *check;
309
310 /* Check if it's in our int pool */
311 check = area;
312 if (check >= OF_int_pool && check < (OF_int_pool + OF_INTPOOL_LEN)) {
313 OF_int_free(env, check);
314 return;
315 }
316 #if 0
317 free(area);
318 #endif
319 }
320 #endif
321
322 /*****************************************************************************/
323 /* Internal structures */
324 /* Property value types */
325 typedef struct OF_node_t OF_node_t;
326 typedef struct OF_prop_t OF_prop_t;
327 typedef struct OF_method_t OF_method_t;
328 typedef struct OF_inst_t OF_inst_t;
329
330 #define OF_ADDRESS_NONE ((uint32_t)(-1))
331
332 /* Tree node */
333 struct OF_node_t {
334 /* Parent node */
335 OF_node_t *parent;
336 /* Link to next node at the same level */
337 OF_node_t *next;
338 /* Link to children, if any */
339 OF_node_t *children, *child_last;
340 /* refcount */
341 int refcount;
342 /* The following ones belong to the package */
343 /* Package */
344 uint16_t pack_id;
345 /* links count */
346 uint16_t link_count;
347 uint16_t link_cur;
348 OF_node_t *link_ref;
349 /* Properties */
350 OF_prop_t *properties, *prop_last, *prop_name, *prop_address;
351 /* Methods */
352 OF_method_t *methods, *method_last;
353 /* private data */
354 void *private_data;
355 /* static data */
356 void *static_data;
357 /* instances */
358 OF_inst_t *instances, *inst_last;
359 };
360
361 /* Node property */
362 struct OF_prop_t {
363 /* Link to next property */
364 OF_prop_t *next;
365 /* The node it belongs to */
366 OF_node_t *node;
367 /* property name */
368 const unsigned char *name;
369 /* property value len */
370 int vlen;
371 /* property value buffer */
372 char *value;
373 /* Property change callback */
374 void (*cb)(OF_env_t *OF_env, OF_prop_t *prop, const void *data, int len);
375 };
376
377 /* Node method */
378 enum {
379 OF_METHOD_INTERNAL = 0,
380 OF_METHOD_EXPORTED,
381 };
382
383 struct OF_method_t {
384 /* Link to next method */
385 OF_method_t *next;
386 /* The package it belongs to */
387 OF_node_t *node;
388 /* method name */
389 unsigned char *name;
390 /* Method function pointer */
391 OF_cb_t func;
392 };
393
394 /* Package instance */
395 struct OF_inst_t {
396 /* Link to next instance of the same package */
397 OF_inst_t *next;
398 /* Link to the parent instance */
399 OF_inst_t *parent;
400 /* The package it belongs to */
401 OF_node_t *node;
402 /* Instance identifier */
403 uint16_t inst_id;
404 /* Instance data */
405 void *data;
406 };
407
408 /* reg property */
409 typedef struct OF_regprop_t OF_regprop_t;
410 struct OF_regprop_t {
411 uint32_t address;
412 uint32_t size;
413 };
414
415 /* range property */
416 typedef struct OF_range_t OF_range_t;
417 struct OF_range_t {
418 uint32_t virt;
419 uint32_t size;
420 uint32_t phys;
421 };
422
423 /* Open firmware tree */
424 #define OF_MAX_PACKAGE 256
425 /* nodes and packages */
426 __attribute__ (( section (".OpenFirmware_vars") ))
427 static OF_node_t *OF_node_root;
428 __attribute__ (( section (".OpenFirmware_vars") ))
429 static uint16_t OF_pack_last_id = 0;
430 __attribute__ (( section (".OpenFirmware_vars") ))
431 static uint16_t inst_last_id = 0;
432 /* To speed up lookup by id, we get a package table */
433 __attribute__ (( section (".OpenFirmware_vars") ))
434 static OF_node_t *OF_packages[OF_MAX_PACKAGE];
435 __attribute__ (( section (".OpenFirmware_vars") ))
436 static OF_node_t *OF_pack_active;
437
438 static OF_prop_t *OF_prop_string_new (OF_env_t *env, OF_node_t *node,
439 const unsigned char *name,
440 const unsigned char *string);
441 static OF_prop_t *OF_prop_int_new (OF_env_t *env, OF_node_t *node,
442 const unsigned char *name, uint32_t value);
443 static OF_prop_t *OF_property_get (OF_env_t *env, OF_node_t *node,
444 const unsigned char *name);
445 static uint16_t OF_pack_handle (OF_env_t *env, OF_node_t *node);
446
447 __attribute__ (( section (".OpenFirmware_vars") ))
448 static uint8_t *RTAS_memory;
449
450 /*****************************************************************************/
451 /* Node management */
452 /* Insert a new node */
453 __attribute__ (( section (".OpenFirmware") ))
OF_pack_new_id(unused OF_env_t * env,OF_node_t * node)454 static uint16_t OF_pack_new_id (unused OF_env_t *env, OF_node_t *node)
455 {
456 uint16_t cur_id;
457
458 for (cur_id = OF_pack_last_id + 1; cur_id != OF_pack_last_id; cur_id++) {
459 if (cur_id == (uint16_t)(OF_MAX_PACKAGE))
460 cur_id = 1;
461 if (OF_packages[cur_id] == NULL) {
462 OF_packages[cur_id] = node;
463 OF_pack_last_id = cur_id;
464 return cur_id;
465 }
466 }
467
468 return (uint16_t)(-1);
469 }
470
OF_node_create(OF_env_t * env,OF_node_t * parent,const unsigned char * name,uint32_t address)471 static OF_node_t *OF_node_create (OF_env_t *env, OF_node_t *parent,
472 const unsigned char *name, uint32_t address)
473 {
474 OF_node_t *new;
475
476 OF_DPRINTF("New node: %s\n", name);
477 new = malloc(sizeof(OF_node_t));
478 if (new == NULL) {
479 ERROR("%s can't alloc new node '%s'\n", __func__, name);
480 return NULL;
481 }
482 memset(new, 0, sizeof(OF_node_t));
483 new->parent = parent;
484 new->refcount = 1;
485 new->link_count = 1;
486 new->prop_name = OF_prop_string_new(env, new, "name", name);
487 if (new->prop_name == NULL) {
488 free(new);
489 ERROR("%s can't alloc new node '%s' name\n", __func__, name);
490 return NULL;
491 }
492 new->prop_address = OF_prop_int_new(env, new, "unit-address", address);
493 if (new->prop_address == NULL) {
494 free(new->prop_name->value);
495 free(new->prop_name);
496 free(new);
497 ERROR("%s can't alloc new node '%s' address\n", __func__, name);
498 return NULL;
499 }
500 /* Link it in parent tree */
501 if (parent != NULL) {
502 /* SHOULD LOCK */
503 if (parent->children == NULL) {
504 parent->children = new;
505 } else {
506 parent->child_last->next = new;
507 }
508 parent->child_last = new;
509 } else {
510 /* This is a bug and should never happen, but for root node */
511 if (strcmp(name, "device-tree") != 0)
512 ERROR("WARNING: parent of '%s' is NULL!\n", name);
513 }
514 // OF_DPRINTF("New node: %s get id\n", name);
515
516 return new;
517 }
518
519 __attribute__ (( section (".OpenFirmware") ))
OF_node_new(OF_env_t * env,OF_node_t * parent,const unsigned char * name,uint32_t address)520 static OF_node_t *OF_node_new (OF_env_t *env, OF_node_t *parent,
521 const unsigned char *name, uint32_t address)
522 {
523 OF_node_t *new;
524
525 new = OF_node_create(env, parent, name, address);
526 if (new == NULL)
527 return NULL;
528 new->pack_id = OF_pack_new_id(env, new);
529 // OF_DPRINTF("New node: %s id=0x%0x\n", name, new->pack_id);
530 OF_pack_active = new;
531
532 return new;
533 }
534
OF_node_parent(unused OF_env_t * env,OF_node_t * node)535 static inline OF_node_t *OF_node_parent (unused OF_env_t *env, OF_node_t *node)
536 {
537 return node->parent;
538 }
539
540 /* Look for a node, given its name */
541 __attribute__ (( section (".OpenFirmware") ))
OF_node_get_child(OF_env_t * env,OF_node_t * parent,const unsigned char * name,uint32_t address)542 static OF_node_t *OF_node_get_child (OF_env_t *env, OF_node_t *parent,
543 const unsigned char *name,
544 uint32_t address)
545 {
546 unsigned char tname[OF_NAMELEN_MAX];
547 OF_node_t *parse, *tmp;
548 OF_prop_t *prop_name, *prop_address;
549 uint32_t *addr_valp;
550 int len, i;
551
552 if (parent == OF_node_root) {
553 OF_DPRINTF("Look for node [%s]\n", name);
554 }
555 len = strlen(name);
556 memcpy(tname, name, len + 1);
557 for (i = len; i > 0; i--) {
558 if (tname[i - 1] == ',') {
559 tname[i - 1] = '\0';
560 len = i;
561 break;
562 }
563 }
564 for (parse = parent->children; parse != NULL; parse = parse->next) {
565 prop_name = parse->prop_name;
566 prop_address = parse->prop_address;
567 if (prop_address == NULL)
568 addr_valp = NULL;
569 else
570 addr_valp = (void *)prop_address->value;
571 #if 0
572 OF_DPRINTF("node [%s] <=> [%s]\n", prop_name->value, tname);
573 #endif
574 if (prop_name != NULL && strncmp(prop_name->value, tname, len) == 0 &&
575 (prop_name->value[len] == '\0') &&
576 (address == OF_ADDRESS_NONE || addr_valp == NULL ||
577 address == *addr_valp)) {
578 parse->refcount++;
579 return parse;
580 }
581 #if 1
582 OF_DPRINTF("look in children [%s]\n", prop_name->value);
583 #endif
584 tmp = OF_node_get_child(env, parse, tname, address);
585 if (tmp != NULL)
586 return tmp;
587 #if 0
588 OF_DPRINTF("didn't find in children [%s]\n", prop_name->value);
589 #endif
590 }
591 if (parent == OF_node_root) {
592 OF_DPRINTF("node [%s] not found\n", name);
593 }
594
595 return NULL;
596 }
597
598 __attribute__ (( section (".OpenFirmware") ))
OF_node_get(OF_env_t * env,const unsigned char * name)599 static OF_node_t *OF_node_get (OF_env_t *env, const unsigned char *name)
600 {
601 unsigned char tname[OF_NAMELEN_MAX];
602 unsigned char *addrp;
603 uint32_t address;
604
605 if (strcmp(name, "device_tree") == 0)
606 return OF_node_root;
607
608 strcpy(tname, name);
609 addrp = strchr(tname, '@');
610 if (addrp == NULL) {
611 address = OF_ADDRESS_NONE;
612 } else {
613 *addrp++ = '\0';
614 address = strtol(addrp, NULL, 16);
615 }
616
617 /* SHOULD LOCK */
618 return OF_node_get_child(env, OF_node_root, name, address);
619 }
620
621 /* Release a node */
622 __attribute__ (( section (".OpenFirmware") ))
OF_node_put(unused OF_env_t * env,OF_node_t * node)623 static void OF_node_put (unused OF_env_t *env, OF_node_t *node)
624 {
625 if (--node->refcount < 0)
626 node->refcount = 0;
627 }
628
629 /*****************************************************************************/
630 /* Packages tree walk */
631 __attribute__ (( section (".OpenFirmware") ))
OF_pack_handle(unused OF_env_t * env,OF_node_t * node)632 static uint16_t OF_pack_handle (unused OF_env_t *env, OF_node_t *node)
633 {
634 if (node == NULL)
635 return 0;
636
637 return node->pack_id;
638 }
639
640 __attribute__ (( section (".OpenFirmware") ))
OF_pack_find_by_name(OF_env_t * env,OF_node_t * base,const unsigned char * name)641 static OF_node_t *OF_pack_find_by_name (OF_env_t *env, OF_node_t *base,
642 const unsigned char *name)
643 {
644 unsigned char tmp[OF_NAMELEN_MAX], *addrp;
645 const unsigned char *sl, *st;
646 OF_node_t *parse;
647 OF_prop_t *prop_name, *prop_address;
648 uint32_t address, *addr_valp;
649 int len;
650
651 OF_DPRINTF("Path [%s] in '%s'\n", name, base->prop_name->value);
652 st = name;
653 if (*st == '/') {
654 st++;
655 }
656 if (*st == '\0') {
657 /* Should never happen */
658 OF_DPRINTF("Done\n");
659 return base;
660 }
661 sl = strchr(st, '/');
662 if (sl == NULL) {
663 len = strlen(st);
664 } else {
665 len = sl - st;
666 }
667 memcpy(tmp, st, len);
668 tmp[len] = '\0';
669 addrp = strchr(tmp, '@');
670 if (addrp == NULL) {
671 address = OF_ADDRESS_NONE;
672 } else {
673 len = addrp - tmp;
674 *addrp++ = '\0';
675 address = strtol(addrp, NULL, 16);
676 }
677 OF_DPRINTF("Look for [%s] '%s' %08x\n", tmp, sl, address);
678 for (parse = base->children; parse != NULL; parse = parse->next) {
679 prop_name = parse->prop_name;
680 prop_address = parse->prop_address;
681 if (prop_address == NULL)
682 addr_valp = NULL;
683 else
684 addr_valp = (void *)prop_address->value;
685 #if 0
686 OF_DPRINTF("Check [%s]\n", prop_name->value);
687 #endif
688 if (prop_name == NULL) {
689 printf("ERROR: missing address in node, parent: '%s'\n",
690 base->prop_name->value);
691 bug();
692 }
693 if (strncmp(prop_name->value, tmp, len) == 0 &&
694 prop_name->value[len] == '\0' &&
695 (address == OF_ADDRESS_NONE || addr_valp == NULL ||
696 address == *addr_valp)) {
697 OF_pack_active = parse;
698 if (sl == NULL) {
699 OF_DPRINTF("Done\n");
700 return parse;
701 }
702 OF_DPRINTF("Recurse: '%s'\n", sl + 1);
703 return OF_pack_find_by_name(env, parse, sl + 1);
704 }
705 }
706 OF_DPRINTF("Didn't found [%s]\n", tmp);
707
708 return NULL;
709 }
710
711 __attribute__ (( section (".OpenFirmware") ))
OF_pack_find(unused OF_env_t * env,uint16_t phandle)712 static OF_node_t *OF_pack_find (unused OF_env_t *env, uint16_t phandle)
713 {
714 if (phandle > OF_MAX_PACKAGE)
715 return NULL;
716 if (OF_packages[phandle] == NULL) {
717 OF_DPRINTF("No package %0x\n", phandle);
718 } else {
719 OF_DPRINTF("return package: %0x %p [%s]\n", phandle,
720 OF_packages[phandle],
721 OF_packages[phandle]->prop_name->value);
722 }
723
724 return OF_packages[phandle];
725 }
726
727 __attribute__ (( section (".OpenFirmware") ))
OF_pack_next(OF_env_t * env,uint16_t phandle)728 static OF_node_t *OF_pack_next (OF_env_t *env, uint16_t phandle)
729 {
730 OF_node_t *node;
731
732 for (node = OF_pack_find(env, phandle); node != NULL; node = node->next) {
733 if (OF_pack_handle(env, node) != phandle)
734 break;
735 }
736 #if 0
737 OF_DPRINTF("found node %p [%s]\n", node, node->prop_name->value);
738 #endif
739
740 return node;
741 }
742
743 __attribute__ (( section (".OpenFirmware") ))
OF_pack_child(OF_env_t * env,uint16_t phandle)744 static OF_node_t *OF_pack_child (OF_env_t *env, uint16_t phandle)
745 {
746 OF_node_t *node;
747
748 node = OF_pack_find(env, phandle);
749 if (node == NULL) {
750 ERROR("%s didn't find pack %04x\n", __func__, phandle);
751 return NULL;
752 }
753 node = node->children;
754 #if 0
755 OF_DPRINTF("found node %p [%s]\n", node, node->prop_name->value);
756 #endif
757
758 return node;
759 }
760
761 __attribute__ (( section (".OpenFirmware") ))
OF_pack_parent(OF_env_t * env,uint16_t phandle)762 static OF_node_t *OF_pack_parent (OF_env_t *env, uint16_t phandle)
763 {
764 OF_node_t *node;
765
766 node = OF_pack_find(env, phandle);
767 if (node == NULL) {
768 ERROR("%s didn't find pack %04x\n", __func__, phandle);
769 return NULL;
770 }
771 node = OF_node_parent(env, node);
772 #if 0
773 OF_DPRINTF("found node %p [%s]\n", node, node->prop_name->value);
774 #endif
775
776 return node;
777 }
778
779 /*****************************************************************************/
780 /* Package properties management */
781 /* Insert a new property */
782 __attribute__ (( section (".OpenFirmware") ))
OF_property_new(unused OF_env_t * env,OF_node_t * node,const unsigned char * name,const void * data,int len)783 static OF_prop_t *OF_property_new (unused OF_env_t *env, OF_node_t *node,
784 const unsigned char *name,
785 const void *data, int len)
786 {
787 OF_prop_t *prop;
788
789 #ifdef DEBUG_OF
790 {
791 OF_prop_t *_prop;
792 _prop = OF_property_get(env, node, name);
793 if (_prop != NULL) {
794 printf("Property '%s' already present !\n", name);
795 bug();
796 }
797 }
798 #endif
799 /* Allocate a new property */
800 prop = malloc(sizeof(OF_prop_t));
801 if (prop == NULL) {
802 ERROR("%s cannot allocate property '%s'\n", __func__, name);
803 return NULL;
804 }
805 memset(prop, 0, sizeof(OF_prop_t));
806 prop->name = strdup(name);
807 if (prop->name == NULL) {
808 free(prop);
809 ERROR("%s cannot allocate property '%s' name\n", __func__, name);
810 return NULL;
811 }
812 /* Fill it */
813 if (data != NULL && len > 0) {
814 prop->value = malloc(len);
815 if (prop->value == NULL) {
816 free(prop);
817 ERROR("%s cannot allocate property '%s' value\n", __func__, name);
818 return NULL;
819 }
820 prop->vlen = len;
821 memcpy(prop->value, data, len);
822 }
823 OF_DPRINTF("New property [%s] '%s'\n\t%p %p %d %p\n", name, prop->name, prop->name, data, len, prop->value);
824 /* Link it */
825 /* SHOULD LOCK */
826 if (node->properties == NULL)
827 node->properties = prop;
828 else
829 node->prop_last->next = prop;
830 node->prop_last = prop;
831
832 return prop;
833 }
834
835 /* Find a property given its name */
836 __attribute__ (( section (".OpenFirmware") ))
OF_property_get(unused OF_env_t * env,OF_node_t * node,const unsigned char * name)837 static OF_prop_t *OF_property_get (unused OF_env_t *env, OF_node_t *node,
838 const unsigned char *name)
839 {
840 OF_prop_t *prop;
841
842 #if 0
843 OF_DPRINTF("Look for property [%s] in 0x%0x '%s'\n", name,
844 node->pack_id, node->prop_name->value);
845 #endif
846 if (node == NULL)
847 return NULL;
848 /* *SHOULD LOCK* */
849 for (prop = node->properties; prop != NULL; prop = prop->next) {
850 #if 0
851 OF_DPRINTF("property [%s] <=> [%s]\n", prop->name, name);
852 #endif
853 if (strcmp(prop->name, name) == 0) {
854 return prop;
855 }
856 }
857 #if 0
858 OF_DPRINTF("property [%s] not found in 0x%08x '%s'\n", name,
859 node->pack_id, node->prop_name->value);
860 #endif
861
862 return NULL;
863 }
864
865 /* Change a property */
866 __attribute__ (( section (".OpenFirmware") ))
OF_property_set(OF_env_t * env,OF_node_t * node,const unsigned char * name,const void * data,int len)867 static OF_prop_t *OF_property_set (OF_env_t *env, OF_node_t *node,
868 const unsigned char *name,
869 const void *data, int len)
870 {
871 OF_prop_t *prop;
872 void *tmp;
873
874 if (node == NULL)
875 return NULL;
876 prop = OF_property_get(env, node, name);
877 if (prop != NULL) {
878 OF_DPRINTF("change property [%s]\n", name);
879 tmp = malloc(len);
880 if (tmp == NULL && len != 0) {
881 ERROR("%s cannot set property '%s'\n", __func__, name);
882 return NULL;
883 }
884 free(prop->value);
885 prop->value = tmp;
886 prop->vlen = len;
887 memcpy(prop->value, data, len);
888 if (prop->cb != NULL) {
889 (*prop->cb)(env, prop, data, len);
890 }
891 } else {
892 OF_DPRINTF("new property [%s]\n", name);
893 prop = OF_property_new(env, node, name, data, len);
894 }
895
896 return prop;
897 }
898
899 __attribute__ (( section (".OpenFirmware") ))
OF_property_len(OF_env_t * env,OF_node_t * node,const unsigned char * name)900 static int OF_property_len (OF_env_t *env, OF_node_t *node,
901 const unsigned char *name)
902 {
903 OF_prop_t *prop;
904
905 prop = OF_property_get(env, node, name);
906 if (prop == NULL)
907 return -1;
908
909 return prop->vlen;
910 }
911
912 __attribute__ (( section (".OpenFirmware") ))
hex2buf(unsigned char * buf,uint32_t value,int fill)913 static unsigned char *hex2buf (unsigned char *buf, uint32_t value, int fill)
914 {
915 int pos, d;
916
917 buf[8] = '\0';
918 pos = 7;
919 if (value == 0) {
920 buf[pos--] = '0';
921 } else {
922 for (; value != 0; pos--) {
923 d = value & 0xF;
924 if (d > 9)
925 d += 'a' - '0' - 10;
926 buf[pos] = d + '0';
927 value = value >> 4;
928 }
929 }
930 if (fill != 0) {
931 for (; pos != -1; pos--) {
932 buf[pos] = '0';
933 }
934 }
935
936 return &buf[pos];
937 }
938
939 __attribute__ (( section (".OpenFirmware") ))
OF_property_copy(OF_env_t * env,void * buffer,int maxlen,OF_node_t * node,const unsigned char * name)940 static int OF_property_copy (OF_env_t *env, void *buffer, int maxlen,
941 OF_node_t *node, const unsigned char *name)
942 {
943 unsigned char tmp[OF_PROPLEN_MAX];
944 OF_prop_t *prop;
945 int len;
946
947 prop = OF_property_get(env, node, name);
948 if (prop == NULL) {
949 ERROR("%s cannot get property '%s' for %s\n", __func__, name,
950 node->prop_name->value);
951 return -1;
952 }
953 len = prop->vlen > maxlen ? maxlen : prop->vlen;
954 if (prop->value != NULL) {
955 tmp[0] = '0';
956 tmp[1] = 'x';
957 hex2buf(tmp + 2, *((uint32_t *)prop->value), 1);
958 } else {
959 *tmp = '\0';
960 }
961 OF_DPRINTF("copy property [%s] len=%d to %p len=%d\n",
962 name, prop->vlen, buffer, maxlen);
963 if (strcmp(name, "name") == 0) {
964 OF_DPRINTF("=> '%s'\n", prop->value);
965 }
966 memcpy(buffer, prop->value, len);
967 // OF_DPRINTF("done\n");
968
969 return len;
970 }
971
972 __attribute__ (( section (".OpenFirmware") ))
OF_property_next(OF_env_t * env,OF_node_t * node,const unsigned char * name)973 static OF_prop_t *OF_property_next (OF_env_t *env, OF_node_t *node,
974 const unsigned char *name)
975 {
976 OF_prop_t *prop, *next;
977
978 if (name == NULL || *name == '\0') {
979 next = node->properties;
980 } else {
981 prop = OF_property_get(env, node, name);
982 if (prop == NULL) {
983 OF_DPRINTF("Property [%s] not found\n", name);
984 next = NULL;
985 } else {
986 next = prop->next;
987 /* Skip address if not set */
988 if (next == node->prop_address &&
989 *((uint32_t *)next->value) == OF_ADDRESS_NONE)
990 next = next->next;
991 }
992 }
993 #if 0
994 OF_DPRINTF("Found property %p\n", next);
995 #endif
996
997 return next;
998 }
999
1000 /* Simplified helpers */
1001 __attribute__ (( section (".OpenFirmware") ))
OF_prop_string_new(OF_env_t * env,OF_node_t * node,const unsigned char * name,const unsigned char * string)1002 static OF_prop_t *OF_prop_string_new (OF_env_t *env, OF_node_t *node,
1003 const unsigned char *name,
1004 const unsigned char *string)
1005 {
1006 #ifdef DEBUG_OF
1007 {
1008 OF_prop_t *prop;
1009 prop = OF_property_get(env, node, name);
1010 if (prop != NULL) {
1011 printf("Property '%s' already present !\n", name);
1012 bug();
1013 }
1014 }
1015 #endif
1016 return OF_property_new(env, node, name,
1017 string, strlen(string) + 1);
1018 }
1019
1020 /* convert '\1' char to '\0' */
OF_prop_string_new1(OF_env_t * env,OF_node_t * node,const unsigned char * name,const unsigned char * string)1021 static OF_prop_t *OF_prop_string_new1 (OF_env_t *env, OF_node_t *node,
1022 const unsigned char *name,
1023 const unsigned char *string)
1024 {
1025 int len, i;
1026 OF_prop_t *ret;
1027 unsigned char *str;
1028
1029 if (strchr(string, '\1') == NULL) {
1030 return OF_prop_string_new(env, node, name, string);
1031 } else {
1032 len = strlen(string) + 1;
1033 str = malloc(len);
1034 if (!str)
1035 return NULL;
1036 memcpy(str, string, len);
1037 for(i = 0; i < len; i++)
1038 if (str[i] == '\1')
1039 str[i] = '\0';
1040 ret = OF_property_new(env, node, name,
1041 str, len);
1042 free(str);
1043 return ret;
1044 }
1045 }
1046
1047 __attribute__ (( section (".OpenFirmware") ))
OF_prop_int_new(OF_env_t * env,OF_node_t * node,const unsigned char * name,uint32_t value)1048 static OF_prop_t *OF_prop_int_new (OF_env_t *env, OF_node_t *node,
1049 const unsigned char *name, uint32_t value)
1050 {
1051 #ifdef DEBUG_OF
1052 {
1053 OF_prop_t *prop;
1054 prop = OF_property_get(env, node, name);
1055 if (prop != NULL) {
1056 printf("Property '%s' already present !\n", name);
1057 bug();
1058 }
1059 }
1060 #endif
1061 return OF_property_new(env, node, name, &value, sizeof(uint32_t));
1062 }
1063
1064 __attribute__ (( section (".OpenFirmware") ))
OF_prop_string_set(OF_env_t * env,OF_node_t * node,const unsigned char * name,const unsigned char * string)1065 static OF_prop_t *OF_prop_string_set (OF_env_t *env, OF_node_t *node,
1066 const unsigned char *name,
1067 const unsigned char *string)
1068 {
1069 const unsigned char *tmp;
1070
1071 tmp = strdup(string);
1072 if (tmp == NULL) {
1073 ERROR("%s cannot duplicate property '%s'\n", __func__, name);
1074 return NULL;
1075 }
1076
1077 return OF_property_set(env, node, name, tmp, strlen(string) + 1);
1078 }
1079
1080 __attribute__ (( section (".OpenFirmware") ))
OF_prop_int_set(OF_env_t * env,OF_node_t * node,const unsigned char * name,uint32_t value)1081 static OF_prop_t *OF_prop_int_set (OF_env_t *env, OF_node_t *node,
1082 const unsigned char *name, uint32_t value)
1083 {
1084 return OF_property_set(env, node, name, &value, sizeof(uint32_t));
1085 }
1086
1087 __attribute__ (( section (".OpenFirmware") ))
1088 unused
OF_set_compatibility(OF_env_t * env,OF_node_t * node,const unsigned char * compat)1089 static OF_prop_t *OF_set_compatibility (OF_env_t *env, OF_node_t *node,
1090 const unsigned char *compat)
1091 {
1092 return OF_prop_string_new(env, node, "compatible", compat);
1093 }
1094
1095 __attribute__ (( section (".OpenFirmware") ))
OF_property_set_cb(unused OF_env_t * OF_env,OF_prop_t * prop,void (* cb)(OF_env_t * OF_env,OF_prop_t * prop,const void * data,int len))1096 static inline void OF_property_set_cb (unused OF_env_t *OF_env,
1097 OF_prop_t *prop,
1098 void (*cb)(OF_env_t *OF_env,
1099 OF_prop_t *prop,
1100 const void *data, int len))
1101 {
1102 prop->cb = cb;
1103 }
1104
1105 /*****************************************************************************/
1106 /* Packages methods management */
1107 __attribute__ (( section (".OpenFirmware") ))
OF_method_new(unused OF_env_t * env,OF_node_t * node,const unsigned char * name,OF_cb_t cb)1108 static OF_method_t *OF_method_new (unused OF_env_t *env, OF_node_t *node,
1109 const unsigned char *name, OF_cb_t cb)
1110 {
1111 OF_method_t *new;
1112
1113 new = malloc(sizeof(OF_method_t));
1114 if (new == NULL) {
1115 ERROR("%s cannot allocate method '%s'\n", __func__, name);
1116 return NULL;
1117 }
1118 memset(new, 0, sizeof(OF_method_t));
1119 new->node = node;
1120 new->name = strdup(name);
1121 if (new->name == NULL) {
1122 free(new);
1123 ERROR("%s cannot allocate method '%s' name\n", __func__, name);
1124 return NULL;
1125 }
1126 OF_DPRINTF("new method name %p %s\n", new, new->name);
1127 new->func = cb;
1128 /* Link it */
1129 /* *SHOULD LOCK* */
1130 if (node->method_last == NULL)
1131 node->methods = new;
1132 else
1133 node->method_last->next = new;
1134 node->method_last = new;
1135
1136 return new;
1137 }
1138
1139 __attribute__ (( section (".OpenFirmware") ))
OF_method_get(unused OF_env_t * env,OF_node_t * node,const unsigned char * name)1140 static OF_method_t *OF_method_get (unused OF_env_t *env, OF_node_t *node,
1141 const unsigned char *name)
1142 {
1143 OF_method_t *parse;
1144
1145 if (node == NULL) {
1146 OF_DPRINTF("No method in NULL package !\n");
1147 return NULL;
1148 }
1149 #if 0
1150 OF_DPRINTF("Look for method %s in package %0x\n",
1151 name, node->pack_id);
1152 #endif
1153 for (parse = node->methods; parse != NULL; parse = parse->next) {
1154 #if 0
1155 OF_DPRINTF("check %p %p\n", parse, parse->name);
1156 OF_DPRINTF("name=%s\n", parse->name);
1157 #endif
1158 if (strcmp(parse->name, name) == 0)
1159 return parse;
1160 }
1161
1162 return NULL;
1163 }
1164
1165 /*****************************************************************************/
1166 /* Packages instances management */
1167 __attribute__ (( section (".OpenFirmware") ))
OF_inst_new_id(unused OF_env_t * env,OF_node_t * node)1168 static uint16_t OF_inst_new_id (unused OF_env_t *env, OF_node_t *node)
1169 {
1170 OF_inst_t *tmp_inst;
1171 uint16_t cur_id;
1172
1173 #if 0
1174 OF_DPRINTF("[%s] %d\n", node->prop_name->value,
1175 inst_last_id);
1176 #endif
1177 for (cur_id = inst_last_id + 1;
1178 cur_id != inst_last_id; cur_id++) {
1179 if (cur_id == (uint16_t)(OF_MAX_PACKAGE))
1180 cur_id = 0;
1181 for (tmp_inst = node->instances; tmp_inst != NULL;
1182 tmp_inst = tmp_inst->next) {
1183 if (tmp_inst->inst_id == cur_id)
1184 continue;
1185 }
1186 inst_last_id = cur_id;
1187 #if 1
1188 OF_DPRINTF("0x%0x\n", cur_id);
1189 #endif
1190 return cur_id;
1191 }
1192 OF_DPRINTF("no ID found\n");
1193
1194 return (uint16_t)(-1);
1195 }
1196
1197 /* Create a new package's instance */
1198 __attribute__ (( section (".OpenFirmware") ))
OF_instance_new(OF_env_t * env,OF_node_t * node)1199 static OF_inst_t *OF_instance_new (OF_env_t *env, OF_node_t *node)
1200 {
1201 OF_inst_t *new, *parent;
1202 uint16_t new_id;
1203
1204 /* TODO: recurse to root... */
1205 new = malloc(sizeof(OF_inst_t));
1206 if (new == NULL) {
1207 ERROR("%s cannot allocate instance of '%s'\n", __func__,
1208 node->prop_name->value);
1209 return NULL;
1210 }
1211 memset(new, 0, sizeof(OF_inst_t));
1212 if (OF_node_parent(env, node) != NULL) {
1213 parent = OF_instance_new(env, OF_node_parent(env, node));
1214 if (parent == NULL) {
1215 free(new);
1216 ERROR("%s cannot allocate instance of '%s' parent\n", __func__,
1217 node->prop_name->value);
1218 return NULL;
1219 }
1220 new->parent = parent;
1221 } else {
1222 new->parent = NULL;
1223 }
1224 new_id = OF_inst_new_id(env, node);
1225 if (new_id == (uint16_t)(-1)) {
1226 free(new);
1227 return NULL;
1228 }
1229 new->inst_id = new_id;
1230 new->node = node;
1231 /* Link it */
1232 /* SHOULD LOCK */
1233 if (node->inst_last == NULL)
1234 node->instances = new;
1235 else
1236 node->inst_last->next = new;
1237 node->inst_last = new;
1238
1239 return new;
1240 }
1241
1242 __attribute__ (( section (".OpenFirmware") ))
OF_instance_get_id(unused OF_env_t * env,OF_inst_t * instance)1243 static uint32_t OF_instance_get_id (unused OF_env_t *env, OF_inst_t *instance)
1244 {
1245 OF_DPRINTF("p: %0x i: %0x\n", instance->node->pack_id, instance->inst_id);
1246 return (instance->node->pack_id << 16) | instance->inst_id;
1247 }
1248
1249 __attribute__ (( section (".OpenFirmware") ))
OF_inst_find(OF_env_t * env,uint32_t ihandle)1250 static OF_inst_t *OF_inst_find (OF_env_t *env, uint32_t ihandle)
1251 {
1252 OF_node_t *node;
1253 OF_inst_t *parse;
1254 uint16_t phandle = ihandle >> 16;
1255
1256 ihandle &= 0xFFFF;
1257 OF_DPRINTF("p: %0x i: %0x\n", phandle, ihandle);
1258 if (ihandle > OF_MAX_PACKAGE)
1259 return NULL;
1260 node = OF_pack_find(env, phandle);
1261 if (node == NULL)
1262 return NULL;
1263 for (parse = node->instances; parse != NULL; parse = parse->next) {
1264 if (parse->inst_id == ihandle)
1265 return parse;
1266 }
1267
1268 return NULL;
1269 }
1270
1271 #if 0
1272 __attribute__ (( section (".OpenFirmware") ))
1273 static OF_inst_t *OF_inst_get_child (OF_env_t *env, OF_node_t *parent,
1274 const uint32_t handle)
1275 {
1276 OF_node_t *parse, *tmp;
1277
1278 for (parse = parent->children; parse != NULL; parse = parse->next) {
1279 if (parse->pack_id == (handle >> 16)) {
1280 return NULL;
1281 }
1282 tmp = OF_inst_get_child(env, parse, handle);
1283 if (tmp != NULL)
1284 return tmp;
1285 }
1286
1287 return NULL;
1288 }
1289
1290 __attribute__ (( section (".OpenFirmware") ))
1291 static OF_inst_t *OF_inst_get (OF_env_t *env, const unsigned char *name)
1292 {
1293 return _OF_node_get(env, &OF_node_root);
1294
1295 }
1296 #endif
1297
1298 #if 0
1299 __attribute__ (( section (".OpenFirmware") ))
1300 int get_node_name (OF_env_t *env, unsigned char *name,
1301 int len, OF_node_t *node)
1302 {
1303 int tmp, total;
1304 int i;
1305
1306 /* Set up manufacturer name */
1307 total = 0;
1308 tmp = 0;
1309 #if 0
1310 if (OF_node_parent(env, node) == NULL ||
1311 node->manufct != OF_node_parent(env, node)->manufct) {
1312 tmp = strlen(node->manufct);
1313 if ((tmp + 2) > len)
1314 return -1;
1315 memcpy(name, node->manufct, tmp);
1316 name += tmp;
1317 } else if (len < 2) {
1318 return -1;
1319 }
1320 *name++ = ',';
1321 len -= tmp + 1;
1322 total += tmp + 1;
1323 #endif
1324 /* Set up device model */
1325 tmp = strlen(node->name);
1326 if ((tmp + 2) > len)
1327 return -1;
1328 memcpy(name, node->model, tmp);
1329 name += tmp;
1330 *name++ = '@';
1331 len -= tmp + 1;
1332 total += tmp + 1;
1333 /* Set up unit address */
1334 tmp = strlen(node->address);
1335 if ((tmp + 2) > len)
1336 return -1;
1337 memcpy(name, node->address, tmp);
1338 name += tmp;
1339 *name++ = ':';
1340 len -= tmp + 1;
1341 total += tmp + 1;
1342 for (i = 0; node->arguments[i] != NULL; i++) {
1343 if (i != 0)
1344 *name++ = ',';
1345 tmp = strlen(node->arguments[i]);
1346 if ((tmp + 2) > len)
1347 return -1;
1348 memcpy(name, node->arguments[i], tmp);
1349 name += tmp;
1350 len -= tmp + 1;
1351 total += tmp + 1;
1352 }
1353 *name = '\0';
1354
1355 return total;
1356 }
1357 #endif
1358
1359 __attribute__ (( section (".OpenFirmware") ))
OF_pack_get_path(OF_env_t * env,unsigned char * name,int len,OF_node_t * node)1360 static int OF_pack_get_path (OF_env_t *env, unsigned char *name,
1361 int len, OF_node_t *node)
1362 {
1363 OF_prop_t *prop_name, *prop_address;
1364 uint32_t address;
1365 int tmp, nlen;
1366
1367 /* Recurse until we reach the root node */
1368 OF_DPRINTF("look for [%s]\n", node->prop_name->value);
1369 if (OF_node_parent(env, node) == NULL) {
1370 name[0] = '/';
1371 tmp = 0;
1372 nlen = 1;
1373 } else {
1374 tmp = OF_pack_get_path(env, name, len, OF_node_parent(env, node));
1375 /* Add node name */
1376 prop_name = node->prop_name;
1377 prop_address = node->prop_address;
1378 #if 1
1379 OF_DPRINTF("Found [%s]\n", prop_name->value);
1380 #endif
1381 if ((len - tmp) < 2) {
1382 OF_DPRINTF("Buffer too short (%d 2)\n", len - tmp);
1383 return 0;
1384 }
1385 if (prop_name == NULL) {
1386 printf("No name in node !\n");
1387 bug();
1388 }
1389 nlen = strlen(prop_name->value);
1390 #if 1
1391 OF_DPRINTF("got '%s' for '%s' parent (%d %d)\n",
1392 name, prop_name->value, tmp, nlen);
1393 #endif
1394 if (name[tmp - 1] != '/') {
1395 name[tmp] = '/';
1396 tmp++;
1397 }
1398 address = *((uint32_t *)prop_address->value);
1399 if (address != OF_ADDRESS_NONE) {
1400 if ((len - tmp - nlen) < 10) {
1401 OF_DPRINTF("Buffer too short (%d %d)\n", len - tmp, nlen + 10);
1402 return 0;
1403 }
1404 } else {
1405 if ((len - tmp - nlen) < 1) {
1406 OF_DPRINTF("Buffer too short (%d %d)\n", len - tmp, nlen + 1);
1407 return 0;
1408 }
1409 }
1410 memcpy(name + tmp, prop_name->value, nlen);
1411 if (address != OF_ADDRESS_NONE) {
1412 OF_DPRINTF("Add address 0x%08x\n", address);
1413 sprintf(name + tmp + nlen, "@%x", address);
1414 nlen += strlen(name + tmp + nlen);
1415 } else {
1416 OF_DPRINTF("No address....\n");
1417 }
1418 }
1419 name[tmp + nlen] = '\0';
1420 OF_DPRINTF("stored [%d]\n", tmp + nlen);
1421 OF_DUMP_STRING(env, name);
1422 #if 1
1423 OF_DPRINTF("name '%s' => '%s' %d\n",
1424 node->properties->value, name, tmp + nlen);
1425 #endif
1426
1427 return tmp + nlen;
1428 }
1429
1430 __attribute__ (( section (".OpenFirmware") ))
OF_inst_get_path(OF_env_t * env,unsigned char * name,int len,OF_inst_t * inst)1431 static int OF_inst_get_path (OF_env_t *env, unsigned char *name,
1432 int len, OF_inst_t *inst)
1433 {
1434 return OF_pack_get_path(env, name, len, inst->node);
1435 }
1436
1437 /*****************************************************************************/
1438 /* Open firmware C interface */
1439 static void OF_serial_write (OF_env_t *OF_env);
1440 static void OF_serial_read (OF_env_t *OF_env);
1441 static void OF_mmu_translate (OF_env_t *OF_env);
1442 static void OF_mmu_map (OF_env_t *OF_env);
1443 static void RTAS_instantiate (OF_env_t *RTAS_env);
1444
1445 static OF_env_t *OF_env_main;
1446
1447 /* Init standard OF structures */
1448 __attribute__ (( section (".OpenFirmware") ))
OF_init(void)1449 int OF_init (void)
1450 {
1451 #if 0
1452 "PowerMac3,1\0MacRISC\0Power Macintosh\0";
1453 "PowerMac1,2\0MacRISC\0Power Macintosh\0";
1454 "AAPL,PowerMac G3\0PowerMac G3\0MacRISC\0Power Macintosh\0";
1455 "AAPL,PowerMac3,0\0MacRISC\0Power Macintosh\0";
1456 "AAPL,Gossamer\0MacRISC\0Power Macintosh\0";
1457 #endif
1458 OF_env_t *OF_env;
1459 OF_node_t *als, *opt, *chs, *pks;
1460 OF_inst_t *inst;
1461 OF_range_t range;
1462
1463 OF_DPRINTF("start\n");
1464 OF_env_main = malloc(sizeof(OF_env_t));
1465 if (OF_env_main == NULL) {
1466 ERROR("%s cannot allocate main OF env\n", __func__);
1467 return -1;
1468 }
1469 // memset(OF_env_main, 0, sizeof(OF_env_t));
1470 OF_env = OF_env_main;
1471 // OF_env_init(OF_env);
1472
1473 OF_DPRINTF("start\n");
1474 /* Set up standard IEEE 1275 nodes */
1475 /* "/device-tree" */
1476 OF_node_root = OF_node_new(OF_env, NULL, "device-tree", OF_ADDRESS_NONE);
1477 if (OF_node_root == NULL) {
1478 ERROR("Cannot create 'device-tree'\n");
1479 return -1;
1480 }
1481 OF_prop_string_new(OF_env, OF_node_root, "device_type", "bootrom");
1482 if (arch == ARCH_HEATHROW) {
1483 const unsigned char compat_str[] =
1484 "PowerMac1,1\0MacRISC\0Power Macintosh";
1485 OF_property_new(OF_env, OF_node_root, "compatible",
1486 compat_str, sizeof(compat_str));
1487 OF_prop_string_new(OF_env, OF_node_root,
1488 "model", "Power Macintosh");
1489 } else {
1490 const unsigned char compat_str[] =
1491 "PowerMac3,1\0MacRISC\0Power Macintosh";
1492 OF_property_new(OF_env, OF_node_root, "compatible",
1493 compat_str, sizeof(compat_str));
1494 OF_prop_string_new(OF_env, OF_node_root,
1495 "model", "PowerMac3,1");
1496 }
1497 #if 0
1498 OF_prop_string_new(OF_env, OF_node_root, "copyright", copyright);
1499 #else
1500 OF_prop_string_new(OF_env, OF_node_root, "copyright",
1501 "Copyright 1983-1999 Apple Computer, Inc. All Rights Reserved");
1502 #endif
1503 OF_prop_string_new(OF_env, OF_node_root, "system-id", "42");
1504 OF_prop_int_new(OF_env, OF_node_root, "#address-cells", 1);
1505 OF_prop_int_new(OF_env, OF_node_root, "#size-cells", 1);
1506 OF_prop_int_new(OF_env, OF_node_root, "clock-frequency", 0x05F03E4D);
1507 /* "/aliases" node */
1508 als = OF_node_new(OF_env, OF_node_root, "aliases", OF_ADDRESS_NONE);
1509 if (als == NULL) {
1510 ERROR("Cannot create 'aliases'\n");
1511 return -1;
1512 }
1513 /* "/chosen" node */
1514 chs = OF_node_new(OF_env, OF_node_root, "chosen", OF_ADDRESS_NONE);
1515 if (chs == NULL) {
1516 ERROR("Cannot create 'choosen'\n");
1517 return -1;
1518 }
1519 /* "/packages" node */
1520 pks = OF_node_new(OF_env, OF_node_root, "packages", OF_ADDRESS_NONE);
1521 if (pks == NULL) {
1522 ERROR("Cannot create 'packages'\n");
1523 return -1;
1524 }
1525 /* "/cpus" node */
1526 {
1527 OF_node_t *cpus;
1528 cpus = OF_node_new(OF_env, OF_node_root, "cpus", OF_ADDRESS_NONE);
1529 if (cpus == NULL) {
1530 ERROR("Cannot create 'cpus'\n");
1531 return -1;
1532 }
1533 OF_prop_int_new(OF_env, cpus, "#address-cells", 1);
1534 OF_prop_int_new(OF_env, cpus, "#size-cells", 0);
1535 OF_node_put(OF_env, cpus);
1536 }
1537 /* "/memory@0" node */
1538 {
1539 OF_node_t *mem;
1540 mem = OF_node_new(OF_env, OF_node_root, "memory", 0);
1541 if (mem == NULL) {
1542 ERROR("Cannot create 'memory'\n");
1543 return -1;
1544 }
1545 OF_prop_string_new(OF_env, mem, "device_type", "memory");
1546 OF_prop_int_new(OF_env, chs, "memory", OF_pack_handle(OF_env, mem));
1547 OF_node_put(OF_env, mem);
1548 }
1549 /* "/openprom" node */
1550 {
1551 OF_node_t *opp;
1552 opp = OF_node_new(OF_env, OF_node_root, "openprom", OF_ADDRESS_NONE);
1553 if (opp == NULL) {
1554 ERROR("Cannot create 'openprom'\n");
1555 return -1;
1556 }
1557 OF_prop_string_new(OF_env, opp, "device_type", "BootROM");
1558 OF_prop_string_new(OF_env, opp, "model", "OpenFirmware 3");
1559 OF_prop_int_new(OF_env, opp, "boot-syntax", 0x0001);
1560 OF_property_new(OF_env, opp, "relative-addressing", NULL, 0);
1561 OF_property_new(OF_env, opp, "supports-bootinfo", NULL, 0);
1562 OF_prop_string_new(OF_env, opp, "built-on", stringify(BUILD_DATE));
1563 OF_prop_string_new(OF_env, als, "rom", "/openprom");
1564 OF_node_put(OF_env, opp);
1565 }
1566 /* "/options" node */
1567 opt = OF_node_new(OF_env, OF_node_root, "options", OF_ADDRESS_NONE);
1568 if (opt == NULL) {
1569 ERROR("Cannot create 'options'\n");
1570 return -1;
1571 }
1572 OF_prop_string_new(OF_env, opt, "little-endian?", "false");
1573 OF_prop_string_new(OF_env, opt, "real-mode?", "false");
1574 // Will play with this...
1575 OF_prop_string_new(OF_env, opt, "security-mode", "none");
1576 /* "/rom@ff800000" node */
1577 {
1578 OF_regprop_t regs;
1579 OF_node_t *rom, *brom;
1580
1581 rom = OF_node_new(OF_env, OF_node_root, "rom", 0xff800000);
1582 if (rom == NULL) {
1583 ERROR("Cannot create 'rom'\n");
1584 return -1;
1585 }
1586 regs.address = 0xFF800000;
1587 regs.size = 0x00000000;
1588 OF_property_new(OF_env, rom, "reg", ®s, sizeof(OF_regprop_t));
1589 range.virt = 0xFF800000;
1590 range.phys = 0xFF800000;
1591 range.size = 0x00800000;
1592 OF_property_new(OF_env, rom, "ranges", &range, sizeof(OF_range_t));
1593 OF_prop_int_new(OF_env, rom, "#address-cells", 1);
1594
1595 /* "/rom/boot-rom@fff00000" node */
1596 brom = OF_node_new(OF_env, rom, "boot-rom", 0xfff00000);
1597 if (brom == NULL) {
1598 ERROR("Cannot create 'boot-rom'\n");
1599 return -1;
1600 }
1601 regs.address = 0xFFF00000;
1602 regs.size = 0x00100000;
1603 OF_property_new(OF_env, brom, "reg", ®s, sizeof(OF_regprop_t));
1604 OF_prop_string_new(OF_env, brom, "write-characteristic", "flash");
1605 OF_prop_string_new(OF_env, brom, "BootROM-build-date",
1606 stringify(BUILD_DATE) " at " stringify(BUILD_TIME));
1607 OF_prop_string_new(OF_env, brom, "BootROM-version", BIOS_VERSION);
1608 OF_prop_string_new(OF_env, brom, "copyright", copyright);
1609 OF_prop_string_new(OF_env, brom, "model", BIOS_str);
1610 OF_prop_int_new(OF_env, brom, "result", 0);
1611 #if 1
1612 {
1613 /* Hack taken 'as-is' from PearPC */
1614 unsigned char info[] = {
1615 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
1616 0x00, 0x01, 0x12, 0xf2, 0x19, 0x99, 0x08, 0x19,
1617 0x94, 0x4e, 0x73, 0x27, 0xff, 0xf0, 0x80, 0x00,
1618 0x00, 0x07, 0x80, 0x01, 0x00, 0x01, 0x12, 0xf2,
1619 0x19, 0x99, 0x08, 0x19, 0xd7, 0xf3, 0xfc, 0x17,
1620 0xff, 0xf8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02,
1621 0x00, 0x01, 0x12, 0xf2, 0x19, 0x99, 0x08, 0x19,
1622 0xbb, 0x10, 0xfc, 0x17,
1623 };
1624 OF_property_new(OF_env, brom, "info", info, sizeof(info));
1625 }
1626 #endif
1627 OF_node_put(OF_env, brom);
1628 OF_node_put(OF_env, rom);
1629 }
1630 #if 0
1631 /* From here, hardcoded hacks to get a Mac-like machine */
1632 /* XXX: Core99 does not seem to like this NVRAM tree */
1633 /* "/nvram@fff04000" node */
1634 {
1635 OF_regprop_t regs;
1636 OF_node_t *nvr;
1637
1638 nvr = OF_node_new(OF_env, OF_node_root, "nvram", 0xfff04000);
1639 if (nvr == NULL) {
1640 ERROR("Cannot create 'nvram'\n");
1641 return -1;
1642 }
1643 OF_prop_string_new(OF_env, nvr, "device_type", "nvram");
1644 /* XXX: use real NVRAM size instead */
1645 OF_prop_int_new(OF_env, nvr, "#bytes", 0x2000);
1646 OF_prop_string_new(OF_env, nvr, "compatible", "nvram,flash");
1647 regs.address = 0xFFF04000;
1648 regs.size = 0x00004000; /* Strange, isn't it ? */
1649 OF_property_new(OF_env, nvr, "reg", ®s, sizeof(regs));
1650 OF_prop_int_new(OF_env, chs, "nvram", OF_pack_handle(OF_env, nvr));
1651 OF_node_put(OF_env, nvr);
1652 }
1653 #endif
1654 /* "/pseudo-hid" : hid emulation as Apple does */
1655 {
1656 OF_node_t *hid;
1657
1658 hid = OF_node_new(OF_env, OF_node_root,
1659 "pseudo-hid", OF_ADDRESS_NONE);
1660 if (hid == NULL) {
1661 ERROR("Cannot create 'pseudo-hid'\n");
1662 return -1;
1663 }
1664
1665 /* "keyboard" node */
1666 {
1667 OF_node_t *kbd;
1668 kbd = OF_node_new(OF_env, hid, "keyboard", OF_ADDRESS_NONE);
1669 if (kbd == NULL) {
1670 ERROR("Cannot create 'keyboard'\n");
1671 return -1;
1672 }
1673 OF_prop_string_new(OF_env, kbd, "device_type", "keyboard");
1674 OF_node_put(OF_env, kbd);
1675 }
1676 /* "mouse" node */
1677 {
1678 OF_node_t *mouse;
1679 mouse = OF_node_new(OF_env, hid, "mouse", OF_ADDRESS_NONE);
1680 if (mouse == NULL) {
1681 ERROR("Cannot create 'mouse'\n");
1682 return -1;
1683 }
1684 OF_prop_string_new(OF_env, mouse, "device_type", "mouse");
1685 OF_node_put(OF_env, mouse);
1686 }
1687 /* "eject-key" node */
1688 {
1689 OF_node_t *ejk;
1690 ejk = OF_node_new(OF_env, hid, "eject-key", OF_ADDRESS_NONE);
1691 if (ejk == NULL) {
1692 ERROR("Cannot create 'eject-key'\n");
1693 return -1;
1694 }
1695 OF_prop_string_new(OF_env, ejk, "device_type", "eject-key");
1696 OF_node_put(OF_env, ejk);
1697 }
1698 OF_node_put(OF_env, hid);
1699 }
1700 if (arch == ARCH_MAC99) {
1701 OF_node_t *unin;
1702 OF_regprop_t regs;
1703
1704 unin = OF_node_new(OF_env, OF_node_root,
1705 "uni-n", 0xf8000000);
1706 if (unin == NULL) {
1707 ERROR("Cannot create 'uni-n'\n");
1708 return -1;
1709 }
1710 OF_prop_string_new(OF_env, unin, "device-type", "memory-controller");
1711 OF_prop_string_new(OF_env, unin, "model", "AAPL,UniNorth");
1712 OF_prop_string_new(OF_env, unin, "compatible", "uni-north");
1713 regs.address = 0xf8000000;
1714 regs.size = 0x01000000;
1715 OF_property_new(OF_env, unin, "reg", ®s, sizeof(regs));
1716 OF_prop_int_new(OF_env, unin, "#address-cells", 1);
1717 OF_prop_int_new(OF_env, unin, "#size-cells", 1);
1718 OF_prop_int_new(OF_env, unin, "device-rev", 3);
1719 OF_node_put(OF_env, unin);
1720 }
1721
1722 #if 1 /* This is mandatory for claim to work
1723 * but I don't know where it should really be (in cpu ?)
1724 */
1725 {
1726 OF_node_t *mmu;
1727
1728 /* "/mmu" node */
1729 mmu = OF_node_new(OF_env, OF_node_root, "mmu", OF_ADDRESS_NONE);
1730 if (mmu == NULL) {
1731 ERROR("Cannot create 'mmu'\n");
1732 return -1;
1733 }
1734 inst = OF_instance_new(OF_env, mmu);
1735 if (inst == NULL) {
1736 OF_node_put(OF_env, mmu);
1737 ERROR("Cannot create 'mmu' instance\n");
1738 return -1;
1739 }
1740 OF_prop_int_new(OF_env, chs, "mmu",
1741 OF_instance_get_id(OF_env, inst));
1742 OF_method_new(OF_env, mmu, "translate", &OF_mmu_translate);
1743 OF_method_new(OF_env, mmu, "map", &OF_mmu_map);
1744 OF_node_put(OF_env, mmu);
1745 }
1746 #endif
1747
1748 /* "/options/boot-args" node */
1749 {
1750 // const unsigned char *args = "-v rootdev cdrom";
1751 //const unsigned char *args = "-v io=0xffffffff";
1752 const unsigned char *args = "-v";
1753 /* Ask MacOS X to print debug messages */
1754 // OF_prop_string_new(OF_env, chs, "machargs", args);
1755 // OF_prop_string_new(OF_env, opt, "boot-command", args);
1756 OF_prop_string_new(OF_env, opt, "boot-args", args);
1757 }
1758
1759 /* Release nodes */
1760 OF_node_put(OF_env, opt);
1761 OF_node_put(OF_env, pks);
1762 OF_node_put(OF_env, chs);
1763 OF_node_put(OF_env, als);
1764 OF_node_put(OF_env, OF_node_root);
1765 OF_DPRINTF("done\n");
1766
1767 return 0;
1768 }
1769
1770 /* Motherboard */
1771 #if 0 // For now, static values are used
1772 __attribute__ (( section (".OpenFirmware") ))
1773 int OF_register_mb (const unsigned char *model, const unsigned char **compats)
1774 {
1775 OF_env_t *OF_env;
1776 OF_node_t *root;
1777 int i;
1778
1779 OF_env = OF_env_main;
1780 OF_DPRINTF("start\n");
1781 root = OF_node_get(OF_env, "device_tree");
1782 if (root == NULL) {
1783 ERROR("Cannot get 'device-tree'\n");
1784 return -1;
1785 }
1786 OF_DPRINTF("add model\n");
1787 OF_prop_string_new(OF_env, OF_node_root, "model", model);
1788 for (i = 0; i < 1 && compats[i] != NULL; i++) {
1789 OF_DPRINTF("add compats %s\n", compats[i]);
1790 OF_set_compatibility(OF_env, OF_node_root, compats[i]);
1791 }
1792 /* we don't implement neither "l2-cache" nor "cache" nodes */
1793 OF_node_put(OF_env, root);
1794 OF_DPRINTF("done\n");
1795
1796 return 0;
1797 }
1798 #endif
1799
1800 /* CPU */
1801 __attribute__ (( section (".OpenFirmware") ))
OF_register_cpu(const unsigned char * name,int num,uint32_t pvr,uint32_t min_freq,uint32_t max_freq,uint32_t bus_freq,uint32_t tb_freq,uint32_t reset_io)1802 int OF_register_cpu (const unsigned char *name, int num, uint32_t pvr,
1803 uint32_t min_freq, uint32_t max_freq, uint32_t bus_freq,
1804 uint32_t tb_freq, uint32_t reset_io)
1805 {
1806 unsigned char tmp[OF_NAMELEN_MAX];
1807 OF_env_t *OF_env;
1808 OF_node_t *cpus, *cpu, *l2c, *chs, *als;
1809
1810 OF_env = OF_env_main;
1811 OF_DPRINTF("start\n");
1812 cpus = OF_node_get(OF_env, "cpus");
1813 if (cpus == NULL) {
1814 ERROR("Cannot get 'cpus'\n");
1815 return -1;
1816 }
1817 cpu = OF_node_new(OF_env, cpus, name, OF_ADDRESS_NONE);
1818 if (cpu == NULL) {
1819 OF_node_put(OF_env, cpus);
1820 ERROR("Cannot create cpu '%s'\n", name);
1821 return -1;
1822 }
1823 OF_prop_string_new(OF_env, cpu, "device_type", "cpu");
1824 OF_prop_int_new(OF_env, cpu, "#address-cells", 0x00000001);
1825 OF_prop_int_new(OF_env, cpu, "#size-cells", 0x00000000);
1826 OF_prop_int_new(OF_env, cpu, "reg", num);
1827 OF_prop_int_new(OF_env, cpu, "cpu-version", pvr);
1828 OF_prop_int_new(OF_env, cpu, "clock-frequency", max_freq);
1829 OF_prop_int_new(OF_env, cpu, "timebase-frequency", tb_freq);
1830 OF_prop_int_new(OF_env, cpu, "bus-frequency", bus_freq);
1831 OF_prop_int_new(OF_env, cpu, "min-clock-frequency", min_freq);
1832 OF_prop_int_new(OF_env, cpu, "max-clock-frequency", max_freq);
1833 OF_prop_int_new(OF_env, cpu, "tlb-size", 0x80);
1834 OF_prop_int_new(OF_env, cpu, "tlb-sets", 0x40);
1835 OF_prop_int_new(OF_env, cpu, "i-tlb-size", 0x40);
1836 OF_prop_int_new(OF_env, cpu, "i-tlb-sets", 0x20);
1837 OF_prop_int_new(OF_env, cpu, "i-cache-size", 0x8000);
1838 OF_prop_int_new(OF_env, cpu, "i-cache-sets", 0x80);
1839 OF_prop_int_new(OF_env, cpu, "i-cache-bloc-size", 0x20);
1840 OF_prop_int_new(OF_env, cpu, "i-cache-line-size", 0x20);
1841 OF_prop_int_new(OF_env, cpu, "d-tlb-size", 0x40);
1842 OF_prop_int_new(OF_env, cpu, "d-tlb-sets", 0x20);
1843 OF_prop_int_new(OF_env, cpu, "d-cache-size", 0x8000);
1844 OF_prop_int_new(OF_env, cpu, "d-cache-sets", 0x80);
1845 OF_prop_int_new(OF_env, cpu, "d-cache-bloc-size", 0x20);
1846 OF_prop_int_new(OF_env, cpu, "d-cache-line-size", 0x20);
1847 OF_prop_int_new(OF_env, cpu, "reservation-granule-size", 0x20);
1848 OF_prop_int_new(OF_env, cpus, "soft-reset", reset_io);
1849 OF_prop_string_new(OF_env, cpus, "graphics", "");
1850 OF_prop_string_new(OF_env, cpus, "performance-monitor", "");
1851 OF_prop_string_new(OF_env, cpus, "data-streams", "");
1852 OF_prop_string_new(OF_env, cpu, "state", "running");
1853 /* We don't implement:
1854 * "dynamic-powerstep" & "reduced-clock-frequency"
1855 * "l2cr-value"
1856 */
1857 /* Add L2 cache */
1858 l2c = OF_node_new(OF_env, cpu, "l2cache", OF_ADDRESS_NONE);
1859 if (l2c == NULL) {
1860 ERROR("Cannot create 'l2cache'\n");
1861 return -1;
1862 }
1863 OF_prop_string_new(OF_env, l2c, "device_type", "cache");
1864 OF_prop_int_new(OF_env, l2c, "i-cache-size", 0x100000);
1865 OF_prop_int_new(OF_env, l2c, "i-cache-sets", 0x2000);
1866 OF_prop_int_new(OF_env, l2c, "i-cache-line-size", 0x40);
1867 OF_prop_int_new(OF_env, l2c, "d-cache-size", 0x100000);
1868 OF_prop_int_new(OF_env, l2c, "d-cache-sets", 0x2000);
1869 OF_prop_int_new(OF_env, l2c, "d-cache-line-size", 0x40);
1870 /* Register it in the cpu node */
1871 OF_prop_int_new(OF_env, cpu, "l2-cache", OF_pack_handle(OF_env, l2c));
1872 OF_node_put(OF_env, l2c);
1873 /* Set it in "/chosen" and "/aliases" */
1874 if (num == 0) {
1875 OF_pack_get_path(OF_env, tmp, 512, cpu);
1876 chs = OF_node_get(OF_env, "chosen");
1877 if (chs == NULL) {
1878 OF_node_put(OF_env, cpus);
1879 ERROR("Cannot get 'chosen'\n");
1880 return -1;
1881 }
1882 OF_prop_int_new(OF_env, chs, "cpu", OF_pack_handle(OF_env, cpu));
1883 OF_node_put(OF_env, chs);
1884 als = OF_node_get(OF_env, "aliases");
1885 if (als == NULL) {
1886 OF_node_put(OF_env, cpus);
1887 ERROR("Cannot get 'aliases'\n");
1888 return -1;
1889 }
1890 OF_prop_string_new(OF_env, als, "cpu", tmp);
1891 OF_node_put(OF_env, als);
1892 }
1893 OF_node_put(OF_env, cpu);
1894 OF_node_put(OF_env, cpus);
1895 OF_DPRINTF("done\n");
1896
1897 return 0;
1898 }
1899
1900 __attribute__ (( section (".OpenFirmware") ))
OF_register_translations(int nb,OF_transl_t * translations)1901 int OF_register_translations (int nb, OF_transl_t *translations)
1902 {
1903 OF_env_t *OF_env;
1904 OF_node_t *cpus, *cpu;
1905 OF_transl_t *new;
1906 int i;
1907
1908 OF_env = OF_env_main;
1909 OF_DPRINTF("start\n");
1910 cpus = OF_node_get(OF_env, "cpus");
1911 if (cpus == NULL) {
1912 OF_node_put(OF_env, cpus);
1913 ERROR("Cannot get 'cpus'\n");
1914 return -1;
1915 }
1916 cpu = cpus->children;
1917 new = malloc(nb * sizeof(OF_transl_t));
1918 if (new == NULL) {
1919 ERROR("Cannot create new translation\n");
1920 return -1;
1921 }
1922 for (i = 0; i < nb; i++) {
1923 new->virt = translations[i].virt;
1924 new->size = translations[i].size;
1925 new->phys = translations[i].phys;
1926 new->mode = translations[i].mode;
1927 OF_DPRINTF("%d\n", i);
1928 }
1929 OF_property_new(OF_env, cpu, "translations",
1930 new, nb * sizeof(OF_transl_t));
1931 OF_node_put(OF_env, cpus);
1932 OF_DPRINTF("done\n");
1933
1934 return 0;
1935 }
1936
1937 /* Memory ranges */
1938 typedef struct OF_mem_t OF_mem_t;
1939 struct OF_mem_t {
1940 uint32_t start;
1941 uint32_t size;
1942 };
1943
1944 #define OF_MAX_MEMRANGES 16
1945 /* First entry is the whole known memory space */
1946 static OF_mem_t OF_mem_ranges[OF_MAX_MEMRANGES + 1];
1947
1948 __attribute__ (( section (".OpenFirmware") ))
OF_register_memory(uint32_t memsize,unused uint32_t bios_size)1949 int OF_register_memory (uint32_t memsize, unused uint32_t bios_size)
1950 {
1951 OF_env_t *OF_env;
1952 OF_node_t *mem;
1953 OF_regprop_t regs[4];
1954 int i;
1955
1956 OF_env = OF_env_main;
1957 OF_DPRINTF("find node\n");
1958 mem = OF_node_get(OF_env, "memory");
1959 if (mem == NULL) {
1960 ERROR("Cannot get 'memory'\n");
1961 return -1;
1962 }
1963 OF_DPRINTF("Memory package: %04x\n", OF_pack_handle(OF_env, mem));
1964 regs[0].address = 0x00000000;
1965 regs[0].size = memsize;
1966 regs[1].address = 0x00000000;
1967 regs[1].size = 0x00000000;
1968 regs[2].address = 0x00000000;
1969 regs[2].size = 0x00000000;
1970 regs[3].address = 0x00000000;
1971 regs[3].size = 0x00000000;
1972 OF_property_new(OF_env, mem, "reg", regs, 4 * sizeof(OF_regprop_t));
1973 #if 0
1974 #if 1
1975 regs[0].address = 0x00000000;
1976 regs[0].size = 0x05800000;
1977 regs[1].address = 0x06000000;
1978 regs[1].size = memsize - 0x06000000;
1979 regs[2].address = 0x00000000;
1980 regs[2].size = 0x00000000;
1981 OF_property_new(OF_env, mem, "available",
1982 regs, 3 * sizeof(OF_regprop_t));
1983 #else
1984 regs[0].address = 0x06000000;
1985 regs[0].size = memsize - 0x06000000;
1986 regs[1].address = 0x00000000;
1987 regs[1].size = 0x00000000;
1988 OF_property_new(OF_env, mem, "available",
1989 regs, 2 * sizeof(OF_regprop_t));
1990 #endif
1991 #endif
1992 OF_node_put(OF_env, mem);
1993 #if 0
1994 {
1995 OF_node_t *mmu;
1996 mmu = OF_node_get(OF_env, "mmu");
1997 if (mmu == NULL) {
1998 ERROR("Cannot get 'mmu'\n");
1999 return -1;
2000 }
2001 regs[0].address = 0x00000000;
2002 regs[0].size = memsize;
2003 OF_property_new(OF_env, mmu, "reg", regs, sizeof(OF_regprop_t));
2004 regs[0].address = 0x00000000;
2005 regs[0].size = 0x05800000;
2006 regs[1].address = 0x06000000;
2007 regs[1].size = memsize - 0x06000000;
2008 regs[2].address = 0x00000000;
2009 regs[2].size = 0x00000000;
2010 OF_property_new(OF_env, mmu, "available",
2011 regs, 3 * sizeof(OF_regprop_t));
2012 OF_node_put(OF_env, mmu);
2013 }
2014 #endif
2015 /* Also update the claim areas */
2016 OF_mem_ranges[0].start = 0x00000000;
2017 OF_mem_ranges[0].size = memsize;
2018 OF_mem_ranges[1].start = 0x58000000;
2019 OF_mem_ranges[1].size = 0x08000000;
2020 for (i = 2; i < OF_MAX_MEMRANGES + 1; i++) {
2021 OF_mem_ranges[i].start = -1;
2022 OF_mem_ranges[i].size = -1;
2023 }
2024 OF_DPRINTF("done\n");
2025
2026 return 0;
2027 }
2028
2029 /* Linux kernel command line */
2030 __attribute__ (( section (".OpenFirmware") ))
OF_register_bootargs(const unsigned char * bootargs)2031 int OF_register_bootargs (const unsigned char *bootargs)
2032 {
2033 OF_env_t *OF_env;
2034 OF_node_t *chs;
2035
2036 OF_env = OF_env_main;
2037 if (bootargs == NULL)
2038 bootargs = "";
2039 chs = OF_node_get(OF_env, "chosen");
2040 if (chs == NULL) {
2041 ERROR("Cannot get 'chosen'\n");
2042 return -1;
2043 }
2044 OF_prop_string_set(OF_env, chs, "bootargs", bootargs);
2045 // OF_prop_string_set(OF_env, OF_node_root, "bootargs", "");
2046 OF_node_put(OF_env, chs);
2047
2048 return 0;
2049 }
2050
2051 __attribute__ (( section (".OpenFirmware") ))
OF_pci_device_new(OF_env_t * OF_env,OF_node_t * parent,pci_dev_t * dev,uint32_t address,uint16_t rev,uint32_t ccode,uint16_t min_grant,uint16_t max_latency)2052 static void *OF_pci_device_new (OF_env_t *OF_env, OF_node_t *parent,
2053 pci_dev_t *dev, uint32_t address,
2054 uint16_t rev, uint32_t ccode,
2055 uint16_t min_grant, uint16_t max_latency)
2056 {
2057 OF_node_t *node;
2058
2059 dprintf("register '%s' '%s' '%s' '%s' 0x%08x in '%s' 0x%08x\n",
2060 dev->name, dev->type, dev->compat, dev->model, address,
2061 parent->prop_name->value, *(uint32_t *)parent->prop_address->value);
2062 node = OF_node_new(OF_env, parent, dev->name, address);
2063 if (node == NULL)
2064 return NULL;
2065 OF_prop_int_new(OF_env, node, "vendor-id", dev->vendor);
2066 OF_prop_int_new(OF_env, node, "device-id", dev->product);
2067 OF_prop_int_new(OF_env, node, "revision-id", rev);
2068 OF_prop_int_new(OF_env, node, "class-code", ccode);
2069 OF_prop_int_new(OF_env, node, "min-grant", min_grant);
2070 OF_prop_int_new(OF_env, node, "max-latency", max_latency);
2071 if (dev->type != NULL)
2072 OF_prop_string_new1(OF_env, node, "device_type", dev->type);
2073 if (dev->compat != NULL)
2074 OF_prop_string_new1(OF_env, node, "compatible", dev->compat);
2075 if (dev->model != NULL)
2076 OF_prop_string_new1(OF_env, node, "model", dev->model);
2077 if (dev->acells != 0)
2078 OF_prop_int_new(OF_env, node, "#address-cells", dev->acells);
2079 if (dev->scells != 0)
2080 OF_prop_int_new(OF_env, node, "#size-cells", dev->scells);
2081 if (dev->icells != 0)
2082 OF_prop_int_new(OF_env, node, "#interrupt-cells", dev->icells);
2083 dprintf("Done %p %p\n", parent, node);
2084
2085 return node;
2086 }
2087
2088 __attribute__ (( section (".OpenFirmware") ))
OF_register_pci_host(pci_dev_t * dev,uint16_t rev,uint32_t ccode,uint32_t cfg_base,uint32_t cfg_len,uint32_t mem_base,uint32_t mem_len,uint32_t io_base,uint32_t io_len,uint32_t rbase,uint32_t rlen,uint16_t min_grant,uint16_t max_latency)2089 void *OF_register_pci_host (pci_dev_t *dev, uint16_t rev, uint32_t ccode,
2090 uint32_t cfg_base, uint32_t cfg_len,
2091 uint32_t mem_base, uint32_t mem_len,
2092 uint32_t io_base, uint32_t io_len,
2093 uint32_t rbase, uint32_t rlen,
2094 uint16_t min_grant, uint16_t max_latency)
2095 {
2096 OF_env_t *OF_env;
2097 pci_range_t ranges[3];
2098 OF_regprop_t regs[1];
2099 OF_node_t *pci_host, *als;
2100 int nranges;
2101 unsigned char buffer[OF_NAMELEN_MAX];
2102
2103 OF_env = OF_env_main;
2104 dprintf("register PCI host '%s' '%s' '%s' '%s'\n",
2105 dev->name, dev->type, dev->compat, dev->model);
2106 pci_host = OF_pci_device_new(OF_env, OF_node_root, dev, cfg_base,
2107 rev, ccode, min_grant, max_latency);
2108 if (pci_host == NULL) {
2109 ERROR("Cannot create pci host\n");
2110 return NULL;
2111 }
2112
2113 als = OF_node_get(OF_env, "aliases");
2114 if (als == NULL) {
2115 ERROR("Cannot get 'aliases'\n");
2116 return NULL;
2117 }
2118 sprintf(buffer, "/%s", dev->name);
2119 OF_prop_string_set(OF_env, als, "pci", buffer);
2120 OF_node_put(OF_env, als);
2121
2122
2123 regs[0].address = cfg_base;
2124 regs[0].size = cfg_len;
2125 OF_property_new(OF_env, pci_host, "reg", regs, sizeof(OF_regprop_t));
2126 nranges = 0;
2127 if (rbase != 0x00000000) {
2128 ranges[nranges].addr.hi = 0x02000000;
2129 ranges[nranges].addr.mid = 0x00000000;
2130 ranges[nranges].addr.lo = rbase;
2131 ranges[nranges].phys = rbase;
2132 ranges[nranges].size_hi = 0x00000000;
2133 ranges[nranges].size_lo = rlen;
2134 nranges++;
2135 }
2136 if (io_base != 0x00000000) {
2137 ranges[nranges].addr.hi = 0x01000000;
2138 ranges[nranges].addr.mid = 0x00000000;
2139 ranges[nranges].addr.lo = 0x00000000;
2140 ranges[nranges].phys = io_base;
2141 ranges[nranges].size_hi = 0x00000000;
2142 ranges[nranges].size_lo = io_len;
2143 nranges++;
2144 }
2145 if (mem_base != 0x00000000) {
2146 ranges[nranges].addr.hi = 0x02000000;
2147 ranges[nranges].addr.mid = 0x00000000;
2148 ranges[nranges].addr.lo = mem_base;
2149 ranges[nranges].phys = mem_base;
2150 ranges[nranges].size_hi = 0x00000000;
2151 ranges[nranges].size_lo = mem_len;
2152 nranges++;
2153 }
2154 OF_property_new(OF_env, pci_host, "ranges", ranges,
2155 nranges * sizeof(pci_range_t));
2156
2157 return pci_host;
2158 }
2159
2160 __attribute__ (( section (".OpenFirmware") ))
OF_register_pci_bridge(void * parent,pci_dev_t * dev,uint32_t cfg_base,uint32_t cfg_len,uint8_t devfn,uint8_t rev,uint32_t ccode,uint16_t min_grant,uint16_t max_latency)2161 void *OF_register_pci_bridge (void *parent, pci_dev_t *dev,
2162 uint32_t cfg_base, uint32_t cfg_len,
2163 uint8_t devfn, uint8_t rev, uint32_t ccode,
2164 uint16_t min_grant, uint16_t max_latency)
2165 {
2166 OF_env_t *OF_env;
2167 OF_regprop_t regs[1];
2168 OF_node_t *pci_bridge;
2169
2170 OF_env = OF_env_main;
2171 OF_DPRINTF("register '%s' %08x '%s' '%s' '%s'\n",
2172 dev->name, devfn >> 3, dev->type, dev->compat, dev->model);
2173 dprintf("register PCI bridge '%s' %08x '%s' '%s' '%s'\n",
2174 dev->name, devfn >> 3, dev->type, dev->compat, dev->model);
2175 pci_bridge = OF_pci_device_new(OF_env, parent, dev, devfn >> 3,
2176 rev, ccode, min_grant, max_latency);
2177 if (pci_bridge == NULL) {
2178 ERROR("Cannot create pci bridge\n");
2179 return NULL;
2180 }
2181 regs[0].address = cfg_base;
2182 regs[0].size = cfg_len;
2183 OF_property_new(OF_env, pci_bridge, "reg", regs, sizeof(OF_regprop_t));
2184
2185 return pci_bridge;
2186 }
2187
2188 __attribute__ (( section (".OpenFirmware") ))
OF_register_pci_device(void * parent,pci_dev_t * dev,uint8_t devfn,uint8_t rev,uint32_t ccode,uint16_t min_grant,uint16_t max_latency)2189 void *OF_register_pci_device (void *parent, pci_dev_t *dev,
2190 uint8_t devfn, uint8_t rev, uint32_t ccode,
2191 uint16_t min_grant, uint16_t max_latency)
2192 {
2193 OF_env_t *OF_env;
2194 OF_node_t *pci_dev;
2195
2196 OF_env = OF_env_main;
2197 OF_DPRINTF("register '%s' %08x '%s' '%s' '%s'\n",
2198 dev->name, devfn >> 3, dev->type, dev->compat, dev->model);
2199 dprintf("register pci device '%s' %08x '%s' '%s' '%s'\n",
2200 dev->name, devfn >> 3, dev->type, dev->compat, dev->model);
2201 pci_dev = OF_pci_device_new(OF_env, parent, dev, devfn >> 3,
2202 rev, ccode, min_grant, max_latency);
2203
2204 return pci_dev;
2205 }
2206
2207 /* XXX: suppress that, used for interrupt map init */
2208 OF_node_t *pci_host_node;
2209 uint32_t pci_host_interrupt_map[7 * 32];
2210 int pci_host_interrupt_map_len = 0;
2211
OF_finalize_pci_host(void * dev,int first_bus,int nb_busses)2212 void OF_finalize_pci_host (void *dev, int first_bus, int nb_busses)
2213 {
2214 OF_env_t *OF_env;
2215 OF_regprop_t regs[1];
2216
2217 OF_env = OF_env_main;
2218 regs[0].address = first_bus;
2219 regs[0].size = nb_busses;
2220 OF_property_new(OF_env, dev, "bus-range", regs, sizeof(OF_regprop_t));
2221 pci_host_node = dev;
2222 }
2223
OF_finalize_pci_device(void * dev,uint8_t bus,uint8_t devfn,uint32_t * regions,uint32_t * sizes,int irq_line)2224 void OF_finalize_pci_device (void *dev, uint8_t bus, uint8_t devfn,
2225 uint32_t *regions, uint32_t *sizes,
2226 int irq_line)
2227 {
2228 OF_env_t *OF_env;
2229 pci_reg_prop_t pregs[6], rregs[6];
2230 uint32_t mask;
2231 int i, j, k;
2232
2233 OF_env = OF_env_main;
2234 /* XXX: only useful for VGA card in fact */
2235 if (regions[0] != 0x00000000)
2236 OF_prop_int_set(OF_env, dev, "address", regions[0] & ~0x0000000F);
2237 for (i = 0, j = 0, k = 0; i < 6; i++) {
2238 if (regions[i] != 0x00000000 && sizes[i] != 0x00000000) {
2239 /* Generate "reg" property
2240 */
2241 if (regions[i] & 1) {
2242 /* IO space */
2243 rregs[j].addr.hi = 0x01000000;
2244 mask = 0x00000001;
2245 } else if (regions[i] & 4) {
2246 /* 64 bits address space */
2247 rregs[j].addr.hi = 0x83000000;
2248 mask = 0x0000000F;
2249 #if 0
2250 } else if ((regions[i] & 0xF) == 0x00) { /* ? */
2251 /* Configuration space */
2252 rregs[j].addr.hi = 0x00000000;
2253 mask = 0x0000000F;
2254 #endif
2255 } else {
2256 /* 32 bits address space */
2257 rregs[j].addr.hi = 0x82000000;
2258 mask = 0x0000000F;
2259 }
2260 /* Set bus number */
2261 rregs[j].addr.hi |= bus << 16;
2262 /* Set device/function */
2263 rregs[j].addr.hi |= devfn << 8;
2264 /* Set register */
2265 #if 1
2266 rregs[j].addr.hi |= 0x10 + (i * sizeof(uint32_t)); /* ? */
2267 #endif
2268 /* Set address */
2269 rregs[j].addr.mid = 0x00000000;
2270 rregs[j].addr.lo = regions[i] & ~mask;
2271 /* Set size */
2272 rregs[j].size_hi = 0x00000000;
2273 rregs[j].size_lo = sizes[i];
2274 #if 0
2275 if ((rregs[j].addr.hi & 0x03000000) != 0x00000000)
2276 #endif
2277 {
2278 /* No assigned address for configuration space */
2279 pregs[k].addr.hi = rregs[j].addr.hi; /* ? */
2280 pregs[k].addr.mid = rregs[j].addr.mid;
2281 pregs[k].addr.lo = rregs[j].addr.lo; /* ? */
2282 pregs[k].size_hi = rregs[j].size_hi;
2283 pregs[k].size_lo = rregs[j].size_lo;
2284 k++;
2285 }
2286 j++;
2287 }
2288 }
2289 if (j > 0) {
2290 OF_property_new(OF_env, dev, "reg",
2291 rregs, j * sizeof(pci_reg_prop_t));
2292 } else {
2293 OF_property_new(OF_env, dev, "reg", NULL, 0);
2294 }
2295 if (k > 0) {
2296 OF_property_new(OF_env, dev, "assigned-addresses",
2297 pregs, k * sizeof(pci_reg_prop_t));
2298 } else {
2299 OF_property_new(OF_env, dev, "assigned-addresses", NULL, 0);
2300 }
2301 if (irq_line >= 0) {
2302 int i;
2303 OF_prop_int_new(OF_env, dev, "interrupts", 1);
2304 i = pci_host_interrupt_map_len;
2305 pci_host_interrupt_map[i++] = (devfn << 8) & 0xf800;
2306 pci_host_interrupt_map[i++] = 0;
2307 pci_host_interrupt_map[i++] = 0;
2308 pci_host_interrupt_map[i++] = 0;
2309 pci_host_interrupt_map[i++] = 0; /* pic handle will be patched later */
2310 pci_host_interrupt_map[i++] = irq_line;
2311 if (arch != ARCH_HEATHROW) {
2312 pci_host_interrupt_map[i++] = 1;
2313 }
2314 pci_host_interrupt_map_len = i;
2315 }
2316 #if 1
2317 {
2318 OF_prop_t *prop_name = ((OF_node_t *)dev)->prop_name;
2319
2320 if (j > 0) {
2321 dprintf("PCI device '%s' %d %d %d reg properties:\n",
2322 prop_name->value, bus, devfn >> 3, devfn & 7);
2323 for (i = 0; i < j; i++) {
2324 dprintf(" addr: %08x %08x %08x size: %08x %08x\n",
2325 rregs[i].addr.hi, rregs[i].addr.mid, rregs[i].addr.lo,
2326 rregs[i].size_hi, rregs[i].size_lo);
2327 }
2328 } else {
2329 dprintf("PCI device '%s' %d %d %d has no reg properties:\n",
2330 prop_name->value, bus, devfn >> 3, devfn & 7);
2331 }
2332 if (k > 0) {
2333 dprintf("PCI device '%s' %d %d %d "
2334 "assigned addresses properties:\n",
2335 prop_name->value, bus, devfn >> 3, devfn & 7);
2336 for (i = 0; i < j; i++) {
2337 dprintf(" addr: %08x %08x %08x size: %08x %08x\n",
2338 pregs[i].addr.hi, pregs[i].addr.mid, pregs[i].addr.lo,
2339 pregs[i].size_hi, pregs[i].size_lo);
2340 }
2341 } else {
2342 dprintf("PCI device '%s' %d %d %d has no "
2343 "assigned addresses properties:\n",
2344 prop_name->value, bus, devfn >> 3, devfn & 7);
2345 }
2346 }
2347 #endif
2348 }
2349
2350 __attribute__ (( section (".OpenFirmware") ))
OF_register_bus(const unsigned char * name,uint32_t address,const unsigned char * type)2351 int OF_register_bus (const unsigned char *name, uint32_t address,
2352 const unsigned char *type)
2353 {
2354 unsigned char buffer[OF_NAMELEN_MAX];
2355 OF_env_t *OF_env;
2356 OF_node_t *bus, *als;
2357
2358 OF_env = OF_env_main;
2359 als = OF_node_get(OF_env, "aliases");
2360 if (als == NULL) {
2361 ERROR("Cannot get 'aliases'\n");
2362 return -1;
2363 }
2364 bus = OF_node_new(OF_env, OF_node_root, name, address);
2365 if (bus == NULL) {
2366 OF_node_put(OF_env, als);
2367 ERROR("Cannot create bus '%s'\n", name);
2368 return -1;
2369 }
2370 OF_prop_string_set(OF_env, bus, "type", type);
2371 sprintf(buffer, "/%s", name);
2372 OF_prop_string_set(OF_env, als, name, buffer);
2373 /* For ISA, should add DMA ranges */
2374 OF_node_put(OF_env, bus);
2375 OF_node_put(OF_env, als);
2376
2377 return 0;
2378 }
2379
2380 // We will need to register stdin & stdout via the serial port
2381 __attribute__ (( section (".OpenFirmware") ))
OF_register_serial(const unsigned char * bus,const unsigned char * name,uint32_t io_base,unused int irq)2382 int OF_register_serial (const unsigned char *bus, const unsigned char *name,
2383 uint32_t io_base, unused int irq)
2384 {
2385 unsigned char tmp[OF_NAMELEN_MAX];
2386 OF_env_t *OF_env;
2387 OF_node_t *busn, *srl, *als;
2388
2389 OF_env = OF_env_main;
2390 als = OF_node_get(OF_env, "aliases");
2391 if (als == NULL) {
2392 ERROR("Cannot get 'aliases'\n");
2393 return -1;
2394 }
2395 busn = OF_node_get(OF_env, bus);
2396 srl = OF_node_new(OF_env, busn, name, io_base);
2397 if (srl == NULL) {
2398 OF_node_put(OF_env, als);
2399 ERROR("Cannot create serial '%s'\n", name);
2400 return -1;
2401 }
2402 OF_prop_string_set(OF_env, srl, "device_type", "serial");
2403 OF_prop_string_set(OF_env, srl, "compatible", "pnpPNP,501");
2404 switch (io_base) {
2405 case 0x3F8:
2406 OF_pack_get_path(OF_env, tmp, 512, srl);
2407 OF_prop_string_new(OF_env, als, "com1", tmp);
2408 break;
2409 case 0x2F8:
2410 OF_pack_get_path(OF_env, tmp, 512, srl);
2411 OF_prop_string_new(OF_env, als, "com2", tmp);
2412 break;
2413 default:
2414 break;
2415 }
2416 /* register read/write methods and create an instance of the package */
2417 OF_method_new(OF_env, srl, "write", &OF_serial_write);
2418 OF_method_new(OF_env, srl, "read", &OF_serial_read);
2419 OF_node_put(OF_env, srl);
2420 OF_node_put(OF_env, busn);
2421 OF_node_put(OF_env, als);
2422
2423 return 0;
2424 }
2425
2426 /* We will also need /isa/rtc */
2427
2428 __attribute__ (( section (".OpenFirmware") ))
OF_register_stdio(const unsigned char * dev_in,const unsigned char * dev_out)2429 int OF_register_stdio (const unsigned char *dev_in,
2430 const unsigned char *dev_out)
2431 {
2432 OF_env_t *OF_env;
2433 OF_node_t *chs, *ndev_in, *ndev_out, *kbd;
2434 OF_inst_t *in_inst, *out_inst;
2435
2436 OF_env = OF_env_main;
2437 chs = OF_node_get(OF_env, "chosen");
2438 if (chs == NULL) {
2439 ERROR("Cannot get 'chosen'\n");
2440 return -1;
2441 }
2442 ndev_in = OF_node_get(OF_env, dev_in);
2443 ndev_out = OF_node_get(OF_env, dev_out);
2444 in_inst = OF_instance_new(OF_env, ndev_in);
2445 if (in_inst == NULL) {
2446 OF_node_put(OF_env, ndev_out);
2447 OF_node_put(OF_env, ndev_in);
2448 OF_node_put(OF_env, chs);
2449 ERROR("Cannot create in_inst\n");
2450 return -1;
2451 }
2452 out_inst = OF_instance_new(OF_env, ndev_out);
2453 if (out_inst == NULL) {
2454 OF_node_put(OF_env, ndev_out);
2455 OF_node_put(OF_env, ndev_in);
2456 OF_node_put(OF_env, chs);
2457 ERROR("Cannot create out_inst\n");
2458 return -1;
2459 }
2460 OF_prop_int_set(OF_env, chs, "stdin",
2461 OF_instance_get_id(OF_env, in_inst));
2462 OF_prop_int_set(OF_env, chs, "stdout",
2463 OF_instance_get_id(OF_env, out_inst));
2464 kbd = OF_node_new(OF_env, ndev_in, "keyboard", OF_ADDRESS_NONE);
2465 if (kbd == NULL) {
2466 OF_node_put(OF_env, ndev_out);
2467 OF_node_put(OF_env, ndev_in);
2468 OF_node_put(OF_env, chs);
2469 ERROR("Cannot create 'keyboard' for stdio\n");
2470 return -1;
2471 }
2472 OF_prop_string_new(OF_env, kbd, "device_type", "keyboard");
2473 OF_node_put(OF_env, kbd);
2474 OF_DPRINTF("stdin h: 0x%0x out : 0x%0x\n",
2475 OF_instance_get_id(OF_env, in_inst),
2476 OF_instance_get_id(OF_env, out_inst));
2477 OF_node_put(OF_env, ndev_out);
2478 OF_node_put(OF_env, ndev_in);
2479 OF_node_put(OF_env, chs);
2480
2481 return 0;
2482 }
2483
keylargo_ata(OF_node_t * mio,uint32_t base_address,uint32_t base,int irq1,int irq2,uint16_t pic_phandle)2484 static void keylargo_ata(OF_node_t *mio, uint32_t base_address,
2485 uint32_t base, int irq1, int irq2,
2486 uint16_t pic_phandle)
2487 {
2488 OF_env_t *OF_env = OF_env_main;
2489 OF_node_t *ata;
2490 OF_regprop_t regs[2];
2491
2492 ata = OF_node_new(OF_env, mio, "ata-4", base);
2493 if (ata == NULL) {
2494 ERROR("Cannot create 'ata-4'\n");
2495 return;
2496 }
2497 OF_prop_string_new(OF_env, ata, "device_type", "ata");
2498 #if 1
2499 OF_prop_string_new(OF_env, ata, "compatible", "key2largo-ata");
2500 OF_prop_string_new(OF_env, ata, "model", "ata-4");
2501 OF_prop_string_new(OF_env, ata, "cable-type", "80-conductor");
2502 #else
2503 OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
2504 OF_prop_string_new(OF_env, ata, "model", "ata-4");
2505 #endif
2506 OF_prop_int_new(OF_env, ata, "#address-cells", 1);
2507 OF_prop_int_new(OF_env, ata, "#size-cells", 0);
2508 regs[0].address = base;
2509 regs[0].size = 0x00001000;
2510 #if 0 // HACK: Don't set up DMA registers
2511 regs[1].address = 0x00008A00;
2512 regs[1].size = 0x00001000;
2513 OF_property_new(OF_env, ata, "reg",
2514 regs, 2 * sizeof(OF_regprop_t));
2515 #else
2516 OF_property_new(OF_env, ata, "reg",
2517 regs, sizeof(OF_regprop_t));
2518 #endif
2519 OF_prop_int_new(OF_env, ata, "interrupt-parent", pic_phandle);
2520 regs[0].address = irq1;
2521 regs[0].size = 0x00000001;
2522 regs[1].address = irq2;
2523 regs[1].size = 0x00000000;
2524 OF_property_new(OF_env, ata, "interrupts",
2525 regs, 2 * sizeof(OF_regprop_t));
2526 if (base == 0x1f000)
2527 ide_pci_pmac_register(base_address + base, 0x00000000, ata);
2528 else
2529 ide_pci_pmac_register(0x00000000, base_address + base, ata);
2530 }
2531
OF_finalize_pci_macio(void * dev,uint32_t base_address,uint32_t size,void * private_data)2532 void OF_finalize_pci_macio (void *dev, uint32_t base_address, uint32_t size,
2533 void *private_data)
2534 {
2535 unsigned char tmp[OF_NAMELEN_MAX];
2536 OF_env_t *OF_env;
2537 pci_reg_prop_t pregs[2];
2538 OF_node_t *mio, *chs, *als;
2539 uint16_t pic_phandle;
2540 int rec_len;
2541 OF_prop_t *mio_reg;
2542
2543 OF_DPRINTF("mac-io: %p\n", dev);
2544 OF_env = OF_env_main;
2545 chs = OF_node_get(OF_env, "chosen");
2546 if (chs == NULL) {
2547 ERROR("Cannot get 'chosen'\n");
2548 return;
2549 }
2550 als = OF_node_get(OF_env, "aliases");
2551 if (als == NULL) {
2552 OF_node_put(OF_env, als);
2553 ERROR("Cannot get 'aliases'\n");
2554 return;
2555 }
2556 /* Mac-IO is mandatory for OSX to boot */
2557 mio = dev;
2558 mio->private_data = private_data;
2559 pregs[0].addr.hi = 0x00000000;
2560 pregs[0].addr.mid = 0x00000000;
2561 pregs[0].addr.lo = 0x00000000;
2562 pregs[0].size_hi = base_address;
2563 pregs[0].size_lo = size;
2564 mio_reg = OF_property_get(OF_env, mio, "reg");
2565 if (mio_reg && mio_reg->vlen >= 5 * 4) {
2566 pregs[0].addr.mid = ((pci_reg_prop_t *)mio_reg->value)->addr.hi;
2567 }
2568 OF_property_new(OF_env, mio, "ranges",
2569 &pregs, sizeof(pci_reg_prop_t));
2570 #if 0
2571 pregs[0].addr.hi = 0x82013810;
2572 pregs[0].addr.mid = 0x00000000;
2573 pregs[0].addr.lo = 0x80800000;
2574 pregs[0].size_hi = 0x00000000;
2575 pregs[0].size_lo = 0x00080000;
2576 OF_property_new(OF_env, mio, "assigned-addresses",
2577 &pregs, sizeof(pci_reg_prop_t));
2578 #endif
2579
2580 if (arch == ARCH_HEATHROW) {
2581 /* Heathrow PIC */
2582 OF_regprop_t regs;
2583 OF_node_t *mpic;
2584 const char compat_str[] = "heathrow\0mac-risc";
2585
2586 mpic = OF_node_new(OF_env, mio, "interrupt-controller", 0x10);
2587 if (mpic == NULL) {
2588 ERROR("Cannot create 'mpic'\n");
2589 goto out;
2590 }
2591 OF_prop_string_new(OF_env, mpic, "device_type", "interrupt-controller");
2592 OF_property_new(OF_env, mpic, "compatible", compat_str, sizeof(compat_str));
2593 OF_prop_int_new(OF_env, mpic, "#interrupt-cells", 1);
2594 regs.address = 0x10;
2595 regs.size = 0x20;
2596 OF_property_new(OF_env, mpic, "reg",
2597 ®s, sizeof(regs));
2598 OF_property_new(OF_env, mpic, "interrupt-controller", NULL, 0);
2599 pic_phandle = OF_pack_handle(OF_env, mpic);
2600 OF_prop_int_new(OF_env, chs, "interrupt-controller", pic_phandle);
2601 OF_node_put(OF_env, mpic);
2602 rec_len = 6;
2603 } else {
2604 /* OpenPIC */
2605 OF_regprop_t regs[4];
2606 OF_node_t *mpic;
2607 mpic = OF_node_new(OF_env, mio, "interrupt-controller", 0x40000);
2608 if (mpic == NULL) {
2609 ERROR("Cannot create 'mpic'\n");
2610 goto out;
2611 }
2612 OF_prop_string_new(OF_env, mpic, "device_type", "open-pic");
2613 OF_prop_string_new(OF_env, mpic, "compatible", "chrp,open-pic");
2614 OF_property_new(OF_env, mpic, "interrupt-controller", NULL, 0);
2615 OF_property_new(OF_env, mpic, "built-in", NULL, 0);
2616 OF_prop_int_new(OF_env, mpic, "clock-frequency", 0x003F7A00);
2617 OF_prop_int_new(OF_env, mpic, "#address-cells", 0);
2618 OF_prop_int_new(OF_env, mpic, "#interrupt-cells", 2);
2619 memset(regs, 0, 4 * sizeof(OF_regprop_t));
2620 regs[0].address = 0x00040000;
2621 regs[0].size = 0x00040000;
2622 OF_property_new(OF_env, mpic, "reg",
2623 ®s, 1 * sizeof(OF_regprop_t));
2624 pic_phandle = OF_pack_handle(OF_env, mpic);
2625 OF_prop_int_new(OF_env, chs, "interrupt-controller", pic_phandle);
2626 OF_node_put(OF_env, mpic);
2627 rec_len = 7;
2628 }
2629
2630 /* patch pci host table */
2631 /* XXX: do it after the PCI init */
2632 {
2633 int i;
2634 uint32_t tab[4];
2635
2636 for(i = 0; i < pci_host_interrupt_map_len; i += rec_len)
2637 pci_host_interrupt_map[i + 4] = pic_phandle;
2638 #if 0
2639 dprintf("interrupt-map:\n");
2640 for(i = 0; i < pci_host_interrupt_map_len; i++) {
2641 dprintf(" %08x", pci_host_interrupt_map[i]);
2642 if ((i % rec_len) == (rec_len - 1))
2643 dprintf("\n");
2644 }
2645 dprintf("\n");
2646 #endif
2647 OF_property_new(OF_env, pci_host_node, "interrupt-map",
2648 pci_host_interrupt_map,
2649 pci_host_interrupt_map_len * sizeof(uint32_t));
2650 tab[0] = 0xf800;
2651 tab[1] = 0;
2652 tab[2] = 0;
2653 tab[3] = 0;
2654 OF_property_new(OF_env, pci_host_node, "interrupt-map-mask",
2655 tab, 4 * sizeof(uint32_t));
2656 }
2657 #if 0
2658 /* escc is useful to get MacOS X debug messages */
2659 {
2660 OF_regprop_t regs[8];
2661 uint32_t irqs[6];
2662 OF_node_t *scc, *chann;
2663 scc = OF_node_new(OF_env, mio, "escc", 0x13000);
2664 if (scc == NULL) {
2665 ERROR("Cannot create 'escc'\n");
2666 goto out;
2667 }
2668 OF_prop_string_new(OF_env, scc, "device_type", "escc");
2669 OF_prop_string_new(OF_env, scc, "compatible", "chrp,es0");
2670 OF_property_new(OF_env, scc, "built-in", NULL, 0);
2671 OF_prop_int_new(OF_env, scc, "#address-cells", 1);
2672 memset(regs, 0, 8 * sizeof(OF_regprop_t));
2673 regs[0].address = 0x00013000;
2674 regs[0].size = 0x00001000;
2675 regs[1].address = 0x00008400;
2676 regs[1].size = 0x00000100;
2677 regs[2].address = 0x00008500;
2678 regs[2].size = 0x00000100;
2679 regs[3].address = 0x00008600;
2680 regs[3].size = 0x00000100;
2681 regs[4].address = 0x00008700;
2682 regs[4].size = 0x00000100;
2683 OF_property_new(OF_env, scc, "reg",
2684 regs, 5 * sizeof(OF_regprop_t));
2685 OF_property_new(OF_env, scc, "ranges", NULL, 0);
2686 /* Set up two channels */
2687 chann = OF_node_new(OF_env, scc, "ch-a", 0x13020);
2688 if (chann == NULL) {
2689 ERROR("Cannot create 'ch-a'\n");
2690 goto out;
2691 }
2692 OF_prop_string_new(OF_env, chann, "device_type", "serial");
2693 OF_prop_string_new(OF_env, chann, "compatible", "chrp,es2");
2694 OF_property_new(OF_env, chann, "built-in", NULL, 0);
2695 OF_prop_int_new(OF_env, chann, "slot-names", 0);
2696 OF_prop_int_new(OF_env, chann, "interrupt-parent", pic_phandle);
2697 memset(regs, 0, 8 * sizeof(OF_regprop_t));
2698 regs[0].address = 0x00013020;
2699 regs[0].size = 0x00000001;
2700 regs[1].address = 0x00013030;
2701 regs[1].size = 0x00000001;
2702 regs[2].address = 0x00013050;
2703 regs[2].size = 0x00000001;
2704 regs[3].address = 0x00008400;
2705 regs[3].size = 0x00000100;
2706 regs[4].address = 0x00008500;
2707 regs[4].size = 0x00000100;
2708 OF_property_new(OF_env, chann, "reg",
2709 regs, 5 * sizeof(OF_regprop_t));
2710 /* XXX: tofix: those are regprops */
2711 irqs[0] = 0x16;
2712 irqs[1] = 0x01;
2713 irqs[2] = 0x05;
2714 irqs[3] = 0x00;
2715 irqs[4] = 0x06;
2716 irqs[5] = 0x00;
2717 OF_property_new(OF_env, chann, "interrupts",
2718 irqs, 6 * sizeof(uint32_t));
2719 OF_node_put(OF_env, chann);
2720 chann = OF_node_new(OF_env, scc, "ch-b", 0x13000);
2721 if (chann == NULL) {
2722 ERROR("Cannot create 'ch-b'\n");
2723 goto out;
2724 }
2725 OF_prop_string_new(OF_env, chann, "device_type", "serial");
2726 OF_prop_string_new(OF_env, chann, "compatible", "chrp,es3");
2727 OF_property_new(OF_env, chann, "built-in", NULL, 0);
2728 OF_prop_int_new(OF_env, chann, "slot-names", 0);
2729 OF_prop_int_new(OF_env, chann, "interrupt-parent", pic_phandle);
2730 memset(regs, 0, 8 * sizeof(OF_regprop_t));
2731 regs[0].address = 0x00013000;
2732 regs[0].size = 0x00000001;
2733 regs[1].address = 0x00013010;
2734 regs[1].size = 0x00000001;
2735 regs[2].address = 0x00013040;
2736 regs[2].size = 0x00000001;
2737 regs[3].address = 0x00008600;
2738 regs[3].size = 0x00000100;
2739 regs[4].address = 0x00008700;
2740 regs[4].size = 0x00000100;
2741 OF_property_new(OF_env, chann, "reg",
2742 regs, 5 * sizeof(OF_regprop_t));
2743 /* XXX: tofix: those are regprops */
2744 irqs[0] = 0x17;
2745 irqs[1] = 0x01;
2746 irqs[2] = 0x07;
2747 irqs[3] = 0x00;
2748 irqs[4] = 0x08;
2749 irqs[5] = 0x00;
2750 OF_property_new(OF_env, chann, "interrupts",
2751 irqs, 6 * sizeof(uint32_t));
2752 OF_node_put(OF_env, chann);
2753 OF_node_put(OF_env, scc);
2754 /* MacOS likes escc-legacy */
2755 scc = OF_node_new(OF_env, mio, "escc-legacy", 0x12000);
2756 if (scc == NULL) {
2757 ERROR("Cannot create 'escc-legacy'\n");
2758 goto out;
2759 }
2760 OF_prop_string_new(OF_env, scc, "device_type", "escc-legacy");
2761 OF_prop_string_new(OF_env, scc, "compatible", "chrp,es1");
2762 OF_property_new(OF_env, scc, "built-in", NULL, 0);
2763 OF_prop_int_new(OF_env, scc, "#address-cells", 1);
2764 memset(regs, 0, 8 * sizeof(OF_regprop_t));
2765 regs[0].address = 0x00012000;
2766 regs[0].size = 0x00001000;
2767 regs[1].address = 0x00008400;
2768 regs[1].size = 0x00000100;
2769 regs[2].address = 0x00008500;
2770 regs[2].size = 0x00000100;
2771 regs[3].address = 0x00008600;
2772 regs[3].size = 0x00000100;
2773 regs[4].address = 0x00008700;
2774 regs[4].size = 0x00000100;
2775 OF_property_new(OF_env, scc, "reg",
2776 regs, 8 * sizeof(OF_regprop_t));
2777 OF_property_new(OF_env, scc, "ranges", NULL, 0);
2778 /* Set up two channels */
2779 chann = OF_node_new(OF_env, scc, "ch-a", 0x12004);
2780 if (chann == NULL) {
2781 ERROR("Cannot create 'ch-a'\n");
2782 goto out;
2783 }
2784 OF_prop_string_new(OF_env, chann, "device_type", "serial");
2785 OF_prop_string_new(OF_env, chann, "compatible", "chrp,es4");
2786 OF_property_new(OF_env, chann, "built-in", NULL, 0);
2787 OF_prop_int_new(OF_env, chann, "interrupt-parent", pic_phandle);
2788 memset(regs, 0, 8 * sizeof(OF_regprop_t));
2789 regs[0].address = 0x00012004;
2790 regs[0].size = 0x00000001;
2791 regs[1].address = 0x00012006;
2792 regs[1].size = 0x00000001;
2793 regs[2].address = 0x0001200A;
2794 regs[2].size = 0x00000001;
2795 regs[3].address = 0x00008400;
2796 regs[3].size = 0x00000100;
2797 regs[4].address = 0x00008500;
2798 regs[4].size = 0x00000100;
2799 OF_property_new(OF_env, chann, "reg",
2800 regs, 8 * sizeof(OF_regprop_t));
2801 /* XXX: tofix: those are regprops */
2802 irqs[0] = 0x16;
2803 irqs[1] = 0x01;
2804 irqs[2] = 0x05;
2805 irqs[3] = 0x00;
2806 irqs[4] = 0x06;
2807 irqs[5] = 0x00;
2808 OF_property_new(OF_env, chann, "interrupts",
2809 irqs, 6 * sizeof(uint32_t));
2810 OF_node_put(OF_env, chann);
2811 chann = OF_node_new(OF_env, scc, "ch-b", 0x12000);
2812 if (chann == NULL) {
2813 ERROR("Cannot create 'ch-b'\n");
2814 goto out;
2815 }
2816 OF_prop_string_new(OF_env, chann, "device_type", "serial");
2817 OF_prop_string_new(OF_env, chann, "compatible", "chrp,es5");
2818 OF_property_new(OF_env, chann, "built-in", NULL, 0);
2819 OF_prop_int_new(OF_env, chann, "interrupt-parent", pic_phandle);
2820 memset(regs, 0, 8 * sizeof(OF_regprop_t));
2821 regs[0].address = 0x00012000;
2822 regs[0].size = 0x00000001;
2823 regs[1].address = 0x00012002;
2824 regs[1].size = 0x00000001;
2825 regs[2].address = 0x00012008;
2826 regs[2].size = 0x00000001;
2827 regs[3].address = 0x00008600;
2828 regs[3].size = 0x00000100;
2829 regs[4].address = 0x00008700;
2830 regs[4].size = 0x00000100;
2831 OF_property_new(OF_env, chann, "reg",
2832 regs, 8 * sizeof(OF_regprop_t));
2833 /* XXX: tofix: those are regprops */
2834 irqs[0] = 0x17;
2835 irqs[1] = 0x01;
2836 irqs[2] = 0x07;
2837 irqs[3] = 0x00;
2838 irqs[4] = 0x08;
2839 irqs[5] = 0x00;
2840 OF_property_new(OF_env, chann, "interrupts",
2841 irqs, 6 * sizeof(uint32_t));
2842 OF_node_put(OF_env, chann);
2843 OF_node_put(OF_env, scc);
2844 }
2845 #endif
2846 /* Keylargo IDE controller: need some work (DMA problem ?) */
2847 if (arch == ARCH_MAC99) {
2848 keylargo_ata(mio, base_address, 0x1f000, 0x13, 0xb, pic_phandle);
2849 keylargo_ata(mio, base_address, 0x20000, 0x14, 0xb, pic_phandle);
2850 }
2851 #if 0
2852 /* Timer */
2853 {
2854 OF_node_t *tmr;
2855 OF_regprop_t regs[1];
2856 tmr = OF_node_new(OF_env, mio, "timer", 0x15000);
2857 if (tmr == NULL) {
2858 ERROR("Cannot create 'timer'\n");
2859 goto out;
2860 }
2861 OF_prop_string_new(OF_env, tmr, "device_type", "timer");
2862 OF_prop_string_new(OF_env, tmr, "compatible", "keylargo-timer");
2863 OF_prop_int_new(OF_env, tmr, "clock-frequency", 0x01194000);
2864 regs[0].address = 0x00015000;
2865 regs[0].size = 0x00001000;
2866 OF_property_new(OF_env, tmr, "reg", regs, sizeof(OF_regprop_t));
2867 OF_prop_int_new(OF_env, tmr, "interrupt-parent", pic_phandle);
2868 regs[0].address = 0x00000020;
2869 regs[0].size = 0x00000001;
2870 OF_property_new(OF_env, tmr, "interrupts",
2871 regs, sizeof(OF_regprop_t));
2872 OF_node_put(OF_env, tmr);
2873 }
2874 #endif
2875 /* VIA-PMU */
2876 {
2877 /* Controls adb, RTC and power-mgt (forget it !) */
2878 OF_node_t *via, *adb;
2879 OF_regprop_t regs[1];
2880 #if 0 // THIS IS A HACK AND IS COMPLETELY ABSURD !
2881 // (but needed has Qemu doesn't emulate via-pmu).
2882 via = OF_node_new(OF_env, mio, "via-pmu", 0x16000);
2883 if (via == NULL) {
2884 ERROR("Cannot create 'via-pmu'\n");
2885 goto out;
2886 }
2887 OF_prop_string_new(OF_env, via, "device_type", "via-pmu");
2888 OF_prop_string_new(OF_env, via, "compatible", "pmu");
2889 #else
2890 via = OF_node_new(OF_env, mio, "via-cuda", 0x16000);
2891 if (via == NULL) {
2892 ERROR("Cannot create 'via-cuda'\n");
2893 goto out;
2894 }
2895 OF_prop_string_new(OF_env, via, "device_type", "via-cuda");
2896 OF_prop_string_new(OF_env, via, "compatible", "cuda");
2897 #endif
2898 regs[0].address = 0x00016000;
2899 regs[0].size = 0x00002000;
2900 OF_property_new(OF_env, via, "reg", regs, sizeof(OF_regprop_t));
2901 OF_prop_int_new(OF_env, via, "interrupt-parent", pic_phandle);
2902 if (arch == ARCH_HEATHROW) {
2903 OF_prop_int_new(OF_env, via, "interrupts", 0x12);
2904 } else {
2905 regs[0].address = 0x00000019;
2906 regs[0].size = 0x00000001;
2907 OF_property_new(OF_env, via, "interrupts",
2908 regs, sizeof(OF_regprop_t));
2909 }
2910 /* force usage of OF bus speeds */
2911 OF_prop_int_new(OF_env, via, "BusSpeedCorrect", 1);
2912 #if 0
2913 OF_prop_int_new(OF_env, via, "pmu-version", 0x00D0740C);
2914 #endif
2915 {
2916 OF_node_t *kbd, *mouse;
2917 /* ADB pseudo-device */
2918 adb = OF_node_new(OF_env, via, "adb", OF_ADDRESS_NONE);
2919 if (adb == NULL) {
2920 ERROR("Cannot create 'adb'\n");
2921 goto out;
2922 }
2923 OF_prop_string_new(OF_env, adb, "device_type", "adb");
2924 #if 0
2925 OF_prop_string_new(OF_env, adb, "compatible", "pmu-99");
2926 #else
2927 OF_prop_string_new(OF_env, adb, "compatible", "adb");
2928 #endif
2929 OF_prop_int_new(OF_env, adb, "#address-cells", 1);
2930 OF_prop_int_new(OF_env, adb, "#size-cells", 0);
2931 OF_pack_get_path(OF_env, tmp, 512, adb);
2932 OF_prop_string_new(OF_env, als, "adb", tmp);
2933
2934 kbd = OF_node_new(OF_env, adb, "keyboard", 2);
2935 if (kbd == NULL) {
2936 ERROR("Cannot create 'kbd'\n");
2937 goto out;
2938 }
2939 OF_prop_string_new(OF_env, kbd, "device_type", "keyboard");
2940 OF_prop_int_new(OF_env, kbd, "reg", 2);
2941
2942 mouse = OF_node_new(OF_env, adb, "mouse", 3);
2943 if (mouse == NULL) {
2944 ERROR("Cannot create 'mouse'\n");
2945 goto out;
2946 }
2947 OF_prop_string_new(OF_env, mouse, "device_type", "mouse");
2948 OF_prop_int_new(OF_env, mouse, "reg", 3);
2949 OF_prop_int_new(OF_env, mouse, "#buttons", 3);
2950 }
2951 {
2952 OF_node_t *rtc;
2953
2954 rtc = OF_node_new(OF_env, via, "rtc", OF_ADDRESS_NONE);
2955 if (rtc == NULL) {
2956 ERROR("Cannot create 'rtc'\n");
2957 goto out;
2958 }
2959 OF_prop_string_new(OF_env, rtc, "device_type", "rtc");
2960 #if 0
2961 OF_prop_string_new(OF_env, rtc, "compatible", "rtc,via-pmu");
2962 #else
2963 OF_prop_string_new(OF_env, rtc, "compatible", "rtc");
2964 #endif
2965 OF_node_put(OF_env, rtc);
2966 }
2967 // OF_node_put(OF_env, via);
2968 }
2969 {
2970 OF_node_t *pmgt;
2971 pmgt = OF_node_new(OF_env, mio, "power-mgt", OF_ADDRESS_NONE);
2972 OF_prop_string_new(OF_env, pmgt, "device_type", "power-mgt");
2973 OF_prop_string_new(OF_env, pmgt, "compatible", "cuda");
2974 OF_prop_string_new(OF_env, pmgt, "mgt-kind", "min-consumption-pwm-led");
2975 OF_node_put(OF_env, pmgt);
2976 }
2977
2978 if (arch == ARCH_HEATHROW) {
2979 /* NVRAM */
2980 OF_node_t *nvr;
2981 OF_regprop_t regs;
2982 nvr = OF_node_new(OF_env, mio, "nvram", 0x60000);
2983 OF_prop_string_new(OF_env, nvr, "device_type", "nvram");
2984 regs.address = 0x60000;
2985 regs.size = 0x00020000;
2986 OF_property_new(OF_env, nvr, "reg", ®s, sizeof(regs));
2987 OF_prop_int_new(OF_env, nvr, "#bytes", 0x2000);
2988 OF_node_put(OF_env, nvr);
2989 }
2990
2991 out:
2992 // OF_node_put(OF_env, mio);
2993 OF_node_put(OF_env, chs);
2994 OF_node_put(OF_env, als);
2995 }
2996
OF_finalize_pci_ide(void * dev,uint32_t io_base0,uint32_t io_base1,uint32_t io_base2,uint32_t io_base3)2997 void OF_finalize_pci_ide (void *dev,
2998 uint32_t io_base0, uint32_t io_base1,
2999 uint32_t io_base2, uint32_t io_base3)
3000 {
3001 OF_env_t *OF_env = OF_env_main;
3002 OF_node_t *pci_ata = dev;
3003 OF_node_t *ata, *atas[2];
3004 int i;
3005
3006 OF_prop_int_new(OF_env, pci_ata, "#address-cells", 1);
3007 OF_prop_int_new(OF_env, pci_ata, "#size-cells", 0);
3008
3009 /* XXX: Darwin handles only one device */
3010 for(i = 0; i < 1; i++) {
3011 ata = OF_node_new(OF_env, pci_ata, "ata-4", i);
3012 if (ata == NULL) {
3013 ERROR("Cannot create 'ata-4'\n");
3014 return;
3015 }
3016 OF_prop_string_new(OF_env, ata, "device_type", "ata");
3017 OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
3018 OF_prop_string_new(OF_env, ata, "model", "ata-4");
3019 OF_prop_int_new(OF_env, ata, "#address-cells", 1);
3020 OF_prop_int_new(OF_env, ata, "#size-cells", 0);
3021 OF_prop_int_new(OF_env, ata, "reg", i);
3022 atas[i] = ata;
3023 }
3024 ide_pci_pc_register(io_base0, io_base1, io_base2, io_base3,
3025 atas[0], atas[1]);
3026 }
3027
3028 /*****************************************************************************/
3029 /* Fake package */
OF_method_fake(OF_env_t * OF_env)3030 static void OF_method_fake (OF_env_t *OF_env)
3031 {
3032 uint32_t ihandle;
3033
3034 ihandle = popd(OF_env);
3035 OF_DPRINTF("ih: %0x %d\n", ihandle, stackd_depth(OF_env));
3036 pushd(OF_env, ihandle);
3037 }
3038
OF_mmu_translate(OF_env_t * OF_env)3039 static void OF_mmu_translate (OF_env_t *OF_env)
3040 {
3041 const unsigned char *args;
3042 uint32_t address, more;
3043 uint32_t ihandle;
3044
3045 OF_CHECK_NBARGS(OF_env, 4);
3046 /* As we get a 1:1 mapping, do nothing */
3047 ihandle = popd(OF_env);
3048 args = (void *)popd(OF_env);
3049 address = popd(OF_env);
3050 more = popd(OF_env);
3051 OF_DPRINTF("Translate address %0x %0x %0x\n", ihandle, address, more);
3052 // BAT_setup(3, more, address, 0x10000000, 1, 1, 2);
3053 pushd(OF_env, address);
3054 pushd(OF_env, 0x00000000);
3055 pushd(OF_env, 0x00000000);
3056 pushd(OF_env, 0);
3057 }
3058
OF_mmu_map(OF_env_t * OF_env)3059 static void OF_mmu_map (OF_env_t *OF_env)
3060 {
3061 const unsigned char *args;
3062 uint32_t address, virt, size;
3063 uint32_t ihandle;
3064
3065 OF_CHECK_NBARGS(OF_env, 6);
3066 /* As we get a 1:1 mapping, do nothing */
3067 ihandle = popd(OF_env);
3068 args = (void *)popd(OF_env);
3069 popd(OF_env);
3070 size = popd(OF_env);
3071 virt = popd(OF_env);
3072 address = popd(OF_env);
3073 OF_DPRINTF("Map %0x %0x %0x %0x\n", ihandle, address,
3074 virt, size);
3075 pushd(OF_env, 0);
3076 }
3077
3078 /* Serial device package */
OF_serial_write(OF_env_t * OF_env)3079 static void OF_serial_write (OF_env_t *OF_env)
3080 {
3081 const unsigned char *args;
3082 OF_inst_t *inst;
3083 OF_node_t *node;
3084 uint32_t ihandle;
3085 unsigned char *str;
3086 int len;
3087
3088 OF_CHECK_NBARGS(OF_env, 4);
3089 ihandle = popd(OF_env);
3090 args = (void *)popd(OF_env);
3091 str = (void *)popd(OF_env);
3092 len = popd(OF_env);
3093 inst = OF_inst_find(OF_env, ihandle);
3094 if (inst == NULL) {
3095 pushd(OF_env, -1);
3096 ERROR("Cannot get serial instance\n");
3097 return;
3098 }
3099 node = inst->node;
3100 // OF_DPRINTF("args: %p str: %p\n", args, str);
3101 /* XXX: should use directly the serial port
3102 * and have another console package.
3103 */
3104 console_write(str, len);
3105 pushd(OF_env, 0);
3106 }
3107
OF_serial_read(OF_env_t * OF_env)3108 static void OF_serial_read (OF_env_t *OF_env)
3109 {
3110 const unsigned char *args;
3111 char *dest;
3112 uint32_t len;
3113 uint32_t ihandle;
3114 uint16_t phandle;
3115 int ret, count;
3116
3117 OF_CHECK_NBARGS(OF_env, 4);
3118 ihandle = popd(OF_env);
3119 args = (void *)popd(OF_env);
3120 phandle = (ihandle >> 16) & 0xFFFF;
3121 dest = (void *)popd(OF_env);
3122 len = popd(OF_env);
3123 ret = -1; /* Don't know why gcc thinks it might be uninitialized... */
3124 for (count = 0; count < 1000; count++) {
3125 ret = console_read(dest, len);
3126 /* Stop if we read something or got an error */
3127 if (ret != 0)
3128 break;
3129 /* Random sleep. Seems allright for serial port */
3130 usleep(10000);
3131 }
3132 if (ret <= 0) {
3133 pushd(OF_env, 0);
3134 } else {
3135 OF_DPRINTF("send '%s'\n", dest);
3136 pushd(OF_env, ret);
3137 }
3138 }
3139
3140 typedef struct blockdev_inst_t {
3141 int type;
3142 union {
3143 bloc_device_t *bd;
3144 part_t *part;
3145 inode_t *file;
3146 } u;
3147 } blockdev_inst_t;
3148
OF_split_args(unsigned char * args,unsigned char ** argv,int max_args)3149 static int OF_split_args (unsigned char *args, unsigned char **argv,
3150 int max_args)
3151 {
3152 unsigned char *pos, *end;
3153 int i;
3154
3155 pos = args;
3156 end = pos;
3157 for (i = 0; i < max_args && *pos != '\0' && end != NULL; i++) {
3158 end = strchr(pos, ',');
3159 if (end != NULL)
3160 *end = '\0';
3161 argv[i] = pos;
3162 pos = end + 1;
3163 }
3164
3165 return i;
3166 }
3167
OF_convert_path(unsigned char ** path)3168 static void OF_convert_path (unsigned char **path)
3169 {
3170 unsigned char *pos;
3171
3172 OF_DPRINTF("%s: '%s'\n", __func__, *path);
3173 for (pos = *path; *pos != '\0'; pos++) {
3174 if (*pos == '\\')
3175 *pos = '/';
3176 }
3177 OF_DPRINTF("%s: '%s'\n", __func__, *path);
3178 pos = *path;
3179 #if 1
3180 if (pos[0] == '/' && pos[1] == '/') {
3181 pos += 2;
3182 *path = pos;
3183 }
3184 #else
3185 for (; *pos == '/'; pos++)
3186 continue;
3187 *path = pos;
3188 #endif
3189 OF_DPRINTF("%s: '%s'\n", __func__, *path);
3190 }
3191
3192 /* Block devices package */
OF_blockdev_open(OF_env_t * OF_env)3193 static void OF_blockdev_open (OF_env_t *OF_env)
3194 {
3195 unsigned char tmp[OF_NAMELEN_MAX];
3196 unsigned char *args, *argv[4];
3197 OF_inst_t *dsk_inst;
3198 OF_node_t *dsk;
3199 bloc_device_t *bd;
3200 blockdev_inst_t *bdinst;
3201 uint32_t ihandle;
3202 uint16_t phandle;
3203 int nargs, partnum;
3204
3205 OF_CHECK_NBARGS(OF_env, 2);
3206 ihandle = popd(OF_env);
3207 args = (void *)popd(OF_env);
3208 phandle = (ihandle >> 16) & 0xFFFF;
3209 dsk_inst = OF_inst_find(OF_env, ihandle);
3210 if (dsk_inst == NULL) {
3211 ERROR("Disk not found (ih: %0x)\n", ihandle);
3212 pushd(OF_env, -1);
3213 return;
3214 }
3215 dsk = dsk_inst->node;
3216 bd = dsk->private_data;
3217 bdinst = malloc(sizeof(blockdev_inst_t));
3218 if (bdinst == NULL) {
3219 ihandle = -1;
3220 ERROR("Cannot alloc blockdev instance\n");
3221 goto out;
3222 }
3223 memset(bdinst, 0, sizeof(blockdev_inst_t));
3224 OF_DPRINTF("called with args '%s'\n", args);
3225 nargs = OF_split_args(args, argv, 4);
3226 partnum = -1;
3227 if (nargs > 0) {
3228 partnum = strtol(argv[0], NULL, 10);
3229 if (partnum > 0) {
3230 OF_DPRINTF("Open partition... %d %d\n", partnum, nargs);
3231 bdinst->type = 1;
3232 bdinst->u.part = part_get(bd, partnum);
3233 if (bdinst->u.part == NULL) {
3234 OF_DPRINTF("Partition %d not found\n", partnum);
3235 free(bdinst);
3236 pushd(OF_env, -1);
3237 return;
3238 }
3239 if (nargs > 1) {
3240 /* TODO: open file */
3241 bdinst->type = 2;
3242 OF_DPRINTF("Open file... %d %d '%s'\n",
3243 partnum, nargs, argv[1]);
3244 OF_convert_path(&argv[1]);
3245 if (*argv[1] != '/') {
3246 sprintf(tmp, "%s/%s",
3247 fs_get_boot_dirname(part_fs(bdinst->u.part)),
3248 argv[1]);
3249 bdinst->u.file = fs_open(part_fs(bdinst->u.part), tmp);
3250 } else {
3251 bdinst->u.file = fs_open(part_fs(bdinst->u.part), argv[1]);
3252 }
3253 if (bdinst->u.file == NULL) {
3254 #if 0
3255 bug();
3256 #endif
3257 pushd(OF_env, 0x00000000);
3258 ERROR("File not found '%s'\n", argv[1]);
3259 return;
3260 }
3261 }
3262 }
3263 }
3264 if (nargs == 0 || partnum == 0) {
3265 OF_DPRINTF("Open disk... %d %d\n", nargs, partnum);
3266 bdinst->type = 0;
3267 bdinst->u.bd = bd;
3268 }
3269 /* TODO: find partition &/| file */
3270 dsk_inst->data = bdinst;
3271 OF_node_put(OF_env, dsk);
3272 out:
3273 pushd(OF_env, ihandle);
3274 }
3275
OF_blockdev_seek(OF_env_t * OF_env)3276 static void OF_blockdev_seek (OF_env_t *OF_env)
3277 {
3278 const unsigned char *args;
3279 OF_inst_t *dsk_inst;
3280 blockdev_inst_t *bdinst;
3281 uint32_t posh, posl, bloc, pos, blocsize, tmp;
3282 uint32_t ihandle;
3283 uint16_t phandle;
3284 int sh;
3285
3286 OF_CHECK_NBARGS(OF_env, 4);
3287 ihandle = popd(OF_env);
3288 args = (void *)popd(OF_env);
3289 phandle = (ihandle >> 16) & 0xFFFF;
3290 posh = popd(OF_env);
3291 posl = popd(OF_env);
3292 dsk_inst = OF_inst_find(OF_env, ihandle);
3293 if (dsk_inst == NULL) {
3294 ERROR("Disk not found (ih: %0x)\n", ihandle);
3295 pushd(OF_env, -1);
3296 return;
3297 }
3298 bdinst = dsk_inst->data;
3299 switch (bdinst->type) {
3300 case 0:
3301 blocsize = bd_seclen(bdinst->u.bd);
3302 for (tmp = blocsize, sh = 0; tmp != 1; tmp = tmp / 2)
3303 sh++;
3304 bloc = ((posh << (32 - sh)) | (posl / blocsize));
3305 pos = posl % blocsize;
3306 OF_DPRINTF("disk: bsize %08x %08x %08x => %08x %08x\n", blocsize,
3307 posh, posl, bloc, pos);
3308 pushd(OF_env, bd_seek(bdinst->u.bd, bloc, pos));
3309 break;
3310 case 1:
3311 blocsize = part_blocsize(bdinst->u.part);
3312 for (tmp = blocsize, sh = 0; tmp != 1; tmp = tmp / 2)
3313 sh++;
3314 bloc = ((posh << (32 - sh)) | (posl / blocsize));
3315 pos = posl % blocsize;
3316 OF_DPRINTF("part: bsize %08x %08x %08x => %08x %08x\n", blocsize,
3317 posh, posl, bloc, pos);
3318 pushd(OF_env, part_seek(bdinst->u.part, bloc, pos));
3319 break;
3320 case 2:
3321 blocsize = part_blocsize(fs_inode_get_part(bdinst->u.file));
3322 for (tmp = blocsize, sh = 0; tmp != 1; tmp = tmp / 2)
3323 sh++;
3324 bloc = ((posh << (32 - sh)) | (posl / blocsize));
3325 pos = posl % blocsize;
3326 OF_DPRINTF("file: bsize %08x %08x %08x => %08x %08x\n", blocsize,
3327 posh, posl, bloc, pos);
3328 pushd(OF_env, fs_seek(bdinst->u.file, bloc, pos));
3329 break;
3330 }
3331 }
3332
OF_blockdev_read(OF_env_t * OF_env)3333 static void OF_blockdev_read (OF_env_t *OF_env)
3334 {
3335 const unsigned char *args;
3336 OF_inst_t *dsk_inst;
3337 blockdev_inst_t *bdinst;
3338 void *dest;
3339 uint32_t len;
3340 uint32_t ihandle;
3341 uint16_t phandle;
3342
3343 OF_CHECK_NBARGS(OF_env, 4);
3344 ihandle = popd(OF_env);
3345 args = (void *)popd(OF_env);
3346 phandle = (ihandle >> 16) & 0xFFFF;
3347 dest = (void *)popd(OF_env);
3348 len = popd(OF_env);
3349 dsk_inst = OF_inst_find(OF_env, ihandle);
3350 if (dsk_inst == NULL) {
3351 ERROR("Disk not found (ih: %0x)\n", ihandle);
3352 pushd(OF_env, -1);
3353 return;
3354 }
3355 bdinst = dsk_inst->data;
3356 set_check(0);
3357 OF_DPRINTF("dest: %p len: %d %d\n", dest, len, bdinst->type);
3358 switch (bdinst->type) {
3359 case 0:
3360 OF_DPRINTF("read disk\n");
3361 pushd(OF_env, bd_read(bdinst->u.bd, dest, len));
3362 break;
3363 case 1:
3364 OF_DPRINTF("read partition\n");
3365 pushd(OF_env, part_read(bdinst->u.part, dest, len));
3366 break;
3367 case 2:
3368 OF_DPRINTF("read file\n");
3369 pushd(OF_env, fs_read(bdinst->u.file, dest, len));
3370 break;
3371 }
3372 OF_DPRINTF("%08x %08x %08x %08x\n",
3373 ((uint32_t *)dest)[0], ((uint32_t *)dest)[1],
3374 ((uint32_t *)dest)[2], ((uint32_t *)dest)[3]);
3375 OF_DPRINTF("%08x %08x %08x %08x\n",
3376 ((uint32_t *)dest)[4], ((uint32_t *)dest)[5],
3377 ((uint32_t *)dest)[6], ((uint32_t *)dest)[7]);
3378
3379 set_check(1);
3380 }
3381
OF_blockdev_get_blocsize(OF_env_t * OF_env)3382 static void OF_blockdev_get_blocsize (OF_env_t *OF_env)
3383 {
3384 const unsigned char *args;
3385 OF_inst_t *dsk_inst;
3386 blockdev_inst_t *bdinst;
3387 uint32_t ihandle;
3388 uint16_t phandle;
3389 uint32_t blocsize;
3390
3391 OF_CHECK_NBARGS(OF_env, 2);
3392 ihandle = popd(OF_env);
3393 args = (void *)popd(OF_env);
3394 phandle = (ihandle >> 16) & 0xFFFF;
3395 dsk_inst = OF_inst_find(OF_env, ihandle);
3396 if (dsk_inst == NULL) {
3397 ERROR("Disk not found (ih: %0x)\n", ihandle);
3398 pushd(OF_env, -1);
3399 return;
3400 }
3401 bdinst = dsk_inst->data;
3402 #if 0
3403 switch (bdinst->type) {
3404 case 0:
3405 blocsize = bd_seclen(bdinst->u.bd);
3406 break;
3407 case 1:
3408 blocsize = part_blocsize(bdinst->u.part);
3409 break;
3410 case 2:
3411 blocsize = 512;
3412 break;
3413 }
3414 #else
3415 blocsize = 512;
3416 #endif
3417 pushd(OF_env, blocsize);
3418 pushd(OF_env, 0);
3419 }
3420
OF_blockdev_dma_alloc(OF_env_t * OF_env)3421 static void OF_blockdev_dma_alloc (OF_env_t *OF_env)
3422 {
3423 const unsigned char *args;
3424 void *address;
3425 uint32_t ihandle;
3426 uint32_t size;
3427
3428 OF_CHECK_NBARGS(OF_env, 3);
3429 ihandle = popd(OF_env);
3430 args = (void *)popd(OF_env);
3431 size = popd(OF_env);
3432 OF_DPRINTF("size: %08x\n", size);
3433 mem_align(size);
3434 address = malloc(size);
3435 if (address != NULL)
3436 memset(address, 0, size);
3437 pushd(OF_env, (uint32_t)address);
3438 pushd(OF_env, 0);
3439 }
3440
OF_blockdev_dma_free(OF_env_t * OF_env)3441 static void OF_blockdev_dma_free (OF_env_t *OF_env)
3442 {
3443 const unsigned char *args;
3444 void *address;
3445 uint32_t ihandle;
3446 uint32_t size;
3447
3448 OF_CHECK_NBARGS(OF_env, 4);
3449 ihandle = popd(OF_env);
3450 args = (void *)popd(OF_env);
3451 size = popd(OF_env);
3452 address = (void *)popd(OF_env);
3453 OF_DPRINTF("address: %p size: %08x\n", address, size);
3454 free(address);
3455 pushd(OF_env, 0);
3456 }
3457
OF_blockdev_register(void * parent,void * private,const unsigned char * type,const unsigned char * name,int devnum,const char * alias)3458 void *OF_blockdev_register (void *parent, void *private,
3459 const unsigned char *type,
3460 const unsigned char *name, int devnum,
3461 const char *alias)
3462 {
3463 unsigned char tmp[OF_NAMELEN_MAX], path[OF_NAMELEN_MAX], *pos;
3464 OF_env_t *OF_env;
3465 OF_node_t *dsk, *als;
3466 int i;
3467
3468 OF_env = OF_env_main;
3469 dsk = OF_node_new(OF_env, parent, name, devnum);
3470 if (dsk == NULL) {
3471 ERROR("Cannot create blockdev '%s'\n", name);
3472 return NULL;
3473 }
3474 OF_prop_string_new(OF_env, dsk, "device_type", "block");
3475 OF_prop_string_new(OF_env, dsk, "category", type);
3476 OF_prop_int_new(OF_env, dsk, "device_id", devnum);
3477 OF_prop_int_new(OF_env, dsk, "reg", devnum);
3478 OF_method_new(OF_env, dsk, "open", &OF_blockdev_open);
3479 OF_method_new(OF_env, dsk, "seek", &OF_blockdev_seek);
3480 OF_method_new(OF_env, dsk, "read", &OF_blockdev_read);
3481 OF_method_new(OF_env, dsk, "block-size",
3482 &OF_blockdev_get_blocsize);
3483 OF_method_new(OF_env, dsk, "dma-alloc", &OF_blockdev_dma_alloc);
3484 OF_method_new(OF_env, dsk, "dma-free", &OF_blockdev_dma_free);
3485 if (strcmp(type, "cdrom") == 0)
3486 OF_method_new(OF_env, dsk, "eject", &OF_method_fake);
3487 OF_method_new(OF_env, dsk, "close", &OF_method_fake);
3488 dsk->private_data = private;
3489 /* Set up aliases */
3490 OF_pack_get_path(OF_env, path, OF_NAMELEN_MAX, dsk);
3491 if (alias != NULL) {
3492 als = OF_node_get(OF_env, "aliases");
3493 if (als == NULL) {
3494 ERROR("Cannot get 'aliases'\n");
3495 return NULL;
3496 }
3497 strcpy(tmp, alias);
3498 if (OF_property_copy(OF_env, NULL, 0, als, tmp) >= 0) {
3499 pos = tmp + strlen(alias);
3500 for (i = 0; ; i++) {
3501 sprintf(pos, "%d", i);
3502 if (OF_property_copy(OF_env, NULL, 0, als, tmp) < 0)
3503 break;
3504 }
3505 }
3506 OF_DPRINTF("Set alias to %s\n", tmp);
3507 OF_prop_string_new(OF_env, dsk, "alias", tmp);
3508 OF_prop_string_new(OF_env, als, tmp, path);
3509 OF_node_put(OF_env, als);
3510 }
3511
3512 return dsk;
3513 }
3514
OF_blockdev_set_boot_device(void * disk,int partnum,const unsigned char * file)3515 void OF_blockdev_set_boot_device (void *disk, int partnum,
3516 const unsigned char *file)
3517 {
3518 unsigned char tmp[OF_NAMELEN_MAX], *pos;
3519 OF_env_t *OF_env;
3520 OF_node_t *dsk = disk, *opts, *chs;
3521
3522 OF_env = OF_env_main;
3523
3524 if (OF_property_copy(OF_env, tmp, OF_NAMELEN_MAX, dsk, "alias") < 0)
3525 OF_pack_get_path(OF_env, tmp, OF_NAMELEN_MAX, dsk);
3526 sprintf(tmp + strlen(tmp), ":%d", partnum);
3527 /* OpenDarwin 6.02 seems to need this one */
3528 opts = OF_node_get(OF_env, "options");
3529 if (opts == NULL) {
3530 ERROR("Cannot get 'options'\n");
3531 return;
3532 }
3533 OF_prop_string_set(OF_env, OF_node_root, "boot-device", tmp);
3534 OF_prop_string_set(OF_env, opts, "boot-device", tmp);
3535 OF_DPRINTF("Set boot device to: '%s'\n", tmp);
3536 OF_node_put(OF_env, opts);
3537 /* Set the real boot path */
3538 pos = tmp + strlen(tmp);
3539 sprintf(pos, ",%s", file);
3540 /* Convert all '/' into '\' in the boot file name */
3541 for (; *pos != '\0'; pos++) {
3542 if (*pos == '/')
3543 *pos = '\\';
3544 }
3545 chs = OF_node_get(OF_env, "chosen");
3546 if (chs == NULL) {
3547 ERROR("Cannot get 'chosen'\n");
3548 return;
3549 }
3550 OF_prop_string_set(OF_env, chs, "bootpath", tmp);
3551 OF_DPRINTF("Set boot path to: '%s'\n", tmp);
3552 OF_node_put(OF_env, chs);
3553 }
3554
3555 /* Display package */
OF_vga_draw_rectangle(OF_env_t * OF_env)3556 static void OF_vga_draw_rectangle (OF_env_t *OF_env)
3557 {
3558 const void *buf;
3559 const unsigned char *args;
3560 uint32_t posx, posy, width, height;
3561 uint32_t ihandle;
3562
3563 OF_CHECK_NBARGS(OF_env, 7);
3564 ihandle = popd(OF_env);
3565 args = (void *)popd(OF_env);
3566 height = popd(OF_env);
3567 width = popd(OF_env);
3568 posy = popd(OF_env);
3569 posx = popd(OF_env);
3570 buf = (const void *)popd(OF_env);
3571 OF_DPRINTF("x=%d y=%d h=%d ", posx, posy, width);
3572 OF_DPRINTF("w=%d buf=%p\n", height, buf);
3573 set_check(0);
3574 vga_draw_buf(buf, width * vga_fb_bpp, posx, posy, width, height);
3575 set_check(1);
3576 pushd(OF_env, 0);
3577 }
3578
OF_vga_fill_rectangle(OF_env_t * OF_env)3579 static void OF_vga_fill_rectangle (OF_env_t *OF_env)
3580 {
3581 const unsigned char *args;
3582 uint32_t color, posx, posy, width, height;
3583 uint32_t ihandle;
3584
3585 OF_CHECK_NBARGS(OF_env, 7);
3586 ihandle = popd(OF_env);
3587 args = (void *)popd(OF_env);
3588 height = popd(OF_env);
3589 width = popd(OF_env);
3590 posy = popd(OF_env);
3591 posx = popd(OF_env);
3592 color = popd(OF_env);
3593 OF_DPRINTF("x=%d y=%d\n", posx, posy);
3594 OF_DPRINTF("h=%d w=%d c=%0x\n", width, height, color);
3595 vga_fill_rect(posx, posy, width, height, color);
3596 pushd(OF_env, 0);
3597 }
3598
OF_vga_set_width(OF_env_t * OF_env,OF_prop_t * prop,const void * data,int len)3599 static void OF_vga_set_width (OF_env_t *OF_env, OF_prop_t *prop,
3600 const void *data, int len)
3601 {
3602 uint32_t width, height, depth;
3603
3604 if (len == sizeof(uint32_t)) {
3605 width = *(uint32_t *)data;
3606 OF_property_copy(OF_env, &height, 4, prop->node, "height");
3607 OF_property_copy(OF_env, &depth, 4, prop->node, "depth");
3608 vga_set_mode(width, height, depth);
3609 }
3610 }
3611
OF_vga_set_height(OF_env_t * OF_env,OF_prop_t * prop,const void * data,int len)3612 static void OF_vga_set_height (OF_env_t *OF_env, OF_prop_t *prop,
3613 const void *data, int len)
3614 {
3615 uint32_t width, height, depth;
3616
3617 if (len == sizeof(uint32_t)) {
3618 OF_property_copy(OF_env, &width, 4, prop->node, "width");
3619 height = *(uint32_t *)data;
3620 OF_property_copy(OF_env, &depth, 4, prop->node, "depth");
3621 vga_set_mode(width, height, depth);
3622 }
3623 }
3624
OF_vga_set_depth(OF_env_t * OF_env,OF_prop_t * prop,const void * data,int len)3625 static void OF_vga_set_depth (OF_env_t *OF_env, OF_prop_t *prop,
3626 const void *data, int len)
3627 {
3628 uint32_t width, height, depth;
3629
3630 if (len == sizeof(uint32_t)) {
3631 OF_property_copy(OF_env, &width, 4, prop->node, "width");
3632 OF_property_copy(OF_env, &height, 4, prop->node, "height");
3633 depth = *(uint32_t *)data;
3634 vga_set_mode(width, height, depth);
3635 }
3636 }
3637
OF_vga_register(const unsigned char * name,unused uint32_t address,int width,int height,int depth,unsigned long vga_bios_addr,unsigned long vga_bios_size)3638 void OF_vga_register (const unsigned char *name, unused uint32_t address,
3639 int width, int height, int depth,
3640 unsigned long vga_bios_addr, unsigned long vga_bios_size)
3641 {
3642 OF_env_t *OF_env;
3643 unsigned char tmp[OF_NAMELEN_MAX];
3644 OF_node_t *disp, *chs, *als;
3645 OF_prop_t *prop;
3646
3647 OF_DPRINTF("Set frame buffer %08x %dx%dx%d\n",
3648 address, width, height, depth);
3649 OF_env = OF_env_main;
3650 disp = OF_node_get(OF_env, name);
3651 if (disp == NULL) {
3652 ERROR("Cannot get display '%s'\n", name);
3653 return;
3654 }
3655 prop = OF_prop_int_new(OF_env, disp, "width", width);
3656 if (prop == NULL) {
3657 OF_node_put(OF_env, disp);
3658 ERROR("Cannot create display width property\n");
3659 return;
3660 }
3661 OF_property_set_cb(OF_env, prop, &OF_vga_set_width);
3662 prop = OF_prop_int_new(OF_env, disp, "height", height);
3663 if (prop == NULL) {
3664 OF_node_put(OF_env, disp);
3665 ERROR("Cannot create display height property\n");
3666 return;
3667 }
3668 OF_property_set_cb(OF_env, prop, &OF_vga_set_height);
3669 switch (depth) {
3670 case 8:
3671 break;
3672 case 15:
3673 depth = 16;
3674 break;
3675 case 32:
3676 break;
3677 default:
3678 /* OF spec this is mandatory, but we have no support for it */
3679 printf("%d bits VGA isn't implemented\n", depth);
3680 bug();
3681 /* Never come here */
3682 break;
3683 }
3684 prop = OF_prop_int_new(OF_env, disp, "depth", depth);
3685 if (prop == NULL) {
3686 ERROR("Cannot create display depth\n");
3687 goto out;
3688 }
3689 OF_property_set_cb(OF_env, prop, &OF_vga_set_depth);
3690 OF_prop_int_new(OF_env, disp, "linebytes", vga_fb_linesize);
3691 OF_method_new(OF_env, disp, "draw-rectangle", &OF_vga_draw_rectangle);
3692 OF_method_new(OF_env, disp, "fill-rectangle", &OF_vga_fill_rectangle);
3693 OF_method_new(OF_env, disp, "color!", &OF_method_fake);
3694 chs = OF_node_get(OF_env, "chosen");
3695 if (chs == NULL) {
3696 ERROR("Cannot get 'chosen'\n");
3697 goto out;
3698 }
3699 OF_prop_int_new(OF_env, chs, "display", OF_pack_handle(OF_env, disp));
3700 OF_node_put(OF_env, chs);
3701 OF_pack_get_path(OF_env, tmp, 512, disp);
3702 printf("Set display '%s' path to '%s'\n", name, tmp);
3703 als = OF_node_get(OF_env, "aliases");
3704 if (als == NULL) {
3705 ERROR("Cannot get 'aliases'\n");
3706 goto out;
3707 }
3708 OF_prop_string_new(OF_env, als, "screen", tmp);
3709 OF_prop_string_new(OF_env, als, "display", tmp);
3710 OF_node_put(OF_env, als);
3711 /* XXX: may also need read-rectangle */
3712
3713 if (vga_bios_size >= 8) {
3714 const uint8_t *p;
3715 int size;
3716 /* check the QEMU VGA BIOS header */
3717 p = (const uint8_t *)vga_bios_addr;
3718 if (p[0] == 'N' && p[1] == 'D' && p[2] == 'R' && p[3] == 'V') {
3719 size = *(uint32_t *)(p + 4);
3720 OF_property_new(OF_env, disp, "driver,AAPL,MacOS,PowerPC",
3721 p + 8, size);
3722 }
3723 }
3724 out:
3725 OF_node_put(OF_env, disp);
3726 }
3727
3728 /* Pseudo packages to make BootX happy */
3729 /* sl_words package */
slw_set_output_level(OF_env_t * OF_env)3730 static void slw_set_output_level (OF_env_t *OF_env)
3731 {
3732 OF_node_t *slw;
3733 const unsigned char *args;
3734 int level;
3735
3736 OF_CHECK_NBARGS(OF_env, 3);
3737 popd(OF_env);
3738 args = (void *)popd(OF_env);
3739 level = popd(OF_env);
3740 slw = OF_node_get(OF_env, "sl_words");
3741 if (slw == NULL) {
3742 pushd(OF_env, -1);
3743 } else {
3744 OF_DPRINTF("Set output level to: %d\n", level);
3745 OF_prop_int_set(OF_env, slw, "outputLevel", level);
3746 OF_node_put(OF_env, slw);
3747 pushd(OF_env, 0);
3748 }
3749 }
3750
3751 #ifdef DEBUG_BIOS
3752 #define EMIT_BUFFER_LEN 256
3753 static unsigned char emit_buffer[EMIT_BUFFER_LEN];
3754 static int emit_pos = 0;
3755 #endif
3756
slw_emit(OF_env_t * OF_env)3757 static void slw_emit (OF_env_t *OF_env)
3758 {
3759 const unsigned char *args;
3760 int c;
3761
3762 OF_CHECK_NBARGS(OF_env, 3);
3763 popd(OF_env);
3764 args = (void *)popd(OF_env);
3765 c = popd(OF_env);
3766 // OF_DPRINTF("Emit char %d\n", c);
3767 #ifdef DEBUG_BIOS
3768 if (emit_pos < EMIT_BUFFER_LEN - 1) {
3769 emit_buffer[emit_pos++] = c;
3770 // outb(0xFF00, c);
3771 outb(0x0F00, c);
3772 } else {
3773 emit_buffer[emit_pos] = '\0';
3774 }
3775 #else
3776 outb(0x0F00, c);
3777 #endif
3778 pushd(OF_env, 0);
3779 }
3780
slw_cr(OF_env_t * OF_env)3781 static void slw_cr (OF_env_t *OF_env)
3782 {
3783 const unsigned char *args;
3784
3785 OF_CHECK_NBARGS(OF_env, 2);
3786 popd(OF_env);
3787 args = (void *)popd(OF_env);
3788 // OF_DPRINTF("Emit CR char\n");
3789 // outb(0xFF01, '\n');
3790 outb(0x0F01, '\n');
3791 #ifdef DEBUG_BIOS
3792 emit_buffer[emit_pos] = '\0';
3793 if (strcmp(emit_buffer, "Call Kernel!") == 0) {
3794 /* Set qemu in debug mode:
3795 * log in_asm,op,int,ioport,cpu
3796 */
3797 uint16_t loglevel = 0x02 | 0x10 | 0x80;
3798 // outw(0xFF02, loglevel);
3799 outb(0x0F02, loglevel);
3800 }
3801 emit_pos = 0;
3802 #endif
3803 pushd(OF_env, 0);
3804 }
3805
slw_init_keymap(OF_env_t * OF_env)3806 static void slw_init_keymap (OF_env_t *OF_env)
3807 {
3808 const unsigned char *args;
3809 OF_node_t *node;
3810 OF_prop_t *prop;
3811 uint32_t phandle, ihandle;
3812
3813 OF_CHECK_NBARGS(OF_env, 3);
3814 ihandle = popd(OF_env);
3815 args = (void *)popd(OF_env);
3816 phandle = ihandle >> 16;
3817 ihandle &= 0xFFFF;
3818 OF_DPRINTF("\n");
3819 node = OF_pack_find(OF_env, phandle);
3820 if (node == NULL) {
3821 ERROR("Cant' init slw keymap\n");
3822 pushd(OF_env, -1);
3823 } else {
3824 prop = OF_property_get(OF_env, node, "keyMap");
3825 if (prop == NULL) {
3826 pushd(OF_env, -1);
3827 } else {
3828 pushd(OF_env, (uint32_t)prop->value);
3829 pushd(OF_env, 0);
3830 }
3831 }
3832 }
3833
slw_update_keymap(OF_env_t * OF_env)3834 static void slw_update_keymap (OF_env_t *OF_env)
3835 {
3836 const unsigned char *args;
3837
3838 OF_CHECK_NBARGS(OF_env, 2);
3839 popd(OF_env);
3840 args = (void *)popd(OF_env);
3841 OF_DPRINTF("\n");
3842 pushd(OF_env, 0);
3843 }
3844
slw_spin(OF_env_t * OF_env)3845 static void slw_spin (OF_env_t *OF_env)
3846 {
3847 const unsigned char *args;
3848 /* XXX: cur_spin should be in sl_words package */
3849 static int cur_spin = 0;
3850 int c;
3851
3852 OF_CHECK_NBARGS(OF_env, 2);
3853 popd(OF_env);
3854 args = (void *)popd(OF_env);
3855 if (cur_spin > 15) {
3856 c = RGB(0x30, 0x30, 0x50);
3857 } else {
3858 c = RGB(0x11, 0x11, 0x11);
3859 }
3860 c = vga_get_color(c);
3861 vga_fill_rect((cur_spin % 15) * 5 + 280, 420, 4, 3, c);
3862 cur_spin = (cur_spin + 1) & 31;
3863 OF_DPRINTF("\n");
3864 pushd(OF_env, -1);
3865 }
3866
slw_spin_init(OF_env_t * OF_env)3867 static void slw_spin_init (OF_env_t *OF_env)
3868 {
3869 const unsigned char *args;
3870
3871 OF_CHECK_NBARGS(OF_env, 8);
3872 popd(OF_env);
3873 args = (void *)popd(OF_env);
3874 popd(OF_env);
3875 popd(OF_env);
3876 popd(OF_env);
3877 popd(OF_env);
3878 popd(OF_env);
3879 popd(OF_env);
3880 pushd(OF_env, -1);
3881 }
3882
slw_pwd(OF_env_t * OF_env)3883 static void slw_pwd (OF_env_t *OF_env)
3884 {
3885 const unsigned char *args;
3886
3887 OF_CHECK_NBARGS(OF_env, 3);
3888 popd(OF_env);
3889 args = (void *)popd(OF_env);
3890 OF_DPRINTF("\n");
3891 pushd(OF_env, -1);
3892 }
3893
slw_sum(OF_env_t * OF_env)3894 static void slw_sum (OF_env_t *OF_env)
3895 {
3896 const unsigned char *args;
3897
3898 OF_CHECK_NBARGS(OF_env, 3);
3899 popd(OF_env);
3900 args = (void *)popd(OF_env);
3901 OF_DPRINTF("\n");
3902 pushd(OF_env, -1);
3903 }
3904
3905 /*****************************************************************************/
3906 /* Client program interface */
3907 /* Client interface services */
3908 static void OF_test (OF_env_t *OF_env);
3909
3910 /* Device tree services */
3911 /* Get next package */
3912 __attribute__ (( section (".OpenFirmware") ))
OF_peer(OF_env_t * OF_env)3913 static void OF_peer (OF_env_t *OF_env)
3914 {
3915 OF_node_t *node;
3916 uint32_t phandle;
3917
3918 OF_CHECK_NBARGS(OF_env, 1);
3919 phandle = popd(OF_env);
3920 OF_DPRINTF("phandle 0x%0x\n", phandle);
3921 if (phandle == 0)
3922 node = OF_node_root;
3923 else
3924 node = OF_pack_next(OF_env, phandle);
3925 if (node == NULL)
3926 pushd(OF_env, 0);
3927 else
3928 pushd(OF_env, OF_pack_handle(OF_env, node));
3929 }
3930
3931 /* Get first child package */
3932 __attribute__ (( section (".OpenFirmware") ))
OF_child(OF_env_t * OF_env)3933 static void OF_child (OF_env_t *OF_env)
3934 {
3935 OF_node_t *node;
3936 uint32_t phandle;
3937
3938 OF_CHECK_NBARGS(OF_env, 1);
3939 phandle = popd(OF_env);
3940 OF_DPRINTF("phandle 0x%0x\n", phandle);
3941 node = OF_pack_child(OF_env, phandle);
3942 if (node == NULL)
3943 pushd(OF_env, 0);
3944 else
3945 pushd(OF_env, OF_pack_handle(OF_env, node));
3946 }
3947
3948 /* Get parent package */
3949 __attribute__ (( section (".OpenFirmware") ))
OF_parent(OF_env_t * OF_env)3950 static void OF_parent (OF_env_t *OF_env)
3951 {
3952 OF_node_t *node;
3953 uint32_t phandle;
3954
3955 OF_CHECK_NBARGS(OF_env, 1);
3956 phandle = popd(OF_env);
3957 OF_DPRINTF("phandle 0x%0x\n", phandle);
3958 node = OF_pack_parent(OF_env, phandle);
3959 if (node == NULL)
3960 pushd(OF_env, 0);
3961 else
3962 pushd(OF_env, OF_pack_handle(OF_env, node));
3963 }
3964
3965 /* Get package related to an instance */
3966 __attribute__ (( section (".OpenFirmware") ))
OF_instance_to_package(OF_env_t * OF_env)3967 static void OF_instance_to_package (OF_env_t *OF_env)
3968 {
3969 uint32_t ihandle;
3970
3971 OF_CHECK_NBARGS(OF_env, 1);
3972 ihandle = popd(OF_env);
3973 OF_DPRINTF("ihandle 0x%0x\n", ihandle);
3974 pushd(OF_env, (ihandle >> 16) & 0xFFFF);
3975 }
3976
3977 /* Get property len */
3978 __attribute__ (( section (".OpenFirmware") ))
OF_getproplen(OF_env_t * OF_env)3979 static void OF_getproplen (OF_env_t *OF_env)
3980 {
3981 unsigned char name[OF_NAMELEN_MAX], *namep;
3982 OF_node_t *node;
3983 uint32_t phandle;
3984
3985 OF_CHECK_NBARGS(OF_env, 2);
3986 phandle = popd(OF_env);
3987 namep = (unsigned char *)popd(OF_env);
3988 OF_lds(name, namep);
3989 OF_DPRINTF("phandle 0x%0x prop [%s]\n", phandle, name);
3990 node = OF_pack_find(OF_env, phandle);
3991 if (node == NULL)
3992 pushd(OF_env, -1);
3993 else
3994 pushd(OF_env, OF_property_len(OF_env, node, name));
3995 }
3996
3997 /* Get property */
3998 __attribute__ (( section (".OpenFirmware") ))
OF_getprop(OF_env_t * OF_env)3999 static void OF_getprop (OF_env_t *OF_env)
4000 {
4001 unsigned char name[OF_NAMELEN_MAX], *namep;
4002 OF_node_t *node;
4003 void *buffer;
4004 uint32_t phandle;
4005 int len, nb_args;
4006
4007 // OF_CHECK_NBARGS(OF_env, 4);
4008 nb_args = stackd_depth(OF_env);
4009 phandle = popd(OF_env);
4010 namep = (unsigned char *)popd(OF_env);
4011 OF_lds(name, namep);
4012 buffer = (void *)popd(OF_env);
4013 if (nb_args == 3) {
4014 /* This hack is needed to boot MacOS X panther (10.3) */
4015 len = 1024;
4016 } else {
4017 len = popd(OF_env);
4018 }
4019 OF_DPRINTF("phandle 0x%0x prop [%s]\n", phandle, name);
4020 OF_DPRINTF("buffer %p len %d\n", buffer, len);
4021 node = OF_pack_find(OF_env, phandle);
4022 if (node == NULL) {
4023 len = -1;
4024 } else {
4025 len = OF_property_copy(OF_env, buffer, len, node, name);
4026 if (len != -1) {
4027 OF_DPRINTF("Copied %d bytes\n", len);
4028 }
4029 }
4030 pushd(OF_env, len);
4031 }
4032
4033 /* Check existence of next property */
4034 __attribute__ (( section (".OpenFirmware") ))
OF_nextprop(OF_env_t * OF_env)4035 static void OF_nextprop (OF_env_t *OF_env)
4036 {
4037 unsigned char name[OF_NAMELEN_MAX], *namep;
4038 OF_node_t *node;
4039 OF_prop_t *next;
4040 unsigned char *next_name;
4041 uint32_t phandle;
4042
4043 OF_CHECK_NBARGS(OF_env, 3);
4044 phandle = popd(OF_env);
4045 namep = (unsigned char *)popd(OF_env);
4046 OF_lds(name, namep);
4047 OF_DPRINTF("phandle 0x%0x prop [%s]\n", phandle, name);
4048 next_name = (unsigned char *)popd(OF_env);
4049 node = OF_pack_find(OF_env, phandle);
4050 if (node == NULL) {
4051 pushd(OF_env, -1);
4052 } else {
4053 next = OF_property_next(OF_env, node, name);
4054 if (next == NULL || next->name == NULL) {
4055 OF_DPRINTF("No next property found [%s]\n", name);
4056 pushd(OF_env, 0);
4057 } else {
4058 OF_DPRINTF("Return property name [%s]\n", next->name);
4059 OF_sts(next_name, (void *)(next->name));
4060 OF_DUMP_STRING(OF_env, next_name);
4061 pushd(OF_env, strlen(next->name) + 1);
4062 }
4063 }
4064 }
4065
4066 /* Set a property */
4067 __attribute__ (( section (".OpenFirmware") ))
OF_setprop(OF_env_t * OF_env)4068 static void OF_setprop (OF_env_t *OF_env)
4069 {
4070 unsigned char name[OF_NAMELEN_MAX], *namep;
4071 unsigned char *value, *buffer;
4072 OF_node_t *node;
4073 OF_prop_t *prop;
4074 uint32_t phandle;
4075 int len;
4076 int i;
4077
4078 OF_CHECK_NBARGS(OF_env, 4);
4079 phandle = popd(OF_env);
4080 namep = (unsigned char *)popd(OF_env);
4081 OF_lds(name, namep);
4082 OF_DPRINTF("phandle 0x%0x prop [%s]\n", phandle, name);
4083 buffer = (unsigned char *)popd(OF_env);
4084 len = popd(OF_env);
4085 node = OF_pack_find(OF_env, phandle);
4086 if (node == NULL) {
4087 pushd(OF_env, -1);
4088 ERROR("Cannot get pack %04x\n", phandle);
4089 return;
4090 }
4091 value = malloc(len);
4092 if (value == NULL && len != 0) {
4093 pushd(OF_env, -1);
4094 ERROR("%s: Cannot alloc property '%s' (%d)\n", __func__, name, len);
4095 return;
4096 }
4097 for (i = 0; i < len; i++)
4098 value[i] = buffer[i];
4099 prop = OF_property_set(OF_env, node, name, value, len);
4100 if (prop == NULL)
4101 len = -1;
4102 pushd(OF_env, len);
4103 }
4104
4105 /* "canon" */
4106
4107 /* Find a device given its path */
4108 __attribute__ (( section (".OpenFirmware") ))
OF_get_alias(OF_env_t * OF_env,const unsigned char * name)4109 static OF_node_t *OF_get_alias (OF_env_t *OF_env, const unsigned char *name)
4110 {
4111 unsigned char tmp[OF_NAMELEN_MAX], *pos, *st;
4112 const unsigned char *alias, *npos;
4113 OF_node_t *als, *node;
4114 OF_prop_t *prop;
4115
4116 node = NULL;
4117 strcpy(tmp, name);
4118 for (st = tmp; *st == '/'; st++)
4119 continue;
4120 pos = strchr(st, '/');
4121 if (pos == NULL) {
4122 pos = strchr(st, ':');
4123 }
4124 if (pos != NULL) {
4125 *pos = '\0';
4126 npos = name + (pos - tmp);
4127 } else {
4128 npos = "";
4129 }
4130 OF_DPRINTF("Look for alias for '%s' => '%s' '%s'\n", name, tmp, npos);
4131 als = OF_pack_find_by_name(OF_env, OF_node_root, "/aliases");
4132 if (als == NULL) {
4133 ERROR("Cannot get 'aliases'\n");
4134 return NULL;
4135 }
4136 prop = OF_property_get(OF_env, als, tmp);
4137 if (prop == NULL) {
4138 OF_DPRINTF("No %s alias !\n", tmp);
4139 goto out;
4140 }
4141 alias = prop->value;
4142 OF_DPRINTF("Found alias '%s' '%s'\n", alias, npos);
4143 sprintf(tmp, "%s%s", alias, npos);
4144 node = OF_pack_find_by_name(OF_env, OF_node_root, tmp);
4145 if (node == NULL) {
4146 printf("%s alias is a broken link !\n", name);
4147 goto out;
4148 }
4149 OF_node_put(OF_env, node);
4150 out:
4151 OF_node_put(OF_env, als);
4152
4153 return node;
4154 }
4155
4156 __attribute__ (( section (".OpenFirmware") ))
OF_finddevice(OF_env_t * OF_env)4157 static void OF_finddevice (OF_env_t *OF_env)
4158 {
4159 unsigned char name[OF_NAMELEN_MAX], *namep;
4160 OF_node_t *node;
4161 int ret;
4162
4163 OF_CHECK_NBARGS(OF_env, 1);
4164 namep = (unsigned char *)popd(OF_env);
4165 OF_lds(name, namep);
4166 OF_DPRINTF("name %p [%s]\n", namep, name);
4167 /* Search first in "/aliases" */
4168 node = OF_get_alias(OF_env, name);
4169 if (node == NULL) {
4170 node = OF_pack_find_by_name(OF_env, OF_node_root, name);
4171 }
4172 if (node == NULL)
4173 ret = -1;
4174 else
4175 ret = OF_pack_handle(OF_env, node);
4176 OF_DPRINTF("ret 0x%0x\n", ret);
4177 pushd(OF_env, ret);
4178 }
4179
4180 /* "instance-to-path */
4181 __attribute__ (( section (".OpenFirmware") ))
OF_instance_to_path(OF_env_t * OF_env)4182 static void OF_instance_to_path (OF_env_t *OF_env)
4183 {
4184 void *buffer;
4185 OF_inst_t *inst;
4186 uint32_t ihandle;
4187 int len;
4188
4189 OF_CHECK_NBARGS(OF_env, 3);
4190 OF_DPRINTF("\n");
4191 ihandle = popd(OF_env);
4192 buffer = (void *)popd(OF_env);
4193 len = popd(OF_env);
4194 OF_DPRINTF("ihandle: 0x%0x len=%d\n", ihandle, len);
4195 inst = OF_inst_find(OF_env, ihandle);
4196 if (inst == NULL)
4197 len = -1;
4198 else
4199 len = OF_inst_get_path(OF_env, buffer, len, inst) + 1;
4200 OF_DUMP_STRING(OF_env, buffer);
4201 pushd(OF_env, len);
4202 }
4203
4204 /* "package-to-path" */
4205 __attribute__ (( section (".OpenFirmware") ))
OF_package_to_path(OF_env_t * OF_env)4206 static void OF_package_to_path (OF_env_t *OF_env)
4207 {
4208 void *buffer;
4209 OF_node_t *node;
4210 uint32_t phandle;
4211 int len;
4212
4213 OF_CHECK_NBARGS(OF_env, 3);
4214 OF_DPRINTF("\n");
4215 phandle = popd(OF_env);
4216 buffer = (void *)popd(OF_env);
4217 len = popd(OF_env);
4218 node = OF_pack_find(OF_env, phandle);
4219 if (node == NULL)
4220 len = -1;
4221 else
4222 len = OF_pack_get_path(OF_env, buffer, len, node) + 1;
4223 OF_DUMP_STRING(OF_env, buffer);
4224 pushd(OF_env, len);
4225 }
4226
4227 /* Call a package's method */
4228 __attribute__ (( section (".OpenFirmware") ))
_OF_callmethod(OF_env_t * OF_env,const unsigned char * name,uint32_t ihandle,const unsigned char * argp)4229 static void _OF_callmethod (OF_env_t *OF_env, const unsigned char *name,
4230 uint32_t ihandle, const unsigned char *argp)
4231 {
4232 OF_node_t *node;
4233 OF_inst_t *inst;
4234 OF_method_t *method;
4235 OF_cb_t cb;
4236
4237 inst = OF_inst_find(OF_env, ihandle);
4238 OF_DPRINTF("Attempt to call method [%s] of package instance 0x%0x\n",
4239 name, ihandle);
4240 if (inst == NULL) {
4241 OF_DPRINTF("No instance %0x\n", ihandle);
4242 pushd(OF_env, -1);
4243 return;
4244 }
4245 node = inst->node;
4246 method = OF_method_get(OF_env, node, name);
4247 if (method != NULL) {
4248 cb = method->func;
4249 } else {
4250 if (strcmp(name, "open") == 0) {
4251 cb = &OF_method_fake;
4252 } else {
4253 printf("Method '%s' not found in '%s'\n",
4254 name, node->prop_name->value);
4255 pushd(OF_env, -1);
4256 bug();
4257 return;
4258 }
4259 }
4260 #if 0
4261 OF_DPRINTF("Push instance method %p (%p)...\n", &method->func,
4262 &slw_emit);
4263 #endif
4264 pushf(OF_env, &cb);
4265 if (argp != NULL)
4266 pushd(OF_env, (uint32_t)argp);
4267 else
4268 pushd(OF_env, 0x00000000);
4269 pushd(OF_env, ihandle);
4270 }
4271
4272 __attribute__ (( section (".OpenFirmware") ))
OF_get_args(unused OF_env_t * env,unsigned char * name)4273 static unsigned char *OF_get_args (unused OF_env_t *env, unsigned char *name)
4274 {
4275 unsigned char *sd;
4276
4277 sd = strchr(name, ':');
4278 if (sd == NULL)
4279 return NULL;
4280 *sd = '\0';
4281
4282 return sd + 1;
4283 }
4284
4285 __attribute__ (( section (".OpenFirmware") ))
OF_callmethod(OF_env_t * OF_env)4286 static void OF_callmethod (OF_env_t *OF_env)
4287 {
4288 const unsigned char *args;
4289 unsigned char name[OF_NAMELEN_MAX], *namep;
4290 uint32_t ihandle;
4291
4292 OF_DPRINTF("\n\n\n#### CALL METHOD ####\n\n");
4293 namep = (unsigned char *)popd(OF_env);
4294 OF_lds(name, namep);
4295 args = OF_get_args(OF_env, name);
4296 ihandle = popd(OF_env);
4297 _OF_callmethod(OF_env, name, ihandle, args);
4298 }
4299
4300 /* Device IO services */
4301 /* Create a new instance of a device's package */
4302 __attribute__ (( section (".OpenFirmware") ))
OF_open(OF_env_t * OF_env)4303 static void OF_open (OF_env_t *OF_env)
4304 {
4305 const unsigned char *args;
4306 unsigned char name[OF_NAMELEN_MAX], *namep;
4307 OF_node_t *node;
4308 OF_inst_t *inst;
4309 uint32_t ihandle;
4310
4311 OF_CHECK_NBARGS(OF_env, 1);
4312 namep = (unsigned char *)popd(OF_env);
4313 OF_lds(name, namep);
4314 OF_DPRINTF("package [%s]\n", name);
4315 args = OF_get_args(OF_env, name);
4316 node = OF_get_alias(OF_env, name);
4317 if (node == NULL) {
4318 node = OF_pack_find_by_name(OF_env, OF_node_root, name);
4319 }
4320 if (node == NULL) {
4321 OF_DPRINTF("package not found !\n");
4322 pushd(OF_env, -1);
4323 return;
4324 }
4325 inst = OF_instance_new(OF_env, node);
4326 if (inst == NULL) {
4327 pushd(OF_env, -1);
4328 ERROR("Cannot create package instance\n");
4329 return;
4330 }
4331 ihandle = OF_instance_get_id(OF_env, inst);
4332 /* If an "open" method exists in the package, call it */
4333 OF_DPRINTF("package [%s] => %0x\n", name, ihandle);
4334 OF_node_put(OF_env, node);
4335 _OF_callmethod(OF_env, "open", ihandle, args);
4336 }
4337
4338 /* De-instanciate a package */
4339 __attribute__ (( section (".OpenFirmware") ))
OF_close(OF_env_t * OF_env)4340 static void OF_close (OF_env_t *OF_env)
4341 {
4342 uint32_t ihandle;
4343
4344 OF_CHECK_NBARGS(OF_env, 1);
4345 ihandle = popd(OF_env);
4346 /* If an "close" method exists in the package, call it */
4347 _OF_callmethod(OF_env, "close", ihandle, NULL);
4348 /* XXX: Should free the instance */
4349 }
4350
4351 /* "read" */
4352 __attribute__ (( section (".OpenFirmware") ))
OF_read(OF_env_t * OF_env)4353 static void OF_read (OF_env_t *OF_env)
4354 {
4355 uint32_t ihandle;
4356
4357 OF_CHECK_NBARGS(OF_env, 3);
4358 ihandle = popd(OF_env);
4359 OF_DPRINTF("ih: %0x\n", ihandle);
4360 /* If a "read" method exists in the package, call it */
4361 _OF_callmethod(OF_env, "read", ihandle, NULL);
4362 }
4363
4364 /* Try call the "read" method of a device's package */
4365 /* "write" */
4366 __attribute__ (( section (".OpenFirmware") ))
OF_write(OF_env_t * OF_env)4367 static void OF_write (OF_env_t *OF_env)
4368 {
4369 uint32_t ihandle;
4370
4371 OF_CHECK_NBARGS(OF_env, 3);
4372 ihandle = popd(OF_env);
4373 // OF_DPRINTF("ih: %0x\n", ihandle);
4374 /* If a "write" method exists in the package, call it */
4375 _OF_callmethod(OF_env, "write", ihandle, NULL);
4376 }
4377
4378 /* "seek" */
4379 __attribute__ (( section (".OpenFirmware") ))
OF_seek(OF_env_t * OF_env)4380 static void OF_seek (OF_env_t *OF_env)
4381 {
4382 uint32_t ihandle;
4383
4384 OF_CHECK_NBARGS(OF_env, 3);
4385 ihandle = popd(OF_env);
4386 OF_DPRINTF("ih: %0x\n", ihandle);
4387 /* If a "seek" method exists in the package, call it */
4388 _OF_callmethod(OF_env, "seek", ihandle, NULL);
4389 }
4390
4391 /* Memory services */
4392 /* Claim some memory space */
4393 __attribute__ (( section (".OpenFirmware") ))
OF_claim_virt(uint32_t virt,uint32_t size,int * range)4394 uint32_t OF_claim_virt (uint32_t virt, uint32_t size, int *range)
4395 {
4396 int i, keep = -1;
4397
4398 OF_DPRINTF("Claim %d bytes at 0x%0x\n", size, virt);
4399 /* First check that the requested memory stands in the physical memory */
4400 if (OF_mem_ranges[0].start > virt ||
4401 (OF_mem_ranges[0].start + OF_mem_ranges[0].size) < (virt + size)) {
4402 ERROR("not in memory: start 0x%0x virt 0x%0x end 0x%0x 0x%0x\n",
4403 OF_mem_ranges[0].start, virt,
4404 OF_mem_ranges[0].start + OF_mem_ranges[0].size,
4405 virt + size);
4406 return (uint32_t)(-1);
4407 }
4408 /* Now check that it doesn't overlap with already claimed areas */
4409 for (i = 1; i < OF_MAX_MEMRANGES + 1; i++) {
4410 if (OF_mem_ranges[i].start == (uint32_t)(-1) ||
4411 OF_mem_ranges[i].size == (uint32_t)(-1)) {
4412 if (keep == -1)
4413 keep = i;
4414 continue;
4415 }
4416 if (OF_mem_ranges[i].start == virt &&
4417 (OF_mem_ranges[i].start + OF_mem_ranges[i].size) == (virt + size)) {
4418 return virt;
4419 }
4420 if (!((OF_mem_ranges[i].start >= (virt + size) ||
4421 (OF_mem_ranges[i].start + OF_mem_ranges[i].size) <= virt))) {
4422 ERROR("overlap: start 0x%0x virt 0x%0x end 0x%0x 0x%0x\n",
4423 OF_mem_ranges[i].start, virt,
4424 OF_mem_ranges[i].start + OF_mem_ranges[i].size,
4425 virt + size);
4426 /* Aie... */
4427 return (uint32_t)(-1);
4428 }
4429 }
4430 OF_DPRINTF("return range: %d\n", keep);
4431 if (keep == -1) {
4432 /* no more rooms */
4433 ERROR("No more rooms\n");
4434 return (uint32_t)(-1);
4435 } else {
4436 ERROR("Give range: start 0x%0x 0x%0x\n", virt, size);
4437 }
4438 if (range != NULL)
4439 *range = keep;
4440
4441 return virt;
4442 }
4443
4444 /* We always try to get the upper address we can */
4445 __attribute__ (( section (".OpenFirmware") ))
OF_claim_size(uint32_t size,int align,int * range)4446 static uint32_t OF_claim_size (uint32_t size, int align, int *range)
4447 {
4448 uint32_t addr, max = (uint32_t)(-1);
4449 int i;
4450
4451 OF_DPRINTF("Try map %d bytes at 0x00000000\n", size);
4452 if (OF_claim_virt(0, size, range) != (uint32_t)(-1))
4453 max = 0;
4454 for (i = 1; i < OF_MAX_MEMRANGES + 1; i++) {
4455 if (OF_mem_ranges[i].start == (uint32_t)(-1) ||
4456 OF_mem_ranges[i].size == (uint32_t)(-1))
4457 continue;
4458 addr = (OF_mem_ranges[i].start + OF_mem_ranges[i].size + align - 1) &
4459 ~(align - 1);
4460 OF_DPRINTF("Try map %d bytes at 0x%0x\n", size, addr);
4461 if ((addr + 1) > (max + 1)) {
4462 if (OF_claim_virt(addr, size, range) != (uint32_t)(-1))
4463 max = addr;
4464 }
4465 }
4466
4467 return max;
4468 }
4469
4470 __attribute__ (( section (".OpenFirmware") ))
OF_claim(OF_env_t * OF_env)4471 static void OF_claim (OF_env_t *OF_env)
4472 {
4473 uint32_t virt, size, addr;
4474 int align;
4475 int i, range;
4476
4477 OF_CHECK_NBARGS(OF_env, 3);
4478 virt = popd(OF_env);
4479 size = popd(OF_env);
4480 align = popd(OF_env);
4481 DPRINTF("virt 0x%0x size 0x%0x align %d\n", virt, size, align);
4482 if (align == 0) {
4483 addr = OF_claim_virt(virt, size, &range);
4484 } else {
4485 for (i = 1; i < align; i = i << 1)
4486 continue;
4487 align = i;
4488 size = (size + align - 1) & ~(align - 1);
4489 addr = OF_claim_size(size, align, &range);
4490 }
4491 if (addr == (uint32_t)-1) {
4492 ERROR("No range match !\n");
4493 pushd(OF_env, -1);
4494 }
4495 if (range != -1) {
4496 OF_mem_ranges[range].start = addr;
4497 OF_mem_ranges[range].size = size;
4498 }
4499 OF_DPRINTF("Give address 0x%0x\n", addr);
4500 pushd(OF_env, addr);
4501 }
4502
4503 /* release some previously claimed memory */
4504 __attribute__ (( section (".OpenFirmware") ))
OF_release(OF_env_t * OF_env)4505 static void OF_release (OF_env_t *OF_env)
4506 {
4507 uint32_t virt, size;
4508 int i;
4509
4510 OF_CHECK_NBARGS(OF_env, 2);
4511 virt = popd(OF_env);
4512 size = popd(OF_env);
4513 OF_DPRINTF("virt 0x%0x size 0x%0x\n", virt, size);
4514 for (i = 0; i < OF_MAX_MEMRANGES; i++) {
4515 if (OF_mem_ranges[i].start == virt && OF_mem_ranges[i].size == size) {
4516 OF_mem_ranges[i].start = (uint32_t)(-1);
4517 OF_mem_ranges[i].size = (uint32_t)(-1);
4518 break;
4519 }
4520 }
4521 }
4522
4523 /* Control transfer services */
4524 /* "boot" */
4525
4526 /* Enter Open-Firmware interpreter */
4527 __attribute__ (( section (".OpenFirmware") ))
OF_enter(OF_env_t * OF_env)4528 static void OF_enter (OF_env_t *OF_env)
4529 {
4530 int n_args;
4531
4532 n_args = stackd_depth(OF_env);
4533 /* means that the bootloader has ended.
4534 * So qemu will...
4535 */
4536 OF_DPRINTF("%d \n", n_args);
4537 // printf("Bootloader has quitted...\n");
4538 // abort();
4539 }
4540
4541 /* Exit client program */
4542 __attribute__ (( section (".OpenFirmware") ))
OF_exit(OF_env_t * OF_env)4543 static void OF_exit (OF_env_t *OF_env)
4544 {
4545 int n_args;
4546
4547 n_args = stackd_depth(OF_env);
4548 /* means that the bootloader has ended.
4549 * So qemu will...
4550 */
4551 OF_DPRINTF("%d \n", n_args);
4552 // printf("Bootloader has quitted...\n");
4553 // abort();
4554 }
4555
4556 /* "chain" */
4557
4558 /* User interface services */
4559 /* "interpret" */
4560
4561 __attribute__ (( section (".OpenFirmware") ))
OF_interpret(OF_env_t * OF_env)4562 static void OF_interpret (OF_env_t *OF_env)
4563 {
4564 const unsigned char *FString;
4565 void *buf;
4566 OF_inst_t *inst;
4567 OF_node_t *pks, *slw, *chs, *disp;
4568 uint32_t ihandle, crc;
4569
4570 OF_DPRINTF("\n");
4571 // OF_CHECK_NBARGS(OF_env, 1);
4572 FString = (const void *)popd(OF_env);
4573 crc = crc32(0, FString, strlen(FString));
4574 OF_DPRINTF("\n\nOF INTERPRETER CALL:\n [%s]\n crc=%0x\n", FString, crc);
4575 /* Do some hacks to make BootX happy */
4576 switch (crc) {
4577 case 0x225b6748: /* MacOS X 10.2 and OpenDarwin 1.41 */
4578 case 0xb1cd4d25: /* OpenDarwin 6.02 */
4579 /* Create "sl_words" package */
4580 popd(OF_env);
4581 /* Find "/packages" */
4582 pks = OF_pack_find_by_name(OF_env, OF_node_root, "/packages");
4583 if (pks == NULL) {
4584 OF_node_put(OF_env, pks);
4585 pushd(OF_env, -1);
4586 ERROR("Cannot get '/packages'\n");
4587 break;
4588 }
4589 slw = OF_node_new(OF_env, pks, "sl_words", OF_ADDRESS_NONE);
4590 if (slw == NULL) {
4591 OF_node_put(OF_env, pks);
4592 pushd(OF_env, -1);
4593 ERROR("Cannot create 'sl_words'\n");
4594 break;
4595 }
4596 /* Create methods */
4597 OF_method_new(OF_env, slw, "slw_set_output_level",
4598 &slw_set_output_level);
4599 OF_method_new(OF_env, slw, "slw_emit", &slw_emit);
4600 OF_method_new(OF_env, slw, "slw_cr", &slw_cr);
4601 OF_method_new(OF_env, slw, "slw_init_keymap", &slw_init_keymap);
4602 OF_method_new(OF_env, slw, "slw_update_keymap", &slw_update_keymap);
4603 OF_method_new(OF_env, slw, "slw_spin", &slw_spin);
4604 OF_method_new(OF_env, slw, "slw_spin_init", &slw_spin_init);
4605 OF_method_new(OF_env, slw, "slw_pwd", &slw_pwd);
4606 OF_method_new(OF_env, slw, "slw_sum", &slw_sum);
4607 /* Init properties */
4608 OF_prop_int_new(OF_env, slw, "outputLevel", 0);
4609 OF_prop_int_new(OF_env, slw, "keyboardIH", 0);
4610 {
4611 #if 0
4612 OF_node_t *kbd;
4613 kbd = OF_pack_find_by_name(OF_env, OF_node_root, "/keyboard");
4614 if (kbd == NULL) {
4615 OF_node_put(OF_env, pks);
4616 pushd(OF_env, -1);
4617 ERROR("Cannot get '/keyboard'\n");
4618 break;
4619 }
4620 buf = malloc(0x20);
4621 if (buf == NULL) {
4622 OF_node_put(OF_env, pks);
4623 pushd(OF_env, -1);
4624 ERROR("Cannot allocate keyboard buff\n");
4625 break;
4626 }
4627 #else
4628 buf = malloc(0x20);
4629 if (buf == NULL) {
4630 OF_node_put(OF_env, pks);
4631 pushd(OF_env, -1);
4632 ERROR("Cannot allocate keyboard buff\n");
4633 break;
4634 }
4635 memset(buf, 0, 0x20);
4636 OF_property_new(OF_env, slw, "keyMap", buf, 0x20);
4637 #endif
4638 }
4639 OF_prop_int_new(OF_env, slw, "screenIH", 0);
4640 OF_prop_int_new(OF_env, slw, "cursorAddr", 0);
4641 OF_prop_int_new(OF_env, slw, "cursorX", 0);
4642 OF_prop_int_new(OF_env, slw, "cursorY", 0);
4643 OF_prop_int_new(OF_env, slw, "cursorW", 0);
4644 OF_prop_int_new(OF_env, slw, "cursorH", 0);
4645 OF_prop_int_new(OF_env, slw, "cursorFrames", 0);
4646 OF_prop_int_new(OF_env, slw, "cursorPixelSize", 0);
4647 OF_prop_int_new(OF_env, slw, "cursorStage", 0);
4648 OF_prop_int_new(OF_env, slw, "cursorTime", 0);
4649 OF_prop_int_new(OF_env, slw, "cursorDelay", 0);
4650 /* Instanciate sl_words */
4651 inst = OF_instance_new(OF_env, slw);
4652 if (inst == NULL) {
4653 OF_node_put(OF_env, pks);
4654 pushd(OF_env, -1);
4655 ERROR("Cannot create sl_words instance\n");
4656 break;
4657 }
4658 ihandle = OF_instance_get_id(OF_env, inst);
4659 /* Release packages */
4660 OF_node_put(OF_env, slw);
4661 OF_node_put(OF_env, pks);
4662 OF_DPRINTF("sl_words instance: %0x\n", ihandle);
4663 /* Set return value */
4664 if (crc == 0xb1cd4d25) /* Hack for OpenDarwin 6.02 */
4665 pushd(OF_env, ihandle);
4666 pushd(OF_env, ihandle);
4667 pushd(OF_env, 0);
4668 break;
4669 case 0x233441d3: /* MacOS X 10.2 and OpenDarwin 1.41 */
4670 /* Create "memory-map" pseudo device */
4671 {
4672 OF_node_t *map;
4673 uint32_t phandle;
4674
4675 /* Find "/packages" */
4676 chs = OF_pack_find_by_name(OF_env, OF_node_root, "/chosen");
4677 if (chs == NULL) {
4678 pushd(OF_env, -1);
4679 ERROR("Cannot get '/chosen'\n");
4680 break;
4681 }
4682 map = OF_node_new(OF_env, chs, "memory-map", OF_ADDRESS_NONE);
4683 if (map == NULL) {
4684 pushd(OF_env, -1);
4685 ERROR("Cannot create 'memory-map'\n");
4686 break;
4687 }
4688 phandle = OF_pack_handle(OF_env, map);
4689 OF_node_put(OF_env, map);
4690 OF_node_put(OF_env, chs);
4691 pushd(OF_env, phandle);
4692 pushd(OF_env, 0);
4693 }
4694 break;
4695 case 0x32a2d18e: /* MacOS X 10.2 and OpenDarwin 6.02 */
4696 /* Return screen ihandle */
4697 disp = OF_get_alias(OF_env, "screen");
4698 if (disp == NULL) {
4699 pushd(OF_env, 0);
4700 pushd(OF_env, -1);
4701 ERROR("Cannot get 'screen' alias\n");
4702 break;
4703 }
4704 inst = OF_instance_new(OF_env, disp);
4705 if (inst == NULL) {
4706 OF_node_put(OF_env, disp);
4707 pushd(OF_env, 0);
4708 pushd(OF_env, -1);
4709 ERROR("Cannot create 'screen' instance\n");
4710 break;
4711 }
4712 ihandle = OF_instance_get_id(OF_env, inst);
4713 OF_node_put(OF_env, disp);
4714 OF_DPRINTF("Return screen ihandle: %0x\n", ihandle);
4715 pushd(OF_env, ihandle);
4716 pushd(OF_env, 0);
4717 break;
4718 case 0xF3A9841F: /* MacOS X 10.2 */
4719 case 0x76fbdf18: /* OpenDarwin 6.02 */
4720 /* Set current display as active package */
4721 disp = OF_get_alias (OF_env, "screen");
4722 if (disp == NULL) {
4723 pushd(OF_env, 0);
4724 pushd(OF_env, -1);
4725 }
4726 OF_node_put(OF_env, disp);
4727 break;
4728 case 0x1c3bc93f: /* MacOS X 10.3 */
4729 /* get-package-property if 0 0 then */
4730 OF_getprop(OF_env);
4731 {
4732 uint32_t len;
4733 len = popd(OF_env);
4734 if (len == (uint32_t)-1)
4735 len = 0;
4736 pushd(OF_env, len);
4737 }
4738 break;
4739 case 0x218d5ccb: /* yaboot */
4740 case 0x27b32255:
4741 case 0x05d332ef:
4742 case 0xc7b5d3b5:
4743 /* skip it */
4744 break;
4745 case 0xf541a878:
4746 case 0x6a9b2be6:
4747 /* Yaboot: set background color to black */
4748 break;
4749 case 0x846077fb:
4750 case 0x299c2c5d: /* gentoo */
4751 /* Yaboot: set foreground color to grey */
4752 break;
4753 case 0x4ad41f2d:
4754 /* Yaboot: wait 10 ms: sure ! */
4755 break;
4756
4757 default:
4758 /* ERROR */
4759 printf("Script: len=%d\n%s\n", (int)strlen(FString), FString);
4760 printf("Call %0x NOT IMPLEMENTED !\n", crc);
4761 bug();
4762 break;
4763 }
4764 OF_DPRINTF("\n\nOF INTERPRETER CALL DONE\n\n");
4765 }
4766
4767 /* "set-callback" */
4768 /* "set-symbol-lookup" */
4769
4770 /* Time services */
4771 /* "milliseconds" */
4772 __attribute__ (( section (".OpenFirmware") ))
OF_milliseconds(OF_env_t * OF_env)4773 static void OF_milliseconds (OF_env_t *OF_env)
4774 {
4775 #if 0
4776 struct timeval tv;
4777
4778 OF_DPRINTF("\n");
4779 OF_CHECK_NBARGS(OF_env, 0);
4780 gettimeofday(&tv, NULL);
4781 pushd(OF_env, (tv.tv_sec * 1000) + (tv.tv_usec / 1000));
4782 #else
4783 static uint32_t ms = 0;
4784
4785 OF_CHECK_NBARGS(OF_env, 0);
4786 pushd(OF_env, ms);
4787 usleep(10000); /* XXX: TOFIX: Random sleep */
4788 ms += 10;
4789 #endif
4790 }
4791
4792 /* Undocumented in IEEE 1275 */
4793 __attribute__ (( section (".OpenFirmware") ))
OF_quiesce(OF_env_t * OF_env)4794 static void OF_quiesce (OF_env_t *OF_env)
4795 {
4796 OF_CHECK_NBARGS(OF_env, 0);
4797 /* Should free all OF resources */
4798 bd_reset_all();
4799 #if defined (DEBUG_BIOS)
4800 {
4801 uint16_t loglevel = 0x02 | 0x10 | 0x80;
4802 // outw(0xFF02, loglevel);
4803 outb(0x0F02, loglevel);
4804 }
4805 #endif
4806 }
4807
4808 typedef struct OF_service_t OF_service_t;
4809 struct OF_service_t {
4810 const unsigned char *name;
4811 OF_cb_t cb;
4812 };
4813
4814 static OF_service_t services[] = {
4815 { "test", &OF_test, },
4816 { "peer", &OF_peer, },
4817 { "child", &OF_child, },
4818 { "parent", &OF_parent, },
4819 { "instance-to-package", &OF_instance_to_package, },
4820 { "getproplen", &OF_getproplen, },
4821 { "getprop", &OF_getprop, },
4822 { "nextprop", &OF_nextprop, },
4823 { "setprop", &OF_setprop, },
4824 { "finddevice", &OF_finddevice, },
4825 { "instance-to-path", &OF_instance_to_path, },
4826 { "package-to-path", &OF_package_to_path, },
4827 { "call-method", &OF_callmethod, },
4828 { "open", &OF_open, },
4829 { "open-package", &OF_open, },
4830 { "close", &OF_close, },
4831 { "read", &OF_read, },
4832 { "write", &OF_write, },
4833 { "seek", &OF_seek, },
4834 { "claim", &OF_claim, },
4835 { "release", &OF_release, },
4836 { "enter", &OF_enter, },
4837 { "exit", &OF_exit, },
4838 { "interpret", &OF_interpret, },
4839 { "milliseconds", &OF_milliseconds, },
4840 { "quiesce", &OF_quiesce, },
4841 };
4842
4843 /* Probe if a named service exists */
4844 __attribute__ (( section (".OpenFirmware") ))
OF_test(OF_env_t * OF_env)4845 static void OF_test (OF_env_t *OF_env)
4846 {
4847 unsigned char name[OF_NAMELEN_MAX], *namep;
4848 uint32_t i;
4849 int ret = -1;
4850
4851 OF_CHECK_NBARGS(OF_env, 1);
4852 namep = (unsigned char *)popd(OF_env);
4853 OF_lds(name, namep);
4854 OF_DPRINTF("service [%s]\n", name);
4855 for (i = 0; i < (sizeof(services) / sizeof(OF_service_t)); i++) {
4856 if (strcmp(services[i].name, name) == 0) {
4857 ret = 0;
4858 break;
4859 }
4860 }
4861 pushd(OF_env, ret);
4862 }
4863
4864 /* Main entry point for PPC clients */
4865 __attribute__ (( section (".OpenFirmware") ))
OF_client_entry(void * p)4866 int OF_client_entry (void *p)
4867 {
4868 unsigned char buffer[OF_NAMELEN_MAX];
4869 OF_env_t OF_env;
4870 OF_cb_t cb;
4871 unsigned char *namep;
4872 uint32_t i;
4873
4874 /* set our environment */
4875 MMU_off();
4876 OF_DPRINTF("Called with arg: %p\n", p);
4877 /* Load function name string */
4878 namep = (unsigned char *)(*(uint32_t *)p);
4879 OF_lds(buffer, namep);
4880 /* Find callback */
4881 cb = NULL;
4882 OF_DPRINTF("Look for service [%s]\n", buffer);
4883 for (i = 0; i < (sizeof(services) / sizeof(OF_service_t)); i++) {
4884 if (strcmp(services[i].name, buffer) == 0) {
4885 cb = services[i].cb;
4886 break;
4887 }
4888 }
4889 if (cb == NULL) {
4890 OF_DPRINTF("service [%s] not implemented\n", buffer);
4891 // bug();
4892 return -1;
4893 }
4894 #if 0
4895 OF_DPRINTF("Service [%s] found\n", buffer);
4896 #endif
4897 /* Set up stack *NON REENTRANT* */
4898 OF_env_init(&OF_env);
4899 /* Launch Forth glue */
4900 C_to_Forth(&OF_env, (uint32_t *)p + 1, &cb);
4901 OF_DPRINTF("done\n");
4902 MMU_on();
4903
4904 return 0;
4905 }
4906
4907 /*****************************************************************************/
4908 /* Run-time abstraction services */
4909 /* RTAS RAM is organised this way:
4910 * RTAS_memory is given by the OS when instanciating RTAS.
4911 * it's an 32 kB area divided in 2 zones:
4912 * Up is a stack, used to call RTAS services
4913 * Down is the variables area.
4914 */
4915
4916 __attribute__ (( section (".RTAS_vars") ))
4917 static OF_cb_t *RTAS_callbacks[32];
4918 #if 0
4919 __attribute__ (( section (".RTAS_vars") ))
4920 static uint8_t *RTAS_base;
4921 #endif
4922
4923 /* RTAS is called in real mode (ie no MMU), privileged with all exceptions
4924 * disabled. It has to preserve all registers except R3 to R12.
4925 * The OS should ensure it's not re-entered.
4926 */
4927 __attribute__ (( section (".RTAS") ))
RTAS_entry(void * p)4928 int RTAS_entry (void *p)
4929 {
4930 OF_env_t RTAS_env;
4931 uint32_t token;
4932
4933 OF_DPRINTF("Called with arg: %p\n", p);
4934 /* set our environment */
4935 token = *(uint32_t *)p;
4936 /* Set up stack */
4937 RTAS_env.stackb = (uint32_t *)(RTAS_memory + 0x8000 - 4);
4938 RTAS_env.stackp = RTAS_env.stackb;
4939 RTAS_env.funcb = (uint32_t *)(RTAS_memory + 0x8000 - OF_STACK_SIZE - 4);
4940 RTAS_env.funcp = RTAS_env.funcb;
4941 /* Call Forth glue */
4942 C_to_Forth(&RTAS_env, (uint32_t *)p + 1, RTAS_callbacks[token & 0x3F]);
4943 OF_DPRINTF("done\n");
4944
4945 return 0;
4946 }
4947
4948 __attribute__ (( section (".RTAS") ))
RTAS_restart_rtas(OF_env_t * RTAS_env)4949 static void RTAS_restart_rtas (OF_env_t *RTAS_env)
4950 {
4951 OF_DPRINTF("\n");
4952 OF_CHECK_NBARGS(RTAS_env, 0);
4953 /* No implementation: return error */
4954 pushd(RTAS_env, -1);
4955 }
4956
4957 __attribute__ (( section (".RTAS") ))
RTAS_nvram_fetch(OF_env_t * RTAS_env)4958 static void RTAS_nvram_fetch (OF_env_t *RTAS_env)
4959 {
4960 uint8_t *buffer;
4961 int offset, length;
4962 int i;
4963
4964 OF_DPRINTF("\n");
4965 OF_CHECK_NBARGS(RTAS_env, 3);
4966 offset = popd(RTAS_env);
4967 buffer = (uint8_t *)popd(RTAS_env);
4968 length = popd(RTAS_env);
4969 for (i = 0; i < length; i++) {
4970 if ((i + offset) >= NVRAM_get_size(nvram)) {
4971 pushd(RTAS_env, -3);
4972 return;
4973 }
4974 *buffer++ = NVRAM_read(nvram, i + offset);
4975 }
4976 pushd(RTAS_env, length);
4977 }
4978
4979 __attribute__ (( section (".RTAS") ))
RTAS_nvram_store(OF_env_t * RTAS_env)4980 static void RTAS_nvram_store (OF_env_t *RTAS_env)
4981 {
4982 uint8_t *buffer;
4983 int offset, length;
4984 int i;
4985
4986 OF_DPRINTF("\n");
4987 OF_CHECK_NBARGS(RTAS_env, 3);
4988 offset = popd(RTAS_env);
4989 buffer = (uint8_t *)popd(RTAS_env);
4990 length = popd(RTAS_env);
4991 for (i = 0; i < length; i++) {
4992 if ((i + offset) >= NVRAM_get_size(nvram)) {
4993 pushd(RTAS_env, -3);
4994 return;
4995 }
4996 NVRAM_write(nvram, i + offset, *buffer++);
4997 }
4998 pushd(RTAS_env, length);
4999 }
5000
5001 __attribute__ (( section (".RTAS") ))
RTAS_get_time_of_day(OF_env_t * RTAS_env)5002 static void RTAS_get_time_of_day (OF_env_t *RTAS_env)
5003 {
5004 #if 0
5005 struct tm tm;
5006 time_t t;
5007
5008 OF_DPRINTF("\n");
5009 OF_CHECK_NBARGS(RTAS_env, 0);
5010 t = get_time();
5011 localtime_r(&t, &tm);
5012 pushd(RTAS_env, 0); /* nanoseconds */
5013 pushd(RTAS_env, tm.tm_sec);
5014 pushd(RTAS_env, tm.tm_min);
5015 pushd(RTAS_env, tm.tm_hour);
5016 pushd(RTAS_env, tm.tm_mday);
5017 pushd(RTAS_env, tm.tm_mon);
5018 pushd(RTAS_env, tm.tm_year);
5019 pushd(RTAS_env, 0); /* status */
5020 #else
5021 pushd(RTAS_env, 0);
5022 pushd(RTAS_env, 0);
5023 pushd(RTAS_env, 0);
5024 pushd(RTAS_env, 0);
5025 pushd(RTAS_env, 0);
5026 pushd(RTAS_env, 0);
5027 pushd(RTAS_env, 0);
5028 pushd(RTAS_env, 0);
5029 #endif
5030 }
5031
5032 __attribute__ (( section (".RTAS") ))
RTAS_set_time_of_day(OF_env_t * RTAS_env)5033 static void RTAS_set_time_of_day (OF_env_t *RTAS_env)
5034 {
5035 #if 0
5036 struct tm tm;
5037 time_t t;
5038
5039 OF_DPRINTF("\n");
5040 OF_CHECK_NBARGS(RTAS_env, 7);
5041 tm.tm_year = popd(RTAS_env);
5042 tm.tm_mon = popd(RTAS_env);
5043 tm.tm_mday = popd(RTAS_env);
5044 tm.tm_hour = popd(RTAS_env);
5045 tm.tm_min = popd(RTAS_env);
5046 tm.tm_sec = popd(RTAS_env);
5047 popd(RTAS_env); /* nanoseconds */
5048 t = mktime(&tm);
5049 set_time_offset(t);
5050 #endif
5051 pushd(RTAS_env, 0); /* status */
5052 }
5053
5054 __attribute__ (( section (".RTAS") ))
RTAS_set_time_for_power_on(OF_env_t * RTAS_env)5055 static void RTAS_set_time_for_power_on (OF_env_t *RTAS_env)
5056 {
5057 OF_DPRINTF("\n");
5058 OF_CHECK_NBARGS(RTAS_env, 7);
5059 /* Do nothing */
5060 pushd(RTAS_env, 0); /* status */
5061 }
5062
5063 __attribute__ (( section (".RTAS") ))
RTAS_event_scan(OF_env_t * RTAS_env)5064 static void RTAS_event_scan (OF_env_t *RTAS_env)
5065 {
5066 OF_DPRINTF("\n");
5067 OF_CHECK_NBARGS(RTAS_env, 4);
5068 /* Pretend there are no new events */
5069 pushd(RTAS_env, 1);
5070 }
5071
5072 __attribute__ (( section (".RTAS") ))
RTAS_check_exception(OF_env_t * RTAS_env)5073 static void RTAS_check_exception (OF_env_t *RTAS_env)
5074 {
5075 OF_DPRINTF("\n");
5076 OF_CHECK_NBARGS(RTAS_env, 6);
5077 /* Pretend we found no exceptions */
5078 pushd(RTAS_env, 1);
5079 }
5080
5081 __attribute__ (( section (".RTAS") ))
RTAS_read_pci_config(OF_env_t * RTAS_env)5082 static void RTAS_read_pci_config (OF_env_t *RTAS_env)
5083 {
5084 OF_DPRINTF("\n");
5085 OF_CHECK_NBARGS(RTAS_env, 2);
5086 /* Hardware error */
5087 pushd(RTAS_env, -1);
5088 }
5089
5090 __attribute__ (( section (".RTAS") ))
RTAS_write_pci_config(OF_env_t * RTAS_env)5091 static void RTAS_write_pci_config (OF_env_t *RTAS_env)
5092 {
5093 OF_DPRINTF("\n");
5094 OF_CHECK_NBARGS(RTAS_env, 3);
5095 /* Hardware error */
5096 pushd(RTAS_env, -1);
5097 }
5098
5099 __attribute__ (( section (".RTAS") ))
RTAS_display_character(OF_env_t * RTAS_env)5100 static void RTAS_display_character (OF_env_t *RTAS_env)
5101 {
5102 int c;
5103
5104 OF_DPRINTF("\n");
5105 OF_CHECK_NBARGS(RTAS_env, 1);
5106 c = popd(RTAS_env);
5107 #if 0
5108 printf("%c", c);
5109 #else
5110 outb(0x0F00, c);
5111 #endif
5112 pushd(RTAS_env, 0);
5113 }
5114
5115 __attribute__ (( section (".RTAS") ))
RTAS_set_indicator(OF_env_t * RTAS_env)5116 static void RTAS_set_indicator (OF_env_t *RTAS_env)
5117 {
5118 const unsigned char *name;
5119 int indic, state;
5120
5121 OF_DPRINTF("\n");
5122 OF_CHECK_NBARGS(RTAS_env, 3);
5123 indic = popd(RTAS_env);
5124 state = popd(RTAS_env);
5125 switch (indic) {
5126 case 1:
5127 name = "tone frequency";
5128 break;
5129 case 2:
5130 name = "tone volume";
5131 break;
5132 case 3:
5133 name = "system power state";
5134 break;
5135 case 4:
5136 name = "warning light";
5137 break;
5138 case 5:
5139 name = "disk activity light";
5140 break;
5141 case 6:
5142 name = "hexadecimal display unit";
5143 break;
5144 case 7:
5145 name = "batery warning time";
5146 break;
5147 case 8:
5148 name = "condition cycle request";
5149 break;
5150 case 9000 ... 9999:
5151 name = "vendor specific";
5152 break;
5153 default:
5154 pushd(RTAS_env, -3);
5155 return;
5156 }
5157 OF_DPRINTF("Set indicator %d [%s] to %d\n", indic, name, state);
5158 pushd(RTAS_env, 0);
5159 }
5160
5161 __attribute__ (( section (".RTAS") ))
RTAS_get_sensor_state(OF_env_t * RTAS_env)5162 static void RTAS_get_sensor_state (OF_env_t *RTAS_env)
5163 {
5164 const unsigned char *name;
5165 int type, index;
5166 int state;
5167
5168 OF_DPRINTF("\n");
5169 OF_CHECK_NBARGS(RTAS_env, 2);
5170 type = popd(RTAS_env);
5171 index = popd(RTAS_env);
5172 switch (index) {
5173 case 1:
5174 name = "key switch";
5175 state = 1; /* Normal */
5176 break;
5177 case 2:
5178 name = "enclosure switch";
5179 state = 0; /* Closed */
5180 break;
5181 case 3:
5182 name = "thermal sensor";
5183 state = 40; /* in degrees Celsius (not too hot !) */
5184 break;
5185 case 4:
5186 name = "lid status";
5187 state = 1; /* Open */
5188 break;
5189 case 5:
5190 name = "power source";
5191 state = 0; /* AC */
5192 break;
5193 case 6:
5194 name = "battery voltage";
5195 state = 6; /* Let's have a moderated answer :-) */
5196 break;
5197 case 7:
5198 name = "battery capacity remaining";
5199 state = 3; /* High */
5200 break;
5201 case 8:
5202 name = "battery capacity percentage";
5203 state = 1000; /* 100 % */
5204 break;
5205 case 9:
5206 name = "EPOW sensor";
5207 state = 5; /* ? */
5208 break;
5209 case 10:
5210 name = "battery condition cycle state";
5211 state = 0; /* none */
5212 break;
5213 case 11:
5214 name = "battery charge state";
5215 state = 2; /* No current flow */
5216 break;
5217 case 9000 ... 9999:
5218 name = "vendor specific";
5219 state = 0;
5220 break;
5221 default:
5222 pushd(RTAS_env, -3);
5223 return;
5224 }
5225 OF_DPRINTF("Pretend sensor %d [%s] is in state %d\n", index, name, state);
5226 pushd(RTAS_env, state);
5227 pushd(RTAS_env, 0);
5228 }
5229
5230 #if 0 // No power management */
5231 __attribute__ (( section (".RTAS") ))
5232 static void RTAS_set_power_level (OF_env_t *RTAS_env)
5233 {
5234 OF_DPRINTF("\n");
5235 }
5236
5237 __attribute__ (( section (".RTAS") ))
5238 static void RTAS_get_power_level (OF_env_t *RTAS_env)
5239 {
5240 OF_DPRINTF("\n");
5241 }
5242
5243 __attribute__ (( section (".RTAS") ))
5244 static void RTAS_assume_power_management (OF_env_t *RTAS_env)
5245 {
5246 OF_DPRINTF("\n");
5247 }
5248
5249 __attribute__ (( section (".RTAS") ))
5250 static void RTAS_relinquish_power_management (OF_env_t *RTAS_env)
5251 {
5252 OF_DPRINTF("\n");
5253 }
5254 #endif
5255
5256 __attribute__ (( section (".RTAS") ))
RTAS_power_off(OF_env_t * RTAS_env)5257 static void RTAS_power_off (OF_env_t *RTAS_env)
5258 {
5259 printf("RTAS was asked to switch off\n");
5260 OF_CHECK_NBARGS(RTAS_env, 2);
5261 // abort();
5262 }
5263
5264 __attribute__ (( section (".RTAS") ))
RTAS_suspend(OF_env_t * RTAS_env)5265 static void RTAS_suspend (OF_env_t *RTAS_env)
5266 {
5267 OF_DPRINTF("\n");
5268 OF_CHECK_NBARGS(RTAS_env, 3);
5269 /* Pretend we don't succeed */
5270 pushd(RTAS_env, -1);
5271 }
5272
5273 __attribute__ (( section (".RTAS") ))
RTAS_hibernate(OF_env_t * RTAS_env)5274 static void RTAS_hibernate (OF_env_t *RTAS_env)
5275 {
5276 OF_DPRINTF("\n");
5277 OF_CHECK_NBARGS(RTAS_env, 3);
5278 /* Pretend we don't succeed */
5279 pushd(RTAS_env, -1);
5280 }
5281
5282 __attribute__ (( section (".RTAS") ))
RTAS_system_reboot(OF_env_t * RTAS_env)5283 static void RTAS_system_reboot (OF_env_t *RTAS_env)
5284 {
5285 printf("RTAS was asked to reboot\n");
5286 OF_CHECK_NBARGS(RTAS_env, 0);
5287 // abort();
5288 }
5289
5290 #if 0 // No power management nor SMP */
5291 __attribute__ (( section (".RTAS") ))
5292 static void RTAS_cache_control (OF_env_t *RTAS_env)
5293 {
5294 OF_DPRINTF("\n");
5295 }
5296
5297 __attribute__ (( section (".RTAS") ))
5298 static void RTAS_freeze_time_base (OF_env_t *RTAS_env)
5299 {
5300 OF_DPRINTF("\n");
5301 }
5302
5303 __attribute__ (( section (".RTAS") ))
5304 static void RTAS_thaw_time_base (OF_env_t *RTAS_env)
5305 {
5306 OF_DPRINTF("\n");
5307 }
5308
5309 __attribute__ (( section (".RTAS") ))
5310 static void RTAS_stop_self (OF_env_t *RTAS_env)
5311 {
5312 OF_DPRINTF("\n");
5313 }
5314
5315 __attribute__ (( section (".RTAS") ))
5316 static void RTAS_start_cpu (OF_env_t *RTAS_env)
5317 {
5318 OF_DPRINTF("\n");
5319 }
5320 #endif
5321
5322 __attribute__ (( section (".RTAS") ))
RTAS_instantiate(OF_env_t * RTAS_env)5323 static void RTAS_instantiate (OF_env_t *RTAS_env)
5324 {
5325 const unsigned char *args;
5326 uint32_t ihandle;
5327 uint32_t base_address;
5328
5329 OF_DPRINTF("\n");
5330 OF_CHECK_NBARGS(RTAS_env, 3);
5331 ihandle = popd(RTAS_env);
5332 args = (void *)popd(RTAS_env);
5333 base_address = popd(RTAS_env);
5334 memmove((void *)base_address, (void *)(&_RTAS_start),
5335 (char *)(&_RTAS_data_end) - (char *)(&_RTAS_start));
5336 OF_DPRINTF("base_address=0x%0x\n", base_address);
5337 pushd(RTAS_env, base_address);
5338 pushd(RTAS_env, 0);
5339 }
5340
5341 __attribute__ (( section (".RTAS") ))
RTAS_new_cb(OF_env_t * env,OF_node_t * rtas,const unsigned char * name,OF_cb_t cb,uint32_t * token_next)5342 static void RTAS_new_cb (OF_env_t *env, OF_node_t *rtas,
5343 const unsigned char *name,
5344 OF_cb_t cb, uint32_t *token_next)
5345 {
5346 OF_prop_int_new(env, rtas, name, 0xabcd0000 | *token_next);
5347 RTAS_callbacks[*token_next] = &cb;
5348 (*token_next)++;
5349 }
5350
5351 __attribute__ (( section (".RTAS") ))
RTAS_init(void)5352 void RTAS_init (void)
5353 {
5354 OF_env_t *RTAS_env;
5355 OF_node_t *rtas, *chs;
5356 OF_prop_t *stdout;
5357 uint32_t token_next = 0, size;
5358
5359 RTAS_env = OF_env_main;
5360 rtas = OF_node_new(RTAS_env, OF_node_root, "rtas", OF_ADDRESS_NONE);
5361 if (rtas == NULL) {
5362 ERROR("RTAS not found\n");
5363 return;
5364 }
5365 size = ((char *)(&_RTAS_data_end) - (char *)(&_RTAS_start) + 0x0000FFFF) &
5366 ~0x0000FFFF;
5367 OF_DPRINTF("RTAS size: %d bytes (%d)\n", size,
5368 (char *)(&_RTAS_data_end) - (char *)(&_RTAS_start));
5369 OF_prop_int_new(RTAS_env, rtas, "rtas-size", size);
5370 OF_prop_int_new(RTAS_env, rtas, "rtas-version", 1);
5371 OF_prop_int_new(RTAS_env, rtas, "rtas-event-scan-rate", 0);
5372 OF_prop_int_new(RTAS_env, rtas, "rtas-error-log-max", 0);
5373 chs = OF_node_get(RTAS_env, "chosen");
5374 if (chs == NULL) {
5375 ERROR("choosen not found\n");
5376 return;
5377 }
5378 stdout = OF_property_get(RTAS_env, chs, "stdout");
5379 if (stdout == NULL) {
5380 OF_node_put(RTAS_env, chs);
5381 ERROR("stdout not found\n");
5382 return;
5383 }
5384 OF_prop_int_new(RTAS_env, rtas, "rtas-display-device",
5385 *(uint32_t *)stdout->value);
5386 /* RTAS tokens */
5387 RTAS_new_cb(RTAS_env, rtas, "restart_rtas",
5388 &RTAS_restart_rtas, &token_next);
5389 RTAS_new_cb(RTAS_env, rtas, "nvram_fetch",
5390 &RTAS_nvram_fetch, &token_next);
5391 RTAS_new_cb(RTAS_env, rtas, "nvram_store",
5392 &RTAS_nvram_store, &token_next);
5393 RTAS_new_cb(RTAS_env, rtas, "get-time-of_day",
5394 &RTAS_get_time_of_day, &token_next);
5395 RTAS_new_cb(RTAS_env, rtas, "set-time-of-day",
5396 &RTAS_set_time_of_day, &token_next);
5397 RTAS_new_cb(RTAS_env, rtas, "set-time-for-power-on",
5398 &RTAS_set_time_for_power_on, &token_next);
5399 RTAS_new_cb(RTAS_env, rtas, "event-scan", &RTAS_event_scan, &token_next);
5400 RTAS_new_cb(RTAS_env, rtas, "check-exception",
5401 &RTAS_check_exception, &token_next);
5402 RTAS_new_cb(RTAS_env, rtas, "read-pci-config",
5403 &RTAS_read_pci_config, &token_next);
5404 RTAS_new_cb(RTAS_env, rtas, "write-pci-config",
5405 &RTAS_write_pci_config, &token_next);
5406 RTAS_new_cb(RTAS_env, rtas, "display-character",
5407 &RTAS_display_character, &token_next);
5408 RTAS_new_cb(RTAS_env, rtas, "set-indicator",
5409 &RTAS_set_indicator, &token_next);
5410 RTAS_new_cb(RTAS_env, rtas, "get-sensor-state",
5411 &RTAS_get_sensor_state, &token_next);
5412 #if 0 // No power management */
5413 RTAS_new_cb(RTAS_env, rtas, "set-power-level",
5414 &RTAS_set_power_level, &token_next);
5415 RTAS_new_cb(RTAS_env, rtas, "get-power-level",
5416 &RTAS_get_power_level, &token_next);
5417 RTAS_new_cb(RTAS_env, rtas, "assume-power-management",
5418 &RTAS_assume_power_management, &token_next);
5419 RTAS_new_cb(RTAS_env, rtas, "relinquish-power-management",
5420 &RTAS_relinquish_power_management, &token_next);
5421 #endif
5422 RTAS_new_cb(RTAS_env, rtas, "power-off", &RTAS_power_off, &token_next);
5423 RTAS_new_cb(RTAS_env, rtas, "suspend", &RTAS_suspend, &token_next);
5424 RTAS_new_cb(RTAS_env, rtas, "hibernate", &RTAS_hibernate, &token_next);
5425 RTAS_new_cb(RTAS_env, rtas, "system-reboot",
5426 &RTAS_system_reboot, &token_next);
5427 #if 0 // No power management nor SMP */
5428 RTAS_new_cb(RTAS_env, rtas, "cache-control",
5429 &RTAS_cache_control, &token_next);
5430 RTAS_new_cb(RTAS_env, rtas, "freeze_time_base",
5431 &RTAS_freeze_time_base, &token_next);
5432 RTAS_new_cb(RTAS_env, rtas, "thaw_time_base",
5433 &RTAS_thaw_time_base, &token_next);
5434 RTAS_new_cb(RTAS_env, rtas, "stop-self", &RTAS_stop_self, &token_next);
5435 RTAS_new_cb(RTAS_env, rtas, "start-cpu", &RTAS_start_cpu, &token_next);
5436 #endif
5437 /* missing
5438 * "update-flash"
5439 * "update-flash-and-reboot"
5440 * "query-cpu-stopped-state" for SMP
5441 */
5442 OF_method_new(RTAS_env, rtas, "instantiate-rtas", &RTAS_instantiate);
5443 OF_node_put(RTAS_env, rtas);
5444 OF_node_new(RTAS_env, OF_node_root, "nomore", OF_ADDRESS_NONE);
5445 DPRINTF("RTAS done\n");
5446 }
5447
5448 /*****************************************************************************/
5449 /* That's all for now... */
5450 /*****************************************************************************/
5451