pathres.fs

来自「BIOS Open Platform!」· FS 代码 · 共 518 行

FS
518
字号
\ tag: Path resolution\ \ this code implements IEEE 1275-1994 path resolution\ \ Copyright (C) 2003 Samuel Rydh\ \ See the file "COPYING" for further information about\ the copyright and warranty status of this work.\ 0 value interpose-ph0 0 create interpose-args , ,: expand-alias ( alias-addr alias-len -- exp-addr exp-len expanded? )  2dup  " /aliases" find-dev 0= if 2drop false exit then  get-package-property if    false  else    2swap 2drop     \ drop trailing 0 from string    dup if 1- then    true  then;\ \ 4.3.1 Resolve aliases\ \ the returned string is allocated with alloc-mem: pathres-resolve-aliases ( path-addr path-len -- path-addr path-len )  over c@ 2f <> if    200 here + >r                \ abuse dictionary for temporary storage    \ If the pathname does not begin with "/", and its first node name     \ component is an alias, replace the alias with its expansion.    ascii / split-before         \ (PATH_NAME, "/")  -> (TAIL HEAD)    ascii : split-before         \ (HEAD, ":")  ->  (ALIAS_ARGS AL_NAME)    expand-alias                 ( TAIL ALIAS_ARGS EXP_ALIAS_NAME expanded? )    if      2 pick 0<> if              \ If ALIAS_ARGS is not empty        ascii / split-after      \ (ALIAS_NAME, "/") -> (AL_TAIL AL_HEAD/)        2swap                    ( TAIL AL_HEAD/ AL_TAIL )        ascii : split-before     \ (AL_TAIL, ":") -> (DEAD_ARGS AL_TAIL)        2swap 2drop              ( TAIL AL_ARGS AL_HEAD ALIAS_TAIL )        2swap                    ( TAIL AL_ARGS AL_TAIL AL_HEAD )        r> tmpstrcat tmpstrcat >r      else        2swap 2drop              \ drop ALIAS_ARGS      then      r> tmpstrcat drop    else      \ put thing back together again      r> tmpstrcat tmpstrcat drop    then  then    strdup  ( path-addr path-len );\ \ search struct\ struct ( search information )  2 cells field >si.path  2 cells field >si.arguments  2 cells field >si.unit_addr  2 cells field >si.node_name  2 cells field >si.free_me  4 cells field >si.unit_phys  /n field >si.unit_phys_len  /n field >si.save-ihandle  /n field >si.save-phandle  /n field >si.top-ihandle  /n field >si.top-opened        \ set after successful open  /n field >si.child            \ node to matchconstant sinfo.size\ \ 4.3.6 node name match criteria\ : match-nodename ( childname len sinfo -- match? )  >r  2dup r@ >si.node_name 2@  ( [childname] [childname] [nodename] )  strcmp 0= if r> 3drop true exit then  \ does NODE_NAME contain a comma?  r@ >si.node_name 2@ ascii , strchr  if r> 3drop false exit then  ( [childname] )  ascii , left-split 2drop r@ >si.node_name 2@  r> drop  strcmp if false else true then;\ \ 4.3.4 exact match child node\ \ If NODE_NAME is not empty, make sure it matches the name property: common-match ( sinfo -- )  >r  \ a) NODE_NAME nonempty  r@ >si.node_name 2@ nip if    " name" r@ >si.child @ get-package-property if -1 throw then    \ name is supposed to be null-terminated    dup 0> if 1- then    \ exit if NODE_NAME does not match    r@ match-nodename 0= if -2 throw then  then  r> drop;  : (exact-match) ( sinfo -- )  >r  \ a) If NODE_NAME is not empty, make sure it matches the name property  r@ common-match  \ b) UNIT_PHYS nonempty?  r@ >si.unit_phys_len @ cells ?dup if    \ check if unit_phys matches    " reg" r@ >si.child @ get-package-property if -3 throw then    ( unitbytes propaddr proplen )    rot r@ >si.unit_phys -rot    ( propaddr unit_phys proplen unitbytes )    swap over < if -4 throw then    comp if -5 throw then  else    \ c) both NODE_NAME and UNIT_PHYS empty?    r@ >si.node_name 2@ nip 0= if -6 throw then  then  r> drop;: exact-match ( sinfo -- match? )  ['] (exact-match) catch if drop false exit then  true;\ \ 4.3.5 wildcard match child node\ : (wildcard-match) ( sinfo -- match? )  >r  \ a) If NODE_NAME is not empty, make sure it matches the name property  r@ common-match  \ b) Fail if "reg" property exist  " reg" r@ >si.child @ get-package-property 0= if -7 throw then  \ c) Fail if both NODE_NAME and UNIT_ADDR are both empty  r@ >si.unit_phys_len @  r@ >si.node_name 2@ nip  or 0= if -1 throw then  \ SUCCESS  r> drop;: wildcard-match ( sinfo -- match? )  ['] (wildcard-match) catch if drop false exit then  true;\ \ 4.3.3 match child node\ : find-child ( sinfo -- phandle )  >r  \ decode unit address string  r@ >si.unit_addr 2@ dup if    ( str len )    " decode-unit" active-package find-method    if      depth 3 - >r execute depth r@ - r> swap      ( ... a_lo ... a_hi olddepth n )      4 min 0 max      dup r@ >si.unit_phys_len !      ( ... a_lo ... a_hi olddepth n )      r@ >si.unit_phys >r      begin 1- dup 0>= while        rot r> dup na1+ >r !      repeat      r> 2drop      depth!    else      \ no decode-unit method... failure      -99 throw    then  else    2drop    \ clear unit_phys    0 r@ >si.unit_phys_len !    \ r@ >si.unit_phys 4 cells 0 fill  then  ( R: sinfo )  ['] exact-match  begin dup while    active-package >dn.child @    begin ?dup while      dup r@ >si.child !      ( xt phandle R: sinfo )      r@ 2 pick execute if 2drop r> >si.child @ exit then      >dn.peer @    repeat    ['] exact-match = if ['] wildcard-match else 0 then  repeat  -99 throw  ;\ \ 4.3.2 Create new linked instance procedure\ : link-one ( sinfo -- )  >r  active-package create-instance  dup 0= if -99 throw then  \ change instance parent  r@ >si.top-ihandle @ over >in.my-parent !  dup r@ >si.top-ihandle !  to my-self  \ b) set my-args field  r@ >si.arguments 2@ strdup my-self >in.arguments 2!    \ e) set my-unit field  r@ >si.unit_addr 2@ nip if    \ copy UNIT_PHYS to the my-unit field    r@ >si.unit_phys my-self >in.my-unit 4 cells move  else    \ set unit-addr from reg property    " reg" active-package get-package-property 0= if      \ ( ihandle prop proplen )      \ copy address to my-unit      4 cells min my-self >in.my-unit swap move    else      \ clear my-unit      my-self >in.my-unit 4 cells 0 fill    then  then  \ top instance has not been opened (yet)  false r> >si.top-opened !;: invoke-open ( sinfo -- )  " open" my-self ['] $call-method  catch if 3drop false then  0= if -99 throw then      true swap >si.top-opened !;\ \ 4.3.7 Handle interposers procedure (supplement)\ : handle-interposers ( sinfo -- )  >r  begin    interpose-ph ?dup   while    0 to interpose-ph    active-package swap active-package!    \ clear unit address and set arguments    0 0 r@ >si.unit_addr 2!    interpose-args 2@ r@ >si.arguments 2!    r@ link-one    true my-self >in.interposed !    interpose-args 2@ free-mem    r@ invoke-open    active-package!  repeat  r> drop;\ \ 4.3.1 Path resolution procedure\ \ close-dev ( ihandle -- )\ : close-dev   begin    dup   while    dup >in.my-parent @    swap close-package  repeat  drop;: path-res-cleanup ( sinfo close? )  \ tear down all instances if close? is set  if    dup >si.top-opened @ if      dup >si.top-ihandle @      ?dup if close-dev then    else      dup >si.top-ihandle @ dup      ( sinfo ihandle ihandle )      dup if >in.my-parent @ swap then      ( sinfo parent ihandle )      ?dup if destroy-instance then      ?dup if close-dev then    then  then  \ restore active-package and my-self  dup >si.save-ihandle @ to my-self  dup >si.save-phandle @ active-package!  \ free any allocated memory  dup >si.free_me 2@ free-mem  sinfo.size free-mem;: (path-resolution) ( context sinfo -- )  >r r@ >si.path 2@  ( context pathstr pathlen )  \ this allocates a copy of the string  pathres-resolve-aliases  2dup r@ >si.free_me 2!  \ If the pathname, after possible alias expansion, begins with "/",  \ begin the search at the root node. Otherwise, begin at the active  \ package.  dup if                    \ make sure string is not empty    over c@ 2f = if      swap char+ swap /c -  \ Remove the "/" from PATH_NAME.      \ Set the active package to the root node.      device-tree @ active-package!    then  then  r@ >si.path 2!  0 0 r@ >si.unit_addr 2!  0 0 r@ >si.arguments 2!  0 r@ >si.top-ihandle !  \ If there is no active package, exit this procedure, returning false.  ( context )  active-package 0= if -99 throw then  \ Begin the creation of an instance chain.  \ NOTE--If, at this step, the active package is not the root node and   \ we are in open-dev or execute-device-method contexts, the instance   \ chain that results from the path resolution process may be incomplete.  active-package swap  ( virt-active-node context )  begin    r@ >si.path 2@ nip          \ nonzero path?  while    \ ( active-node context )    \ is this open-dev or execute-device-method context?    dup if      r@ link-one      over active-package <> my-self >in.interposed !      r@ invoke-open      r@ handle-interposers    then    over active-package!    r@ >si.path 2@              ( PATH )        ascii / left-split          ( PATH COMPONENT )    ascii : left-split          ( PATH ARGS NODE_ADDR )    ascii @ left-split          ( PATH ARGS UNIT_ADDR NODE_NAME )    r@ >si.node_name 2!    r@ >si.unit_addr 2!    r@ >si.arguments 2!    r@ >si.path 2!    ( virt-active-node context )    \ 4.3.1 i) pathname has a leading %?    r@ >si.node_name 2@ 2dup 2dup ascii % strchr nip = if      1- swap 1+ swap r@ >si.node_name 2!      " /packages" find-dev drop active-package!      r@ find-child    else      2drop      nip r@ find-child swap over      ( new-node context new-node )    then    \ (optional: open any nodes between parent and child )    active-package!  repeat  ( virt-active-node type )  dup if r@ link-one then  1 = if    dup active-package <> my-self >in.interposed !    r@ invoke-open     r@ handle-interposers  then  active-package!  r> drop;: path-resolution ( context path-addr path-len -- sinfo true | false )  \ allocate and clear the search block  sinfo.size alloc-mem >r        r@ sinfo.size 0 fill  \ store path  r@ >si.path 2!  \ save ihandle and phandle  my-self r@ >si.save-ihandle !  active-package r@ >si.save-phandle !    \ save context (if we take an exception)  dup  r@ ['] (path-resolution)  catch ?dup if    ( context xxx xxx error )    r> true path-res-cleanup    \ rethrow everything except our "cleanup throw"    dup -99 <> if throw then    3drop    \ ( context ) throw an exception if this is find-device context    if false else -22 throw then    exit  then  \ ( context )  drop r> true  ( sinfo true );: open-dev ( dev-str dev-len -- ihandle | 0 )  1 -rot path-resolution 0= if false exit then  ( sinfo )  my-self swap  false path-res-cleanup  ( ihandle );: execute-device-method( ... dev-str dev-len met-str met-len -- ... false | ?? true )  2swap  2 -rot path-resolution 0= if 2drop false exit then  ( method-str method-len sinfo )  >r  my-self ['] $call-method catch  if 3drop false else true then  r> true path-res-cleanup;: find-device ( dev-str dev-len -- )  2dup " .." strcmp 0= if    2drop    active-package dup if >dn.parent @ then    \ ".." in root note?    dup 0= if -22 throw then    active-package!    exit  then  0 -rot path-resolution 0= if false exit then  ( sinfo )  active-package swap  true path-res-cleanup  active-package!;\ find-device, but without side effects: (find-dev) ( dev-str dev-len -- phandle true | false )  active-package -rot  ['] find-device catch if 3drop false exit then  active-package swap active-package! true;\ Tuck on a node at the end of the chain being created.\ This implementation follows the interpose recommended practice\ (v0.2 draft).: interpose ( arg-str arg-len phandle -- )  to interpose-ph  strdup interpose-args 2!;['] (find-dev) to find-dev

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?