1 \ *****************************************************************************
2 \ * Copyright (c) 2011 IBM Corporation
3 \ * All rights reserved.
4 \ * This program and the accompanying materials
5 \ * are made available under the terms of the BSD License
6 \ * which accompanies this distribution, and is available at
7 \ * http://www.opensource.org/licenses/bsd-license.php
10 \ * IBM Corporation - initial implementation
11 \ ****************************************************************************/
14 TRUE VALUE fdt-cas-fix?
17 fdt-start 0 = IF -1 throw THEN
22 4 field >fdth_struct_off
23 4 field >fdth_string_off
24 4 field >fdth_rsvmap_off
26 4 field >fdth_compat_vers
27 4 field >fdth_boot_cpu
28 4 field >fdth_string_size
29 4 field >fdth_struct_size
32 h# d00dfeed constant OF_DT_HEADER
33 h# 1 constant OF_DT_BEGIN_NODE
34 h# 2 constant OF_DT_END_NODE
35 h# 3 constant OF_DT_PROP
36 h# 4 constant OF_DT_NOP
37 h# 9 constant OF_DT_END
39 \ Create some variables early
40 0 value fdt-start-addr
44 : fdt-init ( fdt-start -- )
46 dup dup >fdth_struct_off l@ + to fdt-struct
47 dup dup >fdth_string_off l@ + to fdt-strings
52 \ Dump fdt header for all to see and check FDT validity
53 : fdt-check-header ( -- )
54 fdt-start-addr dup 0 = IF
55 ." No flat device tree !" cr drop -1 throw EXIT THEN
58 ." Flat device tree header at 0x" dup . s" :" type cr
59 ." magic : 0x" dup >fdth_magic l@ . cr
60 ." total size : 0x" dup >fdth_tsize l@ . cr
61 ." offset to struct : 0x" dup >fdth_struct_off l@ . cr
62 ." offset to strings: 0x" dup >fdth_string_off l@ . cr
63 ." offset to rsvmap : 0x" dup >fdth_rsvmap_off l@ . cr
64 ." version : " dup >fdth_version l@ decimal . hex cr
65 ." last compat vers : " dup >fdth_compat_vers l@ decimal . hex cr
66 dup >fdth_version l@ 2 >= IF
67 ." boot CPU : 0x" dup >fdth_boot_cpu l@ . cr
69 dup >fdth_version l@ 3 >= IF
70 ." strings size : 0x" dup >fdth_string_size l@ . cr
72 dup >fdth_version l@ 17 >= IF
73 ." struct size : 0x" dup >fdth_struct_size l@ . cr
76 dup >fdth_magic l@ OF_DT_HEADER <> IF
77 ." Flat device tree has incorrect magic value !" cr
80 dup >fdth_version l@ 10 < IF
81 ." Flat device tree has usupported version !" cr
89 \ Fetch next tag, skip nops and increment address
90 : fdt-next-tag ( addr -- nextaddr tag )
91 0 ( dummy tag on stack for loop )
93 drop ( drop previous tag )
94 dup l@ ( read new tag )
95 swap 4 + swap ( increment addr )
96 dup OF_DT_NOP <> UNTIL ( loop until not nop )
99 \ Parse unit name and advance addr
100 : fdt-fetch-unit ( addr -- addr $name )
101 dup from-cstring \ get string size
102 2dup + 1 + 3 + fffffffc and -rot
105 \ Update unit with information from the reg property...
106 \ ... this is required for the PCI nodes for example.
107 : fdt-reg-unit ( prop-addr prop-len -- )
108 decode-phys ( prop-addr' prop-len' phys.lo ... phys.hi )
109 set-unit ( prop-addr' prop-len' )
113 \ Lookup a string by index
114 : fdt-fetch-string ( index -- str-addr str-len )
115 fdt-strings + dup from-cstring
118 : fdt-create-dec s" decode-unit" $CREATE , DOES> @ hex64-decode-unit ;
119 : fdt-create-enc s" encode-unit" $CREATE , DOES> @ hex64-encode-unit ;
121 \ Check whether array contains an zero-terminated ASCII string:
122 : fdt-prop-is-string? ( addr len -- string? )
123 dup 1 < IF 2drop FALSE EXIT THEN \ Check for valid length
125 2dup + c@ 0<> IF 2drop FALSE EXIT THEN \ Check zero-termination
129 \ Encode fdt property to OF property
130 : fdt-encode-prop ( addr len -- )
131 2dup fdt-prop-is-string? IF
138 \ Method to unflatten a node
139 : fdt-unflatten-node ( start -- end )
140 \ this can and will recurse
143 \ Get & check first tag of node ( addr -- addr)
144 fdt-next-tag dup OF_DT_BEGIN_NODE <> IF
145 s" Weird tag 0x" type . " at start of node" type cr
151 \ Parse name, split unit address
153 dup 0 = IF drop drop " /" THEN
158 \ Set preliminary unit address - might get overwritten by reg property
160 " #address-cells" get-parent get-package-property IF
171 fdt-next-tag dup OF_DT_END_NODE <>
175 drop dup ( drop tag, dup addr : a1 a1 )
176 dup l@ dup rot 4 + ( fetch size, stack is : a1 s s a2)
177 dup l@ swap 4 + ( fetch nameid, stack is : a1 s s i a3 )
178 rot ( we now have: a1 s i a3 s )
179 fdt-encode-prop rot ( a1 s pa ps i)
180 fdt-fetch-string ( a1 s pa ps na ns )
182 2swap 2dup fdt-reg-unit 2swap
185 + 8 + 3 + fffffffc and
186 ELSE dup OF_DT_BEGIN_NODE = IF
193 REPEAT drop \ drop tag
195 \ Create encode/decode unit
196 " #address-cells" get-node get-package-property IF ELSE
197 decode-int dup fdt-create-dec fdt-create-enc 2drop
206 ." Unflattening device tree..." cr THEN
207 fdt-struct fdt-unflatten-node drop
215 \ XXX FIXME Handle more than one memory node, and deal
216 \ with RMA vs. full access
217 " /memory@0" find-device
218 " reg" get-node get-package-property IF throw -1 THEN
220 \ XXX FIXME Assume one entry only in "reg" property for now
221 decode-phys 2drop decode-phys
222 my-#address-cells 1 > IF 20 << or THEN
225 dup ." Memory size: " . cr
227 \ claim.fs already released the memory between 0 and MIN-RAM-SIZE,
228 \ so we've got only to release the remaining memory now:
229 MIN-RAM-SIZE swap MIN-RAM-SIZE - release
235 \ Claim fdt memory and reserve map
238 dup dup >fdth_tsize l@ 0 claim drop
239 dup >fdth_rsvmap_off l@ +
241 dup dup x@ swap 8 + x@
245 2dup swap ." Reserve map entry: " . ." : " . cr
249 REPEAT drop drop drop
254 \ The following functions are use to replace the FDT phandle and
255 \ linux,phandle properties with our own OF1275 phandles...
257 \ This is used to check whether we successfully replaced a phandle value
258 0 VALUE (fdt-phandle-replaced)
260 \ Replace phandle value in "interrupt-map" property
261 : fdt-replace-interrupt-map ( old new prop-addr prop-len -- old new )
263 dup ( old new prop-addr prop-len prop-len )
265 \ This is a little bit ugly ... we're accessing the property at
266 \ hard-coded offsets instead of analyzing it completely...
267 swap dup 10 + ( old new prop-len prop-addr prop-addr+10 )
269 \ it matches the old phandle value!
271 TRUE TO (fdt-phandle-replaced)
275 ( old new prop-len prop-addr )
277 ( old new new-prop-addr new-prop-len )
282 \ Replace one FDT phandle "old" with a OF1275 phandle "new" in the
284 : fdt-replace-all-phandles ( old new node -- )
285 \ ." Replacing in " dup node>path type cr
287 s" interrupt-map" r@ get-property 0= IF
288 ( old new prop-addr prop-len R: node )
289 fdt-replace-interrupt-map
291 s" interrupt-parent" r@ get-property 0= IF
292 ( old new prop-addr prop-len R: node )
293 decode-int -rot 2drop ( old new val R: node )
294 2 pick = IF ( old new R: node )
295 dup encode-int s" interrupt-parent" r@ set-property
296 TRUE TO (fdt-phandle-replaced)
299 \ ... add more properties that have to be fixed here ...
301 \ Now recurse over all child nodes: ( old new node )
311 \ Check whether a node has "phandle" or "linux,phandle" properties
313 : fdt-fix-node-phandle ( node -- )
315 FALSE TO (fdt-phandle-replaced)
316 s" phandle" r@ get-property 0= IF
317 decode-int ( p-addr2 p-len2 val )
318 \ ." found phandle: " dup . cr
319 r@ s" /" find-node ( p-addr2 p-len2 val node root )
320 fdt-replace-all-phandles ( p-addr2 p-len2 )
322 (fdt-phandle-replaced) IF
324 s" phandle" delete-property
325 s" linux,phandle" delete-property
328 cr ." Warning: Did not replace phandle in " r@ node>path type cr
335 \ Recursively walk through all nodes to fix their phandles:
336 : fdt-fix-phandles ( node -- )
337 \ ." fixing phandles of " dup node>path type cr
338 dup fdt-fix-node-phandle
349 : fdt-create-cas-node ( name -- )
351 2dup " memory@" find-substr 0 = IF
352 fdt-debug IF ." Creating memory@ " cr THEN
354 2dup " @" find-substr nip device-name \ Parse the node name
356 2dup " @" find-substr rot over + 1 + -rot - 1 - \ Jump to addr afte "@"
357 parse-2int nip xlsplit set-unit \ Parse and set unit
360 2dup " ibm,dynamic-reconfiguration-memory" find-substr 0 = IF
361 fdt-debug IF ." Creating ibm,dynamic-reconfiguration-memory " cr THEN
367 false to fdt-cas-fix?
368 ." Node not supported " cr
373 find-node ?dup 0 <> IF set-node THEN
376 : fdt-fix-cas-node ( start -- end )
378 fdt-next-tag dup OF_DT_BEGIN_NODE <> IF
380 false to fdt-cas-fix?
384 dup 0 = IF drop drop " /" THEN
388 1 + + \ Add the string len +@
392 fdt-debug IF ." Setting node: " 2dup type cr THEN
393 2dup find-node ?dup 0 <> IF
396 fdt-debug IF ." Node not found, creating " 2dup type cr THEN
399 fdt-debug IF ." Current now: " pwd cr THEN
401 fdt-next-tag dup OF_DT_END_NODE <>
404 fdt-debug IF ." Found property " cr THEN
405 drop dup ( drop tag, dup addr : a1 a1 )
406 dup l@ dup rot 4 + ( fetch size, stack is : a1 s s a2)
407 dup l@ swap 4 + ( fetch nameid, stack is : a1 s s i a3 )
408 rot ( we now have: a1 s i a3 s )
409 fdt-encode-prop rot ( a1 s pa ps i)
410 fdt-fetch-string ( a1 s pa ps na ns )
412 fdt-debug IF ." Setting property done " cr THEN
413 + 8 + 3 + fffffffc and
414 ELSE dup OF_DT_BEGIN_NODE = IF
419 fdt-debug IF ." Returning back " pwd cr THEN
423 false to fdt-cas-fix?
431 : fdt-fix-cas-success
435 s" /" find-node fdt-fix-phandles