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", &regs, 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", &regs, 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", &regs, 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", &regs, 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                         &regs, 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                         &regs, 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", &regs, 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