1 /* Open firmware emulation.
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...
10 * Copyright (c) 2003-2005 Jocelyn Mayer
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
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.
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
32 #if defined (DEBUG_OF)
33 #define OF_DPRINTF(fmt, args...) \
34 do { dprintf("%s: " fmt, __func__ , ##args); } while (0)
36 #define OF_DPRINTF(fmt, args...) \
43 typedef struct OF_transl_t OF_transl_t;
51 typedef struct OF_env_t 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 */
59 typedef struct OF_bustyp_t OF_bustyp_t;
65 typedef struct pci_address_t pci_address_t;
66 struct pci_address_t {
72 typedef struct pci_reg_prop_t pci_reg_prop_t;
73 struct pci_reg_prop_t {
79 typedef struct pci_range_t pci_range_t;
87 /*****************************************************************************/
88 __attribute__ (( section (".OpenFirmware") ))
89 static void OF_lds (uint8_t *dst, const void *address)
94 for (p = address; *p != '\0'; p++) {
98 OF_DPRINTF("Loaded string %s\n", dst);
101 __attribute__ (( section (".OpenFirmware") ))
102 static void OF_sts (void *address, const uint8_t *src)
105 uint8_t *p = address;
107 OF_DPRINTF("Store string %s\n", src);
108 for (_s = src; *_s != '\0'; _s++) {
114 #define OF_DUMP_STRING(env, buffer) \
116 unsigned char tmp[OF_NAMELEN_MAX]; \
117 OF_lds(tmp, buffer); \
118 OF_DPRINTF("[%s]\n", tmp); \
121 /*****************************************************************************/
122 /* Forth like environmnent */
123 #define OF_CHECK_NBARGS(env, nb) \
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)); \
131 popd_all((env), nb_args); \
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];
144 typedef void (*OF_cb_t)(OF_env_t *OF_env);
146 static inline void _push (uint32_t **stackp, uint32_t data)
148 // OF_DPRINTF("%p 0x%0x\n", *stackp, data);
153 static inline uint32_t _pop (uint32_t **stackp)
156 // OF_DPRINTF("%p 0x%0x\n", *stackp, **stackp);
160 static inline void _pop_all (uint32_t **stackp, int nb)
164 for (i = 0; i < nb; i++)
168 static inline int _stack_depth (uint32_t *stackp, uint32_t *basep)
170 return basep - stackp;
173 static inline void pushd (OF_env_t *OF_env, uint32_t data)
175 _push(&OF_env->stackp, data);
178 static inline uint32_t popd (OF_env_t *OF_env)
180 return _pop(&OF_env->stackp);
183 static inline void popd_all (OF_env_t *OF_env, int nb)
185 _pop_all(&OF_env->stackp, nb);
188 static inline int stackd_depth (OF_env_t *OF_env)
190 return _stack_depth(OF_env->stackp, OF_env->stackb);
193 static inline void pushf (OF_env_t *OF_env, OF_cb_t *func)
195 _push(&OF_env->funcp, (uint32_t)func);
198 static inline OF_cb_t *popf (OF_env_t *OF_env)
200 return (OF_cb_t *)_pop(&OF_env->funcp);
203 static inline void popf_all (OF_env_t *OF_env, int nb)
205 _pop_all(&OF_env->funcp, nb);
208 static inline int stackf_depth (OF_env_t *OF_env)
210 return _stack_depth(OF_env->funcp, OF_env->funcb);
213 static inline void OF_env_init (OF_env_t *OF_env)
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;
222 __attribute__ (( section (".OpenFirmware") ))
223 static void C_to_Forth (OF_env_t *env, void *p, OF_cb_t *cb)
227 uint32_t i, n_args, n_rets, tmp;
229 // OF_DPRINTF("enter\n");
230 /* Fill argument structure */
236 // OF_DPRINTF("n_args=%d n_rets=%d\n", n_args, n_rets);
238 for (i = 0; i < n_args; i++)
241 while (stackf_depth(env) != 0) {
242 // OF_DPRINTF("func stack: %p %p\n", env->funcb, env->funcp);
244 // OF_DPRINTF("Next func: %p %d\n", cb, stackf_depth(env));
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++) {
251 // OF_DPRINTF("Store 0x%0x (%d)\n", tmp, tmp);
254 for (; i < n_rets; i++)
256 OF_CHECK_NBARGS(env, 0);
257 // OF_DPRINTF("done\n");
260 /*****************************************************************************/
261 /* Memory pool (will be needed when it'll become native) */
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];
270 __attribute__ (( section (".OpenFirmware") ))
271 static uint32_t *OF_int_alloc (unused OF_env_t *env)
276 for (i = 0; i < OF_INTBITS_LEN; i++) {
277 tmp = OF_int_bits[i];
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];
288 printf("ALERT: unable to \"allocate\" new integer\n");
293 __attribute__ (( section (".OpenFirmware") ))
294 static void OF_int_free (unused OF_env_t *env,
299 i = area - OF_int_pool;
302 OF_int_bits[i] &= ~(1 << j);
305 __attribute__ (( section (".OpenFirmware") ))
306 static void OF_free (unused OF_env_t *env, void *area)
310 /* Check if it's in our int pool */
312 if (check >= OF_int_pool && check < (OF_int_pool + OF_INTPOOL_LEN)) {
313 OF_int_free(env, check);
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;
330 #define OF_ADDRESS_NONE ((uint32_t)(-1))
336 /* Link to next node at the same level */
338 /* Link to children, if any */
339 OF_node_t *children, *child_last;
342 /* The following ones belong to the package */
350 OF_prop_t *properties, *prop_last, *prop_name, *prop_address;
352 OF_method_t *methods, *method_last;
358 OF_inst_t *instances, *inst_last;
363 /* Link to next property */
365 /* The node it belongs to */
368 const unsigned char *name;
369 /* property value len */
371 /* property value buffer */
373 /* Property change callback */
374 void (*cb)(OF_env_t *OF_env, OF_prop_t *prop, const void *data, int len);
379 OF_METHOD_INTERNAL = 0,
384 /* Link to next method */
386 /* The package it belongs to */
390 /* Method function pointer */
394 /* Package instance */
396 /* Link to next instance of the same package */
398 /* Link to the parent instance */
400 /* The package it belongs to */
402 /* Instance identifier */
409 typedef struct OF_regprop_t OF_regprop_t;
410 struct OF_regprop_t {
416 typedef struct OF_range_t OF_range_t;
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;
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);
447 __attribute__ (( section (".OpenFirmware_vars") ))
448 static uint8_t *RTAS_memory;
450 /*****************************************************************************/
451 /* Node management */
452 /* Insert a new node */
453 __attribute__ (( section (".OpenFirmware") ))
454 static uint16_t OF_pack_new_id (unused OF_env_t *env, OF_node_t *node)
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))
461 if (OF_packages[cur_id] == NULL) {
462 OF_packages[cur_id] = node;
463 OF_pack_last_id = cur_id;
468 return (uint16_t)(-1);
471 static OF_node_t *OF_node_create (OF_env_t *env, OF_node_t *parent,
472 const unsigned char *name, uint32_t address)
476 OF_DPRINTF("New node: %s\n", name);
477 new = malloc(sizeof(OF_node_t));
479 ERROR("%s can't alloc new node '%s'\n", __func__, name);
482 memset(new, 0, sizeof(OF_node_t));
483 new->parent = parent;
486 new->prop_name = OF_prop_string_new(env, new, "name", name);
487 if (new->prop_name == NULL) {
489 ERROR("%s can't alloc new node '%s' name\n", __func__, name);
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);
497 ERROR("%s can't alloc new node '%s' address\n", __func__, name);
500 /* Link it in parent tree */
501 if (parent != NULL) {
503 if (parent->children == NULL) {
504 parent->children = new;
506 parent->child_last->next = new;
508 parent->child_last = new;
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);
514 // OF_DPRINTF("New node: %s get id\n", name);
519 __attribute__ (( section (".OpenFirmware") ))
520 static OF_node_t *OF_node_new (OF_env_t *env, OF_node_t *parent,
521 const unsigned char *name, uint32_t address)
525 new = OF_node_create(env, parent, name, address);
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;
535 static inline OF_node_t *OF_node_parent (unused OF_env_t *env, OF_node_t *node)
540 /* Look for a node, given its name */
541 __attribute__ (( section (".OpenFirmware") ))
542 static OF_node_t *OF_node_get_child (OF_env_t *env, OF_node_t *parent,
543 const unsigned char *name,
546 unsigned char tname[OF_NAMELEN_MAX];
547 OF_node_t *parse, *tmp;
548 OF_prop_t *prop_name, *prop_address;
552 if (parent == OF_node_root) {
553 OF_DPRINTF("Look for node [%s]\n", name);
556 memcpy(tname, name, len + 1);
557 for (i = len; i > 0; i--) {
558 if (tname[i - 1] == ',') {
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)
570 addr_valp = (void *)prop_address->value;
572 OF_DPRINTF("node [%s] <=> [%s]\n", prop_name->value, tname);
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)) {
582 OF_DPRINTF("look in children [%s]\n", prop_name->value);
584 tmp = OF_node_get_child(env, parse, tname, address);
588 OF_DPRINTF("didn't find in children [%s]\n", prop_name->value);
591 if (parent == OF_node_root) {
592 OF_DPRINTF("node [%s] not found\n", name);
598 __attribute__ (( section (".OpenFirmware") ))
599 static OF_node_t *OF_node_get (OF_env_t *env, const unsigned char *name)
601 unsigned char tname[OF_NAMELEN_MAX];
602 unsigned char *addrp;
605 if (strcmp(name, "device_tree") == 0)
609 addrp = strchr(tname, '@');
611 address = OF_ADDRESS_NONE;
614 address = strtol(addrp, NULL, 16);
618 return OF_node_get_child(env, OF_node_root, name, address);
622 __attribute__ (( section (".OpenFirmware") ))
623 static void OF_node_put (unused OF_env_t *env, OF_node_t *node)
625 if (--node->refcount < 0)
629 /*****************************************************************************/
630 /* Packages tree walk */
631 __attribute__ (( section (".OpenFirmware") ))
632 static uint16_t OF_pack_handle (unused OF_env_t *env, OF_node_t *node)
637 return node->pack_id;
640 __attribute__ (( section (".OpenFirmware") ))
641 static OF_node_t *OF_pack_find_by_name (OF_env_t *env, OF_node_t *base,
642 const unsigned char *name)
644 unsigned char tmp[OF_NAMELEN_MAX], *addrp;
645 const unsigned char *sl, *st;
647 OF_prop_t *prop_name, *prop_address;
648 uint32_t address, *addr_valp;
651 OF_DPRINTF("Path [%s] in '%s'\n", name, base->prop_name->value);
657 /* Should never happen */
658 OF_DPRINTF("Done\n");
661 sl = strchr(st, '/');
667 memcpy(tmp, st, len);
669 addrp = strchr(tmp, '@');
671 address = OF_ADDRESS_NONE;
675 address = strtol(addrp, NULL, 16);
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)
684 addr_valp = (void *)prop_address->value;
686 OF_DPRINTF("Check [%s]\n", prop_name->value);
688 if (prop_name == NULL) {
689 printf("ERROR: missing address in node, parent: '%s'\n",
690 base->prop_name->value);
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;
699 OF_DPRINTF("Done\n");
702 OF_DPRINTF("Recurse: '%s'\n", sl + 1);
703 return OF_pack_find_by_name(env, parse, sl + 1);
706 OF_DPRINTF("Didn't found [%s]\n", tmp);
711 __attribute__ (( section (".OpenFirmware") ))
712 static OF_node_t *OF_pack_find (unused OF_env_t *env, uint16_t phandle)
714 if (phandle > OF_MAX_PACKAGE)
716 if (OF_packages[phandle] == NULL) {
717 OF_DPRINTF("No package %0x\n", phandle);
719 OF_DPRINTF("return package: %0x %p [%s]\n", phandle,
720 OF_packages[phandle],
721 OF_packages[phandle]->prop_name->value);
724 return OF_packages[phandle];
727 __attribute__ (( section (".OpenFirmware") ))
728 static OF_node_t *OF_pack_next (OF_env_t *env, uint16_t phandle)
732 for (node = OF_pack_find(env, phandle); node != NULL; node = node->next) {
733 if (OF_pack_handle(env, node) != phandle)
737 OF_DPRINTF("found node %p [%s]\n", node, node->prop_name->value);
743 __attribute__ (( section (".OpenFirmware") ))
744 static OF_node_t *OF_pack_child (OF_env_t *env, uint16_t phandle)
748 node = OF_pack_find(env, phandle);
750 ERROR("%s didn't find pack %04x\n", __func__, phandle);
753 node = node->children;
755 OF_DPRINTF("found node %p [%s]\n", node, node->prop_name->value);
761 __attribute__ (( section (".OpenFirmware") ))
762 static OF_node_t *OF_pack_parent (OF_env_t *env, uint16_t phandle)
766 node = OF_pack_find(env, phandle);
768 ERROR("%s didn't find pack %04x\n", __func__, phandle);
771 node = OF_node_parent(env, node);
773 OF_DPRINTF("found node %p [%s]\n", node, node->prop_name->value);
779 /*****************************************************************************/
780 /* Package properties management */
781 /* Insert a new property */
782 __attribute__ (( section (".OpenFirmware") ))
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)
792 _prop = OF_property_get(env, node, name);
794 printf("Property '%s' already present !\n", name);
799 /* Allocate a new property */
800 prop = malloc(sizeof(OF_prop_t));
802 ERROR("%s cannot allocate property '%s'\n", __func__, name);
805 memset(prop, 0, sizeof(OF_prop_t));
806 prop->name = strdup(name);
807 if (prop->name == NULL) {
809 ERROR("%s cannot allocate property '%s' name\n", __func__, name);
813 if (data != NULL && len > 0) {
814 prop->value = malloc(len);
815 if (prop->value == NULL) {
817 ERROR("%s cannot allocate property '%s' value\n", __func__, name);
821 memcpy(prop->value, data, len);
823 OF_DPRINTF("New property [%s] '%s'\n\t%p %p %d %p\n", name, prop->name, prop->name, data, len, prop->value);
826 if (node->properties == NULL)
827 node->properties = prop;
829 node->prop_last->next = prop;
830 node->prop_last = prop;
835 /* Find a property given its name */
836 __attribute__ (( section (".OpenFirmware") ))
837 static OF_prop_t *OF_property_get (unused OF_env_t *env, OF_node_t *node,
838 const unsigned char *name)
843 OF_DPRINTF("Look for property [%s] in 0x%0x '%s'\n", name,
844 node->pack_id, node->prop_name->value);
849 for (prop = node->properties; prop != NULL; prop = prop->next) {
851 OF_DPRINTF("property [%s] <=> [%s]\n", prop->name, name);
853 if (strcmp(prop->name, name) == 0) {
858 OF_DPRINTF("property [%s] not found in 0x%08x '%s'\n", name,
859 node->pack_id, node->prop_name->value);
865 /* Change a property */
866 __attribute__ (( section (".OpenFirmware") ))
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)
876 prop = OF_property_get(env, node, name);
878 OF_DPRINTF("change property [%s]\n", name);
880 if (tmp == NULL && len != 0) {
881 ERROR("%s cannot set property '%s'\n", __func__, name);
887 memcpy(prop->value, data, len);
888 if (prop->cb != NULL) {
889 (*prop->cb)(env, prop, data, len);
892 OF_DPRINTF("new property [%s]\n", name);
893 prop = OF_property_new(env, node, name, data, len);
899 __attribute__ (( section (".OpenFirmware") ))
900 static int OF_property_len (OF_env_t *env, OF_node_t *node,
901 const unsigned char *name)
905 prop = OF_property_get(env, node, name);
912 __attribute__ (( section (".OpenFirmware") ))
913 static unsigned char *hex2buf (unsigned char *buf, uint32_t value, int fill)
922 for (; value != 0; pos--) {
931 for (; pos != -1; pos--) {
939 __attribute__ (( section (".OpenFirmware") ))
940 static int OF_property_copy (OF_env_t *env, void *buffer, int maxlen,
941 OF_node_t *node, const unsigned char *name)
943 unsigned char tmp[OF_PROPLEN_MAX];
947 prop = OF_property_get(env, node, name);
949 ERROR("%s cannot get property '%s' for %s\n", __func__, name,
950 node->prop_name->value);
953 len = prop->vlen > maxlen ? maxlen : prop->vlen;
954 if (prop->value != NULL) {
957 hex2buf(tmp + 2, *((uint32_t *)prop->value), 1);
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);
966 memcpy(buffer, prop->value, len);
967 // OF_DPRINTF("done\n");
972 __attribute__ (( section (".OpenFirmware") ))
973 static OF_prop_t *OF_property_next (OF_env_t *env, OF_node_t *node,
974 const unsigned char *name)
976 OF_prop_t *prop, *next;
978 if (name == NULL || *name == '\0') {
979 next = node->properties;
981 prop = OF_property_get(env, node, name);
983 OF_DPRINTF("Property [%s] not found\n", name);
987 /* Skip address if not set */
988 if (next == node->prop_address &&
989 *((uint32_t *)next->value) == OF_ADDRESS_NONE)
994 OF_DPRINTF("Found property %p\n", next);
1000 /* Simplified helpers */
1001 __attribute__ (( section (".OpenFirmware") ))
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)
1009 prop = OF_property_get(env, node, name);
1011 printf("Property '%s' already present !\n", name);
1016 return OF_property_new(env, node, name,
1017 string, strlen(string) + 1);
1020 /* convert '\1' char to '\0' */
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)
1029 if (strchr(string, '\1') == NULL) {
1030 return OF_prop_string_new(env, node, name, string);
1032 len = strlen(string) + 1;
1036 memcpy(str, string, len);
1037 for(i = 0; i < len; i++)
1040 ret = OF_property_new(env, node, name,
1047 __attribute__ (( section (".OpenFirmware") ))
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)
1054 prop = OF_property_get(env, node, name);
1056 printf("Property '%s' already present !\n", name);
1061 return OF_property_new(env, node, name, &value, sizeof(uint32_t));
1064 __attribute__ (( section (".OpenFirmware") ))
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)
1069 const unsigned char *tmp;
1071 tmp = strdup(string);
1073 ERROR("%s cannot duplicate property '%s'\n", __func__, name);
1077 return OF_property_set(env, node, name, tmp, strlen(string) + 1);
1080 __attribute__ (( section (".OpenFirmware") ))
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)
1084 return OF_property_set(env, node, name, &value, sizeof(uint32_t));
1087 __attribute__ (( section (".OpenFirmware") ))
1089 static OF_prop_t *OF_set_compatibility (OF_env_t *env, OF_node_t *node,
1090 const unsigned char *compat)
1092 return OF_prop_string_new(env, node, "compatible", compat);
1095 __attribute__ (( section (".OpenFirmware") ))
1096 static inline void OF_property_set_cb (unused OF_env_t *OF_env,
1098 void (*cb)(OF_env_t *OF_env,
1100 const void *data, int len))
1105 /*****************************************************************************/
1106 /* Packages methods management */
1107 __attribute__ (( section (".OpenFirmware") ))
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)
1113 new = malloc(sizeof(OF_method_t));
1115 ERROR("%s cannot allocate method '%s'\n", __func__, name);
1118 memset(new, 0, sizeof(OF_method_t));
1120 new->name = strdup(name);
1121 if (new->name == NULL) {
1123 ERROR("%s cannot allocate method '%s' name\n", __func__, name);
1126 OF_DPRINTF("new method name %p %s\n", new, new->name);
1130 if (node->method_last == NULL)
1131 node->methods = new;
1133 node->method_last->next = new;
1134 node->method_last = new;
1139 __attribute__ (( section (".OpenFirmware") ))
1140 static OF_method_t *OF_method_get (unused OF_env_t *env, OF_node_t *node,
1141 const unsigned char *name)
1146 OF_DPRINTF("No method in NULL package !\n");
1150 OF_DPRINTF("Look for method %s in package %0x\n",
1151 name, node->pack_id);
1153 for (parse = node->methods; parse != NULL; parse = parse->next) {
1155 OF_DPRINTF("check %p %p\n", parse, parse->name);
1156 OF_DPRINTF("name=%s\n", parse->name);
1158 if (strcmp(parse->name, name) == 0)
1165 /*****************************************************************************/
1166 /* Packages instances management */
1167 __attribute__ (( section (".OpenFirmware") ))
1168 static uint16_t OF_inst_new_id (unused OF_env_t *env, OF_node_t *node)
1170 OF_inst_t *tmp_inst;
1174 OF_DPRINTF("[%s] %d\n", node->prop_name->value,
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))
1181 for (tmp_inst = node->instances; tmp_inst != NULL;
1182 tmp_inst = tmp_inst->next) {
1183 if (tmp_inst->inst_id == cur_id)
1186 inst_last_id = cur_id;
1188 OF_DPRINTF("0x%0x\n", cur_id);
1192 OF_DPRINTF("no ID found\n");
1194 return (uint16_t)(-1);
1197 /* Create a new package's instance */
1198 __attribute__ (( section (".OpenFirmware") ))
1199 static OF_inst_t *OF_instance_new (OF_env_t *env, OF_node_t *node)
1201 OF_inst_t *new, *parent;
1204 /* TODO: recurse to root... */
1205 new = malloc(sizeof(OF_inst_t));
1207 ERROR("%s cannot allocate instance of '%s'\n", __func__,
1208 node->prop_name->value);
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) {
1216 ERROR("%s cannot allocate instance of '%s' parent\n", __func__,
1217 node->prop_name->value);
1220 new->parent = parent;
1224 new_id = OF_inst_new_id(env, node);
1225 if (new_id == (uint16_t)(-1)) {
1229 new->inst_id = new_id;
1233 if (node->inst_last == NULL)
1234 node->instances = new;
1236 node->inst_last->next = new;
1237 node->inst_last = new;
1242 __attribute__ (( section (".OpenFirmware") ))
1243 static uint32_t OF_instance_get_id (unused OF_env_t *env, OF_inst_t *instance)
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;
1249 __attribute__ (( section (".OpenFirmware") ))
1250 static OF_inst_t *OF_inst_find (OF_env_t *env, uint32_t ihandle)
1254 uint16_t phandle = ihandle >> 16;
1257 OF_DPRINTF("p: %0x i: %0x\n", phandle, ihandle);
1258 if (ihandle > OF_MAX_PACKAGE)
1260 node = OF_pack_find(env, phandle);
1263 for (parse = node->instances; parse != NULL; parse = parse->next) {
1264 if (parse->inst_id == ihandle)
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)
1276 OF_node_t *parse, *tmp;
1278 for (parse = parent->children; parse != NULL; parse = parse->next) {
1279 if (parse->pack_id == (handle >> 16)) {
1282 tmp = OF_inst_get_child(env, parse, handle);
1290 __attribute__ (( section (".OpenFirmware") ))
1291 static OF_inst_t *OF_inst_get (OF_env_t *env, const unsigned char *name)
1293 return _OF_node_get(env, &OF_node_root);
1299 __attribute__ (( section (".OpenFirmware") ))
1300 int get_node_name (OF_env_t *env, unsigned char *name,
1301 int len, OF_node_t *node)
1306 /* Set up manufacturer name */
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)
1315 memcpy(name, node->manufct, tmp);
1317 } else if (len < 2) {
1324 /* Set up device model */
1325 tmp = strlen(node->name);
1326 if ((tmp + 2) > len)
1328 memcpy(name, node->model, tmp);
1333 /* Set up unit address */
1334 tmp = strlen(node->address);
1335 if ((tmp + 2) > len)
1337 memcpy(name, node->address, tmp);
1342 for (i = 0; node->arguments[i] != NULL; i++) {
1345 tmp = strlen(node->arguments[i]);
1346 if ((tmp + 2) > len)
1348 memcpy(name, node->arguments[i], tmp);
1359 __attribute__ (( section (".OpenFirmware") ))
1360 static int OF_pack_get_path (OF_env_t *env, unsigned char *name,
1361 int len, OF_node_t *node)
1363 OF_prop_t *prop_name, *prop_address;
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) {
1374 tmp = OF_pack_get_path(env, name, len, OF_node_parent(env, node));
1376 prop_name = node->prop_name;
1377 prop_address = node->prop_address;
1379 OF_DPRINTF("Found [%s]\n", prop_name->value);
1381 if ((len - tmp) < 2) {
1382 OF_DPRINTF("Buffer too short (%d 2)\n", len - tmp);
1385 if (prop_name == NULL) {
1386 printf("No name in node !\n");
1389 nlen = strlen(prop_name->value);
1391 OF_DPRINTF("got '%s' for '%s' parent (%d %d)\n",
1392 name, prop_name->value, tmp, nlen);
1394 if (name[tmp - 1] != '/') {
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);
1405 if ((len - tmp - nlen) < 1) {
1406 OF_DPRINTF("Buffer too short (%d %d)\n", len - tmp, nlen + 1);
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);
1416 OF_DPRINTF("No address....\n");
1419 name[tmp + nlen] = '\0';
1420 OF_DPRINTF("stored [%d]\n", tmp + nlen);
1421 OF_DUMP_STRING(env, name);
1423 OF_DPRINTF("name '%s' => '%s' %d\n",
1424 node->properties->value, name, tmp + nlen);
1430 __attribute__ (( section (".OpenFirmware") ))
1431 static int OF_inst_get_path (OF_env_t *env, unsigned char *name,
1432 int len, OF_inst_t *inst)
1434 return OF_pack_get_path(env, name, len, inst->node);
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);
1445 static OF_env_t *OF_env_main;
1447 /* Init standard OF structures */
1448 __attribute__ (( section (".OpenFirmware") ))
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";
1459 OF_node_t *als, *opt, *chs, *pks;
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__);
1469 // memset(OF_env_main, 0, sizeof(OF_env_t));
1470 OF_env = OF_env_main;
1471 // OF_env_init(OF_env);
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");
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");
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");
1498 OF_prop_string_new(OF_env, OF_node_root, "copyright", copyright);
1500 OF_prop_string_new(OF_env, OF_node_root, "copyright",
1501 "Copyright 1983-1999 Apple Computer, Inc. All Rights Reserved");
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);
1510 ERROR("Cannot create 'aliases'\n");
1513 /* "/chosen" node */
1514 chs = OF_node_new(OF_env, OF_node_root, "chosen", OF_ADDRESS_NONE);
1516 ERROR("Cannot create 'choosen'\n");
1519 /* "/packages" node */
1520 pks = OF_node_new(OF_env, OF_node_root, "packages", OF_ADDRESS_NONE);
1522 ERROR("Cannot create 'packages'\n");
1528 cpus = OF_node_new(OF_env, OF_node_root, "cpus", OF_ADDRESS_NONE);
1530 ERROR("Cannot create 'cpus'\n");
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);
1537 /* "/memory@0" node */
1540 mem = OF_node_new(OF_env, OF_node_root, "memory", 0);
1542 ERROR("Cannot create 'memory'\n");
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);
1549 /* "/openprom" node */
1552 opp = OF_node_new(OF_env, OF_node_root, "openprom", OF_ADDRESS_NONE);
1554 ERROR("Cannot create 'openprom'\n");
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);
1566 /* "/options" node */
1567 opt = OF_node_new(OF_env, OF_node_root, "options", OF_ADDRESS_NONE);
1569 ERROR("Cannot create 'options'\n");
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 */
1579 OF_node_t *rom, *brom;
1581 rom = OF_node_new(OF_env, OF_node_root, "rom", 0xff800000);
1583 ERROR("Cannot create 'rom'\n");
1586 regs.address = 0xFF800000;
1587 regs.size = 0x00000000;
1588 OF_property_new(OF_env, rom, "reg", ®s, sizeof(OF_regprop_t));
1589 range.virt = 0xFF800000;
1590 range.phys = 0xFF800000;
1591 range.size = 0x00800000;
1592 OF_property_new(OF_env, rom, "ranges", &range, sizeof(OF_range_t));
1593 OF_prop_int_new(OF_env, rom, "#address-cells", 1);
1595 /* "/rom/boot-rom@fff00000" node */
1596 brom = OF_node_new(OF_env, rom, "boot-rom", 0xfff00000);
1598 ERROR("Cannot create 'boot-rom'\n");
1601 regs.address = 0xFFF00000;
1602 regs.size = 0x00100000;
1603 OF_property_new(OF_env, brom, "reg", ®s, sizeof(OF_regprop_t));
1604 OF_prop_string_new(OF_env, brom, "write-characteristic", "flash");
1605 OF_prop_string_new(OF_env, brom, "BootROM-build-date",
1606 stringify(BUILD_DATE) " at " stringify(BUILD_TIME));
1607 OF_prop_string_new(OF_env, brom, "BootROM-version", BIOS_VERSION);
1608 OF_prop_string_new(OF_env, brom, "copyright", copyright);
1609 OF_prop_string_new(OF_env, brom, "model", BIOS_str);
1610 OF_prop_int_new(OF_env, brom, "result", 0);
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,
1624 OF_property_new(OF_env, brom, "info", info, sizeof(info));
1627 OF_node_put(OF_env, brom);
1628 OF_node_put(OF_env, rom);
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 */
1638 nvr = OF_node_new(OF_env, OF_node_root, "nvram", 0xfff04000);
1640 ERROR("Cannot create 'nvram'\n");
1643 OF_prop_string_new(OF_env, nvr, "device_type", "nvram");
1644 /* XXX: use real NVRAM size instead */
1645 OF_prop_int_new(OF_env, nvr, "#bytes", 0x2000);
1646 OF_prop_string_new(OF_env, nvr, "compatible", "nvram,flash");
1647 regs.address = 0xFFF04000;
1648 regs.size = 0x00004000; /* Strange, isn't it ? */
1649 OF_property_new(OF_env, nvr, "reg", ®s, sizeof(regs));
1650 OF_prop_int_new(OF_env, chs, "nvram", OF_pack_handle(OF_env, nvr));
1651 OF_node_put(OF_env, nvr);
1654 /* "/pseudo-hid" : hid emulation as Apple does */
1658 hid = OF_node_new(OF_env, OF_node_root,
1659 "pseudo-hid", OF_ADDRESS_NONE);
1661 ERROR("Cannot create 'pseudo-hid'\n");
1665 /* "keyboard" node */
1668 kbd = OF_node_new(OF_env, hid, "keyboard", OF_ADDRESS_NONE);
1670 ERROR("Cannot create 'keyboard'\n");
1673 OF_prop_string_new(OF_env, kbd, "device_type", "keyboard");
1674 OF_node_put(OF_env, kbd);
1679 mouse = OF_node_new(OF_env, hid, "mouse", OF_ADDRESS_NONE);
1680 if (mouse == NULL) {
1681 ERROR("Cannot create 'mouse'\n");
1684 OF_prop_string_new(OF_env, mouse, "device_type", "mouse");
1685 OF_node_put(OF_env, mouse);
1687 /* "eject-key" node */
1690 ejk = OF_node_new(OF_env, hid, "eject-key", OF_ADDRESS_NONE);
1692 ERROR("Cannot create 'eject-key'\n");
1695 OF_prop_string_new(OF_env, ejk, "device_type", "eject-key");
1696 OF_node_put(OF_env, ejk);
1698 OF_node_put(OF_env, hid);
1700 if (arch == ARCH_MAC99) {
1704 unin = OF_node_new(OF_env, OF_node_root,
1705 "uni-n", 0xf8000000);
1707 ERROR("Cannot create 'uni-n'\n");
1710 OF_prop_string_new(OF_env, unin, "device-type", "memory-controller");
1711 OF_prop_string_new(OF_env, unin, "model", "AAPL,UniNorth");
1712 OF_prop_string_new(OF_env, unin, "compatible", "uni-north");
1713 regs.address = 0xf8000000;
1714 regs.size = 0x01000000;
1715 OF_property_new(OF_env, unin, "reg", ®s, sizeof(regs));
1716 OF_prop_int_new(OF_env, unin, "#address-cells", 1);
1717 OF_prop_int_new(OF_env, unin, "#size-cells", 1);
1718 OF_prop_int_new(OF_env, unin, "device-rev", 3);
1719 OF_node_put(OF_env, unin);
1722 #if 1 /* This is mandatory for claim to work
1723 * but I don't know where it should really be (in cpu ?)
1729 mmu = OF_node_new(OF_env, OF_node_root, "mmu", OF_ADDRESS_NONE);
1731 ERROR("Cannot create 'mmu'\n");
1734 inst = OF_instance_new(OF_env, mmu);
1736 OF_node_put(OF_env, mmu);
1737 ERROR("Cannot create 'mmu' instance\n");
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);
1748 /* "/options/boot-args" node */
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);
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");
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)
1779 OF_env = OF_env_main;
1780 OF_DPRINTF("start\n");
1781 root = OF_node_get(OF_env, "device_tree");
1783 ERROR("Cannot get 'device-tree'\n");
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]);
1792 /* we don't implement neither "l2-cache" nor "cache" nodes */
1793 OF_node_put(OF_env, root);
1794 OF_DPRINTF("done\n");
1801 __attribute__ (( section (".OpenFirmware") ))
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)
1806 unsigned char tmp[OF_NAMELEN_MAX];
1808 OF_node_t *cpus, *cpu, *l2c, *chs, *als;
1810 OF_env = OF_env_main;
1811 OF_DPRINTF("start\n");
1812 cpus = OF_node_get(OF_env, "cpus");
1814 ERROR("Cannot get 'cpus'\n");
1817 cpu = OF_node_new(OF_env, cpus, name, OF_ADDRESS_NONE);
1819 OF_node_put(OF_env, cpus);
1820 ERROR("Cannot create cpu '%s'\n", name);
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"
1858 l2c = OF_node_new(OF_env, cpu, "l2cache", OF_ADDRESS_NONE);
1860 ERROR("Cannot create 'l2cache'\n");
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" */
1875 OF_pack_get_path(OF_env, tmp, 512, cpu);
1876 chs = OF_node_get(OF_env, "chosen");
1878 OF_node_put(OF_env, cpus);
1879 ERROR("Cannot get 'chosen'\n");
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");
1886 OF_node_put(OF_env, cpus);
1887 ERROR("Cannot get 'aliases'\n");
1890 OF_prop_string_new(OF_env, als, "cpu", tmp);
1891 OF_node_put(OF_env, als);
1893 OF_node_put(OF_env, cpu);
1894 OF_node_put(OF_env, cpus);
1895 OF_DPRINTF("done\n");
1900 __attribute__ (( section (".OpenFirmware") ))
1901 int OF_register_translations (int nb, OF_transl_t *translations)
1904 OF_node_t *cpus, *cpu;
1908 OF_env = OF_env_main;
1909 OF_DPRINTF("start\n");
1910 cpus = OF_node_get(OF_env, "cpus");
1912 OF_node_put(OF_env, cpus);
1913 ERROR("Cannot get 'cpus'\n");
1916 cpu = cpus->children;
1917 new = malloc(nb * sizeof(OF_transl_t));
1919 ERROR("Cannot create new translation\n");
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);
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");
1938 typedef struct OF_mem_t OF_mem_t;
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];
1948 __attribute__ (( section (".OpenFirmware") ))
1949 int OF_register_memory (uint32_t memsize, unused uint32_t bios_size)
1953 OF_regprop_t regs[4];
1956 OF_env = OF_env_main;
1957 OF_DPRINTF("find node\n");
1958 mem = OF_node_get(OF_env, "memory");
1960 ERROR("Cannot get 'memory'\n");
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));
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));
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));
1992 OF_node_put(OF_env, mem);
1996 mmu = OF_node_get(OF_env, "mmu");
1998 ERROR("Cannot get 'mmu'\n");
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);
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;
2024 OF_DPRINTF("done\n");
2029 /* Linux kernel command line */
2030 __attribute__ (( section (".OpenFirmware") ))
2031 int OF_register_bootargs (const unsigned char *bootargs)
2036 OF_env = OF_env_main;
2037 if (bootargs == NULL)
2039 chs = OF_node_get(OF_env, "chosen");
2041 ERROR("Cannot get 'chosen'\n");
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);
2051 __attribute__ (( section (".OpenFirmware") ))
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)
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);
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);
2088 __attribute__ (( section (".OpenFirmware") ))
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)
2097 pci_range_t ranges[3];
2098 OF_regprop_t regs[1];
2099 OF_node_t *pci_host, *als;
2101 unsigned char buffer[OF_NAMELEN_MAX];
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");
2113 als = OF_node_get(OF_env, "aliases");
2115 ERROR("Cannot get 'aliases'\n");
2118 sprintf(buffer, "/%s", dev->name);
2119 OF_prop_string_set(OF_env, als, "pci", buffer);
2120 OF_node_put(OF_env, als);
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));
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;
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;
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;
2154 OF_property_new(OF_env, pci_host, "ranges", ranges,
2155 nranges * sizeof(pci_range_t));
2160 __attribute__ (( section (".OpenFirmware") ))
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)
2167 OF_regprop_t regs[1];
2168 OF_node_t *pci_bridge;
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");
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));
2188 __attribute__ (( section (".OpenFirmware") ))
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)
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);
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;
2212 void OF_finalize_pci_host (void *dev, int first_bus, int nb_busses)
2215 OF_regprop_t regs[1];
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;
2224 void OF_finalize_pci_device (void *dev, uint8_t bus, uint8_t devfn,
2225 uint32_t *regions, uint32_t *sizes,
2229 pci_reg_prop_t pregs[6], rregs[6];
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
2241 if (regions[i] & 1) {
2243 rregs[j].addr.hi = 0x01000000;
2245 } else if (regions[i] & 4) {
2246 /* 64 bits address space */
2247 rregs[j].addr.hi = 0x83000000;
2250 } else if ((regions[i] & 0xF) == 0x00) { /* ? */
2251 /* Configuration space */
2252 rregs[j].addr.hi = 0x00000000;
2256 /* 32 bits address space */
2257 rregs[j].addr.hi = 0x82000000;
2260 /* Set bus number */
2261 rregs[j].addr.hi |= bus << 16;
2262 /* Set device/function */
2263 rregs[j].addr.hi |= devfn << 8;
2266 rregs[j].addr.hi |= 0x10 + (i * sizeof(uint32_t)); /* ? */
2269 rregs[j].addr.mid = 0x00000000;
2270 rregs[j].addr.lo = regions[i] & ~mask;
2272 rregs[j].size_hi = 0x00000000;
2273 rregs[j].size_lo = sizes[i];
2275 if ((rregs[j].addr.hi & 0x03000000) != 0x00000000)
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;
2290 OF_property_new(OF_env, dev, "reg",
2291 rregs, j * sizeof(pci_reg_prop_t));
2293 OF_property_new(OF_env, dev, "reg", NULL, 0);
2296 OF_property_new(OF_env, dev, "assigned-addresses",
2297 pregs, k * sizeof(pci_reg_prop_t));
2299 OF_property_new(OF_env, dev, "assigned-addresses", NULL, 0);
2301 if (irq_line >= 0) {
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;
2314 pci_host_interrupt_map_len = i;
2318 OF_prop_t *prop_name = ((OF_node_t *)dev)->prop_name;
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);
2329 dprintf("PCI device '%s' %d %d %d has no reg properties:\n",
2330 prop_name->value, bus, devfn >> 3, devfn & 7);
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);
2342 dprintf("PCI device '%s' %d %d %d has no "
2343 "assigned addresses properties:\n",
2344 prop_name->value, bus, devfn >> 3, devfn & 7);
2350 __attribute__ (( section (".OpenFirmware") ))
2351 int OF_register_bus (const unsigned char *name, uint32_t address,
2352 const unsigned char *type)
2354 unsigned char buffer[OF_NAMELEN_MAX];
2356 OF_node_t *bus, *als;
2358 OF_env = OF_env_main;
2359 als = OF_node_get(OF_env, "aliases");
2361 ERROR("Cannot get 'aliases'\n");
2364 bus = OF_node_new(OF_env, OF_node_root, name, address);
2366 OF_node_put(OF_env, als);
2367 ERROR("Cannot create bus '%s'\n", name);
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);
2380 // We will need to register stdin & stdout via the serial port
2381 __attribute__ (( section (".OpenFirmware") ))
2382 int OF_register_serial (const unsigned char *bus, const unsigned char *name,
2383 uint32_t io_base, unused int irq)
2385 unsigned char tmp[OF_NAMELEN_MAX];
2387 OF_node_t *busn, *srl, *als;
2389 OF_env = OF_env_main;
2390 als = OF_node_get(OF_env, "aliases");
2392 ERROR("Cannot get 'aliases'\n");
2395 busn = OF_node_get(OF_env, bus);
2396 srl = OF_node_new(OF_env, busn, name, io_base);
2398 OF_node_put(OF_env, als);
2399 ERROR("Cannot create serial '%s'\n", name);
2402 OF_prop_string_set(OF_env, srl, "device_type", "serial");
2403 OF_prop_string_set(OF_env, srl, "compatible", "pnpPNP,501");
2406 OF_pack_get_path(OF_env, tmp, 512, srl);
2407 OF_prop_string_new(OF_env, als, "com1", tmp);
2410 OF_pack_get_path(OF_env, tmp, 512, srl);
2411 OF_prop_string_new(OF_env, als, "com2", tmp);
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);
2426 /* We will also need /isa/rtc */
2428 __attribute__ (( section (".OpenFirmware") ))
2429 int OF_register_stdio (const unsigned char *dev_in,
2430 const unsigned char *dev_out)
2433 OF_node_t *chs, *ndev_in, *ndev_out, *kbd;
2434 OF_inst_t *in_inst, *out_inst;
2436 OF_env = OF_env_main;
2437 chs = OF_node_get(OF_env, "chosen");
2439 ERROR("Cannot get 'chosen'\n");
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");
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");
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);
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");
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);
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)
2488 OF_env_t *OF_env = OF_env_main;
2490 OF_regprop_t regs[2];
2492 ata = OF_node_new(OF_env, mio, "ata-4", base);
2494 ERROR("Cannot create 'ata-4'\n");
2497 OF_prop_string_new(OF_env, ata, "device_type", "ata");
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");
2503 OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
2504 OF_prop_string_new(OF_env, ata, "model", "ata-4");
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));
2516 OF_property_new(OF_env, ata, "reg",
2517 regs, sizeof(OF_regprop_t));
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);
2529 ide_pci_pmac_register(0x00000000, base_address + base, ata);
2532 void OF_finalize_pci_macio (void *dev, uint32_t base_address, uint32_t size,
2535 unsigned char tmp[OF_NAMELEN_MAX];
2537 pci_reg_prop_t pregs[2];
2538 OF_node_t *mio, *chs, *als;
2539 uint16_t pic_phandle;
2543 OF_DPRINTF("mac-io: %p\n", dev);
2544 OF_env = OF_env_main;
2545 chs = OF_node_get(OF_env, "chosen");
2547 ERROR("Cannot get 'chosen'\n");
2550 als = OF_node_get(OF_env, "aliases");
2552 OF_node_put(OF_env, als);
2553 ERROR("Cannot get 'aliases'\n");
2556 /* Mac-IO is mandatory for OSX to boot */
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;
2568 OF_property_new(OF_env, mio, "ranges",
2569 &pregs, sizeof(pci_reg_prop_t));
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));
2580 if (arch == ARCH_HEATHROW) {
2584 const char compat_str[] = "heathrow\0mac-risc";
2586 mpic = OF_node_new(OF_env, mio, "interrupt-controller", 0x10);
2588 ERROR("Cannot create 'mpic'\n");
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;
2596 OF_property_new(OF_env, mpic, "reg",
2597 ®s, sizeof(regs));
2598 OF_property_new(OF_env, mpic, "interrupt-controller", NULL, 0);
2599 pic_phandle = OF_pack_handle(OF_env, mpic);
2600 OF_prop_int_new(OF_env, chs, "interrupt-controller", pic_phandle);
2601 OF_node_put(OF_env, mpic);
2605 OF_regprop_t regs[4];
2607 mpic = OF_node_new(OF_env, mio, "interrupt-controller", 0x40000);
2609 ERROR("Cannot create 'mpic'\n");
2612 OF_prop_string_new(OF_env, mpic, "device_type", "open-pic");
2613 OF_prop_string_new(OF_env, mpic, "compatible", "chrp,open-pic");
2614 OF_property_new(OF_env, mpic, "interrupt-controller", NULL, 0);
2615 OF_property_new(OF_env, mpic, "built-in", NULL, 0);
2616 OF_prop_int_new(OF_env, mpic, "clock-frequency", 0x003F7A00);
2617 OF_prop_int_new(OF_env, mpic, "#address-cells", 0);
2618 OF_prop_int_new(OF_env, mpic, "#interrupt-cells", 2);
2619 memset(regs, 0, 4 * sizeof(OF_regprop_t));
2620 regs[0].address = 0x00040000;
2621 regs[0].size = 0x00040000;
2622 OF_property_new(OF_env, mpic, "reg",
2623 ®s, 1 * sizeof(OF_regprop_t));
2624 pic_phandle = OF_pack_handle(OF_env, mpic);
2625 OF_prop_int_new(OF_env, chs, "interrupt-controller", pic_phandle);
2626 OF_node_put(OF_env, mpic);
2630 /* patch pci host table */
2631 /* XXX: do it after the PCI init */
2636 for(i = 0; i < pci_host_interrupt_map_len; i += rec_len)
2637 pci_host_interrupt_map[i + 4] = pic_phandle;
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))
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));
2654 OF_property_new(OF_env, pci_host_node, "interrupt-map-mask",
2655 tab, 4 * sizeof(uint32_t));
2658 /* escc is useful to get MacOS X debug messages */
2660 OF_regprop_t regs[8];
2662 OF_node_t *scc, *chann;
2663 scc = OF_node_new(OF_env, mio, "escc", 0x13000);
2665 ERROR("Cannot create 'escc'\n");
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");
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 */
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");
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 */
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);
2757 ERROR("Cannot create 'escc-legacy'\n");
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");
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 */
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");
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 */
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);
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);
2855 OF_regprop_t regs[1];
2856 tmr = OF_node_new(OF_env, mio, "timer", 0x15000);
2858 ERROR("Cannot create 'timer'\n");
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);
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);
2884 ERROR("Cannot create 'via-pmu'\n");
2887 OF_prop_string_new(OF_env, via, "device_type", "via-pmu");
2888 OF_prop_string_new(OF_env, via, "compatible", "pmu");
2890 via = OF_node_new(OF_env, mio, "via-cuda", 0x16000);
2892 ERROR("Cannot create 'via-cuda'\n");
2895 OF_prop_string_new(OF_env, via, "device_type", "via-cuda");
2896 OF_prop_string_new(OF_env, via, "compatible", "cuda");
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);
2905 regs[0].address = 0x00000019;
2906 regs[0].size = 0x00000001;
2907 OF_property_new(OF_env, via, "interrupts",
2908 regs, sizeof(OF_regprop_t));
2910 /* force usage of OF bus speeds */
2911 OF_prop_int_new(OF_env, via, "BusSpeedCorrect", 1);
2913 OF_prop_int_new(OF_env, via, "pmu-version", 0x00D0740C);
2916 OF_node_t *kbd, *mouse;
2917 /* ADB pseudo-device */
2918 adb = OF_node_new(OF_env, via, "adb", OF_ADDRESS_NONE);
2920 ERROR("Cannot create 'adb'\n");
2923 OF_prop_string_new(OF_env, adb, "device_type", "adb");
2925 OF_prop_string_new(OF_env, adb, "compatible", "pmu-99");
2927 OF_prop_string_new(OF_env, adb, "compatible", "adb");
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);
2934 kbd = OF_node_new(OF_env, adb, "keyboard", 2);
2936 ERROR("Cannot create 'kbd'\n");
2939 OF_prop_string_new(OF_env, kbd, "device_type", "keyboard");
2940 OF_prop_int_new(OF_env, kbd, "reg", 2);
2942 mouse = OF_node_new(OF_env, adb, "mouse", 3);
2943 if (mouse == NULL) {
2944 ERROR("Cannot create 'mouse'\n");
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);
2954 rtc = OF_node_new(OF_env, via, "rtc", OF_ADDRESS_NONE);
2956 ERROR("Cannot create 'rtc'\n");
2959 OF_prop_string_new(OF_env, rtc, "device_type", "rtc");
2961 OF_prop_string_new(OF_env, rtc, "compatible", "rtc,via-pmu");
2963 OF_prop_string_new(OF_env, rtc, "compatible", "rtc");
2965 OF_node_put(OF_env, rtc);
2967 // OF_node_put(OF_env, via);
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);
2978 if (arch == ARCH_HEATHROW) {
2982 nvr = OF_node_new(OF_env, mio, "nvram", 0x60000);
2983 OF_prop_string_new(OF_env, nvr, "device_type", "nvram");
2984 regs.address = 0x60000;
2985 regs.size = 0x00020000;
2986 OF_property_new(OF_env, nvr, "reg", ®s, sizeof(regs));
2987 OF_prop_int_new(OF_env, nvr, "#bytes", 0x2000);
2988 OF_node_put(OF_env, nvr);
2992 // OF_node_put(OF_env, mio);
2993 OF_node_put(OF_env, chs);
2994 OF_node_put(OF_env, als);
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)
3001 OF_env_t *OF_env = OF_env_main;
3002 OF_node_t *pci_ata = dev;
3003 OF_node_t *ata, *atas[2];
3006 OF_prop_int_new(OF_env, pci_ata, "#address-cells", 1);
3007 OF_prop_int_new(OF_env, pci_ata, "#size-cells", 0);
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);
3013 ERROR("Cannot create 'ata-4'\n");
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);
3024 ide_pci_pc_register(io_base0, io_base1, io_base2, io_base3,
3028 /*****************************************************************************/
3030 static void OF_method_fake (OF_env_t *OF_env)
3034 ihandle = popd(OF_env);
3035 OF_DPRINTF("ih: %0x %d\n", ihandle, stackd_depth(OF_env));
3036 pushd(OF_env, ihandle);
3039 static void OF_mmu_translate (OF_env_t *OF_env)
3041 const unsigned char *args;
3042 uint32_t address, more;
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);
3059 static void OF_mmu_map (OF_env_t *OF_env)
3061 const unsigned char *args;
3062 uint32_t address, virt, size;
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);
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,
3078 /* Serial device package */
3079 static void OF_serial_write (OF_env_t *OF_env)
3081 const unsigned char *args;
3088 OF_CHECK_NBARGS(OF_env, 4);
3089 ihandle = popd(OF_env);
3090 args = (void *)popd(OF_env);
3091 str = (void *)popd(OF_env);
3093 inst = OF_inst_find(OF_env, ihandle);
3096 ERROR("Cannot get serial instance\n");
3100 // OF_DPRINTF("args: %p str: %p\n", args, str);
3101 /* XXX: should use directly the serial port
3102 * and have another console package.
3104 console_write(str, len);
3108 static void OF_serial_read (OF_env_t *OF_env)
3110 const unsigned char *args;
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);
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 */
3129 /* Random sleep. Seems allright for serial port */
3135 OF_DPRINTF("send '%s'\n", dest);
3140 typedef struct blockdev_inst_t {
3149 static int OF_split_args (unsigned char *args, unsigned char **argv,
3152 unsigned char *pos, *end;
3157 for (i = 0; i < max_args && *pos != '\0' && end != NULL; i++) {
3158 end = strchr(pos, ',');
3168 static void OF_convert_path (unsigned char **path)
3172 OF_DPRINTF("%s: '%s'\n", __func__, *path);
3173 for (pos = *path; *pos != '\0'; pos++) {
3177 OF_DPRINTF("%s: '%s'\n", __func__, *path);
3180 if (pos[0] == '/' && pos[1] == '/') {
3185 for (; *pos == '/'; pos++)
3189 OF_DPRINTF("%s: '%s'\n", __func__, *path);
3192 /* Block devices package */
3193 static void OF_blockdev_open (OF_env_t *OF_env)
3195 unsigned char tmp[OF_NAMELEN_MAX];
3196 unsigned char *args, *argv[4];
3197 OF_inst_t *dsk_inst;
3200 blockdev_inst_t *bdinst;
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);
3215 dsk = dsk_inst->node;
3216 bd = dsk->private_data;
3217 bdinst = malloc(sizeof(blockdev_inst_t));
3218 if (bdinst == NULL) {
3220 ERROR("Cannot alloc blockdev instance\n");
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);
3228 partnum = strtol(argv[0], NULL, 10);
3230 OF_DPRINTF("Open partition... %d %d\n", partnum, nargs);
3232 bdinst->u.part = part_get(bd, partnum);
3233 if (bdinst->u.part == NULL) {
3234 OF_DPRINTF("Partition %d not found\n", partnum);
3240 /* TODO: open file */
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)),
3249 bdinst->u.file = fs_open(part_fs(bdinst->u.part), tmp);
3251 bdinst->u.file = fs_open(part_fs(bdinst->u.part), argv[1]);
3253 if (bdinst->u.file == NULL) {
3257 pushd(OF_env, 0x00000000);
3258 ERROR("File not found '%s'\n", argv[1]);
3264 if (nargs == 0 || partnum == 0) {
3265 OF_DPRINTF("Open disk... %d %d\n", nargs, partnum);
3269 /* TODO: find partition &/| file */
3270 dsk_inst->data = bdinst;
3271 OF_node_put(OF_env, dsk);
3273 pushd(OF_env, ihandle);
3276 static void OF_blockdev_seek (OF_env_t *OF_env)
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;
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);
3298 bdinst = dsk_inst->data;
3299 switch (bdinst->type) {
3301 blocsize = bd_seclen(bdinst->u.bd);
3302 for (tmp = blocsize, sh = 0; tmp != 1; tmp = tmp / 2)
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));
3311 blocsize = part_blocsize(bdinst->u.part);
3312 for (tmp = blocsize, sh = 0; tmp != 1; tmp = tmp / 2)
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));
3321 blocsize = part_blocsize(fs_inode_get_part(bdinst->u.file));
3322 for (tmp = blocsize, sh = 0; tmp != 1; tmp = tmp / 2)
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));
3333 static void OF_blockdev_read (OF_env_t *OF_env)
3335 const unsigned char *args;
3336 OF_inst_t *dsk_inst;
3337 blockdev_inst_t *bdinst;
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);
3349 dsk_inst = OF_inst_find(OF_env, ihandle);
3350 if (dsk_inst == NULL) {
3351 ERROR("Disk not found (ih: %0x)\n", ihandle);
3355 bdinst = dsk_inst->data;
3357 OF_DPRINTF("dest: %p len: %d %d\n", dest, len, bdinst->type);
3358 switch (bdinst->type) {
3360 OF_DPRINTF("read disk\n");
3361 pushd(OF_env, bd_read(bdinst->u.bd, dest, len));
3364 OF_DPRINTF("read partition\n");
3365 pushd(OF_env, part_read(bdinst->u.part, dest, len));
3368 OF_DPRINTF("read file\n");
3369 pushd(OF_env, fs_read(bdinst->u.file, dest, len));
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]);
3382 static void OF_blockdev_get_blocsize (OF_env_t *OF_env)
3384 const unsigned char *args;
3385 OF_inst_t *dsk_inst;
3386 blockdev_inst_t *bdinst;
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);
3401 bdinst = dsk_inst->data;
3403 switch (bdinst->type) {
3405 blocsize = bd_seclen(bdinst->u.bd);
3408 blocsize = part_blocsize(bdinst->u.part);
3417 pushd(OF_env, blocsize);
3421 static void OF_blockdev_dma_alloc (OF_env_t *OF_env)
3423 const unsigned char *args;
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);
3434 address = malloc(size);
3435 if (address != NULL)
3436 memset(address, 0, size);
3437 pushd(OF_env, (uint32_t)address);
3441 static void OF_blockdev_dma_free (OF_env_t *OF_env)
3443 const unsigned char *args;
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);
3458 void *OF_blockdev_register (void *parent, void *private,
3459 const unsigned char *type,
3460 const unsigned char *name, int devnum,
3463 unsigned char tmp[OF_NAMELEN_MAX], path[OF_NAMELEN_MAX], *pos;
3465 OF_node_t *dsk, *als;
3468 OF_env = OF_env_main;
3469 dsk = OF_node_new(OF_env, parent, name, devnum);
3471 ERROR("Cannot create blockdev '%s'\n", name);
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");
3494 ERROR("Cannot get 'aliases'\n");
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)
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);
3515 void OF_blockdev_set_boot_device (void *disk, int partnum,
3516 const unsigned char *file)
3518 unsigned char tmp[OF_NAMELEN_MAX], *pos;
3520 OF_node_t *dsk = disk, *opts, *chs;
3522 OF_env = OF_env_main;
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");
3530 ERROR("Cannot get 'options'\n");
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++) {
3545 chs = OF_node_get(OF_env, "chosen");
3547 ERROR("Cannot get 'chosen'\n");
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);
3555 /* Display package */
3556 static void OF_vga_draw_rectangle (OF_env_t *OF_env)
3559 const unsigned char *args;
3560 uint32_t posx, posy, width, height;
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);
3574 vga_draw_buf(buf, width * vga_fb_bpp, posx, posy, width, height);
3579 static void OF_vga_fill_rectangle (OF_env_t *OF_env)
3581 const unsigned char *args;
3582 uint32_t color, posx, posy, width, height;
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);
3599 static void OF_vga_set_width (OF_env_t *OF_env, OF_prop_t *prop,
3600 const void *data, int len)
3602 uint32_t width, height, depth;
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);
3612 static void OF_vga_set_height (OF_env_t *OF_env, OF_prop_t *prop,
3613 const void *data, int len)
3615 uint32_t width, height, depth;
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);
3625 static void OF_vga_set_depth (OF_env_t *OF_env, OF_prop_t *prop,
3626 const void *data, int len)
3628 uint32_t width, height, depth;
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);
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)
3643 unsigned char tmp[OF_NAMELEN_MAX];
3644 OF_node_t *disp, *chs, *als;
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);
3652 ERROR("Cannot get display '%s'\n", name);
3655 prop = OF_prop_int_new(OF_env, disp, "width", width);
3657 OF_node_put(OF_env, disp);
3658 ERROR("Cannot create display width property\n");
3661 OF_property_set_cb(OF_env, prop, &OF_vga_set_width);
3662 prop = OF_prop_int_new(OF_env, disp, "height", height);
3664 OF_node_put(OF_env, disp);
3665 ERROR("Cannot create display height property\n");
3668 OF_property_set_cb(OF_env, prop, &OF_vga_set_height);
3678 /* OF spec this is mandatory, but we have no support for it */
3679 printf("%d bits VGA isn't implemented\n", depth);
3681 /* Never come here */
3684 prop = OF_prop_int_new(OF_env, disp, "depth", depth);
3686 ERROR("Cannot create display depth\n");
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");
3696 ERROR("Cannot get 'chosen'\n");
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");
3705 ERROR("Cannot get 'aliases'\n");
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 */
3713 if (vga_bios_size >= 8) {
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",
3725 OF_node_put(OF_env, disp);
3728 /* Pseudo packages to make BootX happy */
3729 /* sl_words package */
3730 static void slw_set_output_level (OF_env_t *OF_env)
3733 const unsigned char *args;
3736 OF_CHECK_NBARGS(OF_env, 3);
3738 args = (void *)popd(OF_env);
3739 level = popd(OF_env);
3740 slw = OF_node_get(OF_env, "sl_words");
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);
3752 #define EMIT_BUFFER_LEN 256
3753 static unsigned char emit_buffer[EMIT_BUFFER_LEN];
3754 static int emit_pos = 0;
3757 static void slw_emit (OF_env_t *OF_env)
3759 const unsigned char *args;
3762 OF_CHECK_NBARGS(OF_env, 3);
3764 args = (void *)popd(OF_env);
3766 // OF_DPRINTF("Emit char %d\n", c);
3768 if (emit_pos < EMIT_BUFFER_LEN - 1) {
3769 emit_buffer[emit_pos++] = c;
3773 emit_buffer[emit_pos] = '\0';
3781 static void slw_cr (OF_env_t *OF_env)
3783 const unsigned char *args;
3785 OF_CHECK_NBARGS(OF_env, 2);
3787 args = (void *)popd(OF_env);
3788 // OF_DPRINTF("Emit CR char\n");
3789 // outb(0xFF01, '\n');
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
3797 uint16_t loglevel = 0x02 | 0x10 | 0x80;
3798 // outw(0xFF02, loglevel);
3799 outb(0x0F02, loglevel);
3806 static void slw_init_keymap (OF_env_t *OF_env)
3808 const unsigned char *args;
3811 uint32_t phandle, ihandle;
3813 OF_CHECK_NBARGS(OF_env, 3);
3814 ihandle = popd(OF_env);
3815 args = (void *)popd(OF_env);
3816 phandle = ihandle >> 16;
3819 node = OF_pack_find(OF_env, phandle);
3821 ERROR("Cant' init slw keymap\n");
3824 prop = OF_property_get(OF_env, node, "keyMap");
3828 pushd(OF_env, (uint32_t)prop->value);
3834 static void slw_update_keymap (OF_env_t *OF_env)
3836 const unsigned char *args;
3838 OF_CHECK_NBARGS(OF_env, 2);
3840 args = (void *)popd(OF_env);
3845 static void slw_spin (OF_env_t *OF_env)
3847 const unsigned char *args;
3848 /* XXX: cur_spin should be in sl_words package */
3849 static int cur_spin = 0;
3852 OF_CHECK_NBARGS(OF_env, 2);
3854 args = (void *)popd(OF_env);
3855 if (cur_spin > 15) {
3856 c = RGB(0x30, 0x30, 0x50);
3858 c = RGB(0x11, 0x11, 0x11);
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;
3867 static void slw_spin_init (OF_env_t *OF_env)
3869 const unsigned char *args;
3871 OF_CHECK_NBARGS(OF_env, 8);
3873 args = (void *)popd(OF_env);
3883 static void slw_pwd (OF_env_t *OF_env)
3885 const unsigned char *args;
3887 OF_CHECK_NBARGS(OF_env, 3);
3889 args = (void *)popd(OF_env);
3894 static void slw_sum (OF_env_t *OF_env)
3896 const unsigned char *args;
3898 OF_CHECK_NBARGS(OF_env, 3);
3900 args = (void *)popd(OF_env);
3905 /*****************************************************************************/
3906 /* Client program interface */
3907 /* Client interface services */
3908 static void OF_test (OF_env_t *OF_env);
3910 /* Device tree services */
3911 /* Get next package */
3912 __attribute__ (( section (".OpenFirmware") ))
3913 static void OF_peer (OF_env_t *OF_env)
3918 OF_CHECK_NBARGS(OF_env, 1);
3919 phandle = popd(OF_env);
3920 OF_DPRINTF("phandle 0x%0x\n", phandle);
3922 node = OF_node_root;
3924 node = OF_pack_next(OF_env, phandle);
3928 pushd(OF_env, OF_pack_handle(OF_env, node));
3931 /* Get first child package */
3932 __attribute__ (( section (".OpenFirmware") ))
3933 static void OF_child (OF_env_t *OF_env)
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);
3945 pushd(OF_env, OF_pack_handle(OF_env, node));
3948 /* Get parent package */
3949 __attribute__ (( section (".OpenFirmware") ))
3950 static void OF_parent (OF_env_t *OF_env)
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);
3962 pushd(OF_env, OF_pack_handle(OF_env, node));
3965 /* Get package related to an instance */
3966 __attribute__ (( section (".OpenFirmware") ))
3967 static void OF_instance_to_package (OF_env_t *OF_env)
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);
3977 /* Get property len */
3978 __attribute__ (( section (".OpenFirmware") ))
3979 static void OF_getproplen (OF_env_t *OF_env)
3981 unsigned char name[OF_NAMELEN_MAX], *namep;
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);
3994 pushd(OF_env, OF_property_len(OF_env, node, name));
3998 __attribute__ (( section (".OpenFirmware") ))
3999 static void OF_getprop (OF_env_t *OF_env)
4001 unsigned char name[OF_NAMELEN_MAX], *namep;
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);
4014 /* This hack is needed to boot MacOS X panther (10.3) */
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);
4025 len = OF_property_copy(OF_env, buffer, len, node, name);
4027 OF_DPRINTF("Copied %d bytes\n", len);
4033 /* Check existence of next property */
4034 __attribute__ (( section (".OpenFirmware") ))
4035 static void OF_nextprop (OF_env_t *OF_env)
4037 unsigned char name[OF_NAMELEN_MAX], *namep;
4040 unsigned char *next_name;
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);
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);
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);
4066 /* Set a property */
4067 __attribute__ (( section (".OpenFirmware") ))
4068 static void OF_setprop (OF_env_t *OF_env)
4070 unsigned char name[OF_NAMELEN_MAX], *namep;
4071 unsigned char *value, *buffer;
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);
4085 node = OF_pack_find(OF_env, phandle);
4088 ERROR("Cannot get pack %04x\n", phandle);
4091 value = malloc(len);
4092 if (value == NULL && len != 0) {
4094 ERROR("%s: Cannot alloc property '%s' (%d)\n", __func__, name, len);
4097 for (i = 0; i < len; i++)
4098 value[i] = buffer[i];
4099 prop = OF_property_set(OF_env, node, name, value, len);
4107 /* Find a device given its path */
4108 __attribute__ (( section (".OpenFirmware") ))
4109 static OF_node_t *OF_get_alias (OF_env_t *OF_env, const unsigned char *name)
4111 unsigned char tmp[OF_NAMELEN_MAX], *pos, *st;
4112 const unsigned char *alias, *npos;
4113 OF_node_t *als, *node;
4118 for (st = tmp; *st == '/'; st++)
4120 pos = strchr(st, '/');
4122 pos = strchr(st, ':');
4126 npos = name + (pos - tmp);
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");
4133 ERROR("Cannot get 'aliases'\n");
4136 prop = OF_property_get(OF_env, als, tmp);
4138 OF_DPRINTF("No %s alias !\n", tmp);
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);
4146 printf("%s alias is a broken link !\n", name);
4149 OF_node_put(OF_env, node);
4151 OF_node_put(OF_env, als);
4156 __attribute__ (( section (".OpenFirmware") ))
4157 static void OF_finddevice (OF_env_t *OF_env)
4159 unsigned char name[OF_NAMELEN_MAX], *namep;
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);
4170 node = OF_pack_find_by_name(OF_env, OF_node_root, name);
4175 ret = OF_pack_handle(OF_env, node);
4176 OF_DPRINTF("ret 0x%0x\n", ret);
4180 /* "instance-to-path */
4181 __attribute__ (( section (".OpenFirmware") ))
4182 static void OF_instance_to_path (OF_env_t *OF_env)
4189 OF_CHECK_NBARGS(OF_env, 3);
4191 ihandle = popd(OF_env);
4192 buffer = (void *)popd(OF_env);
4194 OF_DPRINTF("ihandle: 0x%0x len=%d\n", ihandle, len);
4195 inst = OF_inst_find(OF_env, ihandle);
4199 len = OF_inst_get_path(OF_env, buffer, len, inst) + 1;
4200 OF_DUMP_STRING(OF_env, buffer);
4204 /* "package-to-path" */
4205 __attribute__ (( section (".OpenFirmware") ))
4206 static void OF_package_to_path (OF_env_t *OF_env)
4213 OF_CHECK_NBARGS(OF_env, 3);
4215 phandle = popd(OF_env);
4216 buffer = (void *)popd(OF_env);
4218 node = OF_pack_find(OF_env, phandle);
4222 len = OF_pack_get_path(OF_env, buffer, len, node) + 1;
4223 OF_DUMP_STRING(OF_env, buffer);
4227 /* Call a package's method */
4228 __attribute__ (( section (".OpenFirmware") ))
4229 static void _OF_callmethod (OF_env_t *OF_env, const unsigned char *name,
4230 uint32_t ihandle, const unsigned char *argp)
4234 OF_method_t *method;
4237 inst = OF_inst_find(OF_env, ihandle);
4238 OF_DPRINTF("Attempt to call method [%s] of package instance 0x%0x\n",
4241 OF_DPRINTF("No instance %0x\n", ihandle);
4246 method = OF_method_get(OF_env, node, name);
4247 if (method != NULL) {
4250 if (strcmp(name, "open") == 0) {
4251 cb = &OF_method_fake;
4253 printf("Method '%s' not found in '%s'\n",
4254 name, node->prop_name->value);
4261 OF_DPRINTF("Push instance method %p (%p)...\n", &method->func,
4266 pushd(OF_env, (uint32_t)argp);
4268 pushd(OF_env, 0x00000000);
4269 pushd(OF_env, ihandle);
4272 __attribute__ (( section (".OpenFirmware") ))
4273 static unsigned char *OF_get_args (unused OF_env_t *env, unsigned char *name)
4277 sd = strchr(name, ':');
4285 __attribute__ (( section (".OpenFirmware") ))
4286 static void OF_callmethod (OF_env_t *OF_env)
4288 const unsigned char *args;
4289 unsigned char name[OF_NAMELEN_MAX], *namep;
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);
4300 /* Device IO services */
4301 /* Create a new instance of a device's package */
4302 __attribute__ (( section (".OpenFirmware") ))
4303 static void OF_open (OF_env_t *OF_env)
4305 const unsigned char *args;
4306 unsigned char name[OF_NAMELEN_MAX], *namep;
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);
4318 node = OF_pack_find_by_name(OF_env, OF_node_root, name);
4321 OF_DPRINTF("package not found !\n");
4325 inst = OF_instance_new(OF_env, node);
4328 ERROR("Cannot create package instance\n");
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);
4338 /* De-instanciate a package */
4339 __attribute__ (( section (".OpenFirmware") ))
4340 static void OF_close (OF_env_t *OF_env)
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 */
4352 __attribute__ (( section (".OpenFirmware") ))
4353 static void OF_read (OF_env_t *OF_env)
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);
4364 /* Try call the "read" method of a device's package */
4366 __attribute__ (( section (".OpenFirmware") ))
4367 static void OF_write (OF_env_t *OF_env)
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);
4379 __attribute__ (( section (".OpenFirmware") ))
4380 static void OF_seek (OF_env_t *OF_env)
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);
4391 /* Memory services */
4392 /* Claim some memory space */
4393 __attribute__ (( section (".OpenFirmware") ))
4394 uint32_t OF_claim_virt (uint32_t virt, uint32_t size, int *range)
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,
4406 return (uint32_t)(-1);
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)) {
4416 if (OF_mem_ranges[i].start == virt &&
4417 (OF_mem_ranges[i].start + OF_mem_ranges[i].size) == (virt + size)) {
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,
4427 return (uint32_t)(-1);
4430 OF_DPRINTF("return range: %d\n", keep);
4433 ERROR("No more rooms\n");
4434 return (uint32_t)(-1);
4436 ERROR("Give range: start 0x%0x 0x%0x\n", virt, size);
4444 /* We always try to get the upper address we can */
4445 __attribute__ (( section (".OpenFirmware") ))
4446 static uint32_t OF_claim_size (uint32_t size, int align, int *range)
4448 uint32_t addr, max = (uint32_t)(-1);
4451 OF_DPRINTF("Try map %d bytes at 0x00000000\n", size);
4452 if (OF_claim_virt(0, size, range) != (uint32_t)(-1))
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))
4458 addr = (OF_mem_ranges[i].start + OF_mem_ranges[i].size + 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))
4470 __attribute__ (( section (".OpenFirmware") ))
4471 static void OF_claim (OF_env_t *OF_env)
4473 uint32_t virt, size, addr;
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);
4483 addr = OF_claim_virt(virt, size, &range);
4485 for (i = 1; i < align; i = i << 1)
4488 size = (size + align - 1) & ~(align - 1);
4489 addr = OF_claim_size(size, align, &range);
4491 if (addr == (uint32_t)-1) {
4492 ERROR("No range match !\n");
4496 OF_mem_ranges[range].start = addr;
4497 OF_mem_ranges[range].size = size;
4499 OF_DPRINTF("Give address 0x%0x\n", addr);
4500 pushd(OF_env, addr);
4503 /* release some previously claimed memory */
4504 __attribute__ (( section (".OpenFirmware") ))
4505 static void OF_release (OF_env_t *OF_env)
4507 uint32_t virt, size;
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);
4523 /* Control transfer services */
4526 /* Enter Open-Firmware interpreter */
4527 __attribute__ (( section (".OpenFirmware") ))
4528 static void OF_enter (OF_env_t *OF_env)
4532 n_args = stackd_depth(OF_env);
4533 /* means that the bootloader has ended.
4536 OF_DPRINTF("%d \n", n_args);
4537 // printf("Bootloader has quitted...\n");
4541 /* Exit client program */
4542 __attribute__ (( section (".OpenFirmware") ))
4543 static void OF_exit (OF_env_t *OF_env)
4547 n_args = stackd_depth(OF_env);
4548 /* means that the bootloader has ended.
4551 OF_DPRINTF("%d \n", n_args);
4552 // printf("Bootloader has quitted...\n");
4558 /* User interface services */
4561 __attribute__ (( section (".OpenFirmware") ))
4562 static void OF_interpret (OF_env_t *OF_env)
4564 const unsigned char *FString;
4567 OF_node_t *pks, *slw, *chs, *disp;
4568 uint32_t ihandle, crc;
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 */
4577 case 0x225b6748: /* MacOS X 10.2 and OpenDarwin 1.41 */
4578 case 0xb1cd4d25: /* OpenDarwin 6.02 */
4579 /* Create "sl_words" package */
4581 /* Find "/packages" */
4582 pks = OF_pack_find_by_name(OF_env, OF_node_root, "/packages");
4584 OF_node_put(OF_env, pks);
4586 ERROR("Cannot get '/packages'\n");
4589 slw = OF_node_new(OF_env, pks, "sl_words", OF_ADDRESS_NONE);
4591 OF_node_put(OF_env, pks);
4593 ERROR("Cannot create 'sl_words'\n");
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);
4613 kbd = OF_pack_find_by_name(OF_env, OF_node_root, "/keyboard");
4615 OF_node_put(OF_env, pks);
4617 ERROR("Cannot get '/keyboard'\n");
4622 OF_node_put(OF_env, pks);
4624 ERROR("Cannot allocate keyboard buff\n");
4630 OF_node_put(OF_env, pks);
4632 ERROR("Cannot allocate keyboard buff\n");
4635 memset(buf, 0, 0x20);
4636 OF_property_new(OF_env, slw, "keyMap", buf, 0x20);
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);
4653 OF_node_put(OF_env, pks);
4655 ERROR("Cannot create sl_words instance\n");
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);
4669 case 0x233441d3: /* MacOS X 10.2 and OpenDarwin 1.41 */
4670 /* Create "memory-map" pseudo device */
4675 /* Find "/packages" */
4676 chs = OF_pack_find_by_name(OF_env, OF_node_root, "/chosen");
4679 ERROR("Cannot get '/chosen'\n");
4682 map = OF_node_new(OF_env, chs, "memory-map", OF_ADDRESS_NONE);
4685 ERROR("Cannot create 'memory-map'\n");
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);
4695 case 0x32a2d18e: /* MacOS X 10.2 and OpenDarwin 6.02 */
4696 /* Return screen ihandle */
4697 disp = OF_get_alias(OF_env, "screen");
4701 ERROR("Cannot get 'screen' alias\n");
4704 inst = OF_instance_new(OF_env, disp);
4706 OF_node_put(OF_env, disp);
4709 ERROR("Cannot create 'screen' instance\n");
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);
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");
4726 OF_node_put(OF_env, disp);
4728 case 0x1c3bc93f: /* MacOS X 10.3 */
4729 /* get-package-property if 0 0 then */
4734 if (len == (uint32_t)-1)
4739 case 0x218d5ccb: /* yaboot */
4747 /* Yaboot: set background color to black */
4750 case 0x299c2c5d: /* gentoo */
4751 /* Yaboot: set foreground color to grey */
4754 /* Yaboot: wait 10 ms: sure ! */
4759 printf("Script: len=%d\n%s\n", (int)strlen(FString), FString);
4760 printf("Call %0x NOT IMPLEMENTED !\n", crc);
4764 OF_DPRINTF("\n\nOF INTERPRETER CALL DONE\n\n");
4767 /* "set-callback" */
4768 /* "set-symbol-lookup" */
4771 /* "milliseconds" */
4772 __attribute__ (( section (".OpenFirmware") ))
4773 static void OF_milliseconds (OF_env_t *OF_env)
4779 OF_CHECK_NBARGS(OF_env, 0);
4780 gettimeofday(&tv, NULL);
4781 pushd(OF_env, (tv.tv_sec * 1000) + (tv.tv_usec / 1000));
4783 static uint32_t ms = 0;
4785 OF_CHECK_NBARGS(OF_env, 0);
4787 usleep(10000); /* XXX: TOFIX: Random sleep */
4792 /* Undocumented in IEEE 1275 */
4793 __attribute__ (( section (".OpenFirmware") ))
4794 static void OF_quiesce (OF_env_t *OF_env)
4796 OF_CHECK_NBARGS(OF_env, 0);
4797 /* Should free all OF resources */
4799 #if defined (DEBUG_BIOS)
4801 uint16_t loglevel = 0x02 | 0x10 | 0x80;
4802 // outw(0xFF02, loglevel);
4803 outb(0x0F02, loglevel);
4808 typedef struct OF_service_t OF_service_t;
4809 struct OF_service_t {
4810 const unsigned char *name;
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, },
4843 /* Probe if a named service exists */
4844 __attribute__ (( section (".OpenFirmware") ))
4845 static void OF_test (OF_env_t *OF_env)
4847 unsigned char name[OF_NAMELEN_MAX], *namep;
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) {
4864 /* Main entry point for PPC clients */
4865 __attribute__ (( section (".OpenFirmware") ))
4866 int OF_client_entry (void *p)
4868 unsigned char buffer[OF_NAMELEN_MAX];
4871 unsigned char *namep;
4874 /* set our environment */
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);
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;
4890 OF_DPRINTF("service [%s] not implemented\n", buffer);
4895 OF_DPRINTF("Service [%s] found\n", buffer);
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");
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.
4916 __attribute__ (( section (".RTAS_vars") ))
4917 static OF_cb_t *RTAS_callbacks[32];
4919 __attribute__ (( section (".RTAS_vars") ))
4920 static uint8_t *RTAS_base;
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.
4927 __attribute__ (( section (".RTAS") ))
4928 int RTAS_entry (void *p)
4933 OF_DPRINTF("Called with arg: %p\n", p);
4934 /* set our environment */
4935 token = *(uint32_t *)p;
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");
4948 __attribute__ (( section (".RTAS") ))
4949 static void RTAS_restart_rtas (OF_env_t *RTAS_env)
4952 OF_CHECK_NBARGS(RTAS_env, 0);
4953 /* No implementation: return error */
4954 pushd(RTAS_env, -1);
4957 __attribute__ (( section (".RTAS") ))
4958 static void RTAS_nvram_fetch (OF_env_t *RTAS_env)
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);
4974 *buffer++ = NVRAM_read(nvram, i + offset);
4976 pushd(RTAS_env, length);
4979 __attribute__ (( section (".RTAS") ))
4980 static void RTAS_nvram_store (OF_env_t *RTAS_env)
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);
4996 NVRAM_write(nvram, i + offset, *buffer++);
4998 pushd(RTAS_env, length);
5001 __attribute__ (( section (".RTAS") ))
5002 static void RTAS_get_time_of_day (OF_env_t *RTAS_env)
5009 OF_CHECK_NBARGS(RTAS_env, 0);
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 */
5032 __attribute__ (( section (".RTAS") ))
5033 static void RTAS_set_time_of_day (OF_env_t *RTAS_env)
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 */
5051 pushd(RTAS_env, 0); /* status */
5054 __attribute__ (( section (".RTAS") ))
5055 static void RTAS_set_time_for_power_on (OF_env_t *RTAS_env)
5058 OF_CHECK_NBARGS(RTAS_env, 7);
5060 pushd(RTAS_env, 0); /* status */
5063 __attribute__ (( section (".RTAS") ))
5064 static void RTAS_event_scan (OF_env_t *RTAS_env)
5067 OF_CHECK_NBARGS(RTAS_env, 4);
5068 /* Pretend there are no new events */
5072 __attribute__ (( section (".RTAS") ))
5073 static void RTAS_check_exception (OF_env_t *RTAS_env)
5076 OF_CHECK_NBARGS(RTAS_env, 6);
5077 /* Pretend we found no exceptions */
5081 __attribute__ (( section (".RTAS") ))
5082 static void RTAS_read_pci_config (OF_env_t *RTAS_env)
5085 OF_CHECK_NBARGS(RTAS_env, 2);
5086 /* Hardware error */
5087 pushd(RTAS_env, -1);
5090 __attribute__ (( section (".RTAS") ))
5091 static void RTAS_write_pci_config (OF_env_t *RTAS_env)
5094 OF_CHECK_NBARGS(RTAS_env, 3);
5095 /* Hardware error */
5096 pushd(RTAS_env, -1);
5099 __attribute__ (( section (".RTAS") ))
5100 static void RTAS_display_character (OF_env_t *RTAS_env)
5105 OF_CHECK_NBARGS(RTAS_env, 1);
5115 __attribute__ (( section (".RTAS") ))
5116 static void RTAS_set_indicator (OF_env_t *RTAS_env)
5118 const unsigned char *name;
5122 OF_CHECK_NBARGS(RTAS_env, 3);
5123 indic = popd(RTAS_env);
5124 state = popd(RTAS_env);
5127 name = "tone frequency";
5130 name = "tone volume";
5133 name = "system power state";
5136 name = "warning light";
5139 name = "disk activity light";
5142 name = "hexadecimal display unit";
5145 name = "batery warning time";
5148 name = "condition cycle request";
5151 name = "vendor specific";
5154 pushd(RTAS_env, -3);
5157 OF_DPRINTF("Set indicator %d [%s] to %d\n", indic, name, state);
5161 __attribute__ (( section (".RTAS") ))
5162 static void RTAS_get_sensor_state (OF_env_t *RTAS_env)
5164 const unsigned char *name;
5169 OF_CHECK_NBARGS(RTAS_env, 2);
5170 type = popd(RTAS_env);
5171 index = popd(RTAS_env);
5174 name = "key switch";
5175 state = 1; /* Normal */
5178 name = "enclosure switch";
5179 state = 0; /* Closed */
5182 name = "thermal sensor";
5183 state = 40; /* in degrees Celsius (not too hot !) */
5186 name = "lid status";
5187 state = 1; /* Open */
5190 name = "power source";
5194 name = "battery voltage";
5195 state = 6; /* Let's have a moderated answer :-) */
5198 name = "battery capacity remaining";
5199 state = 3; /* High */
5202 name = "battery capacity percentage";
5203 state = 1000; /* 100 % */
5206 name = "EPOW sensor";
5210 name = "battery condition cycle state";
5211 state = 0; /* none */
5214 name = "battery charge state";
5215 state = 2; /* No current flow */
5218 name = "vendor specific";
5222 pushd(RTAS_env, -3);
5225 OF_DPRINTF("Pretend sensor %d [%s] is in state %d\n", index, name, state);
5226 pushd(RTAS_env, state);
5230 #if 0 // No power management */
5231 __attribute__ (( section (".RTAS") ))
5232 static void RTAS_set_power_level (OF_env_t *RTAS_env)
5237 __attribute__ (( section (".RTAS") ))
5238 static void RTAS_get_power_level (OF_env_t *RTAS_env)
5243 __attribute__ (( section (".RTAS") ))
5244 static void RTAS_assume_power_management (OF_env_t *RTAS_env)
5249 __attribute__ (( section (".RTAS") ))
5250 static void RTAS_relinquish_power_management (OF_env_t *RTAS_env)
5256 __attribute__ (( section (".RTAS") ))
5257 static void RTAS_power_off (OF_env_t *RTAS_env)
5259 printf("RTAS was asked to switch off\n");
5260 OF_CHECK_NBARGS(RTAS_env, 2);
5264 __attribute__ (( section (".RTAS") ))
5265 static void RTAS_suspend (OF_env_t *RTAS_env)
5268 OF_CHECK_NBARGS(RTAS_env, 3);
5269 /* Pretend we don't succeed */
5270 pushd(RTAS_env, -1);
5273 __attribute__ (( section (".RTAS") ))
5274 static void RTAS_hibernate (OF_env_t *RTAS_env)
5277 OF_CHECK_NBARGS(RTAS_env, 3);
5278 /* Pretend we don't succeed */
5279 pushd(RTAS_env, -1);
5282 __attribute__ (( section (".RTAS") ))
5283 static void RTAS_system_reboot (OF_env_t *RTAS_env)
5285 printf("RTAS was asked to reboot\n");
5286 OF_CHECK_NBARGS(RTAS_env, 0);
5290 #if 0 // No power management nor SMP */
5291 __attribute__ (( section (".RTAS") ))
5292 static void RTAS_cache_control (OF_env_t *RTAS_env)
5297 __attribute__ (( section (".RTAS") ))
5298 static void RTAS_freeze_time_base (OF_env_t *RTAS_env)
5303 __attribute__ (( section (".RTAS") ))
5304 static void RTAS_thaw_time_base (OF_env_t *RTAS_env)
5309 __attribute__ (( section (".RTAS") ))
5310 static void RTAS_stop_self (OF_env_t *RTAS_env)
5315 __attribute__ (( section (".RTAS") ))
5316 static void RTAS_start_cpu (OF_env_t *RTAS_env)
5322 __attribute__ (( section (".RTAS") ))
5323 static void RTAS_instantiate (OF_env_t *RTAS_env)
5325 const unsigned char *args;
5327 uint32_t base_address;
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);
5341 __attribute__ (( section (".RTAS") ))
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)
5346 OF_prop_int_new(env, rtas, name, 0xabcd0000 | *token_next);
5347 RTAS_callbacks[*token_next] = &cb;
5351 __attribute__ (( section (".RTAS") ))
5352 void RTAS_init (void)
5355 OF_node_t *rtas, *chs;
5357 uint32_t token_next = 0, size;
5359 RTAS_env = OF_env_main;
5360 rtas = OF_node_new(RTAS_env, OF_node_root, "rtas", OF_ADDRESS_NONE);
5362 ERROR("RTAS not found\n");
5365 size = ((char *)(&_RTAS_data_end) - (char *)(&_RTAS_start) + 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");
5375 ERROR("choosen not found\n");
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");
5384 OF_prop_int_new(RTAS_env, rtas, "rtas-display-device",
5385 *(uint32_t *)stdout->value);
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);
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);
5439 * "update-flash-and-reboot"
5440 * "query-cpu-stopped-state" for SMP
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");
5448 /*****************************************************************************/
5449 /* That's all for now... */
5450 /*****************************************************************************/