|
|
1.1 root 1: \ tag: Path resolution
2: \
3: \ this code implements IEEE 1275-1994 path resolution
4: \
5: \ Copyright (C) 2003 Samuel Rydh
6: \
7: \ See the file "COPYING" for further information about
8: \ the copyright and warranty status of this work.
9: \
10:
11: 0 value interpose-ph
12: 0 0 create interpose-args , ,
13:
14: : expand-alias ( alias-addr alias-len -- exp-addr exp-len expanded? )
15: 2dup
16: " /aliases" find-dev 0= if 2drop false exit then
17: get-package-property if
18: false
19: else
20: 2swap 2drop
21: \ drop trailing 0 from string
22: dup if 1- then
23: true
24: then
25: ;
26:
27: \
28: \ 4.3.1 Resolve aliases
29: \
30:
31: \ the returned string is allocated with alloc-mem
32: : pathres-resolve-aliases ( path-addr path-len -- path-addr path-len )
33: over c@ 2f <> if
34: 200 here + >r \ abuse dictionary for temporary storage
35:
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? )
41: if
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
49: else
50: 2swap 2drop \ drop ALIAS_ARGS
51: then
52: r> tmpstrcat drop
53: else
54: \ put thing back together again
55: r> tmpstrcat tmpstrcat drop
56: then
57: then
58:
59: strdup
60: ( path-addr path-len )
61: ;
62:
63: \
64: \ search struct
65: \
66:
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
80: constant sinfo.size
81:
82:
83: \
84: \ 4.3.6 node name match criteria
85: \
86:
87: : match-nodename ( childname len sinfo -- match? )
88: >r
89: 2dup r@ >si.node_name 2@
90: ( [childname] [childname] [nodename] )
91: strcmp 0= if r> 3drop true exit then
92:
93: \ does NODE_NAME contain a comma?
94: r@ >si.node_name 2@ ascii , strchr
95: if r> 3drop false exit then
96:
97: ( [childname] )
98: ascii , left-split 2drop r@ >si.node_name 2@
99: r> drop
100: strcmp if false else true then
101: ;
102:
103:
104: \
105: \ 4.3.4 exact match child node
106: \
107:
108: \ If NODE_NAME is not empty, make sure it matches the name property
109: : common-match ( sinfo -- )
110: >r
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
115: dup 0> if 1- then
116: \ exit if NODE_NAME does not match
117: r@ match-nodename 0= if -2 throw then
118: then
119: r> drop
120: ;
121:
122: : (exact-match) ( sinfo -- )
123: >r
124: \ a) If NODE_NAME is not empty, make sure it matches the name property
125: r@ common-match
126:
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
136: else
137: \ c) both NODE_NAME and UNIT_PHYS empty?
138: r@ >si.node_name 2@ nip 0= if -6 throw then
139: then
140:
141: r> drop
142: ;
143:
144: : exact-match ( sinfo -- match? )
145: ['] (exact-match) catch if drop false exit then
146: true
147: ;
148:
149: \
150: \ 4.3.5 wildcard match child node
151: \
152:
153: : (wildcard-match) ( sinfo -- match? )
154: >r
155: \ a) If NODE_NAME is not empty, make sure it matches the name property
156: r@ common-match
157:
158: \ b) Fail if "reg" property exist
159: " reg" r@ >si.child @ get-package-property 0= if -7 throw then
160:
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
165:
166: \ SUCCESS
167: r> drop
168: ;
169:
170: : wildcard-match ( sinfo -- match? )
171: ['] (wildcard-match) catch if drop false exit then
172: true
173: ;
174:
175:
176: \
177: \ 4.3.3 match child node
178: \
179:
180: : find-child ( sinfo -- phandle )
181: >r
182: \ decode unit address string
183: r@ >si.unit_addr 2@ dup if
184: ( str len )
185: " decode-unit" active-package find-method
186: if
187: depth 3 - >r execute depth r@ - r> swap
188: ( ... a_lo ... a_hi olddepth n )
189: 4 min 0 max
190: dup r@ >si.unit_phys_len !
191: ( ... a_lo ... a_hi olddepth n )
192: r@ >si.unit_phys >r
193: begin 1- dup 0>= while
194: rot r> dup la1+ >r l!-be
195: repeat
196: r> 2drop
197: depth!
198: else
199: \ no decode-unit method... failure
200: -99 throw
201: then
202: else
203: 2drop
204: \ clear unit_phys
205: 0 r@ >si.unit_phys_len !
206: \ r@ >si.unit_phys 4 cells 0 fill
207: then
208:
209: ( R: sinfo )
210: ['] exact-match
211: begin dup while
212: active-package >dn.child @
213: begin ?dup while
214: dup r@ >si.child !
215: ( xt phandle R: sinfo )
216: r@ 2 pick execute if 2drop r> >si.child @ exit then
217: >dn.peer @
218: repeat
219: ['] exact-match = if ['] wildcard-match else 0 then
220: repeat
221:
222: -99 throw
223: ;
224:
225:
226: \
227: \ 4.3.2 Create new linked instance procedure
228: \
229:
230: : link-one ( sinfo -- )
231: >r
232: active-package create-instance
233: dup 0= if -99 throw then
234:
235: \ change instance parent
236: r@ >si.top-ihandle @ over >in.my-parent !
237: dup r@ >si.top-ihandle !
238: to my-self
239:
240: \ b) set my-args field
241: r@ >si.arguments 2@ strdup my-self >in.arguments 2!
242:
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
247: else
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
253: else
254: \ clear my-unit
255: my-self >in.my-unit 4 cells 0 fill
256: then
257: then
258:
259: \ top instance has not been opened (yet)
260: false r> >si.top-opened !
261: ;
262:
263: : invoke-open ( sinfo -- )
264: " open" my-self ['] $call-method
265: catch if 3drop false then
266: 0= if -99 throw then
267:
268: true swap >si.top-opened !
269: ;
270:
271: \
272: \ 4.3.7 Handle interposers procedure (supplement)
273: \
274:
275: : handle-interposers ( sinfo -- )
276: >r
277: begin
278: interpose-ph ?dup
279: while
280: 0 to interpose-ph
281: active-package swap active-package!
282:
283: \ clear unit address and set arguments
284: 0 0 r@ >si.unit_addr 2!
285: interpose-args 2@ r@ >si.arguments 2!
286: r@ link-one
287: true my-self >in.interposed !
288: interpose-args 2@ free-mem
289: r@ invoke-open
290:
291: active-package!
292: repeat
293:
294: r> drop
295: ;
296:
297: \
298: \ 4.3.1 Path resolution procedure
299: \
300:
301: \ close-dev ( ihandle -- )
302: \
303: : close-dev
304: begin
305: dup
306: while
307: dup >in.my-parent @
308: swap close-package
309: repeat
310: drop
311: ;
312:
313: : path-res-cleanup ( sinfo close? )
314:
315: \ tear down all instances if close? is set
316: if
317: dup >si.top-opened @ if
318: dup >si.top-ihandle @
319: ?dup if close-dev then
320: else
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
327: then
328: then
329:
330: \ restore active-package and my-self
331: dup >si.save-ihandle @ to my-self
332: dup >si.save-phandle @ active-package!
333:
334: \ free any allocated memory
335: dup >si.free_me 2@ free-mem
336: sinfo.size free-mem
337: ;
338:
339: : (path-resolution) ( context sinfo -- )
340: >r r@ >si.path 2@
341: ( context pathstr pathlen )
342:
343: \ this allocates a copy of the string
344: pathres-resolve-aliases
345: 2dup r@ >si.free_me 2!
346:
347: \ If the pathname, after possible alias expansion, begins with "/",
348: \ begin the search at the root node. Otherwise, begin at the active
349: \ package.
350:
351: dup if \ make sure string is not empty
352: over c@ 2f = if
353: swap char+ swap /c - \ Remove the "/" from PATH_NAME.
354: \ Set the active package to the root node.
355: device-tree @ active-package!
356: then
357: then
358:
359: r@ >si.path 2!
360: 0 0 r@ >si.unit_addr 2!
361: 0 0 r@ >si.arguments 2!
362: 0 r@ >si.top-ihandle !
363:
364: \ If there is no active package, exit this procedure, returning false.
365: ( context )
366: active-package 0= if -99 throw then
367:
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.
372:
373: active-package swap
374: ( virt-active-node context )
375: begin
376: r@ >si.path 2@ nip \ nonzero path?
377: while
378: \ ( active-node context )
379: \ is this open-dev or execute-device-method context?
380: dup if
381: r@ link-one
382: over active-package <> my-self >in.interposed !
383: r@ invoke-open
384: r@ handle-interposers
385: then
386: over active-package!
387:
388: r@ >si.path 2@ ( PATH )
389:
390: ascii / left-split ( PATH COMPONENT )
391: ascii : left-split ( PATH ARGS NODE_ADDR )
392: ascii @ left-split ( PATH ARGS UNIT_ADDR NODE_NAME )
393:
394: r@ >si.node_name 2!
395: r@ >si.unit_addr 2!
396: r@ >si.arguments 2!
397: r@ >si.path 2!
398:
399: ( virt-active-node context )
400:
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!
405: r@ find-child
406: else
407: 2drop
408: nip r@ find-child swap over
409: ( new-node context new-node )
410: then
411:
412: \ (optional: open any nodes between parent and child )
413:
414: active-package!
415: repeat
416:
417: ( virt-active-node type )
418: dup if r@ link-one then
419: 1 = if
420: dup active-package <> my-self >in.interposed !
421: r@ invoke-open
422: r@ handle-interposers
423: then
424: active-package!
425:
426: r> drop
427: ;
428:
429: : path-resolution ( context path-addr path-len -- sinfo true | false )
430: \ allocate and clear the search block
431: sinfo.size alloc-mem >r
432: r@ sinfo.size 0 fill
433:
434: \ store path
435: r@ >si.path 2!
436:
437: \ save ihandle and phandle
438: my-self r@ >si.save-ihandle !
439: active-package r@ >si.save-phandle !
440:
441: \ save context (if we take an exception)
442: dup
443:
444: r@ ['] (path-resolution)
445: catch ?dup if
446: ( context xxx xxx error )
447: r> true path-res-cleanup
448:
449: \ rethrow everything except our "cleanup throw"
450: dup -99 <> if throw then
451: 3drop
452:
453: \ ( context ) throw an exception if this is find-device context
454: if false else -22 throw then
455: exit
456: then
457:
458: \ ( context )
459: drop r> true
460: ( sinfo true )
461: ;
462:
463:
464: : open-dev ( dev-str dev-len -- ihandle | 0 )
465: 1 -rot path-resolution 0= if false exit then
466:
467: ( sinfo )
468: my-self swap
469: false path-res-cleanup
470:
471: ( ihandle )
472: ;
473:
474: : execute-device-method
475: ( ... dev-str dev-len met-str met-len -- ... false | ?? true )
476: 2swap
477: 2 -rot path-resolution 0= if 2drop false exit then
478: ( method-str method-len sinfo )
479: >r
480: my-self ['] $call-method catch
481: if 3drop false else true then
482: r> true path-res-cleanup
483: ;
484:
485: : find-device ( dev-str dev-len -- )
486: 2dup " .." strcmp 0= if
487: 2drop
488: active-package dup if >dn.parent @ then
489: \ ".." in root note?
490: dup 0= if -22 throw then
491: active-package!
492: exit
493: then
494: 0 -rot path-resolution 0= if false exit then
495: ( sinfo )
496: active-package swap
497: true path-res-cleanup
498: active-package!
499: ;
500:
501: \ find-device, but without side effects
502: : (find-dev) ( dev-str dev-len -- phandle true | false )
503: active-package -rot
504: ['] find-device catch if 3drop false exit then
505: active-package swap active-package! true
506: ;
507:
508: \ Tuck on a node at the end of the chain being created.
509: \ This implementation follows the interpose recommended practice
510: \ (v0.2 draft).
511:
512: : interpose ( arg-str arg-len phandle -- )
513: to interpose-ph
514: strdup interpose-args 2!
515: ;
516:
517: ['] (find-dev) to find-dev
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.