3 \ this
code implements
IEEE 1275-1994 path resolution
5 \
Copyright (C) 2003 Samuel Rydh
7 \
See the file
"COPYING" for further information about
8 \
the copyright and warranty status
of this
work.
12 0 0 create
interpose-args
, ,
14 : expand
-alias
( alias
-addr alias
-len
-- exp
-addr exp
-len expanded
? )
16 " /aliases" find
-dev
0= if 2drop false exit then
17 get
-package
-property
if
21 \ drop trailing
0 from
string
28 \
4.3.1 Resolve aliases
31 \
the returned string is
allocated with alloc
-mem
32 : pathres
-resolve
-aliases ( path
-addr path
-len
-- path
-addr path
-len
)
34 200 here
+ >r \ abuse
dictionary for temporary storage
36 \
If the pathname does
not begin with "/", and its
first node
name
37 \ component
is an alias
, replace
the alias
with its
expansion.
38 ascii
/ split
-before \
(PATH_NAME, "/") -> (TAIL HEAD)
39 ascii
: split
-before \
(HEAD, ":") -> (ALIAS_ARGS AL_NAME)
40 expand
-alias
( TAIL ALIAS_ARGS EXP_ALIAS_NAME expanded
? )
42 2 pick
0<> if \
If ALIAS_ARGS is not empty
43 ascii
/ split
-after \
(ALIAS_NAME, "/") -> (AL_TAIL AL_HEAD/)
44 2swap ( TAIL AL_HEAD/ AL_TAIL )
45 ascii
: split
-before \
(AL_TAIL, ":") -> (DEAD_ARGS AL_TAIL)
46 2swap 2drop ( TAIL AL_ARGS AL_HEAD ALIAS_TAIL )
47 2swap ( TAIL AL_ARGS AL_TAIL AL_HEAD )
48 r
> tmpstrcat
tmpstrcat >r
50 2swap 2drop \ drop
ALIAS_ARGS
54 \ put
thing back together again
55 r
> tmpstrcat tmpstrcat drop
60 ( path
-addr path
-len
)
67 struct ( search information
)
68 2 cells
field >si
.path
69 2 cells
field >si
.arguments
70 2 cells
field >si
.unit_addr
71 2 cells
field >si
.node_name
72 2 cells
field >si
.free_me
73 4 cells
field >si
.unit_phys
74 /n
field >si
.unit_phys_len
75 /n
field >si
.save
-ihandle
76 /n
field >si
.save
-phandle
77 /n
field >si
.top
-ihandle
78 /n
field >si
.top
-opened \ set
after successful
open
79 /n
field >si
.child \ node
to match
84 \
4.3.6 node
name match criteria
87 : match-nodename
( childname
len sinfo -- match? )
89 2dup r
@ >si
.node_name
2@
90 ( [childname
] [childname
] [nodename
] )
91 strcmp
0= if r
> 3drop true exit then
93 \ does
NODE_NAME contain a comma
?
94 r
@ >si
.node_name
2@ ascii
, strchr
95 if r
> 3drop false exit then
98 ascii
, left
-split
2drop r
@ >si
.node_name
2@
100 strcmp
if false else true then
105 \
4.3.4 exact
match child node
108 \
If NODE_NAME is not empty
, make
sure it
matches the name property
109 : common
-match ( sinfo -- )
111 \ a
) NODE_NAME nonempty
112 r
@ >si
.node_name
2@ nip
if
113 " name" r
@ >si
.child
@ get
-package
-property
if -1 throw
then
114 \
name is supposed
to be
null-terminated
116 \
exit if NODE_NAME does
not match
117 r
@ match-nodename
0= if -2 throw
then
122 : (exact
-match) ( sinfo -- )
124 \ a
) If NODE_NAME is not empty
, make
sure it
matches the name property
127 \ b
) UNIT_PHYS nonempty
?
128 r
@ >si
.unit_phys_len
@ /l
* ?dup
if
129 \ check
if unit_phys
matches
130 " reg" r
@ >si
.child
@ get
-package
-property
if -3 throw
then
131 ( unitbytes
propaddr proplen
)
132 rot
r@ >si
.unit_phys
-rot
133 ( propaddr unit_phys
proplen unitbytes
)
134 swap over
< if -4 throw
then
135 comp
if -5 throw
then
137 \ c
) both
NODE_NAME and UNIT_PHYS empty
?
138 r@ >si
.node_name
2@ nip
0= if -6 throw
then
144 : exact
-match ( sinfo -- match? )
145 ['] (exact-match) catch if drop false exit then
150 \ 4.3.5 wildcard match child node
153 : (wildcard-match) ( sinfo -- match? )
155 \ a) If NODE_NAME is not empty, make sure it matches the name property
158 \ b) Fail if "reg" property exist
159 " reg" r@ >si.child @ get-package-property 0= if -7 throw then
161 \ c) Fail if both NODE_NAME and UNIT_ADDR are both empty
162 r@ >si.unit_phys_len @
163 r@ >si.node_name 2@ nip
164 or 0= if -1 throw then
170 : wildcard-match ( sinfo -- match? )
171 ['] (wildcard
-match) catch
if drop false exit then
177 \
4.3.3 match child node
180 : find
-child
( sinfo -- phandle
)
182 \ decode
unit address
string
183 r@ >si
.unit_addr
2@ dup
if
185 " decode-unit" active
-package
find-method
187 depth
3 - >r execute
depth r@ - r> swap
188 ( ... a_lo
... a_hi olddepth n
)
190 dup
r@ >si
.unit_phys_len
!
191 ( ... a_lo
... a_hi olddepth n
)
193 begin 1- dup
0>= while
194 rot
r> dup la1
+ >r l
!-be
199 \ no decode
-unit method... failure
205 0 r@ >si
.unit_phys_len
!
206 \
r@ >si
.unit_phys
4 cells
0 fill
212 active-package >dn.child @
215 ( xt phandle R: sinfo )
216 r@ 2 pick execute if 2drop r> >si.child @ exit then
219 ['] exact
-match = if ['] wildcard-match else 0 then
227 \ 4.3.2 Create new linked instance procedure
230 : link-one ( sinfo -- )
232 active-package create-instance
233 dup 0= if -99 throw then
235 \ change instance parent
236 r@ >si.top-ihandle @ over >in.my-parent !
237 dup r@ >si.top-ihandle !
240 \ b) set my-args field
241 r@ >si.arguments 2@ strdup my-self >in.arguments 2!
243 \ e) set my-unit field
244 r@ >si.unit_addr 2@ nip if
245 \ copy UNIT_PHYS to the my-unit field
246 r@ >si.unit_phys my-self >in.my-unit 4 cells move
248 \ set unit-addr from reg property
249 " reg" active-package get-package-property 0= if
250 \ ( ihandle prop proplen )
251 \ copy address to my-unit
252 4 cells min my-self >in.my-unit swap move
255 my-self >in.my-unit 4 cells 0 fill
259 \ top instance has not been opened (yet)
260 false r> >si.top-opened !
263 : invoke-open ( sinfo -- )
264 " open" my-self ['] $call
-method
265 catch
if 3drop false then
268 true swap >si
.top
-opened
!
272 \
4.3.7 Handle interposers procedure (supplement
)
275 : handle
-interposers ( sinfo -- )
281 active
-package
swap active
-package
!
283 \ clear
unit address and set
arguments
284 0 0 r@ >si
.unit_addr
2!
285 interpose-args
2@ r@ >si
.arguments 2!
287 true my-self
>in.interposed
!
288 interpose-args
2@ free
-mem
298 \
4.3.1 Path resolution
procedure
301 \ close
-dev
( ihandle
-- )
313 : path
-res
-cleanup
( sinfo close
? )
315 \ tear down all
instances if close
? is set
317 dup
>si
.top
-opened
@ if
318 dup
>si
.top
-ihandle
@
319 ?dup
if close
-dev
then
321 dup
>si
.top
-ihandle
@ dup
322 ( sinfo ihandle
ihandle )
323 dup
if >in.my-parent
@ swap then
324 ( sinfo parent
ihandle )
325 ?dup
if destroy
-instance then
326 ?dup
if close
-dev
then
330 \ restore
active-package
and my-self
331 dup
>si
.save
-ihandle @ to my-self
332 dup
>si
.save
-phandle @ active-package
!
334 \ free
any allocated memory
335 dup
>si
.free_me
2@ free
-mem
339 : (path
-resolution
) ( context
sinfo -- )
341 ( context
pathstr pathlen
)
343 \ this
allocates a copy
of the string
344 pathres
-resolve
-aliases
345 2dup r@ >si
.free_me
2!
347 \
If the pathname, after possible
alias expansion, begins
with "/",
348 \
begin the search at
the root
node. Otherwise, begin at
the active
351 dup
if \ make
sure string is not empty
353 swap char
+ swap /c
- \
Remove the "/" from
PATH_NAME.
354 \
Set the active package to the root node.
355 device
-tree
@ active-package!
360 0 0 r@ >si
.unit_addr
2!
361 0 0 r@ >si
.arguments 2!
362 0 r@ >si
.top
-ihandle !
364 \
If there
is no
active package, exit this procedure, returning
false.
366 active-package 0= if -99 throw
then
368 \
Begin the creation of an
instance chain.
369 \
NOTE--If, at
this step
, the active package is not the root node and
370 \ we
are in open-dev
or execute
-device
-method contexts
, the instance
371 \
chain that
results from
the path resolution process
may be
incomplete.
374 ( virt
-active-node context )
376 r@ >si
.path 2@ nip \ nonzero
path?
378 \
( active-node context )
379 \
is this open-dev
or execute
-device
-method context?
382 over
active-package <> my-self
>in.interposed
!
384 r@ handle
-interposers
388 r@ >si
.path 2@ ( PATH )
390 ascii
/ left
-split
( PATH COMPONENT )
391 ascii
: left
-split
( PATH ARGS NODE_ADDR )
392 ascii
@ left
-split
( PATH ARGS UNIT_ADDR NODE_NAME )
399 ( virt
-active-node context )
401 \
4.3.1 i
) pathname has a leading
%?
402 r@ >si
.node_name
2@ 2dup 2dup ascii
% strchr nip
= if
403 1- swap 1+ swap r@ >si
.node_name
2!
404 " /packages" find-dev
drop active-package!
408 nip
r@ find-child
swap over
409 ( new-node context new-node )
412 \
(optional
: open any nodes
between parent
and child
)
417 ( virt
-active-node type )
418 dup
if r@ link
-one
then
420 dup
active-package <> my-self
>in.interposed
!
422 r@ handle
-interposers
429 : path-resolution
( context path-addr
path-len -- sinfo true | false )
430 \ allocate
and clear
the search block
431 sinfo.size
alloc-mem
>r
437 \ save
ihandle and phandle
438 my-self
r@ >si
.save
-ihandle !
439 active-package r@ >si
.save
-phandle !
441 \ save
context (if we
take an
exception)
444 r@ ['] (path-resolution)
446 ( context xxx xxx error )
447 r> true path-res-cleanup
449 \ rethrow everything except our "cleanup throw"
450 dup -99 <> if throw then
453 \ ( context ) throw an exception if this is find-device context
454 if false else -22 throw then
464 : open-dev ( dev-str dev-len -- ihandle | 0 )
465 1 -rot path-resolution 0= if false exit then
469 false path-res-cleanup
474 : select-dev ( dev-str dev-len -- ihandle | 0 )
478 : execute-device-method
479 ( ... dev-str dev-len met-str met-len -- ... false | ?? true )
481 2 -rot path-resolution 0= if 2drop false exit then
482 ( method-str method-len sinfo )
484 my-self ['] $call
-method catch
485 if 3drop false else true then
486 r> true path-res
-cleanup
489 : find-device
( dev
-str dev
-len -- )
490 2dup " .." strcmp
0= if
492 active-package dup if >dn
.parent
@ then
494 dup 0= if -22 throw
then
498 0 -rot
path-resolution
0= if false exit then
501 true path-res
-cleanup
505 \
find-device
, but
without side
effects
506 : (find-dev
) ( dev
-str dev
-len -- phandle true | false )
508 ['] find-device catch if 3drop false exit then
509 active-package swap active-package! true
512 \ Tuck on a node at the end of the chain being created.
513 \ This implementation follows the interpose recommended practice
516 : interpose ( arg-str arg-len phandle -- )
518 strdup interpose-args 2!
521 ['] (find-dev
) to find-dev