1\ *****************************************************************************
2\ * Copyright (c) 2017 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
8\ ****************************************************************************/
9
100 VALUE fdtfl-debug
11
12VARIABLE fdtfl-struct
13VARIABLE fdtfl-struct-here
14VARIABLE fdtfl-strings
15VARIABLE fdtfl-strings-cache
16VARIABLE fdtfl-strings-here
17VARIABLE fdtfl-strings-reused \ debug only
18VARIABLE fdlfl-ms \ debug only
19
20: fdt-skip-string ( cur -- cur ) zcount + char+  4 #aligned ;
21
22: zstring=  ( str len zstr -- flag )
23    2dup + c@ 0<> IF
24        3drop false
25        EXIT
26    THEN
27    swap comp 0=
28;
29
30: fdt-find-string ( name namelen -- nameoff true | false )
31    fdtfl-strings @
32    BEGIN
33        dup fdtfl-strings-cache @ <
34    WHILE
35        3dup zstring= IF
36            nip nip             ( curstr )
37            fdtfl-strings @ -
38            true
39            EXIT
40        THEN
41        fdt-skip-string
42    REPEAT
43    3drop
44    false
45;
46
47: fdt-str-allot ( len -- ) fdtfl-strings-here @ + to fdtfl-strings-here ;
48: fdt-str-c, ( char -- ) fdtfl-strings-here @ 1 fdt-str-allot c! ;
49: fdt-str-align  ( -- )
50    fdtfl-strings-here @
51    dup dup 4 #aligned swap -   ( here bytes-to-erase )
52    dup -rot
53    erase
54    fdt-str-allot
55;
56: fdt-str-bytes, ( data len -- ) fdtfl-strings-here @ over fdt-str-allot swap move ;
57: fdt-str-ztr, ( str len -- ) fdt-str-bytes, 0 fdt-str-c, ;
58
59: fdt-add-string ( name namelen -- nameoff )
60    fdtfl-strings-here @ -rot
61    fdt-str-ztr,
62    fdt-str-align
63    fdtfl-strings @ -
64;
65
66: fdt-get-string ( name namelen -- nameoff )
67    2dup fdt-find-string IF
68        -rot 2drop
69        fdtfl-debug IF
70           1 fdtfl-strings-reused +!
71        THEN
72        EXIT
73    THEN
74    fdt-add-string
75;
76
77: fdt-allot ( len -- ) fdtfl-struct-here @ + to fdtfl-struct-here ;
78: fdt-c, ( char -- ) fdtfl-struct-here @ 1 fdt-allot c! ;
79: fdt-align  ( -- )
80    fdtfl-struct-here @
81    dup dup 4 #aligned swap -   ( here bytes-to-erase )
82    dup -rot
83    erase
84    fdt-allot
85;
86: fdt-bytes, ( data len -- ) fdtfl-struct-here @ over fdt-allot swap move ;
87: fdt-ztr, ( str len -- ) fdt-bytes, 0 fdt-c, ;
88: fdt-l, ( token -- ) fdtfl-struct-here @ l! /l fdt-allot ;
89
90: fdt-begin-node ( phandle -- )
91    OF_DT_BEGIN_NODE fdt-l,
92    dup device-tree @ = IF drop s" " ELSE node>qname THEN
93    fdt-ztr,
94    fdt-align
95;
96
97: fdt-end-node ( -- ) OF_DT_END_NODE fdt-l, ;
98
99: fdt-prop ( prop len name namelen -- )
100    OF_DT_PROP fdt-l,
101
102    \ get string offset
103    fdt-get-string      ( prop len nameoff )
104
105    \ store len and nameoff
106    over fdt-l,
107    fdt-l,              ( prop len )
108
109    \ now store the bytes
110    fdt-bytes,
111    fdt-align
112;
113
114: fdt-end ( -- ) OF_DT_END fdt-l, ;
115
116: fdt-copy-property ( link -- )
117    dup link> execute
118    rot
119    link>name name>string
120    2dup s" name" str= IF 4drop EXIT THEN \ skipping useless "name"
121    fdt-prop
122;
123
124: for-all-words ( wid xt -- ) \ xt has sig ( lfa -- )
125    >r
126    cell+ @ BEGIN dup WHILE dup r@ execute @ REPEAT
127    r> 2drop
128;
129
130: fdt-copy-properties ( phandle -- )
131   dup encode-int s" phandle" fdt-prop
132   node>properties @
133   ['] fdt-copy-property for-all-words
134;
135
136: fdt-copy-node ( node --  )
137    fdtfl-debug 1 > IF dup node>path type cr THEN
138    dup fdt-begin-node
139    dup fdt-copy-properties
140    child BEGIN dup WHILE dup recurse peer REPEAT
141    drop
142    fdt-end-node
143;
144
145: fdtfl-strings-preload ( -- )
146    s" reg" fdt-add-string drop
147    s" status" fdt-add-string drop
148    s" 64-bit" fdt-add-string drop
149    s" phandle" fdt-add-string drop
150    s" ibm,vmx" fdt-add-string drop
151    s" ibm,dfp" fdt-add-string drop
152    s" slb-size" fdt-add-string drop
153    s" ibm,purr" fdt-add-string drop
154    s" vendor-id" fdt-add-string drop
155    s" device-id" fdt-add-string drop
156    s" min-grant" fdt-add-string drop
157    s" class-code" fdt-add-string drop
158    s" compatible" fdt-add-string drop
159    s" interrupts" fdt-add-string drop
160    s" cpu-version" fdt-add-string drop
161    s" #size-cells" fdt-add-string drop
162    s" ibm,req#msi" fdt-add-string drop
163    s" revision-id" fdt-add-string drop
164    s" device_type" fdt-add-string drop
165    s" max-latency" fdt-add-string drop
166    s" ibm,chip-id" fdt-add-string drop
167    s" ibm,pft-size" fdt-add-string drop
168    s" ibm,slb-size" fdt-add-string drop
169    s" devsel-speed" fdt-add-string drop
170    s" ibm,loc-code" fdt-add-string drop
171    s" subsystem-id" fdt-add-string drop
172    s" d-cache-size" fdt-add-string drop
173    s" i-cache-size" fdt-add-string drop
174    s" #address-cells" fdt-add-string drop
175    s" clock-frequency" fdt-add-string drop
176    s" cache-line-size" fdt-add-string drop
177    s" ibm,pa-features" fdt-add-string drop
178    s" ibm,my-drc-index" fdt-add-string drop
179    s" d-cache-line-size" fdt-add-string drop
180    s" i-cache-line-size" fdt-add-string drop
181    s" assigned-addresses" fdt-add-string drop
182    s" d-cache-block-size" fdt-add-string drop
183    s" i-cache-block-size" fdt-add-string drop
184    s" timebase-frequency" fdt-add-string drop
185    s" subsystem-vendor-id" fdt-add-string drop
186    s" ibm,segment-page-sizes" fdt-add-string drop
187    s" ibm,ppc-interrupt-server#s" fdt-add-string drop
188    s" ibm,processor-segment-sizes" fdt-add-string drop
189    s" ibm,ppc-interrupt-gserver#s" fdt-add-string drop
190;
191
192: fdt-append-blob ( bytes cur blob -- cur )
193    3dup -rot swap move
194    drop +
195;
196
197: fdt-flatten-tree ( -- tree )
198    100000 alloc-mem dup fdtfl-struct-here ! fdtfl-struct !
199    100000 alloc-mem dup fdtfl-strings-here ! fdtfl-strings !
200
201    fdtfl-debug IF
202        0 fdtfl-strings-reused !
203        milliseconds fdlfl-ms !
204    THEN
205
206    \ Preload strings cache
207    fdtfl-strings-preload
208    fdtfl-strings-here @ fdtfl-strings-cache !
209    \ Render the blobs
210    device-tree @ fdt-copy-node
211    fdt-end
212
213    \ Calculate strings and struct sizes
214    fdtfl-struct-here @ fdtfl-struct @ -
215    fdtfl-strings-here @ fdtfl-strings @ - ( struct-len strings-len )
216
217    2dup + /fdth +
218    10 + \ Reserve 16 bytes for an empty reserved block
219
220    fdtfl-debug IF
221        3dup
222        ." FDTsize=" .d ." Strings=" .d ." Struct=" .d
223        ." Reused str=" fdtfl-strings-reused @ .d
224        milliseconds fdlfl-ms @ - .d ." ms"
225        cr
226    THEN
227
228    \ Allocate flatten DT blob
229    dup alloc-mem                   ( struct-len strings-len total-len fdt )
230    >r                              ( struct-len strings-len total-len r: fdt )
231
232    \ Write header
233    OF_DT_HEADER        r@ >fdth_magic l!
234    dup                 r@ >fdth_tsize l!
235    /fdth 10 + 2 pick + r@ >fdth_struct_off l!
236    /fdth 10 +          r@ >fdth_string_off l!
237    /fdth               r@ >fdth_rsvmap_off l!
238    11                  r@ >fdth_version l!
239    10                  r@ >fdth_compat_vers l!
240    chosen-cpu-unit     r@ >fdth_boot_cpu l!
241    over                r@ >fdth_string_size l!
242    2 pick              r@ >fdth_struct_size l!
243                                    ( struct-len strings-len total-len r: fdt )
244
245    drop                            ( struct-len strings-len r: fdt )
246    r@ /fdth +                      ( struct-len strings-len cur r: fdt )
247
248    \ Write the reserved entry
249    0 over ! cell+ 0 over ! cell+
250
251    \ Write strings and struct blobs
252    fdtfl-strings @ fdt-append-blob
253    fdtfl-struct @ fdt-append-blob
254    drop
255
256    \ Free temporary blobs
257    fdtfl-struct @ 100000 free-mem
258    fdtfl-strings @ 100000 free-mem
259
260    \ Return fdt
261    r>
262;
263
264: fdt-flatten-tree-free ( tree )
265    dup >fdth_tsize l@ free-mem
266;
267