Lines 42-63
Link Here
|
42 |
} |
42 |
} |
43 |
|
43 |
|
44 |
static void |
44 |
static void |
45 |
add_node_to_fdt(void *buffer, phandle_t node, int fdt_offset) |
45 |
add_node_to_fdt(void *buffer, phandle_t parent_node, int fdt_offset) |
46 |
{ |
46 |
{ |
47 |
int i, child_offset, error; |
47 |
int i, child_offset, error; |
48 |
char name[255], *lastprop, *subname; |
48 |
char name[255+1], *lastprop, *subname; // +1 added for always having a trailing '\0' position. |
49 |
void *propbuf; |
49 |
void *propbuf; |
50 |
ssize_t proplen; |
50 |
ssize_t proplen; |
51 |
|
51 |
|
52 |
lastprop = NULL; |
52 |
// WARNING: fdt_setprop adds to the beginning of the property sequence. So, |
53 |
while (OF_nextprop(node, lastprop, name) > 0) { |
53 |
// to avoid reversing the sequence, use it last to first for the originals. |
54 |
proplen = OF_getproplen(node, name); |
|
|
55 |
|
54 |
|
|
|
55 |
int prop_cnt= 0; |
56 |
lastprop= NULL; |
57 |
while (0<OF_nextprop(parent_node, lastprop, name)) { |
58 |
prop_cnt++; |
59 |
lastprop= name; |
60 |
} |
61 |
int prop_want= prop_cnt; |
62 |
for (; 0!=prop_want; prop_want--) { |
63 |
lastprop= NULL; |
64 |
int prop_at= 0; |
65 |
for(; prop_at!=prop_want; prop_at++) { |
66 |
OF_nextprop(parent_node, lastprop, name); |
67 |
lastprop= name; |
68 |
} |
69 |
|
70 |
proplen = OF_getproplen(parent_node, name); |
71 |
|
56 |
/* Detect and correct for errors and strangeness */ |
72 |
/* Detect and correct for errors and strangeness */ |
57 |
if (proplen < 0) |
73 |
if (proplen < 0) { |
|
|
74 |
printf("proplen was negative: %jd while adding property %s to " |
75 |
"parent_node %d\n", (intmax_t)proplen, name, fdt_offset); |
58 |
proplen = 0; |
76 |
proplen = 0; |
59 |
if (proplen > 1024) |
77 |
} |
|
|
78 |
if (proplen > 1024) { |
79 |
printf("proplen was large: %jd while adding property %s to " |
80 |
"parent_node %d\n", (intmax_t)proplen, name, fdt_offset); |
81 |
#if 0 |
82 |
// WARNING: Some Macintoshes end up with video-card driver code as properties. |
83 |
// An example PowerMac7,2 configuration had 2 such properties, each |
84 |
// being 96306 bytes in size. If these were ever used in a truncated |
85 |
// from things would be messed up. So do not force truncations. There |
86 |
// are a few other, smaller properties that bigger than 1 KBytes. I |
87 |
// checked: fdt_platform_load_dtb's 409600 buflen is more than |
88 |
// sufficient for the example context. |
89 |
|
60 |
proplen = 1024; |
90 |
proplen = 1024; |
|
|
91 |
#endif |
92 |
} |
61 |
|
93 |
|
62 |
propbuf = malloc(proplen); |
94 |
propbuf = malloc(proplen); |
63 |
if (propbuf == NULL) { |
95 |
if (propbuf == NULL) { |
Lines 64-88
Link Here
|
64 |
printf("Cannot allocate memory for prop %s\n", name); |
96 |
printf("Cannot allocate memory for prop %s\n", name); |
65 |
return; |
97 |
return; |
66 |
} |
98 |
} |
67 |
OF_getprop(node, name, propbuf, proplen); |
99 |
OF_getprop(parent_node, name, propbuf, proplen); |
68 |
error = fdt_setprop(buffer, fdt_offset, name, propbuf, proplen); |
100 |
error = fdt_setprop(buffer, fdt_offset, name, propbuf, proplen); |
69 |
free(propbuf); |
101 |
free(propbuf); |
70 |
lastprop = name; |
|
|
71 |
if (error) |
102 |
if (error) |
72 |
printf("Error %d adding property %s to " |
103 |
printf("Error %d adding property %s to " |
73 |
"node %d\n", error, name, fdt_offset); |
104 |
"parent_node %d\n", error, name, fdt_offset); |
74 |
} |
105 |
} |
75 |
|
106 |
|
76 |
if (!OF_hasprop(node, "phandle") && !OF_hasprop(node, "linux,phandle") |
107 |
if (!OF_hasprop(parent_node, "phandle") && !OF_hasprop(parent_node, "linux,phandle") |
77 |
&& !OF_hasprop(node, "ibm,phandle")) |
108 |
&& !OF_hasprop(parent_node, "ibm,phandle")) |
78 |
fdt_setprop(buffer, fdt_offset, "phandle", &node, sizeof(node)); |
109 |
fdt_setprop(buffer, fdt_offset, "phandle", &parent_node, sizeof(parent_node)); |
79 |
|
110 |
|
80 |
for (node = OF_child(node); node > 0; node = OF_peer(node)) { |
111 |
// WARNING: fdt_add_subnode adds to the beginning of the node sequence (after |
81 |
OF_package_to_path(node, name, sizeof(name)); |
112 |
// the properties). So, to avoid reversing the sequence, use it last to first |
82 |
subname = strrchr(name, '/'); |
113 |
// for the originals. |
|
|
114 |
|
115 |
// WARNING: openfirmware's package-to-path(nd,nm,len) does not place a trailing '\0' |
116 |
// character in nm when it returns a full_str_len with len<=full_str_len . |
117 |
// For full_str_len<len, a trailing '\0' is placed at nm[full_str_len]. |
118 |
|
119 |
int child_cnt= 0; |
120 |
phandle_t node= OF_child(parent_node); |
121 |
for (; 0<node; node= OF_peer(node)) { |
122 |
child_cnt++; |
123 |
} |
124 |
name[255]= '\0'; // Avoid OF_package_to_path leaving no '\0' at end of long path. |
125 |
int node_want= child_cnt; |
126 |
for (; 0!=node_want; node_want--) { |
127 |
node= OF_child(parent_node); |
128 |
int node_at= 1; |
129 |
for (; node_at!=node_want; node_at++) { |
130 |
node = OF_peer(node); |
131 |
} |
132 |
|
133 |
int full_str_len= OF_package_to_path(node, name, sizeof(name)-1); // Avoids having trailing '\0' missing. |
134 |
if (-1==full_str_len) { // Highly unlikely. |
135 |
printf("add_node_to_fdt got -1 return from OF_packakge_to_path\n"); |
136 |
continue; |
137 |
} |
138 |
|
139 |
// WARNING: For some Macintoshes, name can sometimes contain '\0' characters |
140 |
// in the middle! So there is avoidance-code because the fdt code is |
141 |
// not designed for such. |
142 |
|
143 |
// WARNING: For some Macintoshes, multiple nodes under a parent can have the |
144 |
// same full-path-text (name here). I've adjusted fdt_add_subnode to |
145 |
// allow such to be recorded so that such Macintosh information is |
146 |
// not lost. |
147 |
|
148 |
// full_str_len omits the offical trailing '\0' position. |
149 |
// full_str_len is *not* limited by the sizeof(name)-1 value above: it reports |
150 |
// the space needed to get all the text (ignoring the official trailing '\0'). |
151 |
if (0==full_str_len) { // Highly unlikely. |
152 |
printf("Error: Node name has no bytes before trailing null byte\n"); |
153 |
continue; |
154 |
} |
155 |
if (255<full_str_len) { |
156 |
printf("Error: Node path %s (truncated), needs more than 255+1 bytes\n", name); |
157 |
continue; |
158 |
} |
159 |
|
160 |
// Eliminate any internal '\0' full path characters: makes saved results more standard |
161 |
// and, so, fdt-supported. The extra Macintosh '\0' characters are non-essential. |
162 |
char *from_pos= name; |
163 |
char *to_pos= name; |
164 |
char *original_end= name+full_str_len; |
165 |
while (from_pos<original_end) { |
166 |
if ('\0'!=*from_pos) |
167 |
*to_pos++= *from_pos; |
168 |
else |
169 |
full_str_len--; |
170 |
from_pos++; |
171 |
} |
172 |
*to_pos= '\0'; |
173 |
if (to_pos==name) { // Highly unlikely. |
174 |
printf("Error: Adjusted node name has no bytes before trailing null byte\n"); |
175 |
continue; |
176 |
} |
177 |
|
178 |
subname= strrchr(name,'/'); |
179 |
if (NULL==subname) { // Highly unlikely. |
180 |
printf("Error: Node name %s has no '/'\n", name); |
181 |
continue; |
182 |
} |
83 |
subname++; |
183 |
subname++; |
84 |
child_offset = fdt_add_subnode(buffer, fdt_offset, subname); |
184 |
child_offset = fdt_add_subnode(buffer, fdt_offset, subname); |
85 |
if (child_offset < 0) { |
185 |
if (child_offset < 0) { // Note: fdt_add_subnode was modified to allow duplicate paths. |
86 |
printf("Error %d adding node %s (%s), skipping\n", |
186 |
printf("Error %d adding node %s (%s), skipping\n", |
87 |
child_offset, name, subname); |
187 |
child_offset, name, subname); |
88 |
continue; |
188 |
continue; |
Lines 135-140
Link Here
|
135 |
/* Mark RTAS private data area reserved */ |
235 |
/* Mark RTAS private data area reserved */ |
136 |
fdt_add_mem_rsv(fdtp, base, len); |
236 |
fdt_add_mem_rsv(fdtp, base, len); |
137 |
} else { |
237 |
} else { |
|
|
238 |
#if 0 |
239 |
// Without the /memory0/available information the example |
240 |
// MPC750 iMac G3 PowerMac4,1 crashes shortly after booting |
241 |
// --from trashed memory contents from use of RAM that was |
242 |
// not excluded when available was being deleted. |
243 |
// |
244 |
// My guess is that openfirmware may also report to |
245 |
// avoid address ranges for which other things in the |
246 |
// environment are the cause, not just openfirmware's |
247 |
// internal memory use. |
248 |
// |
249 |
// So do not do the following . . . |
250 |
|
138 |
/* |
251 |
/* |
139 |
* Remove /memory/available properties, which reflect long-gone |
252 |
* Remove /memory/available properties, which reflect long-gone |
140 |
* OF state. Note that this doesn't work if we need RTAS still, |
253 |
* OF state. Note that this doesn't work if we need RTAS still, |
Lines 141-148
Link Here
|
141 |
* since that's part of the firmware. |
254 |
* since that's part of the firmware. |
142 |
*/ |
255 |
*/ |
143 |
offset = fdt_path_offset(fdtp, "/memory@0"); |
256 |
offset = fdt_path_offset(fdtp, "/memory@0"); |
|
|
257 |
if (offset<=0) offset= fdt_path_offset(fdtp, "/memory@0,0"); // G5's |
144 |
if (offset > 0) |
258 |
if (offset > 0) |
145 |
fdt_delprop(fdtp, offset, "available"); |
259 |
fdt_delprop(fdtp, offset, "available"); |
|
|
260 |
#endif |
146 |
} |
261 |
} |
147 |
|
262 |
|
148 |
|
263 |
|
Lines 184-200
Link Here
|
184 |
{ |
299 |
{ |
185 |
void *buffer; |
300 |
void *buffer; |
186 |
size_t buflen = 409600; |
301 |
size_t buflen = 409600; |
|
|
302 |
int ret; |
187 |
|
303 |
|
188 |
buffer = malloc(buflen); |
304 |
buffer = malloc(buflen); |
189 |
fdt_create_empty_tree(buffer, buflen); |
305 |
if (NULL==buffer) { |
190 |
add_node_to_fdt(buffer, OF_peer(0), fdt_path_offset(buffer, "/")); |
306 |
printf("fdt_platform_load_dtb: Large buffer malloc failed.\n"); |
191 |
ofwfdt_fixups(buffer); |
307 |
return 1; // Give up. |
192 |
fdt_pack(buffer); |
308 |
} |
193 |
|
309 |
|
194 |
fdt_load_dtb_addr(buffer); |
310 |
ret= fdt_create_empty_tree(buffer, buflen); |
|
|
311 |
if (ret) { |
312 |
printf("fdt_platform_load_dtb: fdt_create_empty_tree failed\n"); |
313 |
goto cleanup_and_return; |
314 |
} |
315 |
|
316 |
add_node_to_fdt(buffer, OF_peer(0), fdt_path_offset(buffer, "/")); |
317 |
ofwfdt_fixups(buffer); |
318 |
|
319 |
ret= fdt_pack(buffer); |
320 |
if (ret) { |
321 |
printf("fdt_platform_load_dtb: fdt_pack failed\n"); |
322 |
goto cleanup_and_return; |
323 |
} |
324 |
|
325 |
ret= fdt_load_dtb_addr(buffer); |
326 |
if (ret) { |
327 |
printf("fdt_platform_load_dtb: fdt_load_dtb_addr failed\n"); |
328 |
goto cleanup_and_return; |
329 |
} |
330 |
|
331 |
cleanup_and_return: |
195 |
free(buffer); |
332 |
free(buffer); |
196 |
|
333 |
return ret; |
197 |
return (0); |
|
|
198 |
} |
334 |
} |
199 |
|
335 |
|
200 |
void |
336 |
void |