Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • boot/genarch/ofw_tree.c

    r8ea0308 re731b0d  
    2929#include <ofw_tree.h>
    3030#include <ofw.h>
     31#include <ofwarch.h>
    3132#include <types.h>
    3233#include <string.h>
    3334#include <balloc.h>
    3435#include <asm.h>
    35 
    36 #define MAX_PATH_LEN    256
     36#include <memstr.h>
     37
     38#define MAX_PATH_LEN  256
    3739
    3840static ofw_tree_node_t *ofw_tree_node_alloc(void)
     
    4951static void *ofw_tree_space_alloc(size_t size)
    5052{
    51         char *addr;
    52 
    5353        /*
    5454         * What we do here is a nasty hack :-)
     
    6161         * behind the requested memory.
    6262         */
    63         addr = balloc(size + 1, size);
     63        char *addr = balloc(size + 1, size);
    6464        if (addr)
    6565                addr[size] = '\0';
     66       
    6667        return addr;
    6768}
     
    7576 * order to prevent stack from overflowing.
    7677 *
    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.
     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 *
    8284 */
    8385static void ofw_tree_node_process(ofw_tree_node_t *current_node,
    8486    ofw_tree_node_t *parent_node, phandle current)
    8587{
    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 
    9488        while (current_node) {
    9589                /*
    9690                 * Initialize node.
    9791                 */
    98                 current_node->parent = parent_node;
     92                current_node->parent = (ofw_tree_node_t *) balloc_rebase(parent_node);
    9993                current_node->peer = NULL;
    10094                current_node->child = NULL;
     
    10397                current_node->property = NULL;
    10498                current_node->device = NULL;
    105        
     99               
    106100                /*
    107101                 * Get the disambigued name.
    108102                 */
    109                 len = ofw_package_to_path(current, path, MAX_PATH_LEN);
     103                static char path[MAX_PATH_LEN + 1];
     104                size_t len = ofw_package_to_path(current, path, MAX_PATH_LEN);
    110105                if (len == -1)
    111106                        return;
    112        
     107               
    113108                path[len] = '\0';
    114                 for (i = len - 1; i >= 0 && path[i] != '/'; i--)
    115                         ;
    116                 i++;    /* do not include '/' */
    117        
     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++;
    118116                len -= i;
    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        
     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               
    128127                /*
    129128                 * Recursively process the potential child node.
    130129                 */
    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();
     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();
    136133                        if (child_node) {
    137134                                ofw_tree_node_process(child_node, current_node,
    138135                                    child);
    139                                 current_node->child = child_node;
     136                                current_node->child =
     137                                    (ofw_tree_node_t *) balloc_rebase(child_node);
    140138                        }
    141139                }
    142        
     140               
    143141                /*
    144142                 * Count properties.
    145143                 */
     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                 current_node->property =
     158                ofw_tree_property_t *property =
    159159                    ofw_tree_properties_alloc(current_node->properties);
    160                 if (!current_node->property)
     160                if (!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                
    167165                        if (i == current_node->properties)
    168166                                break;
    169                
     167                       
    170168                        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;
     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                       
    178175                        if (size) {
    179                                 void *buf;
    180                        
    181                                 buf = ofw_tree_space_alloc(size);
    182                                 if (current_node->property[i].value = buf) {
     176                                void *buf = ofw_tree_space_alloc(size);
     177                                if (buf) {
    183178                                        /*
    184179                                         * Copy property value to memory node.
    185180                                         */
    186                                         (void) ofw_get_property(current, name,
    187                                             buf, size);
     181                                        (void) ofw_get_property(current, name, buf, size);
     182                                        property[i].value = balloc_rebase(buf);
    188183                                }
    189                         } else {
    190                                 current_node->property[i].value = NULL;
    191                         }
    192                 }
    193 
     184                        } else
     185                                property[i].value = NULL;
     186                }
     187               
    194188                /* Just in case we ran out of memory. */
    195189                current_node->properties = i;
    196 
     190                current_node->property = (ofw_tree_property_t *) balloc_rebase(property);
     191               
     192               
    197193                /*
    198194                 * Iteratively process the next peer node.
     
    202198                 * risk of overflowing the stack is too real.
    203199                 */
    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;
     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);
    211205                                current_node = peer_node;
    212206                                current = peer;
     
    217211                        }
    218212                }
     213               
    219214                /*
    220215                 * No more peers on this level.
     
    226221/** Construct memory representation of OpenFirmware device tree.
    227222 *
    228  * @return              NULL on failure or pointer to the root node.
     223 * @return NULL on failure or kernel pointer to the root node.
     224 *
    229225 */
    230226ofw_tree_node_t *ofw_tree_build(void)
    231227{
    232         ofw_tree_node_t *root;
    233         phandle ssm_node;
    234         ofw_tree_node_t *ssm;
    235        
    236         root = ofw_tree_node_alloc();
     228        ofw_tree_node_t *root = ofw_tree_node_alloc();
    237229        if (root)
    238230                ofw_tree_node_process(root, NULL, ofw_root);
    239 
     231       
    240232        /*
    241233         * The firmware client interface does not automatically include the
     
    243235         * solution is to explicitly stick "ssm" to the OFW tree.
    244236         */
    245         ssm_node = ofw_find_device("/ssm@0,0");
     237        phandle ssm_node = ofw_find_device("/ssm@0,0");
    246238        if (ssm_node != -1) {
    247                 ssm = ofw_tree_node_alloc();
     239                ofw_tree_node_t *ssm = ofw_tree_node_alloc();
    248240                if (ssm) {
    249241                        ofw_tree_node_process(ssm, root,
    250242                            ofw_find_device("/ssm@0,0"));
    251243                        ssm->peer = root->child;
    252                         root->child = ssm;
     244                        root->child = (ofw_tree_node_t *) balloc_rebase(ssm);
    253245                }
    254246        }
    255247       
    256         return root;
    257 }
     248        return (ofw_tree_node_t *) balloc_rebase(root);
     249}
Note: See TracChangeset for help on using the changeset viewer.