summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/board-qemu/slof/fdt.fs
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/SLOF/board-qemu/slof/fdt.fs')
-rw-r--r--qemu/roms/SLOF/board-qemu/slof/fdt.fs435
1 files changed, 435 insertions, 0 deletions
diff --git a/qemu/roms/SLOF/board-qemu/slof/fdt.fs b/qemu/roms/SLOF/board-qemu/slof/fdt.fs
new file mode 100644
index 000000000..8d4635f30
--- /dev/null
+++ b/qemu/roms/SLOF/board-qemu/slof/fdt.fs
@@ -0,0 +1,435 @@
+\ *****************************************************************************
+\ * Copyright (c) 2011 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+0 VALUE fdt-debug
+TRUE VALUE fdt-cas-fix?
+
+\ Bail out if no fdt
+fdt-start 0 = IF -1 throw THEN
+
+struct
+ 4 field >fdth_magic
+ 4 field >fdth_tsize
+ 4 field >fdth_struct_off
+ 4 field >fdth_string_off
+ 4 field >fdth_rsvmap_off
+ 4 field >fdth_version
+ 4 field >fdth_compat_vers
+ 4 field >fdth_boot_cpu
+ 4 field >fdth_string_size
+ 4 field >fdth_struct_size
+drop
+
+h# d00dfeed constant OF_DT_HEADER
+h# 1 constant OF_DT_BEGIN_NODE
+h# 2 constant OF_DT_END_NODE
+h# 3 constant OF_DT_PROP
+h# 4 constant OF_DT_NOP
+h# 9 constant OF_DT_END
+
+\ Create some variables early
+0 value fdt-start-addr
+0 value fdt-struct
+0 value fdt-strings
+
+: fdt-init ( fdt-start -- )
+ dup to fdt-start-addr
+ dup dup >fdth_struct_off l@ + to fdt-struct
+ dup dup >fdth_string_off l@ + to fdt-strings
+ drop
+;
+fdt-start fdt-init
+
+\ Dump fdt header for all to see and check FDT validity
+: fdt-check-header ( -- )
+ fdt-start-addr dup 0 = IF
+ ." No flat device tree !" cr drop -1 throw EXIT THEN
+ hex
+ fdt-debug IF
+ ." Flat device tree header at 0x" dup . s" :" type cr
+ ." magic : 0x" dup >fdth_magic l@ . cr
+ ." total size : 0x" dup >fdth_tsize l@ . cr
+ ." offset to struct : 0x" dup >fdth_struct_off l@ . cr
+ ." offset to strings: 0x" dup >fdth_string_off l@ . cr
+ ." offset to rsvmap : 0x" dup >fdth_rsvmap_off l@ . cr
+ ." version : " dup >fdth_version l@ decimal . hex cr
+ ." last compat vers : " dup >fdth_compat_vers l@ decimal . hex cr
+ dup >fdth_version l@ 2 >= IF
+ ." boot CPU : 0x" dup >fdth_boot_cpu l@ . cr
+ THEN
+ dup >fdth_version l@ 3 >= IF
+ ." strings size : 0x" dup >fdth_string_size l@ . cr
+ THEN
+ dup >fdth_version l@ 17 >= IF
+ ." struct size : 0x" dup >fdth_struct_size l@ . cr
+ THEN
+ THEN
+ dup >fdth_magic l@ OF_DT_HEADER <> IF
+ ." Flat device tree has incorrect magic value !" cr
+ drop -1 throw EXIT
+ THEN
+ dup >fdth_version l@ 10 < IF
+ ." Flat device tree has usupported version !" cr
+ drop -1 throw EXIT
+ THEN
+
+ drop
+;
+fdt-check-header
+
+\ Fetch next tag, skip nops and increment address
+: fdt-next-tag ( addr -- nextaddr tag )
+ 0 ( dummy tag on stack for loop )
+ BEGIN
+ drop ( drop previous tag )
+ dup l@ ( read new tag )
+ swap 4 + swap ( increment addr )
+ dup OF_DT_NOP <> UNTIL ( loop until not nop )
+;
+
+\ Parse unit name and advance addr
+: fdt-fetch-unit ( addr -- addr $name )
+ dup from-cstring \ get string size
+ 2dup + 1 + 3 + fffffffc and -rot
+;
+
+\ Update unit with information from the reg property...
+\ ... this is required for the PCI nodes for example.
+: fdt-reg-unit ( prop-addr prop-len -- )
+ decode-phys ( prop-addr' prop-len' phys.lo ... phys.hi )
+ set-unit ( prop-addr' prop-len' )
+ 2drop
+;
+
+\ Lookup a string by index
+: fdt-fetch-string ( index -- str-addr str-len )
+ fdt-strings + dup from-cstring
+;
+
+: fdt-create-dec s" decode-unit" $CREATE , DOES> @ hex64-decode-unit ;
+: fdt-create-enc s" encode-unit" $CREATE , DOES> @ hex64-encode-unit ;
+
+\ Check whether array contains an zero-terminated ASCII string:
+: fdt-prop-is-string? ( addr len -- string? )
+ dup 1 < IF 2drop FALSE EXIT THEN \ Check for valid length
+ 1-
+ 2dup + c@ 0<> IF 2drop FALSE EXIT THEN \ Check zero-termination
+ test-string
+;
+
+\ Encode fdt property to OF property
+: fdt-encode-prop ( addr len -- )
+ 2dup fdt-prop-is-string? IF
+ 1- encode-string
+ ELSE
+ encode-bytes
+ THEN
+;
+
+\ Method to unflatten a node
+: fdt-unflatten-node ( start -- end )
+ \ this can and will recurse
+ recursive
+
+ \ Get & check first tag of node ( addr -- addr)
+ fdt-next-tag dup OF_DT_BEGIN_NODE <> IF
+ s" Weird tag 0x" type . " at start of node" type cr
+ -1 throw
+ THEN drop
+
+ new-device
+
+ \ Parse name, split unit address
+ fdt-fetch-unit
+ dup 0 = IF drop drop " /" THEN
+ 40 left-parse-string
+ \ Set name
+ device-name
+
+ \ Set preliminary unit address - might get overwritten by reg property
+ dup IF
+ " #address-cells" get-parent get-package-property IF
+ 2drop
+ ELSE
+ decode-int nip nip
+ hex-decode-unit
+ set-unit
+ THEN
+ ELSE 2drop THEN
+
+ \ Iterate sub tags
+ BEGIN
+ fdt-next-tag dup OF_DT_END_NODE <>
+ WHILE
+ dup OF_DT_PROP = IF
+ \ Found property
+ drop dup ( drop tag, dup addr : a1 a1 )
+ dup l@ dup rot 4 + ( fetch size, stack is : a1 s s a2)
+ dup l@ swap 4 + ( fetch nameid, stack is : a1 s s i a3 )
+ rot ( we now have: a1 s i a3 s )
+ fdt-encode-prop rot ( a1 s pa ps i)
+ fdt-fetch-string ( a1 s pa ps na ns )
+ 2dup s" reg" str= IF
+ 2swap 2dup fdt-reg-unit 2swap
+ THEN
+ property
+ + 8 + 3 + fffffffc and
+ ELSE dup OF_DT_BEGIN_NODE = IF
+ drop ( drop tag )
+ 4 -
+ fdt-unflatten-node
+ ELSE
+ drop -1 throw
+ THEN THEN
+ REPEAT drop \ drop tag
+
+ \ Create encode/decode unit
+ " #address-cells" get-node get-package-property IF ELSE
+ decode-int dup fdt-create-dec fdt-create-enc 2drop
+ THEN
+
+ finish-device
+;
+
+\ Start unflattening
+: fdt-unflatten-tree
+ fdt-debug IF
+ ." Unflattening device tree..." cr THEN
+ fdt-struct fdt-unflatten-node drop
+ fdt-debug IF
+ ." Done !" cr THEN
+;
+fdt-unflatten-tree
+
+\ Find memory size
+: fdt-parse-memory
+ \ XXX FIXME Handle more than one memory node, and deal
+ \ with RMA vs. full access
+ " /memory@0" find-device
+ " reg" get-node get-package-property IF throw -1 THEN
+
+ \ XXX FIXME Assume one entry only in "reg" property for now
+ decode-phys 2drop decode-phys
+ my-#address-cells 1 > IF 20 << or THEN
+
+ fdt-debug IF
+ dup ." Memory size: " . cr
+ THEN
+ \ claim.fs already released the memory between 0 and MIN-RAM-SIZE,
+ \ so we've got only to release the remaining memory now:
+ MIN-RAM-SIZE swap MIN-RAM-SIZE - release
+ 2drop device-end
+;
+fdt-parse-memory
+
+
+\ Claim fdt memory and reserve map
+: fdt-claim-reserve
+ fdt-start-addr
+ dup dup >fdth_tsize l@ 0 claim drop
+ dup >fdth_rsvmap_off l@ +
+ BEGIN
+ dup dup x@ swap 8 + x@
+ dup 0 <>
+ WHILE
+ fdt-debug IF
+ 2dup swap ." Reserve map entry: " . ." : " . cr
+ THEN
+ 0 claim drop
+ 10 +
+ REPEAT drop drop drop
+;
+fdt-claim-reserve
+
+
+\ The following functions are use to replace the FDT phandle and
+\ linux,phandle properties with our own OF1275 phandles...
+
+\ This is used to check whether we successfully replaced a phandle value
+0 VALUE (fdt-phandle-replaced)
+
+\ Replace phandle value in "interrupt-map" property
+: fdt-replace-interrupt-map ( old new prop-addr prop-len -- old new )
+ BEGIN
+ dup ( old new prop-addr prop-len prop-len )
+ WHILE
+ \ This is a little bit ugly ... we're accessing the property at
+ \ hard-coded offsets instead of analyzing it completely...
+ swap dup 10 + ( old new prop-len prop-addr prop-addr+10 )
+ dup l@ 5 pick = IF
+ \ it matches the old phandle value!
+ 3 pick swap l!
+ TRUE TO (fdt-phandle-replaced)
+ ELSE
+ drop
+ THEN
+ ( old new prop-len prop-addr )
+ 1c + swap 1c -
+ ( old new new-prop-addr new-prop-len )
+ REPEAT
+ 2drop
+;
+
+\ Replace one FDT phandle "old" with a OF1275 phandle "new" in the
+\ whole tree:
+: fdt-replace-all-phandles ( old new node -- )
+ \ ." Replacing in " dup node>path type cr
+ >r
+ s" interrupt-map" r@ get-property 0= IF
+ ( old new prop-addr prop-len R: node )
+ fdt-replace-interrupt-map
+ THEN
+ s" interrupt-parent" r@ get-property 0= IF
+ ( old new prop-addr prop-len R: node )
+ decode-int -rot 2drop ( old new val R: node )
+ 2 pick = IF ( old new R: node )
+ dup encode-int s" interrupt-parent" r@ set-property
+ TRUE TO (fdt-phandle-replaced)
+ THEN
+ THEN
+ \ ... add more properties that have to be fixed here ...
+ r>
+ \ Now recurse over all child nodes: ( old new node )
+ child BEGIN
+ dup
+ WHILE
+ 3dup RECURSE
+ PEER
+ REPEAT
+ 3drop
+;
+
+\ Check whether a node has "phandle" or "linux,phandle" properties
+\ and replace them:
+: fdt-fix-node-phandle ( node -- )
+ >r
+ FALSE TO (fdt-phandle-replaced)
+ s" phandle" r@ get-property 0= IF
+ decode-int ( p-addr2 p-len2 val )
+ \ ." found phandle: " dup . cr
+ r@ s" /" find-node ( p-addr2 p-len2 val node root )
+ fdt-replace-all-phandles ( p-addr2 p-len2 )
+ 2drop
+ (fdt-phandle-replaced) IF
+ r@ set-node
+ s" phandle" delete-property
+ s" linux,phandle" delete-property
+ ELSE
+ diagnostic-mode? IF
+ cr ." Warning: Did not replace phandle in " r@ node>path type cr
+ THEN
+ THEN
+ THEN
+ r> drop
+;
+
+\ Recursively walk through all nodes to fix their phandles:
+: fdt-fix-phandles ( node -- )
+ \ ." fixing phandles of " dup node>path type cr
+ dup fdt-fix-node-phandle
+ child BEGIN
+ dup
+ WHILE
+ dup RECURSE
+ PEER
+ REPEAT
+ drop
+ device-end
+;
+
+: fdt-create-cas-node ( name -- )
+ 2dup
+ 2dup " memory@" find-substr 0 = IF
+ fdt-debug IF ." Creating memory@ " cr THEN
+ new-device
+ 2dup " @" find-substr nip device-name \ Parse the node name
+ 2dup
+ 2dup " @" find-substr rot over + 1 + -rot - 1 - \ Jump to addr afte "@"
+ parse-2int nip xlsplit set-unit \ Parse and set unit
+ finish-device
+ ELSE
+ 2dup " ibm,dynamic-reconfiguration-memory" find-substr 0 = IF
+ fdt-debug IF ." Creating ibm,dynamic-reconfiguration-memory " cr THEN
+ new-device
+ device-name
+ finish-device
+ ELSE
+ 2drop 2drop
+ false to fdt-cas-fix?
+ ." Node not supported " cr
+ EXIT
+ THEN
+ THEN
+
+ find-node ?dup 0 <> IF set-node THEN
+;
+
+: fdt-fix-cas-node ( start -- end )
+ recursive
+ fdt-next-tag dup OF_DT_BEGIN_NODE <> IF
+ ." Error " cr
+ false to fdt-cas-fix?
+ EXIT
+ THEN drop
+ fdt-fetch-unit
+ dup 0 = IF drop drop " /" THEN
+ 40 left-parse-string
+ 2swap ?dup 0 <> IF
+ nip
+ 1 + + \ Add the string len +@
+ ELSE
+ drop
+ THEN
+ fdt-debug IF ." Setting node: " 2dup type cr THEN
+ 2dup find-node ?dup 0 <> IF
+ set-node 2drop
+ ELSE
+ fdt-debug IF ." Node not found, creating " 2dup type cr THEN
+ fdt-create-cas-node
+ THEN
+ fdt-debug IF ." Current now: " pwd cr THEN
+ BEGIN
+ fdt-next-tag dup OF_DT_END_NODE <>
+ WHILE
+ dup OF_DT_PROP = IF
+ fdt-debug IF ." Found property " cr THEN
+ drop dup ( drop tag, dup addr : a1 a1 )
+ dup l@ dup rot 4 + ( fetch size, stack is : a1 s s a2)
+ dup l@ swap 4 + ( fetch nameid, stack is : a1 s s i a3 )
+ rot ( we now have: a1 s i a3 s )
+ fdt-encode-prop rot ( a1 s pa ps i)
+ fdt-fetch-string ( a1 s pa ps na ns )
+ property
+ fdt-debug IF ." Setting property done " cr THEN
+ + 8 + 3 + fffffffc and
+ ELSE dup OF_DT_BEGIN_NODE = IF
+ drop ( drop tag )
+ 4 -
+ fdt-fix-cas-node
+ get-parent set-node
+ fdt-debug IF ." Returning back " pwd cr THEN
+ ELSE
+ ." Error " cr
+ drop
+ false to fdt-cas-fix?
+ EXIT
+ THEN
+ THEN
+ REPEAT
+ drop \ drop tag
+;
+
+: fdt-fix-cas-success
+ fdt-cas-fix?
+;
+
+s" /" find-node fdt-fix-phandles