Subversion Repositories HelenOS

Rev

Rev 1909 | Rev 3672 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1909 Rev 1973
Line 67... Line 67...
67
 
67
 
68
/** Transfer information from one OpenFirmware node into its memory representation.
68
/** Transfer information from one OpenFirmware node into its memory representation.
69
 *
69
 *
70
 * Transfer entire information from the OpenFirmware device tree 'current' node to
70
 * Transfer entire information from the OpenFirmware device tree 'current' node to
71
 * its memory representation in 'current_node'. This function recursively processes
71
 * its memory representation in 'current_node'. This function recursively processes
-
 
72
 * all node's children. Node's peers are processed iteratively in order to prevent
72
 * all node's peers and children.
73
 * stack from overflowing.
73
 *
74
 *
74
 * @param current_node  Pointer to uninitialized ofw_tree_node structure that will
75
 * @param current_node  Pointer to uninitialized ofw_tree_node structure that will
75
 *          become the memory represenation of 'current'.
76
 *          become the memory represenation of 'current'.
76
 * @param parent_node   Parent ofw_tree_node structure or NULL in case of root node.
77
 * @param parent_node   Parent ofw_tree_node structure or NULL in case of root node.
77
 * @param current   OpenFirmware phandle to the current device tree node.
78
 * @param current   OpenFirmware phandle to the current device tree node.
Line 81... Line 82...
81
{
82
{
82
    static char path[MAX_PATH_LEN+1];
83
    static char path[MAX_PATH_LEN+1];
83
    static char name[OFW_TREE_PROPERTY_MAX_NAMELEN];
84
    static char name[OFW_TREE_PROPERTY_MAX_NAMELEN];
84
    phandle peer;
85
    phandle peer;
85
    phandle child;
86
    phandle child;
86
    unsigned properties = 0;
-
 
87
    size_t len;
87
    size_t len;
88
    int i;
88
    int i;
89
 
89
 
-
 
90
    while (current_node) {
90
    /*
91
        /*
91
     * Initialize node.
92
         * Initialize node.
92
     */
93
         */
93
    current_node->parent = parent_node;
94
        current_node->parent = parent_node;
94
    current_node->peer = NULL;
95
        current_node->peer = NULL;
95
    current_node->child = NULL;
96
        current_node->child = NULL;
96
    current_node->node_handle = current;
97
        current_node->node_handle = current;
97
    current_node->properties = 0;
98
        current_node->properties = 0;
98
    current_node->property = NULL;
99
        current_node->property = NULL;
99
    current_node->device = NULL;
100
        current_node->device = NULL;
100
   
101
   
101
    /*
102
        /*
102
     * Get the disambigued name.
103
         * Get the disambigued name.
103
     */
104
         */
104
    len = ofw_package_to_path(current, path, MAX_PATH_LEN);
105
        len = ofw_package_to_path(current, path, MAX_PATH_LEN);
105
    if (len == -1)
106
        if (len == -1)
106
        return;
107
            return;
107
   
108
   
108
    path[len] = '\0';
109
        path[len] = '\0';
109
    for (i = len - 1; i >= 0 && path[i] != '/'; i--)
110
        for (i = len - 1; i >= 0 && path[i] != '/'; i--)
110
        ;
111
            ;
111
    i++;                                /* do not include '/' */
112
        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;
-
 
132
        }
-
 
133
    }
-
 
134
   
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
   
135
    /*
125
        /*
136
     * Recursively process the potential child node.
126
         * Recursively process the potential child node.
137
     */
127
         */
138
    child = ofw_get_child_node(current);
128
        child = ofw_get_child_node(current);
139
    if (child != 0 && child != -1) {
129
        if (child != 0 && child != -1) {
140
        ofw_tree_node_t *child_node;
130
            ofw_tree_node_t *child_node;
141
       
131
       
142
        child_node = ofw_tree_node_alloc();
132
            child_node = ofw_tree_node_alloc();
143
        if (child_node) {
133
            if (child_node) {
144
            ofw_tree_node_process(child_node, current_node, child);
134
                ofw_tree_node_process(child_node, current_node, child);
145
            current_node->child = child_node;
135
                current_node->child = child_node;
-
 
136
            }
146
        }
137
        }
147
    }
-
 
148
   
138
   
149
    /*
139
        /*
150
     * Count properties.
140
         * Count properties.
151
     */
141
         */
152
    name[0] = '\0';
142
        name[0] = '\0';
153
    while (ofw_next_property(current, name, name) == 1)
143
        while (ofw_next_property(current, name, name) == 1)
154
        current_node->properties++;
144
            current_node->properties++;
155
   
145
   
156
    if (!current_node->properties)
146
        if (!current_node->properties)
157
        return;
147
            return;
158
   
148
   
159
    /*
149
        /*
160
     * Copy properties.
150
         * Copy properties.
161
     */
151
         */
162
    current_node->property = ofw_tree_properties_alloc(current_node->properties);
152
        current_node->property = ofw_tree_properties_alloc(current_node->properties);
163
    if (!current_node->property)
153
        if (!current_node->property)
164
        return;
154
            return;
165
       
155
       
166
    name[0] = '\0';
156
        name[0] = '\0';
167
    for (i = 0; ofw_next_property(current, name, name) == 1; i++) {
157
        for (i = 0; ofw_next_property(current, name, name) == 1; i++) {
168
        size_t size;
158
            size_t size;
169
       
159
       
170
        if (i == current_node->properties)
160
            if (i == current_node->properties)
171
            break;
161
                break;
172
       
162
       
173
        memcpy(current_node->property[i].name, name, OFW_TREE_PROPERTY_MAX_NAMELEN);
163
            memcpy(current_node->property[i].name, name,
-
 
164
                OFW_TREE_PROPERTY_MAX_NAMELEN);
174
        current_node->property[i].name[OFW_TREE_PROPERTY_MAX_NAMELEN] = '\0';
165
            current_node->property[i].name[OFW_TREE_PROPERTY_MAX_NAMELEN] = '\0';
175
 
166
 
176
        size = ofw_get_proplen(current, name);
167
            size = ofw_get_proplen(current, name);
177
        current_node->property[i].size = size;
168
            current_node->property[i].size = size;
178
        if (size) {
169
            if (size) {
179
            void *buf;
170
                void *buf;
180
           
171
           
181
            buf = ofw_tree_space_alloc(size);
172
                buf = ofw_tree_space_alloc(size);
182
            if (current_node->property[i].value = buf) {
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;
183
                /*
202
                /*
184
                 * Copy property value to memory node.
203
                 * Process the peer in next iteration.
185
                 */
204
                 */
186
                (void) ofw_get_property(current, name, buf, size);
205
                continue;
187
            }
206
            }
188
        } else {
-
 
189
            current_node->property[i].value = NULL;
-
 
190
        }
207
        }
-
 
208
        /*
-
 
209
         * No more peers on this level.
-
 
210
         */
-
 
211
        break;
191
    }
212
    }
192
       
-
 
193
    current_node->properties = i;   /* Just in case we ran out of memory. */
-
 
194
}
213
}
195
 
214
 
196
/** Construct memory representation of OpenFirmware device tree.
215
/** Construct memory representation of OpenFirmware device tree.
197
 *
216
 *
198
 * @return NULL on failure or pointer to the root node.
217
 * @return NULL on failure or pointer to the root node.