Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / board-qemu / slof / fdt.fs
diff --git a/qemu/roms/SLOF/board-qemu/slof/fdt.fs b/qemu/roms/SLOF/board-qemu/slof/fdt.fs
new file mode 100644 (file)
index 0000000..8d4635f
--- /dev/null
@@ -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