Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • boot/genarch/ofw_tree.c

    re731b0d r8ea0308  
    2929#include <ofw_tree.h>
    3030#include <ofw.h>
    31 #include <ofwarch.h>
    3231#include <types.h>
    3332#include <string.h>
    3433#include <balloc.h>
    3534#include <asm.h>
    36 #include <memstr.h>
    37 
    38 #define MAX_PATH_LEN  256
     35
     36#define MAX_PATH_LEN    256
    3937
    4038static ofw_tree_node_t *ofw_tree_node_alloc(void)
     
    5149static void *ofw_tree_space_alloc(size_t size)
    5250{
     51        char *addr;
     52
    5353        /*
    5454         * What we do here is a nasty hack :-)
     
    6161         * behind the requested memory.
    6262         */
    63         char *addr = balloc(size + 1, size);
     63        addr = balloc(size + 1, size);
    6464        if (addr)
    6565                addr[size] = '\0';
    66        
    6766        return addr;
    6867}
     
    7675 * order to prevent stack from overflowing.
    7776 *
    78  * @param current_node Pointer to uninitialized ofw_tree_node structure that
    79  *                     will become the memory represenation of 'current'.
    80  * @param parent_node  Parent ofw_tree_node structure or NULL in case of root
    81  *                     node.
    82  * @param current      OpenFirmware phandle to the current device tree node.
    83  *
     77 * @param current_node  Pointer to uninitialized ofw_tree_node structure that
     78 *                      will become the memory represenation of 'current'.
     79 * @param parent_node   Parent ofw_tree_node structure or NULL in case of root
     80 *                      node.
     81 * @param current       OpenFirmware phandle to the current device tree node.
    8482 */
    8583static void ofw_tree_node_process(ofw_tree_node_t *current_node,
    8684    ofw_tree_node_t *parent_node, phandle current)
    8785{
     86        static char path[MAX_PATH_LEN + 1];
     87        static char name[OFW_TREE_PROPERTY_MAX_NAMELEN];
     88        static char name2[OFW_TREE_PROPERTY_MAX_NAMELEN];
     89        phandle peer;
     90        phandle child;
     91        size_t len;
     92        int i;
     93
    8894        while (current_node) {
    8995                /*
    9096                 * Initialize node.
    9197                 */
    92                 current_node->parent = (ofw_tree_node_t *) balloc_rebase(parent_node);
     98                current_node->parent = parent_node;
    9399                current_node->peer = NULL;
    94100                current_node->child = NULL;
     
    97103                current_node->property = NULL;
    98104                current_node->device = NULL;
    99                
     105       
    100106                /*
    101107                 * Get the disambigued name.
    102108                 */
    103                 static char path[MAX_PATH_LEN + 1];
    104                 size_t len = ofw_package_to_path(current, path, MAX_PATH_LEN);
     109                len = ofw_package_to_path(current, path, MAX_PATH_LEN);
    105110                if (len == -1)
    106111                        return;
    107                
     112       
    108113                path[len] = '\0';
    109                
    110                 /* Find last slash */
    111                 int i;
    112                 for (i = len - 1; (i >= 0) && (path[i] != '/'); i--);
    113                
    114                 /* Do not include the slash */
    115                 i++;
     114                for (i = len - 1; i >= 0 && path[i] != '/'; i--)
     115                        ;
     116                i++;    /* do not include '/' */
     117       
    116118                len -= i;
    117                
    118                 /* Add space for trailing '\0' */
    119                 char *da_name = ofw_tree_space_alloc(len + 1);
    120                 if (!da_name)
    121                         return;
    122                
    123                 memcpy(da_name, &path[i], len);
    124                 da_name[len] = '\0';
    125                 current_node->da_name = (char *) balloc_rebase(da_name);
    126                
     119
     120                /* add space for trailing '\0' */
     121                current_node->da_name = ofw_tree_space_alloc(len + 1);
     122                if (!current_node->da_name)
     123                        return;
     124       
     125                memcpy(current_node->da_name, &path[i], len);
     126                current_node->da_name[len] = '\0';
     127       
    127128                /*
    128129                 * Recursively process the potential child node.
    129130                 */
    130                 phandle child = ofw_get_child_node(current);
    131                 if ((child != 0) && (child != -1)) {
    132                         ofw_tree_node_t *child_node = ofw_tree_node_alloc();
     131                child = ofw_get_child_node(current);
     132                if (child != 0 && child != -1) {
     133                        ofw_tree_node_t *child_node;
     134               
     135                        child_node = ofw_tree_node_alloc();
    133136                        if (child_node) {
    134137                                ofw_tree_node_process(child_node, current_node,
    135138                                    child);
    136                                 current_node->child =
    137                                     (ofw_tree_node_t *) balloc_rebase(child_node);
     139                                current_node->child = child_node;
    138140                        }
    139141                }
    140                
     142       
    141143                /*
    142144                 * Count properties.
    143145                 */
    144                 static char name[OFW_TREE_PROPERTY_MAX_NAMELEN];
    145                 static char name2[OFW_TREE_PROPERTY_MAX_NAMELEN];
    146146                name[0] = '\0';
    147147                while (ofw_next_property(current, name, name2) == 1) {
     
    149149                        memcpy(name, name2, OFW_TREE_PROPERTY_MAX_NAMELEN);
    150150                }
    151                
     151
    152152                if (!current_node->properties)
    153153                        return;
    154                
     154       
    155155                /*
    156156                 * Copy properties.
    157157                 */
    158                 ofw_tree_property_t *property =
     158                current_node->property =
    159159                    ofw_tree_properties_alloc(current_node->properties);
    160                 if (!property)
     160                if (!current_node->property)
    161161                        return;
    162162               
    163163                name[0] = '\0';
    164164                for (i = 0; ofw_next_property(current, name, name2) == 1; i++) {
     165                        size_t size;
     166               
    165167                        if (i == current_node->properties)
    166168                                break;
     169               
     170                        memcpy(name, name2, OFW_TREE_PROPERTY_MAX_NAMELEN);
     171                        memcpy(current_node->property[i].name, name,
     172                            OFW_TREE_PROPERTY_MAX_NAMELEN);
     173                        current_node->property[i].name[
     174                            OFW_TREE_PROPERTY_MAX_NAMELEN] = '\0';
     175
     176                        size = ofw_get_proplen(current, name);
     177                        current_node->property[i].size = size;
     178                        if (size) {
     179                                void *buf;
    167180                       
    168                         memcpy(name, name2, OFW_TREE_PROPERTY_MAX_NAMELEN);
    169                         memcpy(property[i].name, name, OFW_TREE_PROPERTY_MAX_NAMELEN);
    170                         property[i].name[OFW_TREE_PROPERTY_MAX_NAMELEN] = '\0';
    171                        
    172                         size_t size = ofw_get_proplen(current, name);
    173                         property[i].size = size;
    174                        
    175                         if (size) {
    176                                 void *buf = ofw_tree_space_alloc(size);
    177                                 if (buf) {
     181                                buf = ofw_tree_space_alloc(size);
     182                                if (current_node->property[i].value = buf) {
    178183                                        /*
    179184                                         * Copy property value to memory node.
    180185                                         */
    181                                         (void) ofw_get_property(current, name, buf, size);
    182                                         property[i].value = balloc_rebase(buf);
     186                                        (void) ofw_get_property(current, name,
     187                                            buf, size);
    183188                                }
    184                         } else
    185                                 property[i].value = NULL;
    186                 }
    187                
     189                        } else {
     190                                current_node->property[i].value = NULL;
     191                        }
     192                }
     193
    188194                /* Just in case we ran out of memory. */
    189195                current_node->properties = i;
    190                 current_node->property = (ofw_tree_property_t *) balloc_rebase(property);
    191                
    192                
     196
    193197                /*
    194198                 * Iteratively process the next peer node.
     
    198202                 * risk of overflowing the stack is too real.
    199203                 */
    200                 phandle peer = ofw_get_peer_node(current);
    201                 if ((peer != 0) && (peer != -1)) {
    202                         ofw_tree_node_t *peer_node = ofw_tree_node_alloc();
    203                         if (peer_node) {
    204                                 current_node->peer = (ofw_tree_node_t *) balloc_rebase(peer_node);
     204                peer = ofw_get_peer_node(current);
     205                if (peer != 0 && peer != -1) {
     206                        ofw_tree_node_t *peer_node;
     207               
     208                        peer_node = ofw_tree_node_alloc();
     209                        if (peer_node) {
     210                                current_node->peer = peer_node;
    205211                                current_node = peer_node;
    206212                                current = peer;
     
    211217                        }
    212218                }
    213                
    214219                /*
    215220                 * No more peers on this level.
     
    221226/** Construct memory representation of OpenFirmware device tree.
    222227 *
    223  * @return NULL on failure or kernel pointer to the root node.
    224  *
     228 * @return              NULL on failure or pointer to the root node.
    225229 */
    226230ofw_tree_node_t *ofw_tree_build(void)
    227231{
    228         ofw_tree_node_t *root = ofw_tree_node_alloc();
     232        ofw_tree_node_t *root;
     233        phandle ssm_node;
     234        ofw_tree_node_t *ssm;
     235       
     236        root = ofw_tree_node_alloc();
    229237        if (root)
    230238                ofw_tree_node_process(root, NULL, ofw_root);
    231        
     239
    232240        /*
    233241         * The firmware client interface does not automatically include the
     
    235243         * solution is to explicitly stick "ssm" to the OFW tree.
    236244         */
    237         phandle ssm_node = ofw_find_device("/ssm@0,0");
     245        ssm_node = ofw_find_device("/ssm@0,0");
    238246        if (ssm_node != -1) {
    239                 ofw_tree_node_t *ssm = ofw_tree_node_alloc();
     247                ssm = ofw_tree_node_alloc();
    240248                if (ssm) {
    241249                        ofw_tree_node_process(ssm, root,
    242250                            ofw_find_device("/ssm@0,0"));
    243251                        ssm->peer = root->child;
    244                         root->child = (ofw_tree_node_t *) balloc_rebase(ssm);
     252                        root->child = ssm;
    245253                }
    246254        }
    247255       
    248         return (ofw_tree_node_t *) balloc_rebase(root);
    249 }
     256        return root;
     257}
Note: See TracChangeset for help on using the changeset viewer.