Changeset b63a7cc in mainline


Ignore:
Timestamp:
2006-11-06T20:19:56Z (18 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2f8f480
Parents:
1b43a04
Message:

Rewrite ofw_tree_node_process() to iterate through the peer list instead of recursing.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • boot/genarch/ofw_tree.c

    r1b43a04 rb63a7cc  
    7070 * Transfer entire information from the OpenFirmware device tree 'current' node to
    7171 * its memory representation in 'current_node'. This function recursively processes
    72  * all node's peers and children.
     72 * all node's children. Node's peers are processed iteratively in order to prevent
     73 * stack from overflowing.
    7374 *
    7475 * @param current_node  Pointer to uninitialized ofw_tree_node structure that will
     
    8485        phandle peer;
    8586        phandle child;
    86         unsigned properties = 0;
    8787        size_t len;
    8888        int i;
    8989
    90         /*
    91          * Initialize node.
    92          */
    93         current_node->parent = parent_node;
    94         current_node->peer = NULL;
    95         current_node->child = NULL;
    96         current_node->node_handle = current;
    97         current_node->properties = 0;
    98         current_node->property = NULL;
    99         current_node->device = NULL;
    100        
    101         /*
    102          * Get the disambigued name.
    103          */
    104         len = ofw_package_to_path(current, path, MAX_PATH_LEN);
    105         if (len == -1)
    106                 return;
    107        
    108         path[len] = '\0';
    109         for (i = len - 1; i >= 0 && path[i] != '/'; i--)
    110                 ;
    111         i++;                                                            /* do not include '/' */
    112        
    113         len -= i;
    114         current_node->da_name = ofw_tree_space_alloc(len + 1);          /* add space for trailing '\0' */
    115         if (!current_node->da_name)
    116                 return;
    117        
    118         memcpy(current_node->da_name, &path[i], len);
    119         current_node->da_name[len] = '\0';
    120        
    121         /*
    122          * Recursively process the potential peer node.
    123          */
    124         peer = ofw_get_peer_node(current);
    125         if (peer != 0 && peer != -1) {
    126                 ofw_tree_node_t *peer_node;
    127                
    128                 peer_node = ofw_tree_node_alloc();
    129                 if (peer_node) {
    130                         ofw_tree_node_process(peer_node, parent_node, peer);
    131                         current_node->peer = peer_node;
     90        while (current_node) {
     91                /*
     92                 * Initialize node.
     93                 */
     94                current_node->parent = parent_node;
     95                current_node->peer = NULL;
     96                current_node->child = NULL;
     97                current_node->node_handle = current;
     98                current_node->properties = 0;
     99                current_node->property = NULL;
     100                current_node->device = NULL;
     101       
     102                /*
     103                 * Get the disambigued name.
     104                 */
     105                len = ofw_package_to_path(current, path, MAX_PATH_LEN);
     106                if (len == -1)
     107                        return;
     108       
     109                path[len] = '\0';
     110                for (i = len - 1; i >= 0 && path[i] != '/'; i--)
     111                        ;
     112                i++;    /* do not include '/' */
     113       
     114                len -= i;
     115
     116                /* add space for trailing '\0' */
     117                current_node->da_name = ofw_tree_space_alloc(len + 1);
     118                if (!current_node->da_name)
     119                        return;
     120       
     121                memcpy(current_node->da_name, &path[i], len);
     122                current_node->da_name[len] = '\0';
     123       
     124       
     125                /*
     126                 * Recursively process the potential child node.
     127                 */
     128                child = ofw_get_child_node(current);
     129                if (child != 0 && child != -1) {
     130                        ofw_tree_node_t *child_node;
     131               
     132                        child_node = ofw_tree_node_alloc();
     133                        if (child_node) {
     134                                ofw_tree_node_process(child_node, current_node, child);
     135                                current_node->child = child_node;
     136                        }
    132137                }
     138       
     139                /*
     140                 * Count properties.
     141                 */
     142                name[0] = '\0';
     143                while (ofw_next_property(current, name, name) == 1)
     144                        current_node->properties++;
     145       
     146                if (!current_node->properties)
     147                        return;
     148       
     149                /*
     150                 * Copy properties.
     151                 */
     152                current_node->property = ofw_tree_properties_alloc(current_node->properties);
     153                if (!current_node->property)
     154                        return;
     155               
     156                name[0] = '\0';
     157                for (i = 0; ofw_next_property(current, name, name) == 1; i++) {
     158                        size_t size;
     159               
     160                        if (i == current_node->properties)
     161                                break;
     162               
     163                        memcpy(current_node->property[i].name, name,
     164                                OFW_TREE_PROPERTY_MAX_NAMELEN);
     165                        current_node->property[i].name[OFW_TREE_PROPERTY_MAX_NAMELEN] = '\0';
     166
     167                        size = ofw_get_proplen(current, name);
     168                        current_node->property[i].size = size;
     169                        if (size) {
     170                                void *buf;
     171                       
     172                                buf = ofw_tree_space_alloc(size);
     173                                if (current_node->property[i].value = buf) {
     174                                        /*
     175                                         * Copy property value to memory node.
     176                                         */
     177                                        (void) ofw_get_property(current, name, buf, size);
     178                                }
     179                        } else {
     180                                current_node->property[i].value = NULL;
     181                        }
     182                }
     183
     184                current_node->properties = i;   /* Just in case we ran out of memory. */
     185
     186                /*
     187                 * Iteratively process the next peer node.
     188                 * Note that recursion is a bad idea here.
     189                 * Due to the topology of the OpenFirmware device tree,
     190                 * the nesting of peer nodes could be to wide and the
     191                 * risk of overflowing the stack is too real.
     192                 */
     193                peer = ofw_get_peer_node(current);
     194                if (peer != 0 && peer != -1) {
     195                        ofw_tree_node_t *peer_node;
     196               
     197                        peer_node = ofw_tree_node_alloc();
     198                        if (peer_node) {
     199                                current_node->peer = peer_node;
     200                                current_node = peer_node;
     201                                current = peer;
     202                                /*
     203                                 * Process the peer in next iteration.
     204                                 */
     205                                continue;
     206                        }
     207                }
     208                /*
     209                 * No more peers on this level.
     210                 */
     211                break;
    133212        }
    134        
    135         /*
    136          * Recursively process the potential child node.
    137          */
    138         child = ofw_get_child_node(current);
    139         if (child != 0 && child != -1) {
    140                 ofw_tree_node_t *child_node;
    141                
    142                 child_node = ofw_tree_node_alloc();
    143                 if (child_node) {
    144                         ofw_tree_node_process(child_node, current_node, child);
    145                         current_node->child = child_node;
    146                 }
    147         }
    148        
    149         /*
    150          * Count properties.
    151          */
    152         name[0] = '\0';
    153         while (ofw_next_property(current, name, name) == 1)
    154                 current_node->properties++;
    155        
    156         if (!current_node->properties)
    157                 return;
    158        
    159         /*
    160          * Copy properties.
    161          */
    162         current_node->property = ofw_tree_properties_alloc(current_node->properties);
    163         if (!current_node->property)
    164                 return;
    165                
    166         name[0] = '\0';
    167         for (i = 0; ofw_next_property(current, name, name) == 1; i++) {
    168                 size_t size;
    169                
    170                 if (i == current_node->properties)
    171                         break;
    172                
    173                 memcpy(current_node->property[i].name, name, OFW_TREE_PROPERTY_MAX_NAMELEN);
    174                 current_node->property[i].name[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;
    180                        
    181                         buf = ofw_tree_space_alloc(size);
    182                         if (current_node->property[i].value = buf) {
    183                                 /*
    184                                  * Copy property value to memory node.
    185                                  */
    186                                 (void) ofw_get_property(current, name, buf, size);
    187                         }
    188                 } else {
    189                         current_node->property[i].value = NULL;
    190                 }
    191         }
    192                
    193         current_node->properties = i;   /* Just in case we ran out of memory. */
    194213}
    195214
Note: See TracChangeset for help on using the changeset viewer.