(headermagic123 aikqemu0 #1^@(stage1H?ޭ?||C| |C||C`| 8N A@|C| |C||C| 8N A@|C| |C||C`| 8N A@|C| |C||C| 8N A@|C| |C||C`| 8N A@|C| |C||C| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8 N A@|C| |C||C `| 8 N A@|C| |C||C `| 8 N A@|C| |C||C `| 8 N A@|C| |C||C `| 8 N A@|C| |C||C `| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8N A@|C| |C||C`| 8 N A@|C| |C||C `| 8!N A@|C| |C||C!`| 8"N A@|C| |C||C"`| 8#N A@|C| |C||C#`| 8$N A@|C| |C||C$`| 8%N A@|C| |C||C%`| 8&N A@|C| |C||C&`| 8'N A@|C| |C||C'`| 8(N A@|C| |C||C(`| 8)N A@|C| |C||C)`| 8*N A@|C| |C||C*`| 8+N A@|C| |C||C+`| 8,N A@|C| |C||C,`| 8-N A@|C| |C||C-`| 8.N A@|C| |C||C.`| 8/N A@|x}`9y}kcx}`dL,8` HE8` H=8` H58`SH-8`LH%8`OH8`FHHq8`I|iN!xf8`X88D"N git-b4c93802a5b2c72fb#A@aHPX`hp!xAa!Aa!Aa (8}@}H} /| 0!8N |)< !A@aHPX`hp!xAa!Aa!Aa (0}8}8}@}&H}PHb#|xH18}@}H} P}A@aHPX`hp!xAa!Aa!Aa (!8|B| |B||BL$`N |H[?25l ********************************************************************** QEMU Starting  Build Date = Nov 5 2015 15:23:31 FW Version = git-b4c93802a5b2c72f |h|H< E1001 - Boot ROM CRC failure  E1002 - Memory could not be initialized  E1003 - Firmware image incomplete internal FLS1-FFS-0. E1004 - Unspecified Internal Firmware Error internal FLSX-SE-0.|x|#x|+x|3x9@s @(x|J|c#xHx;|#AHH}|#x8|#8AH}B,A4Hx}B8|'0A8|' 8`AP|#x|qB8|' A||(8 8`~x}N }|+x|+xH9,@ }N |:8EPB~%x}N }(|#x|jx|#x8 |+xHE, @ ,|*@8`}(N 8`|B}(N 9J9k |-p9AN q@9N !|08@H|+xKY0|H@88!PN }|ixi,AH 9)K}N }|ixy#' pc, A8c8c0Hy#F pc, A8c8c0Hy#e pc, A8c8c0Hy# pc, A8c8c0Hy# pc, A8c8c0Hey# pc, A8c8c0HIy# pc, A8c8c0H-y#"pc, A8c8c0Hy#'pc, A8c8c0Hy#Fpc, A8c8c0Hy#epc, A8c8c0Hy#pc, A8c8c0Hy#pc, A8c8c0Hy#pc, A8c8c0Hiy#pc, A8c8c0HMy#pc, A8c8c0H1}N }|ixK}|ixKt}|ixKxf8`X88D"N |jx8`T8D"|#yA xF jN <``cxcdc`cv<`xd`MxTA8| B< `!x!d!`!8a|H58`xH< `!x!d!`!8!a|hN <@`BxBdB`BDN |fx8`8<`D\K|8Tc0T0| PT||l|||L,8cBN ``|=B9*|xjyJ$!})P*=B;/A4A(Ii}IIN!A(8!|N 9 /)/@|p9*|xc$|*N ```|="=B||x8i|#x8,8!1H"i`/@/A?8{<@xH=`=B+AT?9)U)>+AP8!|N `H`K`8`K``8`K``8`K```|a|~x|#x|+x|3x!aK/|xA/A<}/@;8!xa|N x8exxH1`}^/AxH5`Tc+}A@;K`x8exxH`}^/AX;KP;KH```|Aa|~x|#x|+x|3x!a|;xK/|xA|/@DxHM`ExfxPxxH1`x||}xH`8!xAa|N `xH`ExfxPxxH`8!|c}xAa|N ``||x!K/AD/A8!8`|N xH-`8!|N xH-`8!|N }&!A|a|~x|#x;!Q|+x.%|3x-H$`^,9=}=H^*RA?/@܀  @*x@A,A(;{})[N!A(/@|xH `8|(P||x H %`?x/}$KxALAHA(9y})YN!A(^,9=}=H^*R@,```8!~!|Aa} } N /@>,^(y)6d}8J @xA _<99;@}9H@8!|!AaN U: >8 J @xAK >8 J @xAtKh```y y}JBI>8 J @xA8K,y >8 J @xAK``I}JI>8 J @xAK`y >8 J @xAK``y" >8 J @xAKt`` >8 J @xATKH```}cxCxHI`>8 J @xAK  `8 89C;|$,|$,88(T,T,;x|$,88});x|$,{x}x}J;x# C(99C;0;4868:8<}#J}F,9>}@V,C,,0,4|&,6|.,8|6,:|>,<}F,>99I8;8T,T,|,,;}@,,|,{x;8 |Sx}kx,<,9@<,{9@;(|x{,|x,;0{;|,|x,8{i}Jx I0(|M,9H}H|,,86P}):@,N ```c0N /8x x 89#|M BN /8x 889#|M DIBN @@L}$*H@A@/9%}CJ}$JM 89Jx 9)8| BN /A,89#x 88|DIBN N |?|kx8,!}d[x8!AH`8!|N |="|~x;,!qHi`x|exxK`<88/|~xK`8!|N #/A49 ````C9)})/@y# N 8`N ||#x|+x|~x}%Kx8@!A8apH`8p|x~{ K-`8!x|N |9E="+ 9)/|+xI!aiApaxA @|x|#x@=B*|/#A$9@-I9 =B*|#9)#9Ap8!}J8`I?9)?|N ```8!8`|N ```+xK9Ap?8!8`P}J讙I?9)?|N |a|~x|+x|#x8 8!a|3x|;x}CxH1`/|cA9 ``9)})/@y) })H@T})P/})@D9)y* >9J}IH`````>9)>B8!8`a|N 9 Kx|!Aa!Aapx!>b|zx|#x|+x|3x|gx; :: : 0;a@:@x{1:s/>/A8}Z8P@,+%A';>/p8p@9 'ap8!@p|zPx|!A|ca!AaN ``9A9H\`+iAl+uAd+xA\+XAT+pAL+cAD+sA<+%A+OA,+oA$|3x*8>|+d@`99Ap}|2} B& ( !+0A+.: ;A/A:;}9IUH>+)A+)@9I+ Ad}A;*p{ <KP`<9\+lA}\Sx:K`<9\+hA}\Sx:K`V8}!9J)p~ P6xP9A,!p9-z$ }3R)}H8Ap9JAp}{x8 ~x98pcxKcx}{x8 K<K`}!cx8p88 8 9)pK<ApAp9JApKz$}A}3J8)~x98pcxH8*p}{xKacx}{x8K<Kx`z$}A}3J8)~x98pcxH8*p}{xKcx}{x8K<K(`|< x:0<K<:K`<:K`9';!p9 %'pKD|#yA@+$g@H``8cg#+ 9I(+ A@A/|jx@+08 A/A9C8`H8```|4(}#)L G9J|hJ*/A9 8U>++ }4@9 8+@M 9)}(4}#)(AN /@l+08@`C/x@\9CG#}CSxK@```8`N ``N 8K/x@8cg*K|/a|+x|~x|#xAt%=@HaJ}*Rx}J4UJ~}[Kx}%KxH$```88<x K|x@HxH```9)@(I8@ 0@}=Kx``@<|=D`ha"8A H```;@h^@@x|3x}JJ9JU)0UJ0}IPPUJ}I|Hl||O|L,9)B;A``a8`|N ```;y)BI9)y)MJRxy`+A*@0+@*8`x`c8p8{9D"~x~x}IN ` x}IN p~x  x8h}IN <8p;ǵ@Gx; 9H^=B8uhH4`>p~x  x8h}IN ?; 9_@~H-`~x x~}IN ~x9)> x}IN =; ;ȵ@^jH`>~x9)> x}IN =B; ;ʵ@^jH`>~x9)> x}IN ?; ;ߵ@^jH`>~x9)> x}IN @LI~x x88}IN <8ap;ŵ@; 9H^9H|x ^H+-`8p 8x |fH*`88a x 8pH`! 9I+@p9H(9 ^(~x x}IN <; ;ǵ@9 8})8`9H8^89Hh(^H`}GH}[98B@XA|{98B8a exH`! /@>9I^9@I~x x}IN ``=B; ;ʵ@9Hh8^9H^He`/9(>@9 ~x( x}IN ;H%`x x}IN ;Hq`x x}IN ;H`x x}IN ?8ap;ߵ@:9H^9H|x ^H(`8p 8x |fH(m`8p9(>9(h>H `|iyA898>H&U`>9Ix^9@I~ʳx~x}IN <8ap;ǵ@; 9H^9H|x ^H'`9p |h8x H'`8ap9(>9(|x >H'`9!p 8x |iH'Q`8p8p9(>9(h>H `>,#A9I^9@I~x x}IN =B8ap;ʵ@; 9H^9H|x ^H&`8p 8x |fH&`8p9(>9(h>H `>,#A9I^9@I~x x}IN ```=9)8@_8|}IN ?; 9@9^H~H`~x x~}IN /@~x x8(8}IN <9)9@_||||||||8}IN ?9)8@_8|J}IN 9 ( x}IN =B;9 @g8H` xx}IN ,#A9I^9@I~x x}IN ?; ;ߵ@9H^9Hh^H`>,#AX9I^9@I~x x}IN ```<9)8@_8|}IN <8ap;ǵ@; 9H^9H|x ^Hu`9p |h8x H`8ap9(>9(|x >H)`9!p 8x |iH`8p8p9(>9(h>H`>,#A9I^9@I~x x}IN ```=9)8@_8|}IN <9)8@_8|}IN <9)9F@ _|~x9 i x}IN 9 9)_}IN 9 9)_}IN /@X8`8`cx9D" xx}IN X@@d/89kA5@K8`8`c9D" xx}IN 9@I~x x}IN |B8@@/|BA} BK9 ~x( x}IN 8i~x x}IN 8i~x x}IN 8i~x x}IN 8i~x x}IN 9H(9 ^(~x x}IN 8`x`c8p8x9D"~x~x}IN })"9)_}IN 8`8`c9D" xx}IN 8i~x x}IN /9k8A@5@K,~x xh}IN ~ʳx8(~x}IN >9I^9@I~x x}IN 9@I~x x}IN ~x xh}IN <9U0KҘ/8A::H`7AtvH`|uxwH`A8~jx~x}IN /@8`8`cx9D" xx}IN ~jx~x}IN ~jx~x}IN /9k8Ā5@K/@X@@(/9k8A 5 @K|B0@@/|BAl5@KX|;xKɼ9 KP}JJK/@\8`x`c8p8{9D"~x~x}IN  |`;x!H E`x|dx8` K`888`K}`8!xc |N ||x!K}|cx H```Ka@A8!|N `|`|dx;88`!K`xH a`x|dx8` K`8!|N `|`|dx;88`!K]`xH `x|dx8` K=`888`K)`8!|N ||#x8|dx`8`;(!K`x88`K`xH U`x|dx8` K`8!|N `|`|dx;888`!KM`xH `x|dx8` K-`888`K`8!|N ||c"|#x8c!Ke8!9?|i||c8N ||#x8|dx`8`;H!Ku`x88`Ka`xH `x|dx8` KA`8!|N `||+x|#x8|dx8`!K`x8`8`K`;Xx88`K`xH M`x|dx8` K`888`K`8!|N ``||+x|x88`!K-`x8`8`K`;hx88`K`xH`x|dx8` K`8!|N |`|dx;x88`!K`xH!`x|dx8` Km`888`KY`8!|N |`|dx; 88`!K `xH`x|dx8` K`888`K`8!|N ||~x8`8`;‘!K`x88`Ku`xH `x|dx8` KU`8!|N ``||~x8`8`;
!K`x88`K`xHy`x|dx8` K`8!|N ``|`|dx;‸88`!Km`xH`x|dx8` KM`888`K9`8!|N xт9y)$T}CH*} 6}D x|I*N xт9y)$T}CH*} 6}D#x|I*N xтTy)$|cH*|c$6xcN ``#C} S}HQ})Rx})ty)тi)|Bx!A8(8```|xiтy)$}GH*Ti}IL6y*Ax @A0@@9&|0 @}J"yJ |3x9J}I@ Hp``}GP*}HD6y A 9)}*U(yJтy) yJ$BH@M 88(@x x @X8`N |3xH@@N 9@}IK`||~yAa!a@88!Aa|N ````8bHm``8bH]`>}HK}*I} Jx})ty)тi)}IR/A```;(;;X;B`;b``xy*тU)yJ$|P*|L6xH`>9_yFy_ }K/O}(I|Jx})ty)тi)} B|@@@+AT?9)U)>+AP8!|N `H`K`8`K``8`K``8`K```|a|~x|#x|+x|3x!aK/|xA/A<}/@;8!xa|N x8exxH1`}^/AxH5`Tc+}A@;K`x8exxH`}^/AX;KP;KH```|Aa|~x|#x|+x|3x!a|;xK/|xA|/@DxHM`ExfxPxxH1`x||}xH`8!xAa|N `xH`ExfxPxxH`8!|c}xAa|N ``||x!K/AD/A8!8`|N xH-`8!|N xH-`8!|N `}&!A|a|~x|#x;!Q|+x.%|3x-H$`^,9=}=H^*RA?/@܀  @*x@A,A(;{})[N!A(/@|xH`8|(P||x H`?x/}$KxALAHA(9y})YN!A(^,9=}=H^*R@,```8!~!|Aa} } N `8bHi`8!8`!|Aa} } N `,}#0.|2/AL*9@}&:|H`} ./A(9J}&Kx(}):}J@8`N `f N ```c$N ```99C} D,}@V,9C#9Cy) }#J}F,9}@T,C9C }D,9$}@T,C 9C(}D,$9*}@V,C(9C,}F,*9.}@V,C,9C0}F,.92}@V,C09@}F,2`` 9J}M,9 }D, 9 }D, 9 }D, 9 }D, 9 }D, 9 }D, 9 }D, ,*P})B}J@N ``}&!A|a|~x|#x;!Q|+x.%|3x- H$`^89=}=H^6RA?/@ @*x@A,A(;({})[N!A(/@$|xH` (8|(P||x H%`?(x/}$KxALAHA(9y})YN!A(^89=}=H^6R@,```8!~!|Aa} } N `8bH`8!8`!|Aa} } N ` 8}#0.|2/AL69@}&:|H`} ./A(9J}&Kx(}):}J@8`N `fN ```|!Aa!A``|x|#x; ;BH;b((xH_<99;@}9HA\>/@>,^(y)6d}8J @xA _<99;@}9H@8!|!AaN U: >8 J @xAK >8 J @xAtKh```y y}JBI>8 J @xA8K,y >8 J @xAK``I}JI>8 J @xAK`y >8 J @xAK``y" >8 J @xAKt`` >8 J @xATKH```}cxCxH)`>8 J @xAK  `8 89C;|$,|$,88(T,T,;x|$,88});x|$,{x}x}J;x# C(99C;0;4868:8<}#J}F,9>}@V,C,,0,4|&,6|.,8|6,:|>,<}F,>99I8;8T,T,|,,;}@,,|,{x;8 |Sx}kx,<,9@<,{9@;(|x{,|x,;0{;|,|x,8{i}Jx I0(|M,9H}H|,,86P}):@,N ```c0N ```||#x8|dx`8`;x!KE`x88`K1`xH`x|dx8` K`888`K`8!|c|N ```|/a|+x|~x|#xAt%=@HaJ}*Rx}J4UJ~}[Kx}%KxH$```88<x K|x@HxH```9)@(I8@ 0@}=Kx``@<|=D`ha"8A H```;@h^@@x|3x}JJ9JU)0UJ0}IPPUJ}I|Hl||O|L,9)B;A``a8`|N ```|x|Kx8x 8`@8D"|8`<88 D"/@(T>TD.}JKxyC N ```8`xc N `#xc$8cxc9)y)|cJN `#/@K48`N ```|x#/@TD.T>|Kx8`@88x D"|8`<88D"/A<``cxc`cN T@>PP.}$KxxeN `8`N ``||x|#x!qK1?/|~x8`@xxK!xc&8!|~|N ```||x|#x!qKa?/|~x8`@xxKxcd8!;|~xc|N `#/L 88`@88D"N ```#/L TD.T>|Kx8`@88x D"N |x#/@XTD.|+xT>8`@|Kx88x D"|Wޣ>8`@W@>8S8S.x D"N ```#|#x/L 88`@x 8D"N ``#/L T@>8`@PP.88x D"N C|ix/L /|#xA$8`<8D"/9 A?N ``T@>PP.})K#/A8`N ```/|#x;A@/A/@8`<8|D"/xA ;{88`<8|*D"/9 y) @x }#xN ```/@\8`<8|D"/8`@x K`8`<8|D"/8`xc @x K``8`K``8`<8|D"/8`xc @Xx KP```#/@a/|3x;;@L;|#x{ *;`8`<8|D"/9 @x 7}=;@cxaN `8`N ```|8|x!qK`x8K`x8@K`8xK`9 8#9 #xKy`x8pK`!p8`y*@$8!|N ```x88K`8!|c|N ``|8|x!K`xK`8!|N `|a!A9 !!|+x|#x88|3x|}x!pK9`}>9)H@Ax88K`xx |vs@x8K`8~x| xK)`8~Nt~|zxxK`8|yxxK)`9=B="P= L=B*H>:H|xYJ}*})})PP89I}g} |}k|x&~*|8 }k8Pyk |PPx yc&f|x&8~*}Z* 8p|)* 9 Y} }\PPyJ}YR*|9x89)9K`K˭`8cx} H ``|Kˍ`@A?@A!pc/Ap`8bHܕ`8!8`|!AaN ```="`8i88~ųxH`8`8!|!AaN ``8bHI`8!8`|!AaN  `|!Aa!A|#x8|3x|;x|+x||xK`8x~ xK!`8|{xxK`8|}xxK)`]J|x}*})})PP9 }'|x&9*}[:8 |}@Py y &;Q*{R9Z [9@[]} }^PPyJ}]R*|=x89)=K9`= })a)@}IaJ}IAH0``} B@ |_9 (@A/AhZ} ,H@}H})@H:8`8!|!AaN `} CxK8`K `|="X/!q@|x|#x8|+xXK`x8K`x8K`8xK`9 8#xK`TD.}J;xyC |Ke`8KI`/|{x|A4|K=`8xe cxHy`<8`@8})ft})8U&@>Q&Q&.x D"\+;0yI&yJd}(J9J}IR+/A/x;`;@A0xH``A?+//)@^P{[ ~xxexH9`/A|="\:6 ~|PP8|9 H@Al@@Ad@W,xex<9)}#Kx<H`</I\A`?~x/@x/@,xHE`/@L9@=(~óxIK}/@=B*9)}@N,A``9*/}*AX=+/@`=+/A/@K``A=+//)@9*/}*@}|cxc8!|!AaN >//AWD.}JCxxyJ K9@KKt;xK8`Kl8`Kd ||x|#x!qK9@=_9(s_x HI9  9p `BI9  9 I9  }, I9  `BI9JIK,#@=B*9)} L,?8!|N |Aa|+x|~x|#x|3x!axK=9)H@@}?Kx<99'{g"xI I9  9t `BI9  9 I9  ,I9  } Cx9`U,|U,I9 9J E,IKa,#@4="9DT,@{ ALCx8 H`8!Aa|N ```8`K```||x!KE<9@9%_x_ HI9  9| `BI9  9 I9  |,I9JIKE,#@0<8'9 *|D,|D,x}J;x_)?8!|N ``|=;!/AL?x88x>H`9 ?8!x|N ``8`K`,#AD9"|ix} 9@H``A)I9)x/xB~|xKhK``=B,#9*I@H(``}*Kx*/@j#N /@N ```||iy!A`)/AT)/AH)0/A;H@}>@?U)/@xx88K=]XK8!8`|N `||y!A\?]+A 8!8`|N ` /AKE(/AK5K```8!8`|N ```||x!c K(K8`Ky`8!|N |!Aa|x;!!dl9 88|#x8!K8p8xKq/A?AwI?`/AX9=?l9 !889>.} N,!K,#A@>(9I^(?d|8`dKa`x8p8K/@D8`8!!A|aN ```x88 K/A9!N,+ AxK`|{yAxxdxxK/A9 A9!9 !89!8}@O,K/A|8`d;\`K]`{Z ; ; ;0H@+@\>x^UU)@.} Kx})Sx?\}=Py:!A܈+Ah@+!A+)AxxH`KpP+PA`8bHH`cxxK`K````?XY+_pA$)x88i0|Hi`?X9)?XK@``8b8xH `8`K\x"+AT+ A|+At`8bH`cxxKE`8`K9 !8!9 !9?p} N,8AA!K/A 8`dK`xH0i`K``8bh8HM`K`````N N |yA?|#x8`<8)) 8Q Q .&|?8`N ```T@><PGP.xi H@8`N T@>PP.y  K||ya!aA`?/AT) > /Al?/Ad``9 ??x88 Hu`8!a|N ``K=@aJ=\PA=@ P@?0e)@?|9 @(???HK!`L8 x&K `L x&KE`=\m*/A =@ P@;`,K`Wi@>SiSi.<< <@<`K`||}y!Aa!1A$=|#x|+x|3x /A?/<Ax88 H`9 ?9>U)?+y)]`_}@F,_y[ y T0T>Ah+A```8!x|!AaN < K<``=\=@\aJPA=@ P@~ۖ]`=dU80aJPU)~}IKx}(CxWi^} Kx9_} U,0:~{&xK`|~yAx8K`8z (||xxHy`%x8xHe`x$x8K`/ 8L(?H@|jx@:9{z x;5yk )9 8~8```}J|JyG ;(|(P|,|Z|89 |I.}J|=,9)|E,Bz&ު}@P9 }J9;?>E,}@,?=\m*/A=@ PA?K?`d})4_`@T~U^U)~|;xy) |Cx})UJ=py)$} Sx9)8}IKx} =,K``8`K `/|{x|Ax88:KU`{!`:`||zx:@D```@};P})9_p/??@A8A_;`{!A~xHy`K```</A < 9[I;{p| K<;K``8b 8H`?K```;K;Z~,_?UJH~UJ>_KXV@>RR.:: :@:`K9@K `|,#!A 8|<8`@8x D"8`K`8|8`@88D"/A$8KY`8K`/A$8hK-`8hKm`x8K`8!|N C /@0K`|}&!AaAa|+x!!|;x|}x|#x|3x``>|x:; K`:`{Z :†x:88cx~ ``|8`<88 D"/@pT@>PP.}$Kxxx ``@LK}`@A|8`<88 D"T@>/PP.}$Kxxx A9=|L,/Ah=|.<@$~x P~j&tPA`~xH=`8 |8`@8<D"|8`<88 D"A~xH ``~dx8b8H`8`8!Aa|} !AaN ~sAD;|3U2@>Q2Q2.VR'>zJ!@ha*93|L,S3|/~x P~j&t.<*~sAA@A;|3U2@>Q2Q2.VR'>zJ!AyJ$~óx|P*~exH`+3~R@x~UKp```|!Aa|x!A#/@(|fp})+Ad/|#xA |#x|+x88pxH-`x= py) x!0|9x$|3x|JAT@>xP;P.8x HH``} @P8iy!|,T@>P8iP.|,x }JZ;Al+9)/y@ |HP} Cx@9`||:8yk @} @PT@>y!PP.Ix }JZ;@W@>SS.?_})4`JdT^T=pU)~UJ~y) `@|Sx})Ё_|#xy)$|+xUJ9)}HCx|Kx9_} U,9 ?|?_U)H~U)>??4J* Y|U&@>;(Q&8`@Q&.8x xD"||8`@88<D"K`8cx{ H(```?_U)0U)>PAK`@A|yx8xxKQ|~x|?e)@?||8`@8x8D"|8`@88,8D"8} ,y*@8!p|~PTc!A|a|cN ``8bHI`8`8!!A|aN ````|;x8bH`8!8`!A|aN ```8bH`89?|,9_8|L,},|T,``8b8Hq`?U)8~U)>?|/@K`8`K``8b8H)`8`KW@>;SS.y K`}&A|a!a!A!|x|+x8`08|#x~.,K`808{|}xK`880|vxxHE`x88z K`9]9;|xyA{ 8.5}5,89 |E,89} -,@::`/A99 ** *Wg@>Sg8Sg.TU^|;x_JdUJ~aJ@}JCx}@-,??|?_U)H~U)>??4J* Y|U&@>: Q&8`@Q&.8x ~xD"||8`@88<D"K`8cx~ H`PAK`?_@U)0U)>APA``88b@H```8bX;H`:"hH``````|~#x;Hu`+@`8bH]`y8x~Ƴx~xK|~x|?e)@?||8`@8~x8D"|8`@88$8D"8xxK`A~cx~Dx~xK`x80cxK`x80K-`8!pPW!A|a|c} !AaN 9K\``.598 } -,A ~Cx~x8Ku`1>})I/9] y)$|sy9)9 @,}}=9=}M,:K```zg 88|:|-,8|=,K`|!Aa|~x!1`8bpHE`8`KI`|yA9  >(88H`9 ?? 8`h>?K`/|dxATi>/Ap`8bH`8hK5`x8K`8!!|AaN ``8h8K`|8`@888D"8`dK]`|88`@88x D"|;8`@8x<D"|;`8`<8xD"T@>/P9>P.y> }DSx/>x8`@A$AK-`K`8bH`?8(8p88?09 !s9 !tK5`/|}x8AP880H`8}88H `9@ W@>}IS= @S.=x 9 ```_y(d9)y) |A.B?|U&@>8`@Q&8Q&.8x D"|8`@88 8D"|8`@88(8D";8`<8xD"/<x @(T@>PP.U)a)U&@>Q&Q&.x |8`@x8D"8`dKA`|<.8`@`x'884x D"|8`@88@PP.}$KxU:xgU$Z{Z x @/A g{ /A g{ Wy>!A(|U&@>8`@Q&8Q&.xx D"8;@x A8`<8xD"/@T@>PP.}DSxxA0x@xH`8`<8xD"/A?`?@Ki`?xg{ #K`/@~xxH`K``T@>PP.y9 K$```T@>9 PP.})P8a)U&@>Q&Q&.x K`8bH-`8!!|AaN `8bH`Kt |U)?=`?>?>U)?>U)>?8!xa|N `<0K|``8`K}]`/|{x|XA88K`9@ ix}I8|`}[HP9 }J/HI`B@A H9)K`<(/A(<09[@I(;{|0K;K(;@(K``|!Aa|x`!Q8bHi`8`hK}m`|~yA88hH5`9  ?(8`<8D"/9 @x }?J>Kz`88cx 8`PP.{ @P8`K{q`|yA88K}`|zx8`@K{I`|}yA(8@8K}`88@|yxxH `= 9} ===== @=c)U*@>Q*Q*.9 yJ `}_I.9)B>8|WF@>8`@SF8SF.x D"8`@Kz`||yA8@8K|`88@|{xxHY`= cj}@,<<=@= @\<8|Wf@>8`@Sf8Sf.x D"~@ >H8^P|c!8`@W@>8SS.x D"8@|8`@8<D"8`<88D"/A;``;; ;;@H@\;@{ @;8`<{d8|J8D"T@>/P{dP.8`<}DSxx8A^|J8D"T@>/PPP.x |8|8`@8D"8`Kw`8`<8|8D"T@>/U&@>Q&Q&.x 8|8`@8D"8`Kwm`K`^x#`CK`/@xx;H`@{ A```8!!A|aN T@>9 PP.})@8a)U&@>Q&Q&.x KT@>PP.}$Kxx!@K`8bHa`8!!A|aN `8bH!`K``8b H `xCx8Kz)`x8Kwi`K(`8bXH`#xx8@Ky`x8@Kw1`K`8bH`K`||~y!A=B*9)/*@@``8b8`H=`8!|N ``` /A8`<8D"/8x A|8`@8D"8|8`@88D"X/A$`8Kx`X8Kv` /A$H8@Kx` 8@Ku`/A$@8@Kxy`8@Ku`8/A$P8KxM`88Ku`x8hKv`9 8!> |N `T@>PP.}$Kx9 })#xU&@>Q&Q&.x K`> /@4K``||x!|8`<8D"/8x @$T@>PP.a)@U&@>Q&Q&.x |8`@8D"|Kr`8cx~ Kr`8@8`<@`8D"T@>/PP.}$KxxA<8|8`@8< D"8!8`|N @Kr=`8@8`eJ>aJ ;}@,|8 -,8_T`&UUJ@.@?`|-,d|;x})Cx9})Sx} E,|_ ;aJ}@M,|Kpe`x?8cx~ H,``|Kp=`@A4?A9_} T,y%@Kp`; @@`;8bH1`[@;aJ}@M,|8{K/A~xDx8Kt)`~xx~ųxKt`{# x8`Kt`x8`KqA`xH`8bH`8`8!|!AaN ```[@;;aJ}@M,|8{K/@(``8b88pH`;K``~ijx8xKre`V@.VɀeJ9 aJ |ux}IKx9Y@}@E,9\($} U,x~x~ųx;@KKx`8bH`8`K |!Aa!1||x#/@x= |;xa)@HA#C;E |#x|+x|3x})4J{Z ;$|#xU)~ >i5V@.fb z 8 x8H|`8 8|-,9={h y)}xH@x89J} -,9)B@@\})@P8})iP/Wj{}Jx}@=,AD@,; ;Z @{Z A4};KxKX``W{9ux~E,= >>`|98~E,\T`&UUJ@.@<`|-,)d|Kx8})Cx})Sx} =,|\ 8aJ}@M,|?KlU`8cx~ H9} D,y*AKl1`@A|?A 8} ,,y'@; @@;X@8aJ}@M,|8xK/Ahx8!|!AaN ```8bPH|`8`K``8b88H|`;K`8bpH|`8`Kl`;8bH|e`K, ```|B="r K=:O92j12KH>":Q92j12K0=:O82b1"2KJ~Q:0A9~(y  }90A:2~z1 ~/(90A:}zz ~90A:R~(H:@PQ KJ~Q:0Al9~(y  }90AH:2~z1 ~/(90A$:}zz ~90A:R~(H:@QQ KJ~Q:0A9~(y  }90A:2~z1 ~/(90A:}zz ~90Ah:R~(:RH KPJ~Q:0A<9~(y  }90A:2~z1 ~/(90A:}zz ~90A:R~(H:@SQ KJ~Q:0A:~(z  ~90A:2}zz1 ~0(90A\:2~z1 ~/(90A8:}zz O ~90A:R~(H KJ~Q:0A:~(z  ~90A:2}zz1 ~0(90A:2~z1 ~/(90A:}zz ~9:70 AX:R~(H KDJ~Q:0A0:~(z  ~90A :2}zz1 ~0(90A:2~z1 ~/(90A:}zz ~9:80 A:R~(H KJ~Q:0At:~(z  ~90AP:2}zz1 ~0(90A,:2~z1 ~/(90A:}zz ~9:90 A:R~(H K̊J~Q:0A:~(z  ~90A:2}zz1 ~0(90Ap:2~z1 p ~/(90AL:}zz ~9:00 A$:R~(H KJ~Q:0A:~(z  ~90A:2}zz1 ~0(90A:2~z1 p ~/(90A:}zz ~90Al:R~(H KXJ~Q:0AD:~(z  ~90A :2}zz1 ~0(90A:2~z1 p ~/(90A:}zz / ~90A:R~(H KJ~Q:0A:~(z  ~90Ah:2}zz1 ~0(90AD:2~z1 p ~/(90A :}zz ~9:40 A:R~(H K>":Q92j12K̊J~Q:0A9~(y  }90A:2~z1 ~/(90Ap:}zz o ~90AL:R~(H K8J~Q:0A$:~(z  ~90A:}zz ~90A:R~(H:@HQ KĊJ~Q:0A9~(y  }90A:2~z1 ~/(90Ah:}zz O ~90AD:R~(H K0J~Q:0A9~(y  }90A:2~z1 ~/(90A:}zz / ~90A:R~(H KJ~Q:0A:~(z  ~90Ad:}zz ~90A@:R~(H K,J~Q:0A9~(y  }90A:2~z1 ~/(90A:}zz ~90A:R~(H KJ~Q:0A:~(z  ~90A`:}zz ~90A<:R~(H K(J~Q:0A:~(z  ~90A:}zz ~90A:R~(H KJ~Q:0A:~(z  ~90A:}zz ~90A\:R~(H KHJ~Q:0A4:~(z  ~90A:}zz ~90A:R~(Hq K:Q+@8~K/A ~90A:~(Q K~L/A ~90Ax:~(Q Kd+@@\`:Bp~R/AH ~90A4:~(Q K |8|x8!q8apHg`8pK`|yA 8apK8!x|N `||~y!aA9 ~!q9>p} N,;;!8p8!tprvK`9 ~8p!q9 }!r9>p} N,8pv!tK`888axHf `9 ~8p!p9 !q9>p} N,8x!t9 !v9 !rKM`/@8`KW`=";@/|A^X;0;/A(?U)/A<9=;H@}=A8`8!|N xx8K1`^XK8axKK\`8ax88He`K@````8b`8HHf`8`Kt`||x!c/AK1`9 ?=B89*@iKW`8!8`|N `/AL|!K8!p="=Bi(*6||cJxxc |cxcN ``8`N ```/A\|!K=<H6'(=8`9HA9I<G(}(Ji 8!p|N 8`N ```,#Al|9#|+x9D8!p9cq9v9r8p} G,9!t}@O,K`8!|N ``8`N ```,#A\|9@9$!Ap9@cAq9@Ar9At8p} W,9 !vK `8!|N 8`N ```||~y!aA888axHb!`9 ~8p!p9 !q9 !t9 !v8x9 )`!rKa`!z;;/@$Hty*@!z;@Xxx8pK/A9Ap} V,y*@x8xK8`dKR`KR1`8cx} H0```xx8pKe9Ap} V,y*@$KQ`@A9Ap} V,y*ALx8xK8`dKR-`KQ`8cx} `KQ`@@ xx8pK9Ap} V,y*@KQ`>{ #K}`/@xxHb`!z;A``8!8`|N `8bHb5`8!8`|N ```||y!A`?/AT_)+ Al+AP>/Al9 ??x88 H_q`8!|N 0(8KT`9 ? >/@K`||~x!q|(8 <,KO`8cx| H,```|9 D,KO`@A8>(9 =|,}H,=9(0}*HPy'!}&fp|T`&|HP||B@><^(})4U)~><88|x"T@>PU*@>P.Q*Q*.y}Sx8`@8}CxD"/@x8!x|N 8!;x|N ``8} <,U)F>+A9 >KUJF>^K``#/A /A|Aa!aC )P /A\9 a)HAxdQ&|*Q&.8`@x 8D"KL`?b;;{H8cx} H `AKL`@AlxK@/#@8`9 ::: |8!Aa|N ``8bH]i`8!8`Aa|N `8`N ``8`Kl``9j ;\,|\,x&8*{}i"x8 ,!*=  + |*KL``}&|!Aa!A#/AI/AP |#x|#x|+x88PKN`8?}@6,|yx/y*"UH@>QHQH.U*@>Q*Q*.9 @A ?})t})H})vy)=)9)@8 |4,},9}@E,=@T^h|Kx} 5,8`B@6,.:@;:9 9 }@D,>>>UJiJeJaJ }@E,|zd8`@|*8<D";xK!Px81C#xKNU`@8!x|!} AaN `cxDx8KM5`98} D,9xj"|`5,U)}@E,i)9^e)8a) @U,|vx} 5,; K`;KT``~óxdxExKM`K4 ```||x|#x8!KMA`8KJ`8!|N ``||x8`|#x!KI`/A`9 ?88HWy`88KK`8!9 }#Kx|N ``8!9 }#Kx|N `||x!/A$c 8KL`8KIY`x888HV`8!|N ```|9 |x;|#x8!qc?(9 0?,8HV1`+A@_(8; |,} ,yJ&x9J|Kx}(R|Q*=@I 8!|N ```||x8`|#x!KG`9 /A,xxK88KI`9  8!}#Kx|N ``|9|~x!X9? }@L,#UJiJ}F3x9_ |U,9_|,|U,|8`@}%Kx88D"x;KX8!|N `|+xx(x"U$6`0KL```|px!Aa!Aa!|}x|#x8c8`<8D"/;@T@>PP.|3xxF"8`<88D"/AH9 y) :``y)d8`<J8xD"/@TT@>PP.U$>+@<8`<8xD"/9 @T@>PP.}DSxxF"H@A$8`<8xD"/@T@>PP.|3xx#@d/A^;;Z@{ {Z @0>&? >;"b@c9H(```+Al;@{ @;@8`<{&8xD"/9 y) @T@>PP.y +@q)+@8`<8xD"/@T@>PP.`U&@>Q&Q&.x |8`@8xD"8`KC)`xK8`<8xD"8x88$K]/A]2(8}J4UJ~:1 yU ~=}U;yU^:@8q K/Ả:/A48/A~w|:VcVddc8|f=,|-,9@8}{xzn KU/A4/~xA|:=9 88~(8l`|3xx"|=,}I=,K/A889}(4,}@4,zF$y%|Sx|1*8(~0/Al zF(|:x`,T6x"pK)|<x~Dx K|K`9] }sx`CpGclPCdqK`/@H88~0K}{xK ;8~K@{ A(```8`8!px|!Aa!AaN `9 K``)H8@8`<8xD"/AH``8`<8xD"/@T@>PP.|3xx#@;_8`<8ExD"/;@T@>PP.}$Kxx"8`<8ExD"/:@dT@>PP.yW KP```T@>PP.}Cxx#@8`K8x K8`~xK``K``VSfSf.x D"xK/A||8xxHM9`>^(|HPx888@A9I^8 _08i}$,yF"}@M,U9Ii|U,a |,}%,|8!8`!A|aN `9 ^(#H>8|HPx88@@\8 8|$,|`$,y&89^xƐ,|x|B|A*=@G |K```8!8`!A|aN ````8bHM`8!8`!A|aN ||}y!Aa!QAd=|#x|+x|3x /A?/<Ax88 HJ`9 ?>U)?+y)]`_^_^UJ_^UJ>_AT+A``8!x!Aa|N <K\``]\mI/A``8b8xHL`?KP/A_=/ @;;`=x8/AKA9 ?>/A̡_> UJ<}JCx})QyH 9@y) W{8}'Jg{8cg9)|-,8|@0<ax, 8|;x8x"|M,|M,9 }-,* K K```8`K; `/|yx|A888K=]`)x9@|8`@|iH```A)I9)@/@B</A8<);9<K`9 P8?;>x#x>x/ALK_(Cxdx8K<`80>/A_? UJ<}IKx9@}Iy' >y })B<89)TȀ;`a>x}%,9}80a8|;xx"|M,|M,9*}M,j K ? >^x|HPx888@A9I^9I 8i}T,_08U}@M,i9) yF"a |,|%,}M,?K`;;`K4KU/@`8b(HI`K`_> U<}Sx^|Iy }GSx}&Jy) K4;KPP.}$Kxx@8`<8xD"/9 y) @T@>PP.y) /U*<@|UF@>8`@QF8QF.xx D"|;@`8`<8xD"T@>/P9?P.y? }DSx/?x8`d@AAK6`K8`8!|N 8!8`|N })xy* K8``|a|{y!a /AAX8;;xKI?Px/A8K%88K8K8K p8hK8K9=;(/}=@80|8`@88D"|/A$~8K8`~8K6)`8~;K8`<8xD"/AU @>PQ P.Q .x|Kxxy'"U&@>Q&T@>Q&.PP.x|CxK@K|```|!Aa|x`!Q8bHD`?8`y)$?K5`|~yA88HA`9  ?( 8`<8D"/9 @x }=J8`<>88D"/9 y) @T@>PP.x }=J8`<>88D"/9 y) @T@>PP.y }?J~8`<>8;xD"/@0T@>PP.}$Kxx@x8K/A8`<8xD"/@T@>PP.|;xx@8`<8xD"/8x A4|8`@8xD";@``8`<8xD"T@>/P9?P.y? }DSx/?x8`d@AAK1`K|8`@888<D"8`<88D"/@pT@>PP.}Cxx/>@X8`K1`/~A88H?`~88K3`~|xi"Tf@>PfU*@>Pf.Q*;0Q*.x8`@|Sx8xD";^H8CxKu/A0;8`<8xD"/9 ?@,x"T@>U*@>PQ*P.Q*.y}Sxy ^hyJd}&Sx|x"T@>PU*@>P.Q*Q*.y}Sx8`@}Cx8xD";>8#xK/@8`<8xD"/@x"T@>UG@>PQGP.QG.y)});xy)y*"U&@>Q&UG@>Q&.QGQG.x|;x|8`@8xD"|CxK|8`@8x8D"|~8K3`~8K0E``8b(H?`8!!A|aN ```9 >`8bH?a`K`T@>PP.a)U&@>Q&Q&.x K````8bH?`8!!A|aN ~|x"T@>PU*@>P.Q*Q*.y}Sx8`@8}CxD">88|U&@>8`@Q&8Q&.x D"8 |8`@88D";88`<8xD"/9 @,x"T@>U*@>PQ*P.Q*.y}Sxy  ^0yJ}&Sx|x"T@>PU*@>P.Q*Q*.y}Sx8`@8x}CxD";(8`<8xD"/= y) @T@>PP.}CxT^}IKx|U&@>8`@Q&8Q&.xx D";{08`<8exD"/9 ?@,x"T@>PUG@>P.QGQG.y)});xy)^yJd}&Sx|x"T@>PUG@>P.QGQG.y)});x8`@}&Kx8exD"|8xK/A,8xK8||xxK|cx/@|8`@8ex8D"|~8K/]`~8K,`#xKK```||ixc |N xK=B*T|~xKT```|=B*Txh x 9IP@9@!Q@9y P@8@;9I{ P@9@AAP=B8`*X`c9@8pA!p9 !t9 !x9!!9 |!KQ`8!|N ``="8`IX89 `c8pAp9@At9A!xA!|KP`=B*TK,```="8`IX99 `c8pAp9@At9A!xA!|KPU`=B*T9IK```="iP="X="T="`N =B*T9)H@@8`N `K|=HT|ix9JP@!qAP=8`HX!|9!9!Ap9@At9 9@`c8pAx!KOY`8!|N ="IT|ix9JP@@ 8`N |=B P8`9@8`c!ap!|8p9!9tAx!AKN`a8!|N ```|=B*T/!qA8`;H\```xK9?y# @K |cTi 6})A]y# }?P@9 #@@@lAhK?9?}';/;PAH=B T9HP@Ay# K|~xxK9?y# Ax```8!x|N ;K```|!Aa!;|3x|#x|+x|{xW6?;PKu=T|zxKe|cP@Ah=B{\ *T9IP@@9Z9)yH &pH@@;;::::;H``;{ xH0`}<y* @@`}88@Aȁ]8`8p`cAptx!|KL`K```CxK==9:HTy( a9JP@@l;Z;Z[8!cx|!AaN `9 ;;K=!|HX9!8`9!Ap9@At9 9@8p`cAx!KK1`KL=8`9@`c8p!p9 !t9 !x9!!9 A!|KJ`=9Z&pyH 9)H@A="8` X89 A|8pp9A9`ct!xA!KJy`K ```|="T!qK8`88|0P8ap|Kap8!1#|i|N ``|="IT|ix9JP@!qAL=B8` X89@!|`cp9!98ptAx!AKI}`8!|N `=|ixHT9JP@@ 8`N |=HP8`9`c!aAp!|9@9!At!8p9@9 Ax!KH`a8!|N ``|=HT|ix9JP@!qAP=8`HX!|9!9!Ap9@At9 9@`c8pAx!KHI`8!|N =|ixHT9JP@@ 8`N |=HP8`9`c!aAp!|9@9!At!8p9@9 Ax!KG`a8!|N ``|=HT|ix9JP@!qAP=8`HX!|9!9!Ap9@At9 9@`c8pAx!KG`8!|N =="HT9)P@A,=Hh/@9@iIN ``8`N ```9 =B*hN `||kx!q8ap}d[x8!AH-`/|}x@8;9!p{ ;o`88Kԕ`@@8!x|N ``}&=B|*Ta/!A|xx!1;;`A?|#x;P|+x: .$-%;+"-8{9)|h;H@@cxKM@\8{xc K|zA/A@@A;;{ ~H`;{ @A8]}48`9JH@Ax;KM{ @@~óx~x8 H)=`/@9:;{U) 6{})x88!x|} } } !AaN ```=8`9)H@@P@AWZ 6=ZH@[{^ A9 ;`KX```xc KM|xKtxK=K ``|| ?!Aa!|x|;P@;:;; ;A;`H``;A`^{ 9JP@A܁^8`;`c8pApt!x!|AaKB`@8!!|AaN  `="8`VK`|/8c|c!@(8|K8!p8`|N `8K}8!p8`|N ``||#x|x|+x88|3x!a8apK!xap9)+@8c8|cKx8apxxK!xpHA ;;K8!x|N ``9$+@|=B*Tx H@"!Aa!{ z @>::P;; ;A;`H0`6A9IP@@L8~H@|~xc @9)H@9@{ AKс6|jxA9IP@A68`8p`c!pt!x|AaK?`68~|~H@xc A|uJ8|c|K988a8K!8i8||cK K8!8`|!AaN `8`N  ```,#@ 8`N ||c|!K}8!p8`|N ``| Aa!Aa|#x!|+x@P8`8! Aa|!AaN |zx88a8KQ!A/A}PHA{Z { :R}YP~W}X@d=~JP(T?;PH@AL=Hh/@<9@^/A(;xxH{;@8>{ 9)H@8`A;}CSxK{A{ ~x8~RK~R@::::;`H``;Ad^{ 9JP@\AA؁^8`;`c8pAptx!|aK<`@9 =B*hH~x8K{ |Px|;ZK={J (T9)H@@K8`K`="8`IX99 8p`cAp9@At9A!xA|A!K;`K``|="V8`?ibcm,!aK)= CP8aa)U08py)8Qe)lo8a)gp!tK= CP8pa)U18Qy)8e)lo8aa)gp!tKxKYxKQ`8bK`8a8p88KK8!|N N ="iTN ``````|x} |x|#xx!qK]`|~xAHd}?@\{ K5`9? xW>/|~x@8!x|N ```8!8`|N |?;|#x|~8x!q8;H````9>8i}>xc KQ`/|iyxA<9_A4}<9>8i}_xc }>K`/|iyx@Hq`x|exxH`/?;/A8@t8!8`|N ```8!x|N ,#Ax|?A;a|+xx~ !a;;|;@H$`}'Kx9A4G};{ xK`}</|jyx@țIHQ`dx|exxH`/?/AA;K```</=AA;jx{ 9 ;H `B@ 9)})/=@8i8!|{Aa|N ``8!8`Aa|N 8`N 8`K``|a|+x|#x|3x|~x!aK x xH`P|{xxH`|c;cA;H,```|;;{ { Km`xH`@xAy> 8=x;K9`H ```|@}?KxK`xHM`9?{ @|~Jxc A8`8!a|N 8`K||y!Aa!AAX|+xKx|yxxK;|{xH```}?{ K `9?/@[P:CK`/|xx@{~ :~ݳx{ ````x;K`@{ }@;Zz { ~߳x```x;K`@{ @x~K`|P#x|K`8`8!|!AaN 8`K ```}&|y|!Aa!AAt|#x|+x|3xK|~yAlxH`x8cxe xH`/@P8`8!|!A} aN ```xdxKix|zxxK9#P|x#K`|xyA.{ @x~x;xz H``````x;K`@{ {@xKm`9?/=A,``}?{ xKE`9?/=@;;{ H|;;{ KA`xHu`xAy> ;x8K `@H;{ x;{ `x;K`@{ @xK`@,`{ 8;K`A{ 8;Ku`@K```8`K``8!xdxxx|!A} aK ``|aA|x8`|#x|+x!aK `|}yA/AH8xxH`\9 == 8]=@H8` =B?*;K `=8|ix9C(8`="IK `=Bj<``cK =`=="i/A=B/A</A/A8=@y&,aJ`iyF9)8`y<(K/]`;|dy@X?`?@c{``\(8`}*}**y>,{~;xK/`@9 8!= xAa|N ```8bH`=h/A8 K`="i/A8K`=Bj/A<`K`x8K`8`8!Aa|N ```?/@?/@;K`8b0HI`K0`8bH5`8`K``||y!A$? /@,x8K`8!|N `8`K-a`="i/A8 K`="i/A8Ke`="i/A<`KE`9 ? Kl`||wy!Aa!AA |+x<?`?`E|#x;;`c{yJ&;}(P.}HRy%U&8@xA,Jy$ x|"@}ESx@}DSxH`{,8`{~xK,`?/9)U)>y*!?@?=)?Adx8!!|AaN ``~x}\H)`Kh8`K ``|,#!A\|#x8gxd,e8yD8899 K+`|dy@08!x|N `;K```;8bHE`K```|Aa9} ||x9 !Q9@``}H9)}HRyJ B/A?<;TU\}3xU)@.|CxUJ@.})CxSxy) { =BU&@>Q&8`@Q&.88Tx D"g=W@>8`@S8S.8Tx D";T;8`@88|*D">88`@88|JD"7;@8`8!Aa|N `?;An;`;>y*@ y(Ap;9 iH08`@a)8U&@>8Q&Q&.x D"8`<88D"/@T@>;PP.}*8y) , @h```8`K=`8`<88D"/9?y?!9 y) @T@>PP.y }*8/AA;{U)>:+{{ @=B*y(@tAr!pW>UG>\UJU&><}IKxy) K;{9 +y) U)>{{ :@K```;9 K`}(8,@P`8bH`8`K="8`<88D"/t@T@>PP.}DSxxA(kK ```="8|x8`PP.}?xW@>SS.x ="8`@8D"N ```li/@D+AD`98⑸9'H``A0I99)/ @@8`N `98⑸=B9 8`*=B|B'*N ```|!Aa<!Af8`?B;ZK=`|yyA88H `<Cx`@ 8Km`<?88|zPx }@ 88`@D"=8`<88D"/@|T@>;1PP.}$KxxA H\``x /A@D8`dK`8`<88D"T@>/P9?y?!P.TA#xK /@:;;~xxx``x88H `|=@ ;8@9}I;0yG"}@E,|E,@J8`@{"8U&@>88Q&Q&.x D"W@>8`@S8S.88x D"8`@8<88D"8`@8888D"8`@8888D"<8`@`88x D"8`@888D"?x;(x88H `|=@ ;8@9}^J;0yG"}@E,|E,@J8`@{ "8U&@>8(Q&Q&.9 =@x D"W@>8`@S8S.8(x D"8`@8<8(D"8`@888(D"8`@8<8(D"8`@888( D"8`@8<8D"9 #x9 8!!|AaN /@X#x8K]`8!8`!|AaN `8bH 5`8`Kh ``||x!# /@ 8!|N `="8`@888D"="8`@888D"8` K`="8`@888(D"="8`@888(D"="8`@8888D"="8`@8888D"="8`<88TD"/<`x @$T@>PP.U)~U&@>Q&Q&.x ="?;8`@88TD"<`xc K8` K`<`K8` K`=><i@ x`@ |~K`9 x? 8K5`8!|N ``||}y!qA<8`<88(D"/9 y) AX?;?^@H@Ah9J8`yJ&}?R y@t8!|N ?T@>;P?P.^@x H@@8!8`|N `8;|T,@ |T,} ,xx9)|3xy% | P}=H-`x88H`|8@8`@8|<,8(D">@8!x9)U)~>@|N ```8`K```||}y!qAP<|#x8`<888D"/;{ @T@>PP.x =8`<888D"/A9 ;y) =B;9J{&8= |,(@ x{ } ,x|cCx|iPH`9?O,9 ? 9 ? |<8`@8x88D"x8!|N `T@>;PW~P.H@}$Kxy) A8T~T@>PP.{ K 8`K```|li/!A8!8`|N `+|+xA`99b9+`I99)/ @A@=B|3x8=B8p}kB+*H)`p8!|3x|K`99bK```````#/A49 ````C9)})/@y# N 8`N ,%A#/A/A+A@@@|9EyJ 9J}IH(```D/ P@A4B@0@,#/@D8`|jP|cN ``}#|jP|cN 8`N }#} CxKD8`K}#9@K``$/A|/M 9|jxy 9} H `B@P9J*8x $/@/9JA489 x 8|*BN `N |jxKN `/8x x 89#|M BN ``/8x 889#|M DIBN `@@L}$*H@A@/9%}CJ}$JM 89Jx 9)8| BN /A,89#x 88|DIBN N 9#+M 8c |cN ```9#+M 8c|cN ```||#x8|+xx`}%Kx!Hq`8!p|N ```|!8!AH)`8!p|N `|?|kx8X!}d[x8!AH`8!|N ``|="|~x;X!qK`x|exxK``88|~xK`8!|N `||#x|+x|~x}%Kx8@!A8apH`8p|x~{ K`8!x|N ```|9E`+ 9"|+xI!aiApaxA @|x|#x@=B*9J}IH`````>9)>B8!8`a|N 9 Kx|!Aa!Aapx!`|zx|#x|+x|3x|gx; :: : 0;a@:@x{1:b>/A8}Z8P@,+%A';>/p8p@9 'ap8!@p|zPx|!A|ca!AaN ``9A9H\`+iAl+uAd+xA\+XAT+pAL+cAD+sA<+%A+OA,+oA$|3x*8>|+d@`99Ap}|2} B& ( !+0A+.: ;A/A:;}9IUH>+)A+)@9I+ Ad}A;*p{ <KP`<9\+lA}\Sx:K`<9\+hA}\Sx:K`V8}!9J)p~ P6xP9A,!p9-z$ }3R)}H8Ap9JAp}{x8 ~x98pcxKcx}{x8 K<K`}!cx8p88 8 9)pK<ApAp9JApKz$}A}3J8)~x98pcxH8*p}{xKacx}{x8K<Kx`z$}A}3J8)~x98pcxH8*p}{xKcx}{x8K<K(`|< x:0<K<:K`<:K`9';!p9 %'pKD``|#yA@+$g@H``8cg#+ 9I(+ A@A/|jx@+08 A/A9C8`H8```|4(}#)L G9J|hJ*/A9 8U>++ }4@9 8+@M 9)}(4}#)(AN /@l+08@`C/x@\9CG#}CSxK@```8`N ``N 8K/x@8cg*K @OOPPPQ@QRPRS0STUUV VW0W`WWXZ[\]cdeg gij0jPkmnrttuyz`zz{p{|p||}}~~p@PP @p`@@`0 P`  @0@PҀ @@ݐ@``P`0   0 `p0p$% %&(@(p()0)+..//0@01p11256 6@679`9<===>@ABDGJKLMQ0QRPVXZ`[\]0^^^_0__` `p`a0ab@cdkget-msecsusdma-allocdma-freealloc-memfree-memdma-map-indma-map-outconfig-l@config-w@config-l!config-w!translate-my-addressBITMAP: start %lx, size %ld, blocksize %ld 0 16 32 48 63 %dError: Bitmap start %lx, size %ld, requested address %lx, size %ld ELF32: VirtAddr(%lx) != PhysAddr(%lx) not supported, aborting ELF64: VirtAddr(%lx) != PhysAddr(%lx) not supported, aborting ELF relocation out of bounds! ERROR: Unhandled relocation (A) type %i elf-claim-segmentvirtioblk_read: Access beyond end of device!virtio-blk: Unaligned sector read %d virtioblk_read failed! status = %i slofVersion check failed, rc = %d Attach failed, rc = %d Walk failed, rc = %d Stat failed, rc = %d Open failed, rc = %d Read failed, rc = %d Unable to allocate virtio-net driver memory allocation failed! virtionet: Failed to allocate buffers! virtio-net: Receive buffer not big enough! virtionet: Packet too big! Error: %s 9P2000.uunknown.usb_get_pipeusb_send_ctrlusb_transfer_bulksetup_new_device%s: Failed ErrorDevice Error%s: alloc failed %d ptr %p desc_type %d Device not supported %06X %s: bulk reset failed USB Interface class -%x- Not supported ohci_get_pipe_introhci_transfer_bulkohci_send_ctrlusb-ohci: Warning ED not aligned to 16byte boundary%s: alloc failed Timed out waiting for interrupt %x USB: Error TD null %p USB: Error %s %p usb-ohci: Not a bulk pipe. usb-ohci: buffer size not supported - %d %s: tds NULL recieved ED Halted %s: headp %08X tailp %08X next_td %08X attr %08X %s: timed out - failed Request: %02X OHCI: initializing usb-ohci: Unable to allocate memory usb-ohci: Unable to allocate/unaligned HCCA memory %p ** HCD Reset failed...usb-ohci: oops could not allocate intr_pipe Start removing device usb-ohci: unable to setup device on port %d ohci-hcdNOERRORCRCBITSTUFFINGDATATOGGLEMISMATCHSTALLDEVICENOTRESPONDINGPIDCHECKFAILUREUNEXPECTEDPIDDATAOVERRUNDATAUNDERRUNreservedBUFFEROVERRUNBUFFERUNDERRUNNOT ACCESSEDehci_exitehci_send_ctrlehci_transfer_bulk EHCI: Initializing usb-ehci: Unable to allocate memory usb-ehci: reset failed usb-ehci: Unable to allocate frame list usb-ehci: Unable to allocate interrupt queue head usb-ehci: Unable to allocate async queue head usb-ehci: unable to setup device on port %d %s: already called once usb-ehci: Not a control pipe. Error allocating qTDs. usb-ehci: control transfer timed out_ %s: handshake failed usb-ehci: Not a bulk pipe. usb-ehci: bulk transfer size too big usb-ehci: bulk transfer timed out_ ehci-hcds" dev-keyb.fs" INCLUDEDs" dev-mouse.fs" INCLUDEDs" dev-storage.fs" INCLUDEDs" dev-hub.fs" INCLUDEDusb_hid_kbd_init%s: unable to allocate keyboard buffer usb-hub: NULL usb-hub: unable to setup device on port %d xhci_get_pipeTRB_TYPE %d usb-xhci: bulk transfer size too big poll intr failed usb-xhci: allocation failed for interrupt endpoint usb-xhci: allocation failed for bulk endpoint usb-xhci: %s alloc_intr failed %p XHCI: Initializing usb-xhci: Unable to allocate memory usb-xhci: 64 Byte context not supported usb-xhci: failed to initialize XHCI controller. xhci-hcdPowered-OFFPolling*** Disconnected ***DisabledLoopbackCompliancek****** Reset ************ Enabled ******ERROR @{[]}\~|ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()  _+{}||:"~<>?079.136428/*-+ 1234567890.|abcdefghijklmnopqrstuvwxyz1234567890  -=[]\\;'`,.//*-+ 1234567890.\free spaceCreating common NVRAM partition commonUnable to allocate veth driver veth: Failed to allocate memory ! veth: Error %ld registering interface ! veth: Dropping too big packet [%d bytes] veth: Error %ld sending packet !   (8Xyxz{&'((8HXvhwxx|Failed to read MAC address from EEPROM! 82547EI/GI Copper82547EI Mobile52546EB Copper, Dual Port82546EB Fiber, Dual Port82546GB Copper, Dual Port82546GB Fiber, Dual Port82546GB SerDes, Dual Port82545EM Copper82545EM Fiber82545GM Copper82545GM Fiber82545GM SerDes82544EI Copper82544GC Copper82541EI Copper82541EI Mobile82541GI Copper82541GI Mobile82541ER Copper82541PI82540EM Mobile82540EP Mobile82540EP Desktop82540EM Desktop 0123456789ABCDEFhEVALUATE x0@8h0h xP`8( @888pBP <FORTH-WORDLIST   (LASTWORD TIB POCKETS H0EREGS |PCIREGS hCISTACK  COMP-BUFFER  PAFLOF-START L HEAP-START HEAP-END  FDT-START  ROMFS-BASE @ EPAPR-MAGIC X`EPAPR-IMA-SIZE BRANCH L0BRANCH l BREAKPOINT LIT DOTICKDUP8(OVERh@PICKXDROPpSWAP>R(R>pR@RPICKDEPTHDEPTH!0RDEPTHl0RDEPTH!H+Dh-*LSHIFTRSHIFT4ASHIFTpANDORXOR$(@`@!XC@pC!W@ W!LL@L!X@X!  UNALIGNED-W@@0 UNALIGNED-W!P UNALIGNED-L@p UNALIGNED-L!<hU<0<=0=`DODO(DO?DO@DOLOOPHXDO+LOOPpDOLEAVE DO?LEAVETEXIT SEMICOLONEXECUTEMOVE(RMOVE@MRMOVEXRFILL pZCOUNT HASH-SIZE \HASH CLEAN-HASH| HASH-TABLEx-1 \ 0 \@1 \`2 \3 \4 \8 \H#10 \H#20 \  H#FF \@H#FFFF \` H#FFFFFFFF \D#10 \ /C \/W \/L \/X \(/N \HCELL \h/C* /W* /L* /X* 8/N* XHCA+ xxWA+ xLA+ xXA+ (xNA+ Xx8CA1+ xhWA1+ xLA1+ xXA1+ 8xNA1+ Xx(CHAR+ xXCELL+ 8CHAR- CELL- XCHARS CELLS X0CHARS+ XCELLS+ HDOTO 8PhSLITERAL 88x?DUP 88xTUCK P2DUP PP3DUP hhh2OVER hhh2DROP 3DROP NIP CLEAR P(@ROT p-ROT 2SWAP 2ROT 0ROLL 80p0p-ROLL 8Hp0p82>R 2R> X2R@ P?PICK2* p U2/ pP2/ p<< >> >>A INVERT 08(NOT 8XTRUE \FALSE \> U> <=   <>  P>=  0<= P00<> P`0> P0>= P@U<=  pU>=  WITHIN 8BETWEEN pxhD2* 0P0UD2/ `? `D2/ `? hNEGATE PABS 8MAX PMIN U* 1+ px1- pH2+ xx2- EVEN (0BOUNDS PxS>D 8HDNEGATE 88 xDABS 8M+ 8x8(D+ 8xD- *' 88UM* P@P8 hM* 8/' 8P 0p UM/MOD @P8h8SM/REM PH FM/MOD 88P0Xx`U/MOD PH(/MOD Xp`/ p MOD p*/MOD p*/  @WBSPLIT 8PpLWSPLIT 8pXLSPLIT 80 LBSPLIT xXWSPLIT 8XBSPLIT 8BWJOIN  hWLJOIN  BLJOIN xxWBFLIP x LWFLIP XLXJOIN 0 XLFLIP 8LBFLIP WXJOIN HXWFLIP XBXJOIN XBFLIP 8 ALIGNED XXxXhI J UNLOOP p+! PxhCOMP`OFF hON hPIN ňTERMINAL (PhP@ŨBL \  BELL \@BS \`CARRET \ ƀLINEFEED \ ƠEMIT <CR <TYPE  P(hLL-CR ƐƸhSPACE 0ǨSPACES PPǸhCOUNT 8h(PACK 8(88hUPC 8az LCC 8AZ xHKEY <KEY? <ACCEPT <SPAN  EXPECT 0h@REFILL @ 8`PPŘh@0exBASE @DECIMAL Ph`HEX PhˠOCTAL PhPAD xTODIGIT 8 'x0xPMU/MOD 88H<#  8h8HOLD  8PXhpSIGN -̀# PPh̀ #S 0 p#>  8P(.) H8P΀U# PP8h̀πU#S ϐ8U#>  8P (U.) H0p. (ǸШS. иU. ЀǸ.R ((P@U.R Ѐ(P.D PPxиPh`.H PP˰иPhҸ.S 8PP@Xhиh? PиDIGIT P8AZ08P  >NUMBER 8 PPPPPPPxPhX$NUMBER 8  8-8xhX8 (PP  8@ALLOT x, hX PC,  ؐW,  L,  X, (8 PALIGN XX PؠِPLACE h PH8hpSTRING, P( ڰNOOP CURRENT (LAST @P SEARCH-ORDER ۀCONTEXT ۠ LINK>NAME HNAME> h8(hxLINK> `܈ NAME>STRING h8LATEST 0(REVEAL) <PHEADER ٠`P`@hPؠ٠xREVEAL @P`h@P`h STRING=CIX(FIND) <x((FIND)) 8x`pPpޘ (FIND-ORDER) 88ۘPPވ(  @P`($FIND) x80`8܈h$FIND 0   'IMMEDIATE \X IMMEDIATE? p IMMEDIATE `P8p FINDCHAR PPPxP8000  h@0PARSE ŘPx0PŘPH0 8px8ŘPSKIPWS 0P8ŘPpPŘPx00(pŘ`0 PARSE-WORD @0` WHICHPOCKET XPOCKET HpPxpPpx8PphWORD `8 8P8hPhHCHAR 0( )`@\ ŘPXŘhƸ`STATE [ (] h0?COMP PzpCOMPILE, `: 0݈  @:NONAME ٠  @P;  C" "` 8ؠ P(ؠh٠S" P( 8"`888Z" xPp." P( "`.( )`PCOMPILE 8PTHERE +COMP Pph -COMP 0PP  RESOLVE-ORIG PhHAHEAD  PIF  PTHEN `PELSE  P`CASE PENDCASE  (X` OF ( P  ENDOF @ RESOLVE-DEST BEGIN AGAIN  UNTIL  HWHILE REPEAT `LEAVES  RESOLVE-LOOP PP8PPhh(DO P 8Ph?DO P PhP`LOOP  h@+LOOP  @0LEAVE  Ph?LEAVE  Ph SAVE-SOURCE P@0PŘP`RESTORE-SOURCE Řh0h@hOK-STRok ABORTED-STRAborted EXCEPTION-STR Exception # UNKNOWN-STRUndefined wordHW-EXCEPTION-HANDLER <8 SHOW-STACK? h SHOWSTACK 0 NOSHOWSTACK P PRINT-STACK ( PRINT-EXCEPTION 88 (88Xx PRINT-STATUS Ǹ8 (( 8800 8P88XP8X COMPILE-WORD P    X  INTERPRET-WORD (   X  INTERPRET PŘh08PP@EVAL X DOABORT" (XhHABORT"  ` UNDEFINED-STRundefined word SET-UNDEFINED-WORD  8(88(x8x8 ' 0  @`QUIT P`и>ǸʈPǸ x8pxHxMAP-FILE <P UNMAP-FILE <x WRITE-FILE <INCLUDED h PƸH 8X(XINCLUDE 0$CREATE ݈    CREATE 08DODOES> @PhDOES>   CONSTANT 0݈  \XVALUE 0݈  VARIABLE 0݈  PBUFFER: 0݈   xDEFER 0݈  < ĨALIAS 0݈  L @STRUCT P END-STRUCT FIELD 0݈  P`xLITERAL  ` [COMPILE]  POSTPONE 0  @` 0   [CHAR] x[']    FIND 88H 0TO  P( h BEHAVIOR P P>BODY @x BODY> @  RECURSIVE  RECURSE @P (d# 0PPxXPh ph# 0PP˰XPh o# 0PPXPh @ hv-putchar  hv-getchar  hv-haschar! hv-reg-crq!@  hv-free-crq! ( hv-send-crq! H hv-put-tce" hcheck-and-patch-sc1% RB@"l RB!" RW@" RW!#4 RL@#RL!#(RX@$@RX!$LXhv-logical-memop$phv-cas%hv-rtas-update%Pget-print-version%virtio-vring-size&,virtio-get-qsize&d virtio-get-config&Hvirtio-set-qaddr&pvirtio-blk-init'Lvirtio-blk-shutdown'virtio-blk-read'virtio-scsi-init)virtio-scsi-shutdown)L8virtio-scsi-send)`virtio-fs-init(virtio-fs-shutdown(virtio-fs-load(virtio-net-open*virtio-net-close*tvirtio-net-read*@virtio-net-write*hUSB-OHCI-REGISTER+8USB-EHCI-REGISTER+\USB-XHCI-REGISTER+ USB-HCD-INIT+ USB-HCD-EXIT+( USB-HID-INIT,H USB-HID-EXIT,Th USB-READ-KEYB,USB-KEY-AVAILABLE, USB-HUB-INIT, USB-MSC-INIT-4 USB-MSC-EXIT-lUSB-TRANSFER-CTRL-0USB-TRANSFER-BULK-X bootmsg-cp.hbootmsg-warning. bootmsg-error.bootmsg-debugcp/Dbootmsg-setlevel/bootmsg-nvupdate088bootmsg-checklevel/` ELF-LOAD-FILE0\ELF-LOAD-FILE-TO-ADDR0nvram-c@1(nvram-c!2nvram-w@1`nvram-w!2L0nvram-l@1Pnvram-l!2pnvram-x@1nvram-x!2internal-reset-nvram5 nvram-debug5 wipe-nvram5get-nvram-partition38get-named-nvram-partition3`new-nvram-partition4@increase-nvram-partition5erase-nvram-partitionD<delete-nvram-partitionDinternal-get-env58internal-add-env6`internal-del-env7internal-set-envE@internal-nvram-initC8get-nvram-baseCget-nvram-sizeC get-flash-baseD @get-flash-size@` get-mbx-baseA LIBVETH-OPENAH LIBVETH-CLOSEA LIBVETH-READB LIBVETH-WRITEBPE1K-OPENB E1K-CLOSEB@E1K-READ8` E1K-WRITE8 E1K-MAC-SETUP98HID0!9HID0@FPHID1!HXHID1@GHID4!H HID4@E8HID5!GPHID5@GHhMSR@FMSR!GxSDR1@FSDR1!FPVR@GPIR@8TBL@@TBU@@P(DABR@?@DABR!@XHIOR@?pHIOR!?SPRG0@>SPRG0!@ SPRG1@>hSPRG1!>8SPRG2@>SPRG2!>SPRG3@?(0SPRG3!>HHSPRG0@: `HSPRG0!?XHSPRG1@:lHSPRG1!:<DEC@<DEC!<MMCR0!:PMC1@:(ICBI; JUMP-CLIENT;XXCLIENTINTERFACE <WRITE-LOG-BYTE-ENTRY  PCALL-C; START-RTAS; FLUSHCACHEr 2dup 2dup hash ( str len str len hash R: head ) dup >r @ dup ( str len str len *hash *hash R: head hash ) IF ( str len str len *hash R: head hash ) link>name name>string string=ci ( str len true|false R: head hash ) dup 0= IF THEN ELSE nip nip ( str len 0 R: head hash ) THEN IF \ hash found 2drop r> @ r> drop ( *hash R: ) exit THEN \ hash not found r> r> swap >r ((find)) ( str len head R: hash=0 ) dup IF dup r> ! ( link R: ) ELSE r> drop ( 0 R: ) THEN ; : hash-reveal hash off ; ' hash-reveal to (reveal) ' hash-find to (find) : >name ( xt -- nfa ) \ note: still has the "immediate" field! BEGIN char- dup c@ UNTIL ( @lastchar ) dup dup aligned - cell+ char- ( @lastchar lenmodcell ) dup >r - BEGIN dup c@ r@ <> WHILE cell- r> cell+ >r REPEAT r> drop char- ; VARIABLE mask -1 mask ! VARIABLE huge-tftp-load 1 huge-tftp-load ! : sms-get-tftp-blocksize 598 ; : default-hw-exception s" Exception #" type . ; ' default-hw-exception to hw-exception-handler : diagnostic-mode? false ; \ 2B DOTICK'D later in envvar.fs : memory-test-suite ( addr len -- fail? ) diagnostic-mode? IF ." Memory test mask value: " mask @ . cr ." No memory test suite currently implemented! " cr THEN false ; : 0.r 0 swap <# 0 ?DO # LOOP #> type ; : cnt-bits ( 64-bit-value -- #bits=1 ) dup IF 41 1 DO dup 1- and dup 0= IF drop i LEAVE THEN LOOP THEN ; : bcd-to-bin ( bcd -- bin ) dup f and swap 4 rshift a * + ; : 2log ( n -- lb{n} ) 8 cells 0 DO 1 rshift dup 0= IF drop i LEAVE THEN LOOP ; : log2 ( n -- log2-n ) 1- 2log 1+ ; CREATE $catpad 400 allot : $cat ( str1 len1 str2 len2 -- str3 len3 ) >r >r dup >r $catpad swap move r> dup $catpad + r> swap r@ move r> + $catpad swap ; : $cat-comma ( str2 len2 str1 len1 -- "str1, str2" len1+len2+2 ) 2dup + s" , " rot swap move 2+ 2swap $cat ; : $cat-space ( str2 len2 str1 len1 -- "str1 str2" len1+len2+1 ) 2dup + bl swap c! 1+ 2swap $cat ; : $cathex ( str len val -- str len' ) (u.) $cat ; : 2CONSTANT CREATE , , DOES> [ here ] 2@ ; CONSTANT <2constant> : $2CONSTANT $CREATE , , DOES> 2@ ; : 2VARIABLE CREATE 0 , 0 , DOES> ; : (is-user-word) ( name-str name-len xt -- ) -rot $CREATE , DOES> @ execute ; : zplace ( str len buf -- ) 2dup + 0 swap c! swap move ; : rzplace ( str len buf -- ) 2dup + 0 swap rb! swap rmove ; : strdup ( str len -- dupstr len ) here over allot swap 2dup 2>r move 2r> ; : str= ( str1 len1 str2 len2 -- equal? ) rot over <> IF 3drop false ELSE comp 0= THEN ; : test-string ( param len -- true | false ) 0 ?DO dup i + c@ \ Get character / byte at current index dup 20 < swap 7e > OR IF \ Is it out of range 32 to 126 (=ASCII) drop FALSE UNLOOP EXIT \ FALSE means: No ASCII string THEN LOOP drop TRUE \ Only ASCII found --> it is a string ; : #aligned ( adr alignment -- adr' ) negate swap negate and negate ; : #join ( lo hi #bits -- x ) lshift or ; : #split ( x #bits -- lo hi ) 2dup rshift dup >r swap lshift xor r> ; : /string ( str len u -- str' len' ) >r swap r@ chars + swap r> - ; : skip ( str len c -- str' len' ) >r BEGIN dup WHILE over c@ r@ = WHILE 1 /string REPEAT THEN r> drop ; : scan ( str len c -- str' len' ) >r BEGIN dup WHILE over c@ r@ <> WHILE 1 /string REPEAT THEN r> drop ; : split ( str len char -- left len right len ) >r 2dup r> findchar IF >r over r@ 2swap r> 1+ /string ELSE 0 0 THEN ; : rfindchar ( str len char -- offs true | false ) swap 1 - 0 swap do over i + c@ over dup bl = if <= else = then if 2drop i dup dup leave then -1 +loop = ; : rsplit ( str len char -- left len right len ) >r 2dup r> rfindchar IF >r over r@ 2swap r> 1+ /string ELSE 0 0 THEN ; : left-parse-string ( str len char -- R-str R-len L-str L-len ) split 2swap ; : replace-char ( str len chout chin -- ) >r -rot BEGIN 2dup 4 pick findchar WHILE tuck - -rot + r@ over c! swap REPEAT r> 2drop 2drop ; : \-to-/ ( str len -- str' len ) strdup 2dup [char] \ [char] / replace-char ; : isdigit ( char -- true | false ) 30 39 between ; : ishexdigit ( char -- true | false ) 30 39 between 41 46 between OR 61 66 between OR ; : $dh-number ( addr len -- true | number false ) base @ >r decimal dup 2 > IF over dup c@ [char] 0 = over 1 + c@ 20 or [char] x = AND IF hex 2 + swap 2 - rot THEN drop THEN $number r> base ! ; : // dup >r 1- + r> / ; \ division, round up : c@+ ( adr -- c adr' ) dup c@ swap char+ ; : 2c@ ( adr -- c1 c2 ) c@+ c@ ; : 4c@ ( adr -- c1 c2 c3 c4 ) c@+ c@+ c@+ c@ ; : 8c@ ( adr -- c1 c2 c3 c4 c5 c6 c7 c8 ) c@+ c@+ c@+ c@+ c@+ c@+ c@+ c@ ; : 4dup ( n1 n2 n3 n4 -- n1 n2 n3 n4 n1 n2 n3 n4 ) 2over 2over ; : 4drop ( n1 n2 n3 n4 -- ) 2drop 2drop ; : 5dup ( 1 2 3 4 5 -- 1 2 3 4 5 1 2 3 4 5 ) 4 pick 4 pick 4 pick 4 pick 4 pick ; : 5drop 4drop drop ; : 5nip nip nip nip nip nip ; : 6dup ( 1 2 3 4 5 6 -- 1 2 3 4 5 6 1 2 3 4 5 6 ) 5 pick 5 pick 5 pick 5 pick 5 pick 5 pick ; : signed ( n1 -- n2 ) dup 80000000 and IF FFFFFFFF00000000 or THEN ; : r dup r> swap c! 1+ 2 ( dst-adr+1 2 ) ELSE drop 1 ( dst-adr 1 ) THEN +LOOP ; : add-specialchar ( dst-adr special -- dst-adr' ) over c! 1+ ( dst-adr' ) 1 >in +! \ advance input-index ; : parse-" ( dst-adr -- dst-adr' ) [char] " parse dup 3 pick + >r ( dst-adr str len R: dst-adr' ) >r swap r> move r> ( dst-adr' ) ; : (") ( dst-adr -- dst-adr' ) begin ( dst-adr ) parse-" ( dst-adr' ) >in @ dup span @ >= IF ( dst-adr' >in-@ ) drop EXIT THEN ib + c@ CASE [char] ( OF parse-hexstring ENDOF [char] " OF [char] " add-specialchar ENDOF dup OF EXIT ENDOF ENDCASE again ; CREATE "pad 100 allot : " ( [text<">< >] -- text-str text-len ) state @ IF \ compile sliteral, pstr into dict "pad dup (") over - ( str len ) ['] sliteral compile, dup c, ( str len ) bounds ?DO i c@ c, LOOP align ['] count compile, ELSE pocket dup (") over - \ Interpretation, put string THEN \ in temp buffer ; immediate : (cr carret emit ; : $forget ( str len -- ) 2dup last @ ( str len str len last-bc ) BEGIN dup >r ( str len str len last-bc R: last-bc ) cell+ char+ count ( str len str len found-str found-len R: last-bc ) string=ci IF ( str len R: last-bc ) r> @ last ! 2drop clean-hash EXIT ( -- ) THEN 2dup r> @ dup 0= ( str len str len next-bc next-bc ) UNTIL drop 2drop 2drop \ clean hash table ; : forget ( "old-name<>" -- ) parse-word $forget ; : linked ( var -- ) here over @ , swap ! ; HEX VARIABLE wordlists forth-wordlist wordlists ! : wordlist ( -- wid ) here wordlists linked 0 , ; 10 CONSTANT max-in-search-order \ should define elsewhere : also ( -- ) clean-hash context dup cell+ dup to context >r @ r> ! ; : previous ( -- ) clean-hash context cell- to context ; : only ( -- ) clean-hash search-order to context ( minimal-wordlist search-order ! ) ; : seal ( -- ) clean-hash context @ search-order dup to context ! ; : get-order ( -- wid_n .. wid_1 n ) context >r search-order BEGIN dup r@ u<= WHILE dup @ swap cell+ REPEAT r> drop search-order - cell / ; : set-order ( wid_n .. wid_1 n -- ) \ XXX: special cases for 0, -1 clean-hash 1- cells search-order + dup to context BEGIN dup search-order u>= WHILE dup >r ! r> cell- REPEAT drop ; : get-current ( -- wid ) current ; : set-current ( wid -- ) to current ; : definitions ( -- ) context @ set-current ; : VOCABULARY ( C: "name" -- ) ( -- ) CREATE wordlist drop DOES> clean-hash context ! ; : FORTH ( -- ) clean-hash forth-wordlist context ! ; : .voc ( wid -- ) \ display name for wid \ needs work ( body> or something like that ) dup cell- @ ['] vocabulary ['] forth within IF 2 cells - >name name>string type ELSE u. THEN space ; : vocs ( -- ) \ display all wordlist names cr wordlists BEGIN @ dup WHILE dup .voc REPEAT drop ; : order ( -- ) cr ." context: " get-order 0 ?DO .voc LOOP cr ." current: " get-current .voc ; : voc-find ( wid -- 0 | link ) clean-hash cell+ @ (find) clean-hash ; : (function) ; defer (defer) 0 value (value) 0 constant (constant) variable (variable) create (create) alias (alias) (function) cell buffer: (buffer:) ' (function) @ \ ( ) ' (function) cell + @ \ ( ... ) ' (defer) @ \ ( ... ) ' (value) @ \ ( ... ) ' (constant) @ \ ( ... ) ' (variable) @ \ ( ... ) ' (create) @ \ ( ... ) ' (alias) @ \ ( ... ) ' (buffer:) @ \ ( ... ) forget (function) constant constant constant constant constant constant constant constant constant ' lit constant ' sliteral constant ' 0branch constant <0branch> ' branch constant ' doloop constant ' dotick constant ' doto constant ' do?do constant ' do+loop constant ' do constant ' exit constant ' doleave constant ' do?leave constant 500 CONSTANT AVAILABLE-SIZE 4000 CONSTANT MIN-RAM-RESERVE \ prevent from using first pages : MIN-RAM-SIZE \ Initially available memory size epapr-ima-size IF epapr-ima-size ELSE 20000000 \ assumed minimal memory size THEN ; MIN-RAM-SIZE CONSTANT MIN-RAM-SIZE STRUCT cell field available>address cell field available>size CONSTANT /available CREATE available AVAILABLE-SIZE /available * allot available AVAILABLE-SIZE /available * erase VARIABLE mem-pre-released 0 mem-pre-released ! : available>size@ available>size @ ; : available>address@ available>address @ ; : available>size! available>size ! ; : available>address! available>address ! ; : available! ( addr size available-ptr -- ) dup -rot available>size! available>address! ; : available@ ( available-ptr -- addr size ) dup available>address@ swap available>size@ ; : (?available-segment<) ( start1 end1 start2 end2 -- true/false ) drop < nip ; : (?available-segment>) ( start1 end1 start2 end2 -- true/false ) -rot 2drop > ; : (?available-segment-#) ( start1 end1 start2 end2 -- true/false ) 2dup 5 roll -rot ( e1 s2 e2 s1 s2 e2 ) between >r between r> and not ; : (find-available) ( addr addr+size-1 a-ptr a-size -- a-ptr' found ) ?dup 0= IF -rot 2drop false EXIT THEN \ Not Found 2dup 2/ dup >r /available * + dup available>size@ 0= IF 2drop r> RECURSE EXIT THEN dup >r available@ over + 1- 2>r 2swap 2dup 2r@ (?available-segment>) IF 2swap 2r> 2drop r> /available + -rot r> - 1- nip RECURSE EXIT \ Look Right THEN 2dup 2r@ (?available-segment<) IF 2swap 2r> 2drop r> 2drop r> RECURSE EXIT \ Look Left THEN 2dup 2r@ (?available-segment-#) IF \ Conflict - segments overlap 2r> 2r> 3drop 3drop 2drop 1212 throw THEN 2r> 3drop 3drop r> r> drop ( a-ptr' -- ) dup available>size@ 0<> ( a-ptr' found -- ) ; : (find-available) ( addr size -- seg-ptr found ) over + 1- available AVAILABLE-SIZE ['] (find-available) catch IF 2drop 2drop 0 false THEN ; : dump-available ( available-ptr -- ) cr dup available - /available / AVAILABLE-SIZE swap - 0 ?DO dup available@ ?dup 0= IF 2drop UNLOOP EXIT THEN swap . . cr /available + LOOP dup ; : .available available dump-available ; : (drop-available) ( available-ptr -- ) dup available - /available / \ current element index AVAILABLE-SIZE swap - \ # of remaining elements ( first nelements ) 1- 0 ?DO dup /available + dup available@ ( current next next>address next>size ) ?dup 0= IF 2drop LEAVE \ NULL element - goto last copy THEN 3 roll available! ( next ) LOOP 0 0 rot available! ; : (stick-to-previous-available) ( addr size available-ptr -- naddr nsize nptr success ) dup available = IF false EXIT \ This was the first available segment THEN dup /available - dup available@ + 4 pick = IF nip \ Drop available-ptr since we are going to previous one rot drop \ Drop start addr, we take the previous one dup available@ 3 roll + rot true ELSE drop false THEN ; : (insert-available) ( available-ptr -- available-ptr ) dup \ current element dup available - /available / \ current element index AVAILABLE-SIZE swap - \ # of remaining elements dup 0<= 3 pick available>size@ 0= or IF drop drop EXIT THEN over available@ rot ( first first/=current/ first>address first>size nelements ) 1- 0 ?DO 2>r /available + dup available@ 2r> 4 pick available! dup 0= IF rot /available + available! UNLOOP EXIT THEN LOOP ( first next/=last/ last[0]>address last[0]>size ) ?dup 0<> IF cr ." release error: available map overflow" cr ." Dumping available property" .available cr ." No space for one before last entry:" cr swap . . cr ." Dying ..." cr 123 throw THEN 2drop ; : insert-available ( addr size available-ptr -- addr size available-ptr ) dup available>address@ 0<> IF dup available>address@ rot dup -rot - 3 pick = IF \ if (available>address@ - size == addr) over available>size@ + swap (stick-to-previous-available) IF dup /available + (drop-available) THEN ELSE swap (stick-to-previous-available) not IF (insert-available) THEN THEN ELSE (stick-to-previous-available) drop THEN ; defer release : drop-available ( addr size available-ptr -- addr ) dup >r available@ over 4 pick swap - ?dup 0<> IF dup 3 roll swap r> available! - over - ?dup 0= IF drop ELSE swap 2 pick + swap release THEN ELSE nip ( req_addr req_size segment_size ) over - ?dup 0= IF drop r> (drop-available) ELSE -rot over + rot r> available! THEN THEN ; : pwr2roundup ( value -- pwr2value ) dup CASE 0 OF EXIT ENDOF 1 OF EXIT ENDOF ENDCASE dup 1 DO drop i dup +LOOP dup + ; : (claim-best-fit) ( len align -- len base ) pwr2roundup 1- -1 -1 available AVAILABLE-SIZE /available * + available DO i \ Must be saved now, before we use Return stack -rot >r >r swap >r available@ ?dup 0= IF drop r> r> r> LEAVE THEN \ EOL 2 pick - dup 0< IF 2drop \ Can't Fit: Too Small ELSE dup 2 pick r@ and - 0< IF 2drop \ Can't Fit When Aligned ELSE r> -rot dup r@ U< IF 2r> 2drop swap 2 pick + 2 pick invert and >r >r >r ELSE 2drop >r THEN THEN THEN r> r> r> /available +LOOP -rot 2drop ( len best-fit-base/or -1 if none found/ ) ; : (adjust-release0) ( 0 size -- addr' size' ) 2dup MIN-RAM-SIZE dup 3 roll + -rot - dup 0< IF 2drop ELSE 2swap 2drop 0 mem-pre-released ! THEN ; : claim ( [ addr ] len align -- base ) ?dup 0<> IF (claim-best-fit) dup -1 = IF 2drop cr ." claim error : aligned allocation failed" cr ." available:" cr .available 321 throw EXIT THEN swap THEN 2dup (find-available) not IF drop 2drop 321 throw EXIT THEN ( req_addr req_size available-ptr ) drop-available ; : .release ( addr len -- ) over 0= mem-pre-released @ and IF (adjust-release0) THEN 2dup (find-available) IF drop swap cr ." release error: region " . ." , " . ." already released" cr ELSE ?dup 0= IF swap cr ." release error: Bad/conflicting region " . ." , " . ." or available list full " cr ELSE ( addr size available-ptr ) insert-available ( addr size available-ptr ) available! THEN THEN ; ' .release to release 0 MIN-RAM-SIZE release 1 mem-pre-released ! 0 MIN-RAM-RESERVE 0 ' claim CATCH IF ." claim failed!" cr 2drop THEN drop paflof-start ffff not and 1f00000 0 ' claim CATCH IF ." claim failed!" cr 2drop THEN drop heap-end heap-start - log2 1+ CONSTANT (max-heads#) CREATE heads (max-heads#) cells allot heads (max-heads#) cells erase : size>head ( size -- headptr ) log2 3 max cells heads + ; : alloc-mem ( len -- a-addr ) dup 0= IF EXIT THEN 1 over log2 3 max ( len 1 log_len ) dup (max-heads#) >= IF cr ." Out of internal memory." cr 3drop 0 EXIT THEN lshift >r ( len R: 1<head dup @ IF dup @ dup >r @ swap ! r> r> drop EXIT THEN ( headptr R: 1< 2drop 2drop 0 EXIT THEN r> + >r 0 over ! swap ! r> ; : free-mem ( a-addr len -- ) dup 0= IF 2drop EXIT THEN size>head 2dup @ swap ! ! ; : #links ( a -- n ) @ 0 BEGIN over WHILE 1+ swap @ swap REPEAT nip ; : .free ( -- ) 0 (max-heads#) 0 DO heads i cells + #links dup IF cr dup . ." * " 1 i lshift dup . ." = " * dup . THEN + LOOP cr ." Total " . ; heap-start heap-end heap-start - free-mem false VALUE debug-find-component? VARIABLE device-tree VARIABLE current-node : get-node current-node @ dup 0= ABORT" No active device tree node" ; STRUCT cell FIELD node>peer cell FIELD node>parent cell FIELD node>child cell FIELD node>properties cell FIELD node>words cell FIELD node>instance-template cell FIELD node>instance-size cell FIELD node>space? cell FIELD node>space cell FIELD node>addr1 cell FIELD node>addr2 cell FIELD node>addr3 END-STRUCT : find-method ( str len phandle -- false | xt true ) node>words @ voc-find dup IF link> true THEN ; 0 VALUE my-self 400 CONSTANT max-instance-size STRUCT /n FIELD instance>node /n FIELD instance>parent /n FIELD instance>args /n FIELD instance>args-len /n FIELD instance>size /n FIELD instance>#units /n FIELD instance>unit1 \ For instance-specific "my-unit" /n FIELD instance>unit2 /n FIELD instance>unit3 /n FIELD instance>unit4 CONSTANT /instance-header : >instance ( offset -- myself+offset ) my-self 0= ABORT" No instance!" dup my-self instance>size @ >= ABORT" Instance access out of bounds!" my-self + ; : (create-instance-var) ( initial-value -- ) get-node dup node>instance-size @ cell+ max-instance-size >= ABORT" Instance is bigger than max-instance-size!" dup node>instance-template @ ( iv phandle tmp-ih ) swap node>instance-size dup @ ( iv tmp-ih *instance-size instance-size ) dup , \ compile current instance ptr swap 1 cells swap +! ( iv tmp-ih instance-size ) + ! ; : create-instance-var ( "name" initial-value -- ) CREATE (create-instance-var) PREVIOUS ; : (create-instance-buf) ( buffersize -- ) aligned \ align size to multiples of cells dup get-node node>instance-size @ + ( buffersize' newinstancesize ) max-instance-size > ABORT" Instance is bigger than max-instance-size!" get-node node>instance-template @ get-node node>instance-size @ + over erase \ clear according to IEEE 1275 get-node node>instance-size @ ( buffersize' old-instance-size ) dup , \ compile current instance ptr + get-node node>instance-size ! \ store new size ; : create-instance-buf ( "name" buffersize -- ) CREATE (create-instance-buf) PREVIOUS ; VOCABULARY instance-words ALSO instance-words DEFINITIONS : VARIABLE 0 create-instance-var DOES> [ here ] @ >instance ; : VALUE create-instance-var DOES> [ here ] @ >instance @ ; : DEFER 0 create-instance-var DOES> [ here ] @ >instance @ execute ; : BUFFER: create-instance-buf DOES> [ here ] @ >instance ; PREVIOUS DEFINITIONS CONSTANT CONSTANT CONSTANT CONSTANT : (instance?) ( xt -- xt true|false ) dup @ = IF dup cell+ @ cell+ @ ['] >instance = ELSE false THEN ; : (doito) ( value R:*CFA -- ) r> cell+ dup >r @ cell+ cell+ @ >instance ! ; ' (doito) CONSTANT <(doito)> : to ( value wordname<> -- ) ' (instance?) state @ IF IF ['] (doito) ELSE ['] DOTO THEN , , EXIT THEN IF cell+ cell+ @ >instance ! \ interp mode instance value ELSE cell+ ! \ interp mode normal value THEN ; IMMEDIATE : behavior ( defer-xt -- contents-xt ) dup cell+ @ = IF \ Is defer-xt an INSTANCE DEFER ? 2 cells + @ >instance @ ELSE behavior THEN ; : INSTANCE ALSO instance-words ; : my-parent my-self instance>parent @ ; : my-args my-self instance>args 2@ swap ; : set-my-args ( old-addr len -- ) dup IF \ IF len > 0 ( old-addr len ) dup alloc-mem \ | allocate space for new args ( old-addr len new-addr ) 2dup my-self instance>args 2! \ | write into instance struct ( old-addr len new-addr ) swap move \ | and copy the args ( ) ELSE \ ELSE ( old-addr len ) my-self instance>args 2! \ | set new args to zero, too ( ) THEN \ FI ; : create-instance-data ( -- instance ) get-node dup node>instance-template @ ( phandle instance-template ) swap node>instance-size @ ( instance-template instance-size ) dup >r dup alloc-mem dup >r swap move r> ( instance ) dup instance>size r> swap ! \ Store size for destroy-instance dup instance>#units 0 swap ! \ Use node unit by default ; : create-instance ( -- ) my-self create-instance-data dup to my-self instance>parent ! get-node my-self instance>node ! ; : destroy-instance ( instance -- ) dup instance>args @ ?dup IF \ Free instance args? over instance>args-len @ free-mem THEN dup instance>size @ free-mem ; : ihandle>phandle ( ihandle -- phandle ) dup 0= ABORT" no current instance" instance>node @ ; : push-my-self ( ihandle -- ) r> my-self >r >r to my-self ; : pop-my-self ( -- ) r> r> to my-self >r ; : call-package push-my-self execute pop-my-self ; : $call-static ( ... str len node -- ??? ) find-method IF execute ELSE -1 throw THEN ; : $call-my-method ( str len -- ) my-self ihandle>phandle $call-static ; : $call-method ( str len ihandle -- ) push-my-self ['] $call-my-method CATCH ?dup IF pop-my-self THROW THEN pop-my-self ; 0 VALUE calling-child : $call-parent my-self ihandle>phandle TO calling-child my-parent $call-method 0 TO calling-child ; : create-node ( parent -- new ) max-instance-size alloc-mem ( parent instance-mem ) dup max-instance-size erase >r ( parent R: instance-mem ) align wordlist >r wordlist >r ( parent R: instance-mem wl wl ) here ( parent new R: instance-mem wl wl ) 0 , swap , 0 , \ Set node>peer, node>parent & node>child r> , r> , \ Set node>properties & node>words to wl r> , /instance-header , \ Set instance-template & instance-size FALSE , 0 , \ Set node>space? and node>space 0 , 0 , 0 , \ Set node>addr* ; : peer node>peer @ ; : parent node>parent @ ; : child node>child @ ; : peer dup IF peer ELSE drop device-tree @ THEN ; : link ( new head -- ) \ link a new node at the end of a linked list BEGIN dup @ WHILE @ REPEAT ! ; : link-node ( parent child -- ) swap dup IF node>child link ELSE drop device-tree ! THEN ; : set-node ( phandle -- ) current-node @ IF previous THEN dup current-node ! ?dup IF node>words @ also context ! THEN definitions ; : get-parent get-node parent ; : new-node ( -- phandle ) \ active node becomes new node's parent; current-node @ dup create-node tuck link-node dup set-node ; : finish-node ( -- ) get-node parent set-node ; : device-end ( -- ) 0 set-node ; CREATE $indent 100 allot VARIABLE indent 0 indent ! true value encode-first? : decode-int over >r 4 /string r> 4c@ swap 2swap swap bljoin ; : decode-64 decode-int -rot decode-int -rot 2swap swap lxjoin ; : decode-string ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 str len ) dup 0= IF 2dup EXIT THEN \ string properties with zero length over BEGIN dup c@ 0= IF 1+ -rot swap 2 pick over - rot over - -rot 1- EXIT THEN 1+ AGAIN ; : (prune) ( name len head -- ) dup >r (find) ?dup IF r> BEGIN dup @ WHILE 2dup @ = IF >r @ r> ! EXIT THEN @ REPEAT 2drop ELSE r> drop THEN ; : prune ( name len -- ) last (prune) ; : set-property ( data dlen name nlen phandle -- ) true to encode-first? get-current >r node>properties @ set-current 2dup prune $2CONSTANT r> set-current ; : delete-property ( name nlen -- ) get-node get-current >r node>properties @ set-current prune r> set-current ; : property ( data dlen name nlen -- ) get-node set-property ; : get-property ( str len phandle -- true | data dlen false ) ?dup 0= IF cr cr cr ." get-property for " type ." on zero phandle" cr cr true EXIT THEN node>properties @ voc-find dup IF link> execute false ELSE drop true THEN ; : get-package-property ( str len phandle -- true | data dlen false ) get-property ; : get-my-property ( str len -- true | data dlen false ) my-self ihandle>phandle get-property ; : get-parent-property ( str len -- true | data dlen false ) my-parent ihandle>phandle get-property ; : get-inherited-property ( str len -- true | data dlen false ) my-self ihandle>phandle BEGIN 3dup get-property 0= IF rot drop rot drop rot drop false EXIT THEN parent dup 0= IF 3drop true EXIT THEN AGAIN ; 20 CONSTANT indent-prop : .prop-int ( str len -- ) space 400 min 0 ?DO i over + dup ( str act-addr act-addr ) c@ 2 0.r 1+ dup c@ 2 0.r 1+ dup c@ 2 0.r 1+ c@ 2 0.r ( str ) i c and c = IF \ check for multipleof 16 bytes cr indent @ indent-prop + 1+ 0 \ linefeed + indent DO space \ print spaces LOOP ELSE space space \ print two spaces THEN 4 +LOOP drop ; : .prop-bytes ( str len -- ) 2dup -4 and .prop-int ( str len ) dup 3 and dup IF ( str len len%4 ) >r -4 and + r> ( str' len%4 ) bounds ( str' str'+len%4 ) DO i c@ 2 0.r \ Print last 3 bytes LOOP ELSE 3drop THEN ; : .prop-string ( str len ) 2dup space type cr indent @ indent-prop + 0 DO space LOOP \ Linefeed .prop-bytes ; : .propbytes ( xt -- ) execute dup IF over cell- @ execute ELSE 2drop THEN ; : .property ( lfa -- ) cr indent @ 0 ?DO space LOOP link> dup >name name>string 2dup type nip ( len ) indent-prop swap - ( xt 20-len ) dup 0< IF drop 0 THEN 0 ( xt number-of-space 0 ) ?DO space LOOP .propbytes ; : (.properties) ( phandle -- ) node>properties @ cell+ @ BEGIN dup WHILE dup .property @ REPEAT drop ; : .properties ( -- ) get-node (.properties) ; : next-property ( str len phandle -- false | str' len' true ) ?dup 0= IF device-tree @ THEN \ XXX: is this line required? node>properties @ >r 2dup 0= swap 0= or IF 2drop r> cell+ ELSE r> voc-find THEN @ dup IF link>name name>string true THEN ; : encode-start ( -- prop 0 ) ['] .prop-int compile, false to encode-first? here 0 ; : encode-int ( val -- prop prop-len ) encode-first? IF ['] .prop-int compile, \ Execution token for print false to encode-first? THEN here swap lbsplit c, c, c, c, /l ; : encode-bytes ( str len -- prop-addr prop-len ) encode-first? IF ['] .prop-bytes compile, \ Execution token for print false to encode-first? THEN here over 2dup 2>r allot swap move 2r> ; : encode-string ( str len -- prop-addr prop-len ) encode-first? IF ['] .prop-string compile, \ Execution token for print false to encode-first? THEN encode-bytes 0 c, char+ ; : encode+ ( prop1-addr prop1-len prop2-addr prop2-len -- prop-addr prop-len ) nip + ; : encode-int+ encode-int encode+ ; : encode-64 xlsplit encode-int rot encode-int+ ; : encode-64+ encode-64 encode+ ; : device-name encode-string s" name" property ; : device-type encode-string s" device_type" property ; : model encode-string s" model" property ; : compatible encode-string s" compatible" property ; : #address-cells s" #address-cells" rot parent get-property ABORT" parent doesn't have a #address-cells property!" decode-int nip nip ; : my-#address-cells ( -- #address-cells ) get-node #address-cells ; : child-#address-cells ( -- #address-cells ) s" #address-cells" get-node get-property ABORT" node doesn't have a #address-cells property!" decode-int nip nip ; : child-#size-cells ( -- #address-cells ) s" #size-cells" get-node get-property ABORT" node doesn't have a #size-cells property!" decode-int nip nip ; : encode-phys ( phys.hi ... phys.low -- prop len ) encode-first? IF encode-start ELSE here 0 THEN my-#address-cells 0 ?DO rot encode-int+ LOOP ; : encode-child-phys ( phys.hi ... phys.low -- prop len ) encode-first? IF encode-start ELSE here 0 THEN child-#address-cells 0 ?DO rot encode-int+ LOOP ; : encode-child-size ( size.hi ... size.low -- prop len ) encode-first? IF encode-start ELSE here 0 THEN child-#size-cells 0 ?DO rot encode-int+ LOOP ; : decode-phys my-#address-cells BEGIN dup WHILE 1- >r decode-int r> swap >r REPEAT drop my-#address-cells BEGIN dup WHILE 1- r> swap REPEAT drop ; : decode-phys-and-drop my-#address-cells BEGIN dup WHILE 1- >r decode-int r> swap >r REPEAT 3drop my-#address-cells BEGIN dup WHILE 1- r> swap REPEAT drop ; : reg >r encode-phys r> encode-int+ s" reg" property ; : >space node>space @ ; : >space? node>space? @ ; : >address dup >r #address-cells dup 3 > IF r@ node>addr3 @ swap THEN dup 2 > IF r@ node>addr2 @ swap THEN 1 > IF r@ node>addr1 @ THEN r> drop ; : >unit dup >r >address r> >space ; : (my-phandle) ( -- phandle ) my-self ?dup IF ihandle>phandle ELSE get-node dup 0= ABORT" no active node" THEN ; : my-space ( -- phys.hi ) (my-phandle) >space ; : my-address (my-phandle) >address ; : my-unit my-self instance>#units @ IF 0 my-self instance>#units @ 1- DO my-self instance>unit1 i cells + @ -1 +LOOP ELSE my-self ihandle>phandle >unit THEN ; : my-unit-64 ( -- phys.lo+1|phys.lo ) my-unit ( phys.lo ... phys.hi ) (my-phandle) #address-cells ( phys.lo ... phys.hi #ad-cells ) CASE 1 OF EXIT ENDOF 2 OF lxjoin EXIT ENDOF 3 OF drop lxjoin EXIT ENDOF dup OF 2drop lxjoin EXIT ENDOF ENDCASE ; : set-space get-node dup >r node>space ! true r> node>space? ! ; : set-address my-#address-cells 1 ?DO get-node node>space i cells + ! LOOP ; : set-unit set-space set-address ; : set-unit-64 ( phys.lo|phys.hi -- ) my-#address-cells 2 <> IF ." set-unit-64: #address-cells <> 2 " abort THEN xlsplit set-unit ; : set-args ( arg-str len unit-str len -- ) s" decode-unit" get-parent $call-static set-unit set-my-args ; : $cat-unit dup parent 0= IF drop EXIT THEN dup >space? not IF drop EXIT THEN dup >r >unit s" encode-unit" r> parent $call-static dup IF dup >r here swap move s" @" $cat here r> $cat ELSE 2drop THEN ; : $cat-instance-unit dup parent 0= IF drop EXIT THEN dup instance>#units @ 0= IF ihandle>phandle $cat-unit EXIT THEN dup >r push-my-self ['] my-unit CATCH IF pop-my-self r> drop EXIT THEN pop-my-self s" encode-unit" r> ihandle>phandle parent $call-static dup IF dup >r here swap move s" @" $cat here r> $cat ELSE 2drop THEN ; : node>name dup >r s" name" rot get-property IF r> (u.) ELSE 1- r> drop THEN ; : node>qname dup node>name rot ['] $cat-unit CATCH IF drop THEN ; : node>path here 0 rot BEGIN dup WHILE dup parent REPEAT 2drop dup 0= IF [char] / c, THEN BEGIN dup WHILE [char] / c, node>qname here over allot swap move REPEAT drop here 2dup - allot over - ; : interposed? ( ihandle -- flag ) dup instance>parent @ dup 0= IF 2drop false EXIT THEN ihandle>phandle swap ihandle>phandle parent <> ; : instance>qname dup >r interposed? IF s" %" ELSE 0 0 THEN r@ dup ihandle>phandle node>name rot ['] $cat-instance-unit CATCH IF drop THEN $cat r> instance>args 2@ swap dup IF 2>r s" :" $cat 2r> $cat ELSE 2drop THEN ; : instance>qpath \ With interposed nodes. here 0 rot BEGIN dup WHILE dup instance>parent @ REPEAT 2drop dup 0= IF [char] / c, THEN BEGIN dup WHILE [char] / c, instance>qname here over allot swap move REPEAT drop here 2dup - allot over - ; : instance>path \ Without interposed nodes. here 0 rot BEGIN dup WHILE dup interposed? 0= IF dup THEN instance>parent @ REPEAT 2drop dup 0= IF [char] / c, THEN BEGIN dup WHILE [char] / c, instance>qname here over allot swap move REPEAT drop here 2dup - allot over - ; : .node node>path type ; : pwd get-node .node ; : .instance instance>qpath type ; : .chain dup instance>parent @ ?dup IF recurse THEN cr dup . instance>qname type ; defer find-node : set-alias ( alias-name len device-name len -- ) encode-string 2swap s" /aliases" find-node ?dup IF set-property ELSE 4drop THEN ; : find-alias ( alias-name len -- false | dev-path len ) s" /aliases" find-node dup IF get-property 0= IF 1- dup 0= IF nip THEN ELSE false THEN THEN ; : .alias ( alias-name len -- ) find-alias dup IF type ELSE ." no alias available" THEN ; : (.print-alias) ( lfa -- ) link> dup >name name>string 2dup s" name" string=ci IF 2drop drop ELSE cr type space ." : " execute type THEN ; : (.list-alias) ( phandle -- ) node>properties @ cell+ @ BEGIN dup WHILE dup (.print-alias) @ REPEAT drop ; : list-alias ( -- ) s" /aliases" find-node dup IF (.list-alias) THEN ; 8 CONSTANT MAX-ALIAS 1 VALUE alias-ind : get-next-alias ( $alias-name -- $next-alias-name|FALSE ) 2dup find-alias IF drop 1 TO alias-ind BEGIN 2dup alias-ind $cathex 2dup find-alias WHILE drop 2drop alias-ind 1 + TO alias-ind alias-ind MAX-ALIAS = IF 2drop FALSE EXIT THEN REPEAT strdup 2swap 2drop THEN ; : devalias ( "{alias-name}<>{device-specifier}" -- ) parse-word parse-word dup IF set-alias ELSE 2drop dup IF .alias ELSE 2drop list-alias THEN THEN ; : sub-alias ( arg-str arg-len -- arg' len' | false ) 2dup 2dup [char] / findchar ?dup IF ELSE 2dup [char] : findchar THEN ( a l a l [p] -1|0 ) IF nip dup ELSE 2drop 0 THEN >r find-alias ?dup IF ( a l a' p' -- R:p | a' l' -- R:0 ) r@ IF 2swap r@ - swap r> + swap $cat strdup ( a" l-p+p' -- ) ELSE ( a' l' -- R:0 ) r> drop ( a' l' -- ) THEN ELSE ( a l -- R:p | -- R:0 ) r> IF 2drop THEN false ( 0 -- ) THEN ; : de-alias ( arg-str arg-len -- arg' len' ) BEGIN over c@ [char] / <> dup IF drop 2dup sub-alias ?dup THEN WHILE 2swap 2drop REPEAT ; : +indent ( not-last? -- ) IF s" | " ELSE s" " THEN $indent indent @ + swap move 4 indent +! ; : -indent ( -- ) -4 indent +! ; : ls-phandle ( node -- ) . ." : " ; : ls-node ( node -- ) cr dup ls-phandle $indent indent @ type dup peer IF ." |-- " ELSE ." +-- " THEN node>qname type ; : (ls) ( node -- ) child BEGIN dup WHILE dup ls-node dup child IF dup peer +indent dup recurse -indent THEN peer REPEAT drop ; : ls ( -- ) get-node cr dup ls-phandle dup node>path type (ls) 0 indent ! ; : show-devs ( {device-specifier} -- ) skipws 0 parse dup IF de-alias ELSE 2drop s" /" THEN ( str len ) find-node dup 0= ABORT" No such device path" (ls) ; VARIABLE interpose-node 2VARIABLE interpose-args : interpose ( arg len phandle -- ) interpose-node ! interpose-args 2! ; 0 VALUE user-instance-#units CREATE user-instance-units 4 cells allot : copy-instance-unit ( -- ) user-instance-#units IF user-instance-#units my-self instance>#units ! user-instance-units my-self instance>unit1 user-instance-#units cells move 0 to user-instance-#units THEN ; : open-node ( arg len phandle -- ihandle|0 ) current-node @ >r my-self >r \ Save current node and instance set-node create-instance set-my-args copy-instance-unit s" open" get-node find-method IF execute ELSE TRUE THEN 0= IF my-self destroy-instance 0 to my-self THEN my-self ( ihandle|0 ) r> to my-self r> set-node \ Restore current node and instance interpose-node @ IF my-self >r to my-self interpose-args 2@ interpose-node @ interpose-node off recurse r> to my-self THEN ; : close-node ( ihandle -- ) my-self >r to my-self s" close" ['] $call-my-method CATCH IF 2drop THEN my-self destroy-instance r> to my-self ; : close-dev ( ihandle -- ) my-self >r to my-self BEGIN my-self WHILE my-parent my-self close-node to my-self REPEAT r> to my-self ; : new-device ( -- ) my-self new-node ( parent-ihandle phandle ) node>instance-template @ ( parent-ihandle ihandle ) dup to my-self ( parent-ihanlde ihandle ) instance>parent ! get-node my-self instance>node ! max-instance-size my-self instance>size ! ; : finish-device ( -- ) get-node >space? 0= IF s" reg" get-node get-property 0= IF decode-int set-space 2drop THEN THEN finish-node my-parent to my-self ; : extend-device ( phandle -- ) my-self >r dup set-node node>instance-template @ dup to my-self r> swap instance>parent ! ; : split ( str len char -- left len right len ) >r 2dup r> findchar IF >r over r@ 2swap r> 1+ /string ELSE 0 0 THEN ; : generic-decode-unit ( str len ncells -- addr.lo ... addr.hi ) dup >r -rot BEGIN r@ WHILE r> 1- >r [char] , split 2swap $number IF 0 THEN r> swap >r >r REPEAT r> 3drop BEGIN dup WHILE 1- r> swap REPEAT drop ; : generic-encode-unit ( addr.lo ... addr.hi ncells -- str len ) 0 0 rot ?dup IF 0 ?DO rot (u.) $cat s" ," $cat LOOP 1- THEN ; : hex-decode-unit ( str len ncells -- addr.lo ... addr.hi ) base @ >r hex generic-decode-unit r> base ! ; : hex-encode-unit ( addr.lo ... addr.hi ncells -- str len ) base @ >r hex generic-encode-unit r> base ! ; : hex64-decode-unit ( str len ncells -- addr.lo ... addr.hi ) dup 2 <> IF hex-decode-unit ELSE drop base @ >r hex $number IF 0 0 ELSE xlsplit THEN r> base ! THEN ; : hex64-encode-unit ( addr.lo ... addr.hi ncells -- str len ) dup 2 <> IF hex-encode-unit ELSE drop base @ >r hex lxjoin (u.) r> base ! THEN ; : handle-leading-/ ( path len -- path' len' ) dup IF over c@ [char] / = IF 1 /string device-tree @ set-node THEN THEN ; : match-name ( name len node -- match? ) over 0= IF 3drop true EXIT THEN s" name" rot get-property IF 2drop false EXIT THEN 1- string=ci ; \ XXX should use decode-string 0 VALUE #search-unit CREATE search-unit 4 cells allot : match-unit ( node -- match? ) dup >space? IF node>space search-unit #search-unit 0 ?DO 2dup @ swap @ <> IF 2drop false UNLOOP EXIT THEN cell+ swap cell+ swap LOOP 2drop true ELSE drop true THEN ; : match-node ( name len node -- match? ) dup >r match-name r> match-unit and ; \ XXX e3d : find-kid ( name len -- node|0 ) dup -1 = IF \ are we supposed to stay in the same node? -> resolve-relatives 2drop get-node ELSE get-node child >r BEGIN r@ WHILE 2dup r@ match-node IF 2drop r> EXIT THEN r> peer >r REPEAT r> 3drop false THEN ; : set-search-unit ( unit len -- ) 0 to #search-unit 0 to user-instance-#units dup 0= IF 2drop EXIT THEN s" #address-cells" get-node get-property THROW decode-int to #search-unit 2drop s" decode-unit" get-node $call-static #search-unit 0 ?DO search-unit i cells + ! LOOP ; : resolve-relatives ( path len -- path' len' ) 2dup 2 = swap s" .." comp 0= and IF get-node parent ?dup IF set-node drop -1 ELSE s" Already in root node." type THEN THEN 2dup 1 = swap c@ [CHAR] . = and IF drop -1 THEN ; : set-instance-unit ( unitaddr len -- ) dup 0= IF 2drop 0 to user-instance-#units EXIT THEN 2dup 0 -rot bounds ?DO i c@ [char] , = IF 1+ THEN \ Count the commas LOOP 1+ dup to user-instance-#units hex-decode-unit user-instance-#units 0 ?DO user-instance-units i cells + ! LOOP ; : split-component ( path. -- path'. args. name. unit. ) [char] / split 2swap ( path'. component. ) [char] : split 2swap ( path'. args. name@unit. ) [char] @ split ( path'. args. name. unit. ) ; : find-component ( path len -- path' len' args len node|0 ) debug-find-component? IF ." find-component for " 2dup type cr THEN split-component ( path'. args. name. unit. ) debug-find-component? IF ." -> unit =" 2dup type cr ." -> stack =" .s cr THEN ['] set-search-unit CATCH IF ." WARNING: Obsolete old wildcard hack " .s cr set-instance-unit THEN resolve-relatives find-kid ( path' len' args len node|0 ) dup IF dup >space? not #search-unit 0 > AND user-instance-#units 0= AND IF #search-unit dup to user-instance-#units 0 ?DO search-unit i cells + @ user-instance-units i cells + ! LOOP THEN THEN dup IF dup >space? user-instance-#units 0 > AND IF cr ." find-component with unit mismatch!" .s cr drop 0 THEN THEN ; : .find-node ( path len -- phandle|0 ) current-node @ >r handle-leading-/ current-node @ 0= IF 2drop r> set-node 0 EXIT THEN BEGIN dup WHILE \ handle one component: find-component ( path len args len node ) dup 0= IF 3drop 2drop r> set-node 0 EXIT THEN set-node 2drop REPEAT 2drop get-node r> set-node ; ' .find-node to find-node : find-node ( path len -- phandle|0 ) de-alias find-node ; : delete-node ( phandle -- ) dup node>instance-template @ max-instance-size free-mem dup node>parent @ node>child @ ( phandle 1st peer ) 2dup = IF node>peer @ swap node>parent @ node>child ! EXIT THEN dup node>peer @ BEGIN 2 pick 2dup <> WHILE drop nip dup node>peer @ dup 0= IF 2drop drop unloop EXIT THEN REPEAT drop node>peer @ swap node>peer ! drop ; : open-dev ( path len -- ihandle|0 ) 0 to user-instance-#units de-alias current-node @ >r handle-leading-/ current-node @ 0= IF 2drop r> set-node 0 EXIT THEN my-self >r 0 to my-self 0 0 >r >r BEGIN dup WHILE \ handle one component: ( arg len ) r> r> get-node open-node to my-self find-component ( path len args len node ) dup 0= IF 3drop 2drop my-self close-dev r> to my-self r> set-node 0 EXIT THEN set-node >r >r REPEAT 2drop r> r> get-node open-node to my-self my-self r> to my-self r> set-node ; : select-dev open-dev dup to my-self ihandle>phandle set-node ; : unselect-dev my-self close-dev 0 to my-self device-end ; : find-device ( str len -- ) \ set as active node find-node dup 0= ABORT" No such device path" set-node ; : dev parse-word find-device ; : (lsprop) ( node --) dup cr $indent indent @ type ." node: " node>qname type false +indent (.properties) cr -indent ; : (show-children) ( node -- ) child BEGIN dup WHILE dup (lsprop) dup child IF false +indent dup recurse -indent THEN peer REPEAT drop ; : lsprop ( {device-specifier} -- ) skipws 0 parse dup IF de-alias ELSE 2drop s" /" THEN find-device get-node dup dup cr ." node: " node>path type (.properties) cr (show-children) 0 indent ! ; : (node>path) node>path ; : node>path ( phandle -- str len ) node>path dup allot ; 0 VALUE packages : find-package ( name len -- false | phandle true ) dup 0 <= IF 2drop FALSE EXIT THEN over c@ [char] / = IF find-node dup IF TRUE THEN EXIT THEN 0 >r packages child BEGIN dup WHILE dup >r node>name 2over string=ci r> swap IF r> drop dup >r THEN peer REPEAT 3drop r> dup IF true THEN ; : open-package ( arg len phandle -- ihandle | 0 ) open-node ; : close-package ( ihandle -- ) close-node ; : $open-package ( arg len name len -- ihandle | 0 ) find-package IF open-package ELSE 2drop false THEN ; : pci-address-type ( node address prop_type -- type ) -rot 2 pick ( prop_type node address prop_type ) 0= IF swap s" reg" rot get-property ( prop_type address data dlen false ) ELSE swap s" assigned-addresses" rot get-property ( prop_type address data dlen false ) THEN IF 2drop -1 EXIT THEN 4 / 5 / 0 DO dup l@ FF AND 0<> ( prop_type address data cfgspace_offset? ) 3 pick 0= ( prop_type address data cfgspace_offset? reg_prop? ) AND NOT IF 2dup 4 + ( prop_type address data address data' ) 2dup @ 2 pick 8 + @ + <= -rot @ >= and IF l@ 03000000 and 18 rshift nip swap drop ( type ) UNLOOP EXIT THEN THEN 4 5 * + LOOP 3drop -1 ; : (range-read-cells) ( range-addr #cells -- range-value ) 1 = IF l@ ELSE @ THEN ; : (map-one-range) ( type range pnac nsc nac address -- address true | address false ) over 3 = 5 pick l@ 3000000 and 18 rshift 7 pick <> and IF >r 2drop 3drop r> false EXIT THEN 4 pick 4 pick 3 pick + 4 * + 3 pick (range-read-cells) 5 pick 3 pick 3 = IF 4 + THEN 3 pick (range-read-cells) dup >r dup 3 pick > >r + over <= r> or IF >r 2drop 3drop r> r> drop false EXIT THEN dup r> - 5 pick 5 pick 3 = IF 4 + THEN 3 pick 4 * + 5 pick (range-read-cells) + >r 3drop 3drop r> true ; : translate-address ( node address -- address ) 2dup 1 pci-address-type ( node address type ) dup -1 = IF drop 2dup 0 pci-address-type ( node address type ) THEN rot parent BEGIN dup parent 0= IF 2drop EXIT THEN s" #address-cells" 2 pick get-property 2drop l@ >r \ nac s" #size-cells" 2 pick get-property 2drop l@ >r \ nsc s" #address-cells" 2 pick parent get-property 2drop l@ >r \ pnac -rot ( node address type ) s" ranges" 4 pick get-property IF 3drop ABORT" no ranges property; not translatable" THEN r> r> r> 3 roll 4 / >r 3dup + + >r 5 roll r> r> swap / 0 ?DO 6dup (map-one-range) IF nip leave THEN nip 4 roll 4 pick 4 pick 4 pick + + 4 * + 4 -roll LOOP >r 2drop 2drop r> ( node type address ) swap rot parent ( address type node ) dup 0= UNTIL ; : translate-my-address ( address -- address' ) get-node swap translate-address ; : find-substr ( basestr-ptr basestr-len substr-ptr substr-len -- pos ) dup 0 = IF 2drop 2drop 0 exit THEN dup 3 pick <= IF 2 pick over - 1+ 0 DO dup 0 DO over i + c@ 4 pick j + i + c@ = IF dup i 1+ = IF 2drop 2drop j unloop unloop exit THEN ELSE leave THEN LOOP LOOP THEN 2drop nip ; : find-isubstr ( basestr-ptr basestr-len substr-ptr substr-len -- pos ) dup 0 = IF 2drop 2drop 0 exit THEN dup 3 pick <= IF 2 pick over - 1+ 0 DO dup 0 DO over i + c@ lcc 4 pick j + i + c@ lcc = IF dup i 1+ = IF 2drop 2drop j unloop unloop exit THEN ELSE leave THEN LOOP LOOP THEN 2drop nip ; : find-nextline ( str-ptr str-len -- pos ) dup 0 ?DO over i + c@ CASE 0a OF dup 1- i = IF 2drop i 1+ unloop exit THEN over i 1+ + c@ 0d = IF 2drop i 2+ ELSE 2drop i 1+ THEN unloop exit ENDOF 0d OF dup 1- i = IF 2drop i 1+ unloop exit THEN over i 1+ + c@ 0a = IF 2drop i 2+ ELSE 2drop i 1+ THEN unloop exit ENDOF ENDCASE LOOP nip ; : string-at ( str1-ptr str1-len pos -- str2-ptr str2-len ) -rot 2 pick - -rot swap chars + swap ; : string-cat ( addr1 len1 addr2 len2 -- addr1 len1+len2 ) rot dup >r over + -rot 3 pick r> chars + -rot 0 ?DO 2dup c@ swap c! char+ swap char+ swap LOOP 2drop ; : char-cat ( addr len character -- addr len+1 ) -rot 2dup >r >r 1+ rot r> r> chars + c! ; : overlap ( src dest size -- true|false ) 3dup over + within IF 3drop true ELSE rot tuck + within THEN ; : parse-2int ( str len -- val.lo val.hi ) [char] , split ?dup IF eval ELSE drop 0 THEN -rot ?dup IF eval ELSE drop 0 THEN ; : cpeek ( addr -- false | byte true ) c@ true ; : cpoke ( byte addr -- success? ) c! true ; : wpeek ( addr -- false | word true ) w@ true ; : wpoke ( word addr -- success? ) w! true ; : lpeek ( addr -- false | lword true ) l@ true ; : lpoke ( lword addr -- success? ) l! true ; defer reboot ( -- ) defer halt ( -- ) defer disable-watchdog ( -- ) defer reset-watchdog ( -- ) defer set-watchdog ( +n -- ) defer set-led ( type instance state -- status ) defer get-flashside ( -- side ) defer set-flashside ( side -- status ) defer read-bootlist ( -- ) defer furnish-boot-file ( -- adr len ) defer set-boot-file ( adr len -- ) defer mfg-mode? ( -- flag ) defer of-prompt? ( -- flag ) defer debug-boot? ( -- flag ) defer bmc-version ( -- adr len ) defer cursor-on ( -- ) defer cursor-off ( -- ) : nop-reboot ( -- ) ." reboot not available" abort ; : nop-halt ( -- ) ." halt not available" abort ; : nop-disable-watchdog ( -- ) ; : nop-reset-watchdog ( -- ) ; : nop-set-watchdog ( +n -- ) drop ; : nop-set-led ( type instance state -- status ) drop drop drop ; : nop-get-flashside ( -- side ) ." Cannot get flashside" cr ABORT ; : nop-set-flashside ( side -- status ) ." Cannot set flashside" cr ABORT ; : nop-read-bootlist ( -- ) ; : nop-furnish-bootfile ( -- adr len ) s" net:" ; : nop-set-boot-file ( adr len -- ) 2drop ; : nop-mfg-mode? ( -- flag ) false ; : nop-of-prompt? ( -- flag ) false ; : nop-debug-boot? ( -- flag ) false ; : nop-bmc-version ( -- adr len ) s" XXXXX" ; : nop-cursor-on ( -- ) ; : nop-cursor-off ( -- ) ; ' nop-reboot to reboot ' nop-halt to halt ' nop-disable-watchdog to disable-watchdog ' nop-reset-watchdog to reset-watchdog ' nop-set-watchdog to set-watchdog ' nop-set-led to set-led ' nop-get-flashside to get-flashside ' nop-set-flashside to set-flashside ' nop-read-bootlist to read-bootlist ' nop-furnish-bootfile to furnish-boot-file ' nop-set-boot-file to set-boot-file ' nop-mfg-mode? to mfg-mode? ' nop-of-prompt? to of-prompt? ' nop-debug-boot? to debug-boot? ' nop-bmc-version to bmc-version ' nop-cursor-on to cursor-on ' nop-cursor-off to cursor-off : reset-all reboot ; 10000000 VALUE default-load-base 2000000 VALUE flash-load-base 0 VALUE load-base-override : get-load-base load-base-override 0<> IF load-base-override ELSE " load-base" evaluate THEN ; : xt>name ( xt -- str len ) BEGIN cell - dup c@ 0 2 within IF dup 2+ swap 1+ c@ exit THEN AGAIN ; cell -1 * CONSTANT -cell : cell- ( n -- n-cell-size ) [ cell -1 * ] LITERAL + ; : find-xt-addr ( addr -- xt ) BEGIN dup @ = IF EXIT THEN cell- AGAIN ; : (.immediate) ( xt -- ) xt>name drop 2 - c@ \ skip len and flags immediate? IF ." IMMEDIATE" THEN ; : (.xt) ( xt -- ) xt>name type ; : trace-back ( ) 1 BEGIN cr dup dup . ." : " rpick dup . ." : " ['] tib here within IF dup rpick find-xt-addr (.xt) THEN 1+ dup rdepth 5 - >= IF cr drop EXIT THEN AGAIN ; VARIABLE see-my-type-column : (see-my-type) ( indent limit xt str len -- indent limit xt ) dup see-my-type-column @ + dup 50 >= IF -rot over " " comp 0= IF 2drop see-my-type-column ! ELSE rot drop ( indent limit xt str len ) pocket swap 2dup >r >r ( indent limit xt str pk len R: len pk ) move r> r> ( indent limit xt pk len ) 2 pick (u.) dup -rot cr type ( indent limit xt pk len xt-len ) " :" type 1+ ( indent limit xt pk len prefix-len ) 5 pick dup spaces + ( indent limit xt pk len prefix-len ) over + see-my-type-column ! ( indent limit xt pk len ) type THEN ( indent limit xt ) ELSE see-my-type-column ! type ( indent limit xt ) THEN ; : (see-my-type-init) ( -- ) ffff see-my-type-column ! \ just enforce a new line ; : (see-colon-body) ( indent limit xt -- indent limit xt ) (see-my-type-init) \ enforce new line BEGIN ( indent limit xt ) cell+ 2dup <> over @ dup <> rot and ( indent limit xt @xt flag ) WHILE ( indent limit xt @xt ) xt>name (see-my-type) " " (see-my-type) dup @ ( indent limit xt @xt) CASE <0branch> OF cell+ dup @ over + cell+ dup >r (u.) (see-my-type) r> ( indent limit xt target) 2dup < IF over 4 pick 3 + -rot recurse nip nip nip cell- ( indent limit xt ) ELSE drop ( indent limit xt ) THEN (see-my-type-init) ENDOF \ enforce new line OF cell+ dup @ over + cell+ (u.) (see-my-type) " " (see-my-type) ENDOF OF cell+ dup @ (u.) (see-my-type) " " (see-my-type) ENDOF OF cell+ dup @ (u.) (see-my-type) " " (see-my-type) ENDOF OF cell+ dup @ xt>name (see-my-type) " " (see-my-type) ENDOF OF cell+ dup @ (u.) (see-my-type) " " (see-my-type) ENDOF OF cell+ dup @ (u.) (see-my-type) " " (see-my-type) ENDOF OF cell+ dup @ over + cell+ (u.) (see-my-type) " " (see-my-type) ENDOF OF cell+ dup @ over + cell+ (u.) (see-my-type) " " (see-my-type) ENDOF OF cell+ " """ (see-my-type) dup count dup >r (see-my-type) " """ (see-my-type) " " (see-my-type) r> -cell and + ENDOF ENDCASE REPEAT drop ; : (see-colon) ( xt -- ) (see-my-type-init) 1 swap 0 swap ( indent limit xt ) " : " (see-my-type) dup xt>name (see-my-type) rot drop 4 -rot (see-colon-body) ( indent limit xt ) rot drop 1 -rot (see-my-type-init) " ;" (see-my-type) 3drop ; : (see-create) ( xt -- ) dup cell+ @ CASE <2constant> OF dup cell+ cell+ dup @ swap cell+ @ . . ." 2CONSTANT " ENDOF OF dup cell+ cell+ @ . ." INSTANCE VALUE " ENDOF OF ." INSTANCE VARIABLE " ENDOF dup OF ." CREATE " ENDOF ENDCASE (.xt) ; : (see) ( xt -- ) cr dup dup @ CASE OF ." VARIABLE " (.xt) ENDOF OF dup execute . ." VALUE " (.xt) ENDOF OF dup execute . ." CONSTANT " (.xt) ENDOF OF dup cell+ @ swap ." DEFER " (.xt) ." is " (.xt) ENDOF OF dup cell+ @ swap ." ALIAS " (.xt) ." " (.xt) ENDOF OF ." BUFFER: " (.xt) ENDOF OF (see-create) ENDOF OF (see-colon) ENDOF dup OF ." ??? PRIM " (.xt) ENDOF ENDCASE (.immediate) cr ; : see ( "old-name<>" -- ) ' (see) ; 0 value forth-ip true value trace>stepping? true value trace>print? true value trace>up? 0 value trace>depth 0 value trace>rdepth 0 value trace>recurse : trace-depth+ ( -- ) trace>depth 1+ to trace>depth ; : trace-depth- ( -- ) trace>depth 1- to trace>depth ; : stepping ( -- ) true to trace>stepping? ; : tracing ( -- ) false to trace>stepping? ; : trace-print-on ( -- ) true to trace>print? ; : trace-print-off ( -- ) false to trace>print? ; : fip-add ( n -- ) forth-ip + to forth-ip ; 0 value debug-last-xt 0 value debug-last-xt-content : trace-print ( -- ) forth-ip cr u. ." : " forth-ip @ dup ['] breakpoint = IF drop debug-last-xt-content THEN xt>name type ." " ." ( " .s ." ) | " ; : trace-interpret ( -- ) rdepth 1- to trace>rdepth BEGIN depth . [char] > dup emit emit space source expect ( str len ) ['] interpret catch print-status AGAIN ; : trace-xt ( xt -- ) trace>recurse IF r> drop \ Drop return of 'trace-xt call cell+ \ Step over ":" ELSE debug-last-xt-content = IF ['] breakpoint @ debug-last-xt ! \ Re-arm break point r> drop \ Drop return of 'trace-xt call cell+ \ Step over ":" ELSE ['] breakpoint debug-last-xt ! \ Re-arm break point 2r> 2drop THEN THEN to forth-ip true to trace>print? BEGIN trace>print? IF trace-print THEN forth-ip ( ip ) trace>stepping? IF BEGIN key CASE [char] d OF dup @ @ = IF \ recurse only into colon definitions trace-depth+ 1 to trace>recurse dup >r @ recurse THEN true ENDOF [char] u OF trace>depth IF tracing trace-print-off true ELSE false THEN ENDOF [char] f OF drop cr trace-interpret ENDOF \ quit trace and start interpreter FIXME rstack [char] c OF tracing true ENDOF [char] t OF trace-back false ENDOF [char] q OF drop cr quit ENDOF 20 OF true ENDOF dup OF cr ." Press d: Down into current word" cr ." Press u: Up to caller" cr ." Press f: Switch to forth interpreter, 'resume' will continue tracing" cr ." Press c: Switch to tracing" cr ." Press : Execute current word" cr ." Press q: Abort execution, switch to interpreter" cr false ENDOF ENDCASE UNTIL THEN ( ip' ) dup to forth-ip @ ( xt ) dup ['] breakpoint = IF drop debug-last-xt-content THEN dup ( xt xt ) CASE OF drop forth-ip cell+ dup dup c@ + -cell and to forth-ip ENDOF OF drop forth-ip cell+ @ cell fip-add ENDOF OF drop forth-ip cell+ @ cell fip-add ENDOF OF drop forth-ip cell+ @ cell+ ! cell fip-add ENDOF <(doito)> OF drop forth-ip cell+ @ cell+ cell+ @ >instance ! cell fip-add ENDOF <0branch> OF drop IF cell fip-add ELSE forth-ip cell+ @ cell+ fip-add THEN ENDOF OF drop 2dup <> IF swap >r >r cell fip-add ELSE forth-ip cell+ @ cell+ fip-add 2drop THEN ENDOF OF drop forth-ip cell+ @ cell+ fip-add ENDOF OF drop r> r> 2drop forth-ip cell+ @ cell+ fip-add ENDOF OF drop IF r> r> 2drop forth-ip cell+ @ cell+ fip-add ELSE cell fip-add THEN ENDOF OF drop r> 1+ r> 2dup = IF 2drop cell fip-add ELSE >r >r forth-ip cell+ @ cell+ fip-add THEN ENDOF OF drop r> + r> 2dup >= IF 2drop cell fip-add ELSE >r >r forth-ip cell+ @ cell+ fip-add THEN ENDOF OF trace>depth 0> IF trace-depth- 1 to trace>recurse stepping drop r> recurse ELSE drop exit THEN ENDOF OF trace>depth 0> IF trace-depth- stepping drop r> recurse ELSE drop exit THEN ENDOF dup OF execute ENDOF ENDCASE forth-ip cell+ to forth-ip AGAIN ; : resume ( -- ) trace>rdepth rdepth! forth-ip cell - trace-xt ; : debug-off ( -- ) debug-last-xt IF debug-last-xt-content debug-last-xt ! \ Restore overwritten token 0 to debug-last-xt THEN ; : (break-entry) ( -- ) debug-last-xt dup @ ['] breakpoint <> swap ( debug-addr? debug-last-xt ) debug-last-xt-content swap ! \ Restore overwritten token r> drop \ Don't return to bp, but to caller debug-last-xt-content <> and IF \ Execute non colon definition debug-last-xt cr u. ." : " debug-last-xt xt>name type ." " ." ( " .s ." ) | " key drop debug-last-xt execute ELSE debug-last-xt 0 to trace>depth 0 to trace>recurse trace-xt \ Trace colon definition THEN ; ' (break-entry) to BP : debug-address ( addr -- ) debug-off ( xt ) \ Remove active breakpoint dup to debug-last-xt ( xt ) \ Save token for later debug dup @ to debug-last-xt-content ( xt ) \ Save old value ['] breakpoint swap ! ; : (debug ( xt -- ) debug-off ( xt ) \ Remove active breakpoint dup to debug-last-xt ( xt ) \ Save token for later debug dup @ to debug-last-xt-content ( xt ) \ Save old value ['] breakpoint @ swap ! ; : debug ( "old-name<>" -- ) parse-word $find IF \ Get xt for old-name (debug ELSE ." undefined word " type cr THEN ; : words last @ BEGIN ?dup WHILE dup cell+ char+ count type space @ REPEAT ; : .calls ( xt -- ) current-node @ >r 0 set-node \ only search commands, according too IEEE1275 last BEGIN @ ?dup WHILE ( xt currxt ) dup cell+ char+ ( xt currxt name* ) dup dup c@ + 1+ aligned ( xt currxt name* CFA ) dup @ = IF ( xt currxt name* CFA ) BEGIN cell+ dup @ ['] semicolon <> WHILE ( xt currxt *name pos ) dup @ 4 pick = IF ( xt currxt *name pos ) over count type space BEGIN cell+ dup @ ['] semicolon = UNTIL cell - \ eat up other occurrences THEN REPEAT THEN 2drop ( xt currxt ) REPEAT drop r> set-node \ restore node ; 0 value #sift-count false value sift-compl-only : $inner-sift ( text-addr text-len LFA -- ... word-addr word-len true | false ) dup cell+ char+ count \ get word name 2dup 6 pick 6 pick find-isubstr \ is there a partly match? sift-compl-only IF 0= ELSE over < THEN IF #sift-count 1+ to #sift-count \ count completions true ELSE 2drop false THEN ; : $sift ( text-addr text-len -- ) current-node @ >r 0 set-node \ only search commands, according too IEEE1275 sift-compl-only >r false to sift-compl-only \ all substrings, not only compl. last BEGIN @ ?dup WHILE \ walk the whole dictionary $inner-sift IF type space THEN REPEAT 2drop 0 to #sift-count \ we don't need completions here. r> to sift-compl-only \ restore previous sifting mode r> set-node \ restore node ; : sifting ( "text< >" -- ) parse-word $sift ; : ([IF]) BEGIN BEGIN parse-word dup 0= WHILE 2drop refill REPEAT 2dup s" [IF]" str= IF 1 throw THEN 2dup s" [ELSE]" str= IF 2 throw THEN 2dup s" [THEN]" str= IF 3 throw THEN s" \" str= IF linefeed parse 2drop THEN AGAIN ; : [IF] ( flag -- ) IF exit THEN 1 BEGIN ['] ([IF]) catch CASE 1 OF 1+ ENDOF 2 OF dup 1 = if 1- then ENDOF 3 OF 1- ENDOF ENDCASE dup 0 <= UNTIL drop ; immediate : [ELSE] 0 [COMPILE] [IF] ; immediate : [THEN] ; immediate : $dnumber base @ >r decimal $number r> base ! ; : (.d) base @ >r decimal (.) r> base ! ; : (ipaddr) ( "a.b.c.d" -- FALSE | n1 n2 n3 n4 TRUE ) base @ >r decimal over s" 000.000.000.000" comp 0= IF 2drop false r> base ! EXIT THEN [char] . left-parse-string $number IF 2drop false r> base ! EXIT THEN -rot [char] . left-parse-string $number IF 2drop false r> base ! EXIT THEN -rot [char] . left-parse-string $number IF 2drop false r> base ! EXIT THEN -rot $number IF false r> base ! EXIT THEN true r> base ! ; : (ipformat) ( n1 n2 n3 n4 -- str len ) base @ >r decimal 0 <# # # # [char] . hold drop # # # [char] . hold drop # # # [char] . hold drop # # #s #> r> base ! ; : ipformat ( n1 n2 n3 n4 -- ) (ipformat) type ; 4000 to default-load-base deadbeef here l! here c@ de = CONSTANT ?bigendian here c@ ef = CONSTANT ?littleendian ?bigendian [IF] : x!-le >r xbflip r> x! ; : x@-le x@ xbflip ; : l!-le >r lbflip r> l! ; : l@-le l@ lbflip ; : w!-le >r wbflip r> w! ; : w@-le w@ wbflip ; : rx!-le >r xbflip r> rx! ; : rx@-le rx@ xbflip ; : rl!-le >r lbflip r> rl! ; : rl@-le rl@ lbflip ; : rw!-le >r wbflip r> rw! ; : rw@-le rw@ wbflip ; : l!-be l! ; : l@-be l@ ; : w!-be w! ; : w@-be w@ ; : rl!-be rl! ; : rl@-be rl@ ; : rw!-be rw! ; : rw@-be rw@ ; [ELSE] : x!-le x! ; : x@-le x@ ; : l!-le l! ; : l@-le l@ ; : w!-le w! ; : w@-le w@ ; : rx!-le rx! ; : rx@-le rx@ ; : rl!-le rl! ; : rl@-le rl@ ; : rw!-le rw! ; : rw@-le rw@ ; : l!-be >r lbflip r> l! ; : l@-be l@ lbflip ; : w!-be >r wbflip r> w! ; : w@-be w@ wbflip ; : rl!-be >r lbflip r> rl! ; : rl@-be rl@ lbflip ; : rw!-be >r wbflip r> rw! ; : rw@-be rw@ wbflip ; [THEN] : #join ( lo hi #bits -- x ) lshift or ; : #split ( x #bits -- lo hi ) 2dup rshift dup >r swap lshift xor r> ; : blink ; : reset-dual-emit ; : console-clean-fifo ; : bootmsg-nvupdate ; : asm-cout 2drop drop ; defer nvramlog-write-byte : .nvramlog-write-byte ( byte -- ) drop ; ' .nvramlog-write-byte to nvramlog-write-byte : nvramlog-write-string ( str len -- ) dup 0> IF 0 DO dup c@ nvramlog-write-byte char+ LOOP ELSE drop THEN drop ; : nvramlog-write-number ( number format -- ) 0 swap <# 0 ?DO # LOOP #> nvramlog-write-string ; : nvramlog-write-string-cr ( str len -- ) nvramlog-write-string a nvramlog-write-byte d nvramlog-write-byte ; : log-string ( str len -- ) type ; : log-string 2drop ; create debugstr 255 allot 0 VALUE debuglen : cp ( checkpoint -- ) bootmsg-cp ; : (warning) ( id level ptr len -- ) dup TO debuglen debugstr swap move \ copy into buffer 0 debuglen debugstr + c! \ terminate '\0' debugstr bootmsg-warning ; : warning" ( id level [text<">] -- ) postpone s" state @ IF ['] (warning) compile, ELSE (warning) THEN ; immediate : (debug-cp) ( id level ptr len -- ) dup TO debuglen debugstr swap move \ copy into buffer 0 debuglen debugstr + c! \ terminate '\0' debugstr bootmsg-debugcp ; : debug-cp" ( id level [text<">] -- ) postpone s" state @ IF ['] (debug-cp) compile, ELSE (debug-cp) THEN ; immediate : (error) ( id ptr len -- ) dup TO debuglen debugstr swap move \ copy into buffer 0 debuglen debugstr + c! \ terminate '\0' debugstr bootmsg-error ; : error" ( id level [text<">] -- ) postpone s" state @ IF ['] (error) compile, ELSE (error) THEN ; immediate bootmsg-nvupdate 000 cp STRUCT cell FIELD >r0 cell FIELD >r1 cell FIELD >r2 cell FIELD >r3 cell FIELD >r4 cell FIELD >r5 cell FIELD >r6 cell FIELD >r7 cell FIELD >r8 cell FIELD >r9 cell FIELD >r10 cell FIELD >r11 cell FIELD >r12 cell FIELD >r13 cell FIELD >r14 cell FIELD >r15 cell FIELD >r16 cell FIELD >r17 cell FIELD >r18 cell FIELD >r19 cell FIELD >r20 cell FIELD >r21 cell FIELD >r22 cell FIELD >r23 cell FIELD >r24 cell FIELD >r25 cell FIELD >r26 cell FIELD >r27 cell FIELD >r28 cell FIELD >r29 cell FIELD >r30 cell FIELD >r31 cell FIELD >cr cell FIELD >xer cell FIELD >lr cell FIELD >ctr cell FIELD >srr0 cell FIELD >srr1 cell FIELD >dar cell FIELD >dsisr CONSTANT ciregs-size : .16 10 0.r 3 spaces ; : .8 8 spaces 8 0.r 3 spaces ; : .4regs cr 4 0 DO dup @ .16 8 cells+ LOOP drop ; : .fixed-regs cr ." R0 .. R7 R8 .. R15 R16 .. R23 R24 .. R31" dup 8 0 DO dup .4regs cell+ LOOP drop ; : .special-regs cr ." CR / XER LR / CTR SRR0 / SRR1 DAR / DSISR" cr dup >cr @ .8 dup >lr @ .16 dup >srr0 @ .16 dup >dar @ .16 cr dup >xer @ .16 dup >ctr @ .16 dup >srr1 @ .16 >dsisr @ .8 ; : .regs cr .fixed-regs cr .special-regs cr cr ; : .hw-exception ( reason-code exception-nr -- ) ." ( " dup . ." ) " CASE 200 OF ." Machine Check" ENDOF 300 OF ." Data Storage" ENDOF 380 OF ." Data Segment" ENDOF 400 OF ." Instruction Storage" ENDOF 480 OF ." Instruction Segment" ENDOF 500 OF ." External" ENDOF 600 OF ." Alignment" ENDOF 700 OF ." Program" ENDOF 800 OF ." Floating-point unavailable" ENDOF 900 OF ." Decrementer" ENDOF 980 OF ." Hypervisor Decrementer" ENDOF C00 OF ." System Call" ENDOF D00 OF ." Trace" ENDOF F00 OF ." Performance Monitor" ENDOF F20 OF ." VMX Unavailable" ENDOF 1200 OF ." System Error" ENDOF 1600 OF ." Maintenance" ENDOF 1800 OF ." Thermal" ENDOF dup OF ." Unknown" ENDOF ENDCASE ." Exception [ " . ." ]" ; : .sw-exception ( exception-nr -- ) ." Exception [ " . ." ] triggered by boot firmware." ; : be-hw-exception ( [reason-code] exception-nr -- ) cr cr dup 0> IF .hw-exception ELSE .sw-exception THEN cr eregs .regs ; ' be-hw-exception to hw-exception-handler : (boot-exception-handler) ( x1...xn exception-nr -- x1...xn) dup IF dup 0 > IF negate cp 9 emit ." : " type ELSE CASE -6d OF cr ." W3411: Client application returned." cr ENDOF -6c OF cr ." E3400: It was not possible to boot from any device " ." specified in the VPD." cr ENDOF -6b OF cr ." E3410: Boot list successfully read from VPD " ." but no useful information received." cr ENDOF -6a OF cr ." E3420: Boot list could not be read from VPD." cr ENDOF -69 OF cr ." E3406: Client application returned an error" abort"-str @ count dup IF ." : " type cr ELSE ." ." cr 2drop THEN ENDOF -68 OF cr ." E3405: No such device" cr ENDOF -67 OF cr ." E3404: Not a bootable device!" cr ENDOF -66 OF cr ." E3408: Failed to claim memory for the executable" cr ENDOF -65 OF cr ." E3407: Load failed" cr ENDOF -64 OF cr ." E3403: Bad executable: " abort"-str @ count type cr ENDOF -63 OF cr ." E3409: Unknown FORTH Word" cr ENDOF -2 OF cr ." E3401: Aborting boot, " abort"-str @ count type cr ENDOF dup OF ." E3402: Aborting boot, internal error" cr ENDOF ENDCASE THEN ELSE drop THEN ; ' (boot-exception-handler) to boot-exception-handler : throw-error ( error-code "error-string" -- ) skipws 0a parse rot throw ; : enable-ext-int ( -- ) msr@ 8000 or msr! ; : disable-ext-int ( -- ) msr@ 8000 not and msr! ; : gen-ext-int ( -- ) 7fffffff dec! \ Reset decrementer enable-ext-int \ Enable interrupt FF 20000508418 rx! \ Interrupt priority mask 10 20000508410 rx! \ Interrupt priority ; : mm-log-warning 2drop ; : write-mm-log ( data length type -- status ) 3drop 0 ; 100 cp : beep bell emit ; : TABLE-EXECUTE CREATE DOES> swap cells+ @ ?dup IF execute ELSE beep THEN ; 0 VALUE accept-adr 0 VALUE accept-max 0 VALUE accept-len 0 VALUE accept-cur : esc 1b emit ; : csi esc 5b emit ; : move-cursor ( -- ) esc ." 8" accept-cur IF csi base @ decimal accept-cur 0 .r base ! ." C" THEN ; : redraw-line ( -- ) accept-cur accept-len = IF EXIT THEN move-cursor accept-adr accept-len accept-cur /string type csi ." K" move-cursor ; : full-redraw-line ( -- ) accept-cur 0 to accept-cur move-cursor accept-adr accept-len type csi ." K" to accept-cur move-cursor ; : redraw-prompt ( -- ) cr depth . [char] > emit ; : insert-char ( char -- ) accept-len accept-max = IF drop beep EXIT THEN accept-cur accept-len <> IF csi ." @" dup emit accept-adr accept-cur + dup 1+ accept-len accept-cur - move ELSE dup emit THEN accept-adr accept-cur + c! accept-cur 1+ to accept-cur accept-len 1+ to accept-len redraw-line ; : delete-char ( -- ) accept-cur accept-len = IF beep EXIT THEN accept-len 1- to accept-len accept-adr accept-cur + dup 1+ swap accept-len accept-cur - move csi ." P" redraw-line ; STRUCT cell FIELD his>next cell FIELD his>prev cell FIELD his>len 0 FIELD his>buf CONSTANT /his 0 VALUE his-head 0 VALUE his-tail 0 VALUE his-cur : add-history ( -- ) accept-len 0= IF EXIT THEN /his accept-len + alloc-mem his-tail IF dup his-tail his>next ! ELSE dup to his-head THEN his-tail over his>prev ! 0 over his>next ! dup to his-tail accept-len over his>len ! accept-adr swap his>buf accept-len move ; : history ( -- ) his-head BEGIN dup WHILE cr dup his>buf over his>len @ type his>next @ REPEAT drop ; : select-history ( his -- ) dup to his-cur dup IF dup his>len @ accept-max min dup to accept-len to accept-cur his>buf accept-adr accept-len move ELSE drop 0 to accept-len 0 to accept-cur THEN full-redraw-line ; 0 value ?tab-pressed 0 value tab-last-adr 0 value tab-last-len : $same-string ( addr-1 len-1 addr-2 len-2 -- addr-1 len-1' ) dup 0= IF \ The second parameter is not a string. 2drop EXIT \ bail out THEN rot min 0 0 -rot ( addr1 addr2 0 len' 0 ) DO ( addr1 addr2 len-1' ) 2 pick i + c@ lcc 2 pick i + c@ lcc = IF 1 + ELSE leave THEN LOOP nip ; : $tab-sift-words ( text-addr text-len -- sift-count ) sift-compl-only >r true to sift-compl-only \ save sifting mode last BEGIN @ ?dup WHILE \ loop over all words $inner-sift IF \ any completions possible? 2dup bounds DO I c@ lcc I c! LOOP ?tab-pressed IF 2dup type space THEN \ prints possibilities tab-last-adr tab-last-len $same-string \ find matching substring ... to tab-last-len to tab-last-adr \ ... and save it THEN repeat 2drop #sift-count 0 to #sift-count \ how many words were found? r> to sift-compl-only \ restore sifting completion mode ; 0 value current-stack : new-stack ( cells <>name -- ) create >r here ( here R: cells ) dup r@ 2 + cells ( here here bytes R: cells ) dup allot erase ( here R: cells) cell+ r> ( here+1cell cells ) swap ! ( ) DOES> to current-stack ; : reset-stack ( -- ) 0 current-stack ! ; : stack-depth ( -- depth ) current-stack @ ; : push ( value -- ) current-stack @ current-stack cell+ @ over <= ABORT" Stack overflow" cells 1 current-stack +! current-stack 2 cells + + ! ; : pop ( -- value ) current-stack @ 0= ABORT" Stack underflow" current-stack @ cells current-stack + cell+ @ -1 current-stack +! ; 10 new-stack device-stack : (next-dev) ( node -- node' addr len ) device-stack dup (node>path) rot dup child IF dup push child -rot EXIT THEN dup peer IF peer -rot EXIT THEN drop BEGIN stack-depth WHILE pop peer ?dup IF -rot EXIT THEN REPEAT 0 -rot ; : $inner-sift-nodes ( text-addr text-len node -- ... path-addr path-len true | false ) (next-dev) ( text-addr text-len node' path-addr path-len ) dup 0= IF drop false EXIT THEN 2dup 6 pick 6 pick find-isubstr ( text-addr text-len node' path-addr path-len pos ) 0= IF #sift-count 1+ to #sift-count \ count completions true ELSE 2drop false THEN ; : .nodes ( -- ) s" /" find-node BEGIN dup WHILE (next-dev) type cr REPEAT drop reset-stack ; create sift-node-buffer 1000 allot 0 value sift-node-num : sift-node-buffer sift-node-buffer sift-node-num 100 * + sift-node-num 1+ dup 10 = IF drop 0 THEN to sift-node-num ; : $tab-sift-nodes ( text-addr text-len -- sift-count ) s" /" find-node BEGIN dup WHILE $inner-sift-nodes IF \ any completions possible? sift-node-buffer swap 2>r 2r@ move 2r> \ make an almost permanent copy without strdup ?tab-pressed IF 2dup type space THEN \ prints possibilities tab-last-adr tab-last-len $same-string \ find matching substring ... to tab-last-len to tab-last-adr \ ... and save it THEN REPEAT 2drop drop #sift-count 0 to #sift-count \ how many words were found? reset-stack ; : $tab-sift ( text-addr text-len -- sift-count ) ?tab-pressed IF beep space THEN \ cosmetical fix for dup IF bl rsplit dup IF 2swap THEN ELSE 0 0 THEN >r >r 0 dup to tab-last-len to tab-last-adr \ reset last possible match current-node @ IF \ if we are in a node? 2dup 2>r \ save text $tab-sift-words to #sift-count \ search in current node first 2r> \ fetch text to complete, again THEN 2dup 2>r current-node @ >r 0 set-node \ now search in global words $tab-sift-words to #sift-count r> set-node 2r> $tab-sift-nodes r> r> dup IF s" " $cat THEN tab-last-adr tab-last-len $cat to tab-last-len to tab-last-adr \ ... and save the whole string ; : handle-^A 0 to accept-cur move-cursor ; : handle-^B accept-cur ?dup IF 1- to accept-cur ( csi ." D" ) move-cursor THEN ; : handle-^D delete-char ( redraw-line ) ; : handle-^E accept-len to accept-cur move-cursor ; : handle-^F accept-cur accept-len <> IF accept-cur 1+ to accept-cur csi ." C" THEN ; : handle-^H accept-cur 0= IF beep EXIT THEN handle-^B delete-char ; : handle-^I accept-adr accept-len $tab-sift 0 > IF ?tab-pressed IF redraw-prompt full-redraw-line false to ?tab-pressed ELSE tab-last-adr accept-adr tab-last-len move \ copy matching substring tab-last-len dup to accept-len to accept-cur \ len and cursor position full-redraw-line \ redraw new string true to ?tab-pressed \ second tab will print possible matches THEN THEN ; : handle-^K BEGIN accept-cur accept-len <> WHILE delete-char REPEAT ; : handle-^L history redraw-prompt full-redraw-line ; : handle-^N his-cur IF his-cur his>next @ ELSE his-head THEN dup to his-cur select-history ; : handle-^P his-cur IF his-cur his>prev @ ELSE his-tail THEN dup to his-cur select-history ; : handle-^Q \ Does not handle terminal formatting yet. key insert-char ; : handle-^R full-redraw-line ; : handle-^U 0 to accept-len 0 to accept-cur full-redraw-line ; : handle-fn key drop beep ; TABLE-EXECUTE handle-CSI 0 , ' handle-^P , ' handle-^N , ' handle-^F , ' handle-^B , 0 , 0 , 0 , ' handle-^A , 0 , 0 , ' handle-^E , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , TABLE-EXECUTE handle-meta 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ' handle-fn , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ' handle-CSI , 0 , 0 , 0 , 0 , : handle-ESC-O key dup 48 = IF handle-^A ELSE dup 46 = IF handle-^E THEN THEN drop ; : handle-ESC-5b key dup 31 = IF \ HOME key drop ( drops closing 7e ) handle-^A ELSE dup 33 = IF \ DEL key drop handle-^D ELSE dup 34 = IF \ END key drop handle-^E ELSE dup 1f and handle-CSI THEN THEN THEN drop ; : handle-ESC key dup 5b = IF handle-ESC-5b ELSE dup 4f = IF handle-ESC-O ELSE dup 1f and handle-meta THEN THEN drop ; TABLE-EXECUTE handle-control 0 , \ ^@: ' handle-^A , ' handle-^B , 0 , \ ^C: ' handle-^D , ' handle-^E , ' handle-^F , 0 , \ ^G: ' handle-^H , ' handle-^I , \ tab 0 , \ ^J: ' handle-^K , ' handle-^L , 0 , \ ^M: enter: handled in main loop ' handle-^N , 0 , \ ^O: ' handle-^P , ' handle-^Q , ' handle-^R , 0 , \ ^S: 0 , \ ^T: ' handle-^U , 0 , \ ^V: 0 , \ ^W: 0 , \ ^X: 0 , \ ^Y: insert save buffer 0 , \ ^Z: ' handle-ESC , 0 , \ ^\: 0 , \ ^]: 0 , \ ^^: 0 , \ ^_: : (accept) ( adr len -- len' ) cursor-on to accept-max to accept-adr 0 to accept-len 0 to accept-cur 0 to his-cur 1b emit 37 emit BEGIN key dup 0d <> WHILE dup 9 <> IF 0 to ?tab-pressed THEN \ reset state machine dup 7f = IF drop 8 THEN \ Handle DEL as if it was BS. ??? bogus dup bl < IF handle-control ELSE dup 80 and IF dup a0 < IF 7f and handle-meta ELSE drop beep THEN ELSE insert-char THEN THEN REPEAT drop add-history accept-len to accept-cur move-cursor space accept-len cursor-off ; ' (accept) to accept 120 cp 1 VALUE /dump ' c@ VALUE 'dump 0 VALUE dump-first 0 VALUE dump-last 0 VALUE dump-cur : .char ( c -- ) dup bl 7f within 0= IF drop [char] . THEN emit ; : dump-line ( -- ) cr dump-cur dup 8 0.r [char] : emit 10 /dump / 0 DO space dump-cur dump-first dump-last within IF dump-cur 'dump execute /dump 2* 0.r ELSE /dump 2* spaces THEN dump-cur /dump + to dump-cur LOOP /dump 1 <> IF drop EXIT THEN to dump-cur 2 spaces 10 0 DO dump-cur dump-first dump-last within IF dump-cur 'dump execute .char ELSE space THEN dump-cur 1+ to dump-cur LOOP ; : (dump) ( addr len reader size -- ) to /dump to 'dump bounds /dump negate and to dump-first to dump-last dump-first f invert and to dump-cur base @ hex BEGIN dump-line dump-cur dump-last >= UNTIL base ! ; : du ( -- ) dump-last 100 'dump /dump (dump) ; : dump ['] c@ 1 (dump) ; : wdump ['] w@ 2 (dump) ; : ldump ['] l@ 4 (dump) ; : xdump ['] x@ 8 (dump) ; : rdump ['] rb@ 1 (dump) ; cistack ciregs >r1 ! \ kernel wants a stack :-) 140 cp STRUCT cell field romfs>file-header cell field romfs>data cell field romfs>data-size cell field romfs>flags CONSTANT /romfs-lookup-control-block CREATE romfs-lookup-cb /romfs-lookup-control-block allot romfs-lookup-cb /romfs-lookup-control-block erase : create-filename ( string -- string\0 ) here >r dup 8 + allot r@ over 8 + erase r@ zplace r> ; : romfs-lookup ( fn-str fn-len -- data size | false ) create-filename romfs-base romfs-lookup-cb romfs-lookup-entry call-c 0= IF romfs-lookup-cb dup romfs>data @ swap romfs>data-size @ ELSE false THEN ; : ibm,romfs-lookup ( fn-str fn-len -- data-high data-low size | 0 0 false ) romfs-lookup dup 0= if drop 0 0 false else swap dup 20 rshift swap ffffffff and then ; : romfs-lookup-client ibm,romfs-lookup ; STRUCT cell field romfs>next-off cell field romfs>size cell field romfs>flags cell field romfs>data-off cell field romfs>name CONSTANT /romfs-cb : romfs-map-file ( fn-str fn-len -- file-addr file-size ) romfs-base >r BEGIN 2dup r@ romfs>name zcount string=ci not WHILE ( fn-str fn-len ) ( R: rom-cb-file-addr ) r> romfs>next-off dup @ dup 0= IF 1 THROW THEN + >r REPEAT ( fn-str fn-len ) ( R: rom-cb-file-addr ) 2drop r@ romfs>data-off @ r@ + r> romfs>size @ ; : flash-header ( -- address | false ) get-flash-base 28 + \ prepare flash header file address dup rx@ \ fetch "magic123" 6d61676963313233 <> IF \ IF flash is not valid drop \ | forget address false \ | return false THEN \ FI ; CREATE bdate-str 10 allot : bdate2human ( -- addr len ) flash-header 40 + rx@ (.) drop dup 0 + bdate-str 6 + 4 move dup 4 + bdate-str 0 + 2 move dup 6 + bdate-str 3 + 2 move dup 8 + bdate-str b + 2 move a + bdate-str e + 2 move 2d bdate-str 2 + c! 2d bdate-str 5 + c! 20 bdate-str a + c! 3a bdate-str d + c! bdate-str 10 ; : included ( fn fn-len -- ) 2dup >r >r romfs-lookup dup IF r> drop r> drop evaluate ELSE drop ." Cannot open file : " r> r> type cr THEN ; : include ( " fn " -- ) parse-word included ; : ?include ( flag " fn " -- ) parse-word rot IF included ELSE 2drop THEN ; : include? ( nargs flag " fn " -- ) parse-word rot IF rot drop included ELSE 2drop 0 ?DO drop LOOP THEN ; : (print-romfs-file-info) ( file-addr -- ) 9 emit dup b 0.r 2 spaces dup 8 + @ 6 0.r 2 spaces 20 + zcount type cr ; : romfs-list ( -- ) romfs-base 0 cr BEGIN + dup (print-romfs-file-info) dup @ dup 0= UNTIL 2drop ; 200 cp : .slof-logo cr ." ..`. .. ....... .. ...... ......." cr ." ..`...`''.`'. .''``````..''. .`''```''`. `''``````" cr ." .`` .:' ': `''..... .''. ''` .''..''......." cr ." ``.':.';. ``````''`.''. .''. ''``''`````'`" cr ." ``.':':` .....`''.`'`...... `'`.....`''.`'` " cr ." .`.`'`` .'`'`````. ``'''''' ``''`'''`. `'` " ; 201 cp : banner cr ." Type 'boot' and press return to continue booting the system." s" /packages/sms" find-node IF cr ." Type 'sms-start' and press return to enter the configuration menu." THEN cr ." Type 'reset-all' and press return to reboot the system." cr cr ; : .banner banner console-clean-fifo ; : .banner .slof-logo .banner ; 220 cp DEFER find-boot-sector ( -- ) 240 cp d# 512000000 VALUE tb-frequency \ default value - needed for "ms" to work -1 VALUE cpu-frequency : slof-build-id ( -- str len ) flash-header 10 + a ; : slof-revision s" 001" ; : read-version-and-date flash-header 0= IF s" " encode-string ELSE flash-header 10 + 10 here swap rmove here 10 s" , " $cat bdate2human $cat encode-string THEN ; : from-cstring ( addr - len ) dup dup BEGIN c@ 0 <> WHILE 1 + dup REPEAT swap - ; : invert-region-cs ( addr len cellsize -- ) >r over swap r@ rshift r> swap 1 hv-logical-memop drop ; : invert-region ( addr len -- ) 2dup or 7 and CASE 0 OF 3 invert-region-cs ENDOF 4 OF 2 invert-region-cs ENDOF 3 and 2 OF 1 invert-region-cs ENDOF dup OF 0 invert-region-cs ENDOF ENDCASE ; 260 cp : tb@ ( -- tb ) BEGIN tbu@ tbl@ tbu@ rot over <> WHILE 2drop REPEAT 20 lshift swap ffffffff and or ; : milliseconds ( -- ms ) tb@ d# 1000 * tb-frequency / ; : microseconds ( -- us ) tb@ d# 1000000 * tb-frequency / ; : ms ( ms-to-wait -- ) milliseconds + BEGIN milliseconds over >= UNTIL drop ; : get-msecs ( -- n ) milliseconds ; : us ( us-to-wait -- ) microseconds + BEGIN microseconds over >= UNTIL drop ; 270 cp variable ip variable fcode-end variable fcode-num 1 value fcode-spread 2 value fcode-offset false value eva-debug? true value fcode-debug? defer fcode-rb@ defer fcode@ ' c@ to fcode-rb@ create token-table 2000 cells allot \ 1000h = 4096d : ?offset16 ( -- true|false ) fcode-offset 2 = ; : ?arch64 ( -- true|false ) cell 8 = ; : ?bigendian ( -- true|false ) deadbeef fcode-num ! fcode-num ?arch64 IF 4 + THEN c@ de = ; : reset-fcode-end ( -- ) false fcode-end ! ; : get-ip ( -- n ) ip @ ; : set-ip ( n -- ) ip ! ; : next-ip ( -- ) get-ip 1+ set-ip ; : jump-n-ip ( n -- ) get-ip + set-ip ; : read-byte ( -- n ) get-ip fcode-rb@ ; : ?compile-mode ( -- on|off ) state @ ; : save-evaluator-state get-ip eva-debug? IF ." saved ip " dup . cr THEN fcode-end @ eva-debug? IF ." saved fcode-end " dup . cr THEN fcode-offset eva-debug? IF ." saved fcode-offset " dup . cr THEN fcode-spread eva-debug? IF ." saved fcode-spread " dup . cr THEN ['] fcode@ behavior eva-debug? IF ." saved fcode@ " dup . cr THEN ; : restore-evaluator-state eva-debug? IF ." restored fcode@ " dup . cr THEN to fcode@ eva-debug? IF ." restored fcode-spread " dup . cr THEN to fcode-spread eva-debug? IF ." restored fcode-offset " dup . cr THEN to fcode-offset eva-debug? IF ." restored fcode-end " dup . cr THEN fcode-end ! eva-debug? IF ." restored ip " dup . cr THEN set-ip ; : token-table-index ( fcode# -- addr ) cells token-table + ; : join-immediate ( xt immediate? addr -- xt+immediate? addr ) -rot + swap ; : split-immediate ( xt+immediate? -- xt immediate? ) dup 1 and 2dup - rot drop swap ; : literal, ( n -- ) postpone literal ; : fc-string, postpone sliteral dup c, bounds ?do i c@ c, loop ; : set-token ( xt immediate? fcode# -- ) token-table-index join-immediate ! ; : get-token ( fcode# -- xt immediate? ) token-table-index @ split-immediate ; ?bigendian [IF] \ Big endian access functions first : read-fcode-num16 ( -- n ) 0 fcode-num ! ?arch64 IF read-byte fcode-num 6 + C! next-ip read-byte fcode-num 7 + C! ELSE read-byte fcode-num 2 + C! next-ip read-byte fcode-num 3 + C! THEN fcode-num @ ; : read-fcode-num32 ( -- n ) 0 fcode-num ! ?arch64 IF read-byte fcode-num 4 + C! next-ip read-byte fcode-num 5 + C! next-ip read-byte fcode-num 6 + C! next-ip read-byte fcode-num 7 + C! ELSE read-byte fcode-num 0 + C! next-ip read-byte fcode-num 1 + C! next-ip read-byte fcode-num 2 + C! next-ip read-byte fcode-num 3 + C! THEN fcode-num @ ; [ELSE] \ Now the little endian access functions : read-fcode-num16 ( -- n ) 0 fcode-num ! ?arch64 IF read-byte fcode-num 7 + C! next-ip read-byte fcode-num 6 + C! ELSE read-byte fcode-num 1 + C! next-ip read-byte fcode-num 0 + C! THEN fcode-num @ ; : read-fcode-num32 ( adr -- n ) 0 fcode-num ! ?arch64 IF read-byte fcode-num 7 + C! next-ip read-byte fcode-num 6 + C! next-ip read-byte fcode-num 5 + C! next-ip read-byte fcode-num 4 + C! ELSE read-byte fcode-num 3 + C! next-ip read-byte fcode-num 2 + C! next-ip read-byte fcode-num 1 + C! next-ip read-byte fcode-num 0 + C! THEN fcode-num @ ; [THEN] : read-fcode# ( -- FCode# ) read-byte dup 01 0F between IF drop read-fcode-num16 THEN ; : read-header ( adr -- ) next-ip read-byte drop next-ip read-fcode-num16 drop next-ip read-fcode-num32 drop ; : read-fcode-string ( -- str len ) read-byte \ get string length ( -- len ) next-ip get-ip \ get string addr ( -- len str ) swap \ type needs the parameters swapped ( -- str len ) dup 1- jump-n-ip \ jump to the end of the string in FCode ; -1 VALUE break-fcode-addr 0 VALUE break-fcode-steps : evaluate-fcode ( -- ) BEGIN get-ip break-fcode-addr = IF TRUE fcode-end ! THEN fcode-end @ 0= WHILE fcode@ ( fcode# ) eva-debug? IF dup get-ip 8 u.r ." : " ." [" 3 u.r ." ] " THEN get-token 0= ?compile-mode AND IF ( xt ) compile, ELSE \ immediate or "interpretation" mode eva-debug? IF dup xt>name type space THEN execute THEN eva-debug? IF .s cr THEN break-fcode-steps IF break-fcode-steps 1- TO break-fcode-steps break-fcode-steps 0= IF TRUE fcode-end ! THEN THEN next-ip REPEAT ; : steps-fcode ( n -- ) to break-fcode-steps break-fcode-addr >r -1 to break-fcode-addr reset-fcode-end evaluate-fcode r> to break-fcode-addr ; : step-fcode ( -- ) 1 steps-fcode ; : fcode-revision ( -- n ) 00030000 \ major * 65536 + minor ; : b(lit) ( -- n ) next-ip read-fcode-num32 ?compile-mode IF literal, THEN ; : b(") next-ip read-fcode-string ?compile-mode IF fc-string, align postpone count THEN ; : b(') next-ip read-fcode# get-token drop ?compile-mode IF literal, THEN ; : ?jump-direction ( n -- ) dup 8000 >= IF 10000 - \ Create cell-sized negative value THEN fcode-offset - \ IP is already behind offset, so subtract offset size ; : ?negative 8000 and ; : dest-on-top 0 >r BEGIN dup @ 0= WHILE >r REPEAT BEGIN r> dup WHILE swap REPEAT drop ; : read-fcode-offset next-ip ?offset16 IF read-fcode-num16 ELSE read-byte dup 80 and IF FF00 or THEN \ Fake 16-bit signed offset THEN ; : b?branch ( flag -- ) ?compile-mode IF read-fcode-offset ?negative IF dest-on-top postpone until ELSE postpone if THEN ELSE ( flag ) IF fcode-offset jump-n-ip \ Skip over offset value ELSE read-fcode-offset ?jump-direction jump-n-ip THEN THEN ; immediate : bbranch ( -- ) ?compile-mode IF read-fcode-offset ?negative IF dest-on-top postpone again ELSE postpone else get-ip next-ip fcode@ B2 = IF drop ELSE set-ip THEN THEN ELSE read-fcode-offset ?jump-direction jump-n-ip THEN ; immediate : b(resolve) ( -- ) ?compile-mode IF postpone then THEN ; immediate : b(;) compile, reveal postpone [ ; immediate : b(:) ( -- ) compile, ] ; immediate : b(case) ( sel -- sel ) postpone case ; immediate : b(endcase) postpone endcase ; immediate : b(of) postpone of read-fcode-offset drop \ read and discard offset ; immediate : b(endof) postpone endof read-fcode-offset drop ; immediate : b(do) postpone do read-fcode-offset drop ; immediate : b(?do) postpone ?do read-fcode-offset drop ; immediate : b(loop) postpone loop read-fcode-offset drop ; immediate : b(+loop) postpone +loop read-fcode-offset drop ; immediate : b(leave) postpone leave ; immediate 0 VALUE fc-instance? : fc-instance ( -- ) \ Mark next defining word as instance-specific. TRUE TO fc-instance? ; : new-token \ unnamed local fcode function align here next-ip read-fcode# 0 swap set-token ; : external-token ( -- ) \ named local fcode function next-ip read-fcode-string header ( str len -- ) \ create a header in the current dictionary entry new-token ; : new-token eva-debug? IF s" x" get-ip >r next-ip read-fcode# r> set-ip (u.) $cat strdup header THEN new-token ; : named-token fcode-debug? IF external-token ELSE next-ip read-fcode-string 2drop \ Forget about the name new-token THEN ; : b(to) ( val -- ) next-ip read-fcode# get-token drop ( val xt ) dup @ ( val xt @xt ) dup = over = OR IF drop >body cell - ?compile-mode IF literal, postpone ! ELSE ! THEN ELSE <> IF ( val xt ) TRUE ABORT" Invalid destination for FCODE b(to)" THEN dup cell+ @ ( val xt @xt+1cell ) dup <> swap <> AND IF TRUE ABORT" Invalid destination for FCODE b(to)" THEN >body @ ( val instance-offset ) ?compile-mode IF literal, postpone >instance postpone ! ELSE >instance ! THEN ELSE THEN ; immediate : b(value) fc-instance? IF , \ Needed for "(instance?)" for example , (create-instance-var) FALSE TO fc-instance? ELSE , , THEN reveal ; : b(variable) fc-instance? IF , \ Needed for "(instance?)" , 0 (create-instance-var) FALSE TO fc-instance? ELSE , 0 , THEN reveal ; : b(constant) , , reveal ; : undefined-defer cr cr ." Uninitialized defer word has been executed!" cr cr true fcode-end ! ; : b(defer) fc-instance? IF , \ Needed for "(instance?)" , ['] undefined-defer (create-instance-var) reveal FALSE TO fc-instance? ELSE , reveal postpone undefined-defer THEN ; : b(create) , postpone noop reveal ; : b(field) ( E: addr -- addr+offset ) ( F: offset size -- offset+size ) , over literal, postpone + compile, reveal + ; : b(buffer:) ( E: -- a-addr) ( F: size -- ) fc-instance? IF , \ Needed for "(instance?)" , (create-instance-buf) FALSE TO fc-instance? ELSE , allot THEN reveal ; : suspend-fcode ( -- ) noop \ has to be implemented more efficiently ;-) ; : offset16 ( -- ) 2 to fcode-offset ; : version1 ( -- ) 1 to fcode-spread 1 to fcode-offset read-header ; : start0 ( -- ) 0 to fcode-spread offset16 read-header ; : start1 ( -- ) 1 to fcode-spread offset16 read-header ; : start2 ( -- ) 2 to fcode-spread offset16 read-header ; : start4 ( -- ) 4 to fcode-spread offset16 read-header ; : end0 ( -- ) true fcode-end ! ; : end1 ( -- ) end0 ; : ferror ( -- ) clear end0 cr ." FCode# " fcode-num @ . ." not assigned!" cr ." FCode evaluation aborted." cr ." ( -- S:" depth . ." R:" rdepth . ." ) " .s cr abort ; : reset-local-fcodes FFF 800 DO ['] ferror 0 i set-token LOOP ; : byte-load ( addr xt -- ) >r >r save-evaluator-state r> r> reset-fcode-end 1 to fcode-spread dup 1 = IF drop ['] rb@ THEN to fcode-rb@ set-ip reset-local-fcodes depth >r evaluate-fcode r> depth 1- <> IF clear end0 cr ." Ambiguous stack depth after byte-load!" cr ." FCode evaluation aborted." cr cr ELSE restore-evaluator-state THEN ['] c@ to fcode-rb@ ; : fc-c@ ( addr -- byte ) dup MIN-RAM-SIZE > IF rb@ ELSE c@ THEN ; : fc-w@ ( addr -- word ) dup MIN-RAM-SIZE > IF rw@ ELSE w@ THEN ; : fc-= IF 10000 - THEN ; : fc-l@ ( addr -- long ) dup MIN-RAM-SIZE > IF rl@ ELSE l@ THEN ; : fc- IF rx@ ELSE x@ THEN ; : fc-c! ( byte addr -- ) dup MIN-RAM-SIZE > IF rb! ELSE c! THEN ; : fc-w! ( word addr -- ) dup MIN-RAM-SIZE > IF rw! ELSE w! THEN ; : fc-l! ( long addr -- ) dup MIN-RAM-SIZE > IF rl! ELSE l! THEN ; : fc-x! ( dlong addr -- ) dup MIN-RAM-SIZE > IF rx! ELSE x! THEN ; : fc-fill ( add len byte -- ) 2 pick MIN-RAM-SIZE > IF rfill ELSE fill THEN ; : fc-move ( src dst len -- ) 2 pick MIN-RAM-SIZE > \ Check src 2 pick MIN-RAM-SIZE > \ Check dst OR IF rmove ELSE move THEN ; : free-virtual ( virt size -- ) s" map-out" $call-parent ; : map-low ( phys.lo ... size -- virt ) my-space swap s" map-in" $call-parent ; : mac-address ( -- mac-str mac-len ) s" local-mac-address" get-my-property IF 0 0 THEN ; VARIABLE #line 0 #line ! VARIABLE #out 0 #out ! : display-status ( n -- ) ." Device status: " . cr ; VARIABLE group-code 0 group-code ! : dma-alloc ( byte -- virtual ) s" dma-alloc" $call-parent ; : my-params ( -- addr len ) s" params" get-my-property IF 0 0 THEN ; : sbus-intr>cpu ( sbus-intr# -- cpu-intr# ) ; : intr ( interrupt# vector -- ) >r sbus-intr>cpu encode-int r> encode-int+ s" intr" property ; : driver ( addr len -- ) encode-string s" name" property ; : processor-type ( -- cpu-type ) 0 ; : firmware-version ( -- n ) 10000 \ Just a dummy value ; : fcode-version ( -- n ) fcode-revision ; : fc-abort ." FCode called abort: IP " get-ip . ( ." STACK: " .s ) depth dup 0< IF abort THEN . rdepth . cr abort ; : fc-0 ." 0(lit): STACK ( S: " depth . ." R: " rdepth . ." ): " depth 0> IF .s THEN 0 ; : fc-1 ." 1(lit): STACK ( S: " depth . ." R: " rdepth . ." ): " depth 0> IF .s THEN 1 ; : parse-1hex 1 hex-decode-unit ; : fc-set-pci-mmio-tokens ( -- ) ['] rw@-le 0 232 set-token ['] rw!-le 0 233 set-token ['] rl@-le 0 234 set-token ['] rl!-le 0 235 set-token ['] rx@-le 0 22E set-token ['] rx!-le 0 22F set-token ; : fc-set-normal-mmio-tokens ( -- ) ['] rw@ 0 232 set-token ['] rw! 0 233 set-token ['] rl@ 0 234 set-token ['] rl! 0 235 set-token ['] rx@ 0 22E set-token ['] rx! 0 22F set-token ; : reset-token-table FFF 0 DO ['] ferror 0 i set-token LOOP ; reset-token-table ' end0 0 00 set-token ' b(lit) 1 10 set-token ' b(') 1 11 set-token ' b(") 1 12 set-token ' bbranch 1 13 set-token ' b?branch 1 14 set-token ' b(loop) 1 15 set-token ' b(+loop) 1 16 set-token ' b(do) 1 17 set-token ' b(?do) 1 18 set-token ' i 0 19 set-token ' j 0 1A set-token ' b(leave) 1 1B set-token ' b(of) 1 1C set-token ' execute 0 1D set-token ' + 0 1E set-token ' - 0 1F set-token ' * 0 20 set-token ' / 0 21 set-token ' mod 0 22 set-token ' and 0 23 set-token ' or 0 24 set-token ' xor 0 25 set-token ' invert 0 26 set-token ' lshift 0 27 set-token ' rshift 0 28 set-token ' >>a 0 29 set-token ' /mod 0 2A set-token ' u/mod 0 2B set-token ' negate 0 2C set-token ' abs 0 2D set-token ' min 0 2E set-token ' max 0 2F set-token ' >r 0 30 set-token ' r> 0 31 set-token ' r@ 0 32 set-token ' exit 0 33 set-token ' 0= 0 34 set-token ' 0<> 0 35 set-token ' 0< 0 36 set-token ' 0<= 0 37 set-token ' 0> 0 38 set-token ' 0>= 0 39 set-token ' < 0 3A set-token ' > 0 3B set-token ' = 0 3C set-token ' <> 0 3D set-token ' u> 0 3E set-token ' u<= 0 3F set-token ' u< 0 40 set-token ' u>= 0 41 set-token ' >= 0 42 set-token ' <= 0 43 set-token ' between 0 44 set-token ' within 0 45 set-token ' DROP 0 46 set-token ' DUP 0 47 set-token ' OVER 0 48 set-token ' SWAP 0 49 set-token ' ROT 0 4A set-token ' -ROT 0 4B set-token ' TUCK 0 4C set-token ' nip 0 4D set-token ' pick 0 4E set-token ' roll 0 4F set-token ' ?dup 0 50 set-token ' depth 0 51 set-token ' 2drop 0 52 set-token ' 2dup 0 53 set-token ' 2over 0 54 set-token ' 2swap 0 55 set-token ' 2rot 0 56 set-token ' 2/ 0 57 set-token ' u2/ 0 58 set-token ' 2* 0 59 set-token ' /c 0 5A set-token ' /w 0 5B set-token ' /l 0 5C set-token ' /n 0 5D set-token ' ca+ 0 5E set-token ' wa+ 0 5F set-token ' la+ 0 60 set-token ' na+ 0 61 set-token ' char+ 0 62 set-token ' wa1+ 0 63 set-token ' la1+ 0 64 set-token ' cell+ 0 65 set-token ' chars 0 66 set-token ' /w* 0 67 set-token ' /l* 0 68 set-token ' cells 0 69 set-token ' on 0 6A set-token ' off 0 6B set-token ' +! 0 6C set-token ' @ 0 6D set-token ' fc-l@ 0 6E set-token ' fc-w@ 0 6F set-token ' fc- 0 85 set-token ' >body 0 86 set-token ' fcode-revision 0 87 set-token ' span 0 88 set-token ' unloop 0 89 set-token ' expect 0 8A set-token ' alloc-mem 0 8B set-token ' free-mem 0 8C set-token ' key? 0 8D set-token ' key 0 8E set-token ' emit 0 8F set-token ' type 0 90 set-token ' (cr 0 91 set-token ' cr 0 92 set-token ' #out 0 93 set-token ' #line 0 94 set-token ' hold 0 95 set-token ' <# 0 96 set-token ' u#> 0 97 set-token ' sign 0 98 set-token ' u# 0 99 set-token ' u#s 0 9A set-token ' u. 0 9B set-token ' u.r 0 9C set-token ' . 0 9D set-token ' .r 0 9E set-token ' .s 0 9F set-token ' base 0 A0 set-token ' $number 0 A2 set-token ' digit 0 A3 set-token ' -1 0 A4 set-token ' 0 0 A5 set-token ' 1 0 A6 set-token ' 2 0 A7 set-token ' 3 0 A8 set-token ' bl 0 A9 set-token ' bs 0 AA set-token ' bell 0 AB set-token ' bounds 0 AC set-token ' here 0 AD set-token ' aligned 0 AE set-token ' wbsplit 0 AF set-token ' bwjoin 0 B0 set-token ' b(resolve) 1 B2 set-token ' new-token 0 B5 set-token ' named-token 0 B6 set-token ' b(:) 1 B7 set-token ' b(value) 1 B8 set-token ' b(variable) 1 B9 set-token ' b(constant) 1 BA set-token ' b(create) 1 BB set-token ' b(defer) 1 BC set-token ' b(buffer:) 1 BD set-token ' b(field) 1 BE set-token ' fc-instance 1 C0 set-token ' b(;) 1 C2 set-token ' b(to) 1 C3 set-token ' b(case) 1 C4 set-token ' b(endcase) 1 C5 set-token ' b(endof) 1 C6 set-token ' # 0 C7 set-token ' #s 0 C8 set-token ' #> 0 C9 set-token ' external-token 0 CA set-token ' $find 0 CB set-token ' offset16 0 CC set-token ' evaluate 0 CD set-token ' c, 0 D0 set-token ' w, 0 D1 set-token ' l, 0 D2 set-token ' , 0 D3 set-token ' um* 0 D4 set-token ' um/mod 0 D5 set-token ' d+ 0 D8 set-token ' d- 0 D9 set-token ' get-token 0 DA set-token ' set-token 0 DB set-token ' state 0 DC set-token \ possibly broken ' compile, 0 DD set-token ' behavior 0 DE set-token ' start0 0 F0 set-token ' start1 0 F1 set-token ' start2 0 F2 set-token ' start4 0 F3 set-token ' ferror 0 FC set-token ' version1 0 FD set-token ' end1 0 FF set-token ' dma-alloc 0 101 set-token \ Obsolete ' my-address 0 102 set-token ' my-space 0 103 set-token ' free-virtual 0 105 set-token ' my-params 0 10f set-token \ Obsolete ' property 0 110 set-token ' encode-int 0 111 set-token ' encode+ 0 112 set-token ' encode-phys 0 113 set-token ' encode-string 0 114 set-token ' encode-bytes 0 115 set-token ' reg 0 116 set-token ' intr 0 117 set-token \ Obsolete ' driver 0 118 set-token \ Obsolete ' model 0 119 set-token ' device-type 0 11A set-token ' parse-2int 0 11B set-token ' new-device 0 11F set-token ' diagnostic-mode? 0 120 set-token ' display-status 0 121 set-token \ Maybe obsolete ' memory-test-suite 0 122 set-token ' group-code 0 123 set-token \ Obsolete ' mask 0 124 set-token ' get-msecs 0 125 set-token ' ms 0 126 set-token ' finish-device 0 127 set-token ' decode-phys 0 128 set-token ' interpose 0 12B set-token \ Recommended practice: Interposition ' map-low 0 130 set-token ' sbus-intr>cpu 0 131 set-token \ Obsolete ' mac-address 0 1A4 set-token ' device-name 0 201 set-token ' my-args 0 202 set-token ' my-self 0 203 set-token ' find-package 0 204 set-token ' open-package 0 205 set-token ' close-package 0 206 set-token ' find-method 0 207 set-token ' call-package 0 208 set-token ' $call-parent 0 209 set-token ' my-parent 0 20A set-token ' ihandle>phandle 0 20B set-token ' my-unit 0 20D set-token ' $call-method 0 20E set-token ' $open-package 0 20F set-token ' processor-type 0 210 set-token \ Obsolete ' firmware-version 0 211 set-token \ Obsolete ' fcode-version 0 212 set-token \ Obsolete ' (is-user-word) 0 214 set-token ' suspend-fcode 0 215 set-token ' fc-abort 0 216 set-token ' catch 0 217 set-token ' throw 0 218 set-token ' get-my-property 0 21A set-token ' decode-int 0 21B set-token ' decode-string 0 21C set-token ' get-inherited-property 0 21D set-token ' delete-property 0 21E set-token ' get-package-property 0 21F set-token ' cpeek 0 220 set-token ' wpeek 0 221 set-token ' lpeek 0 222 set-token ' cpoke 0 223 set-token ' wpoke 0 224 set-token ' lpoke 0 225 set-token ' lwflip 0 226 set-token ' lbflip 0 227 set-token ' lbflips 0 228 set-token ' rb@ 0 230 set-token ' rb! 0 231 set-token fc-set-normal-mmio-tokens \ Set rw@, rw!, rl@, rl!, rx@ and rx! ' wbflips 0 236 set-token ' lwflips 0 237 set-token ' child 0 23B set-token ' peer 0 23C set-token ' next-property 0 23D set-token ' byte-load 0 23E set-token ' set-args 0 23F set-token ' left-parse-string 0 240 set-token ' bxjoin 0 241 set-token ' fc- ABORT" Locals stack exceeded!" ?dup IF ( ... n ) 1 swap DO i fc-local! \ Store pre-initialized locals -1 +LOOP THEN ; : fc-push-locals ( n -- ) uses-locals? ABORT" Definition pushes locals multiple times!" true TO uses-locals? ( n ) ['] literal execute ['] (fc-push-locals) compile, ; : fc-push-0-locals 0 fc-push-locals ; : fc-push-1-locals 1 fc-push-locals ; : fc-push-2-locals 2 fc-push-locals ; : fc-push-3-locals 3 fc-push-locals ; : fc-push-4-locals 4 fc-push-locals ; : fc-push-5-locals 5 fc-push-locals ; : fc-push-6-locals 6 fc-push-locals ; : fc-push-7-locals 7 fc-push-locals ; : fc-push-8-locals 8 fc-push-locals ; : fc-pop-locals ( -- ) localsstack 8 cells - TO localsstack localsstack localsstackbuf - 0 < ABORT" Locals stack undeflow!" ; : fc-locals-exit uses-locals? IF ['] fc-pop-locals compile, THEN ['] exit compile, ; : fc-locals-b(;) uses-locals? IF ['] fc-pop-locals compile, THEN false TO uses-locals? ['] b(;) execute ; : fc-set-locals-tokens ( -- ) ['] fc-push-0-locals 1 407 set-token ['] fc-push-1-locals 1 408 set-token ['] fc-push-2-locals 1 409 set-token ['] fc-push-3-locals 1 40a set-token ['] fc-push-4-locals 1 40b set-token ['] fc-push-5-locals 1 40c set-token ['] fc-push-6-locals 1 40d set-token ['] fc-push-7-locals 1 40e set-token ['] fc-push-8-locals 1 40f set-token ['] fc-local-1-@ 0 410 set-token ['] fc-local-2-@ 0 411 set-token ['] fc-local-3-@ 0 412 set-token ['] fc-local-4-@ 0 413 set-token ['] fc-local-5-@ 0 414 set-token ['] fc-local-6-@ 0 415 set-token ['] fc-local-7-@ 0 416 set-token ['] fc-local-8-@ 0 417 set-token ['] fc-local-1-! 0 418 set-token ['] fc-local-2-! 0 419 set-token ['] fc-local-3-! 0 41a set-token ['] fc-local-4-! 0 41b set-token ['] fc-local-5-! 0 41c set-token ['] fc-local-6-! 0 41d set-token ['] fc-local-7-! 0 41e set-token ['] fc-local-8-! 0 41f set-token ['] fc-locals-exit 1 33 set-token ['] fc-locals-b(;) 1 c2 set-token ; fc-set-locals-tokens 0 value buff 0 value buff-size ' read-fcode# to fcode@ : execute-rom-fcode ( addr len | false -- ) reset-fcode-end ?dup IF diagnostic-mode? IF ." , executing ..." cr THEN dup >r r@ alloc-mem dup >r swap rmove r@ set-ip evaluate-fcode diagnostic-mode? IF ." Done." cr THEN r> r> free-mem THEN ; : rom-code-ignored ( image-addr name len -- image-addr ) diagnostic-mode? IF type ." code found in image " dup . ." , ignoring ..." cr ELSE 2drop THEN ; : pci-find-rom ( baseaddr -- addr ) dup IF dup rw@-le aa55 = IF diagnostic-mode? IF ." Device ROM header found at " dup . cr THEN ELSE drop 0 THEN THEN ; : pci-find-fcode ( baseaddr -- addr len | false ) BEGIN 1ff NOT and \ Image must start at 512 byte boundary pci-find-rom dup WHILE dup 18 + rw@-le + ( pcir-addr ) dup rw@-le 4350 ( 'PC' ) <> ( pcir-addr hasPC? ) over 2+ rw@-le 5249 ( 'IR' ) <> OR IF diagnostic-mode? IF ." Invalid PCI Data structure, ignoring ROM contents" cr THEN drop false EXIT THEN ( pcir-addr ) dup 14 + rb@ CASE \ Get image code type 0 OF s" Intel x86 BIOS" rom-code-ignored ENDOF 1 OF diagnostic-mode? IF ." Open Firmware FCode found in image at " dup . cr THEN dup 1ff NOT AND \ Back to the ROM image header dup 2+ rw@-le + \ Pointer to FCODE (PCI bus binding ch.9) swap 10 + rw@-le 200 * \ Image length EXIT ENDOF 2 OF s" HP PA RISC" rom-code-ignored ENDOF 3 OF s" EFI" rom-code-ignored ENDOF dup OF s" Unknown type" rom-code-ignored ENDOF ENDCASE dup 15 + rb@ 80 and IF \ End of last image? drop false EXIT THEN dup 10 + rw@-le 200 * + \ Next image start REPEAT ; : pci-execute-fcode ( baseaddr -- ) pci-find-fcode dup 0= IF 2drop EXIT THEN ( addr len ) fc-set-pci-mmio-tokens \ Prepare PCI access functions ['] execute-rom-fcode CATCH IF cr ." FCODE failed!" cr 2drop THEN fc-set-normal-mmio-tokens \ Restore normal MMIO access functions ; 2e0 cp 100 CONSTANT quiesce-xt# CREATE quiesce-xts quiesce-xt# cells allot quiesce-xts quiesce-xt# cells erase 0 VALUE quiesce-done? : add-quiesce-xt ( xt -- ) quiesce-xt# 0 DO quiesce-xts I cells + ( xt arrayptr ) dup @ 0= ( xt arrayptr true|false ) IF ! UNLOOP EXIT ELSE ( xt arrayptr ) over swap ( xt xt arrayptr ) @ = \ xt already stored ? IF drop UNLOOP EXIT THEN ( xt ) THEN LOOP drop ( xt -- ) ." Warning: quiesce xt list is full." cr ; : quiesce ( -- ) quiesce-done? IF EXIT THEN true to quiesce-done? quiesce-xt# 0 DO quiesce-xts I cells + ( arrayptr ) @ dup IF ( xt ) EXECUTE ELSE drop UNLOOP EXIT THEN LOOP ; 300 cp : load-dev-hci ( num name-str name-len ) s" dev-hci.fs" INCLUDED ; 0 VALUE ohci-init 0 VALUE ehci-init 0 VALUE xhci-init 0 VALUE usb-alias-num : get-usb-alias-num usb-alias-num dup 1+ to usb-alias-num ; : set-ohci-alias ( -- ) 1 to ohci-init get-usb-alias-num ( num ) s" ohci" 1 load-dev-hci ; : set-ehci-alias ( -- ) 1 to ehci-init get-usb-alias-num ( num ) s" ehci" 2 load-dev-hci ; : set-xhci-alias ( -- ) 1 to xhci-init get-usb-alias-num ( num ) s" xhci" 3 load-dev-hci ; : usb-enumerate ( hcidev -- ) USB-HCD-INIT ; : usb-scan ( -- ) ." Scanning USB " cr ohci-init 1 = IF USB-OHCI-REGISTER THEN ehci-init 1 = IF USB-EHCI-REGISTER THEN xhci-init 1 = IF USB-XHCI-REGISTER THEN usb-alias-num 0 ?DO " usb" i $cathex find-device " get-hci-dev" get-node find-method IF execute usb-enumerate ELSE ." get-base-address method not found for usb@" i . ." Device type: " " device_type" get-node get-property 0= IF decode-string type cr 2drop THEN THEN LOOP 0 set-node \ FIXME Setting it back ; 320 cp : .ansi-attr-off 1b emit ." [0m" ; \ ESC Sequence: all terminal attributes off : .ansi-blue 1b emit ." [34m" ; \ ESC Sequence: foreground-color = blue : .ansi-green 1b emit ." [32m" ; \ ESC Sequence: foreground-color = green : .ansi-red 1b emit ." [31m" ; \ ESC Sequence: foreground-color = green : .ansi-bold 1b emit ." [1m" ; \ ESC Sequence: foreground-color bold false VALUE scsi-supp-present? : scsi-xt-err ." SCSI-ERROR (Intern) " ; ' scsi-xt-err VALUE scsi-open-xt \ preset with an invalid token : .wordlists ( -- ) .ansi-red get-order ( -- wid1 .. widn n ) dup space 28 emit .d ." word lists : " 0 DO . 08 emit 2c emit LOOP 08 emit \ 'bs' 29 emit \ ')' cr space 28 emit ." Context: " context dup . @ 5b emit . 8 emit 5d emit space ." / Current: " current . .ansi-attr-off cr ; : .context ( num -- ) .ansi-red space 5b emit 23 emit . 3a emit context @ . 8 emit 5d emit space .ansi-attr-off ; : scsi-open ( -- ) scsi-supp-present? NOT IF s" scsi-support.fs" included ( xt-open ) to scsi-open-xt ( ) true to scsi-supp-present? THEN scsi-open-xt execute ; 340 cp 0 VALUE fdt-debug TRUE VALUE fdt-cas-fix? 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 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 : 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 : 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 ) ; : fdt-fetch-unit ( addr -- addr $name ) dup from-cstring \ get string size 2dup + 1 + 3 + fffffffc and -rot ; : fdt-reg-unit ( prop-addr prop-len -- ) decode-phys ( prop-addr' prop-len' phys.lo ... phys.hi ) set-unit ( prop-addr' prop-len' ) 2drop ; : 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 ; : 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 ; : fdt-encode-prop ( addr len -- ) 2dup fdt-prop-is-string? IF 1- encode-string ELSE encode-bytes THEN ; : fdt-unflatten-node ( start -- end ) recursive 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 fdt-fetch-unit dup 0 = IF drop drop " /" THEN 40 left-parse-string device-name 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 BEGIN fdt-next-tag dup OF_DT_END_NODE <> WHILE dup OF_DT_PROP = IF 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 " #address-cells" get-node get-package-property IF ELSE decode-int dup fdt-create-dec fdt-create-enc 2drop THEN finish-device ; : 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 : fdt-parse-memory " /memory@0" find-device " reg" get-node get-package-property IF throw -1 THEN decode-phys 2drop decode-phys my-#address-cells 1 > IF 20 << or THEN fdt-debug IF dup ." Memory size: " . cr THEN MIN-RAM-SIZE swap MIN-RAM-SIZE - release 2drop device-end ; fdt-parse-memory : 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 0 VALUE (fdt-phandle-replaced) : fdt-replace-interrupt-map ( old new prop-addr prop-len -- old new ) BEGIN dup ( old new prop-addr prop-len prop-len ) WHILE swap dup 10 + ( old new prop-len prop-addr prop-addr+10 ) dup l@ 5 pick = IF 3 pick swap l! TRUE TO (fdt-phandle-replaced) ELSE drop THEN 1c + swap 1c - REPEAT 2drop ; : fdt-replace-all-phandles ( old new node -- ) >r s" interrupt-map" r@ get-property 0= IF fdt-replace-interrupt-map THEN s" interrupt-parent" r@ get-property 0= IF 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 r> child BEGIN dup WHILE 3dup RECURSE PEER REPEAT 3drop ; : 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 ) 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 ; : fdt-fix-phandles ( node -- ) 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 360 cp defer (client-exec) defer client-exec defer callback defer continue-client 0 VALUE chosen-node : chosen chosen-node dup 0= IF drop s" /chosen" find-node dup to chosen-node THEN ; : set-chosen ( prop len name len -- ) chosen set-property ; : get-chosen ( name len -- [ prop len ] success ) chosen get-property 0= ; " /" find-node dup 0= IF drop new-device s" /" device-name ELSE extend-device THEN " /chosen" find-node dup 0= IF drop new-device s" chosen" device-name s" " encode-string s" bootargs" property s" " encode-string s" bootpath" property finish-device ELSE drop THEN new-device s" aliases" device-name finish-device new-device s" options" device-name finish-device new-device s" openprom" device-name 0 0 s" relative-addressing" property finish-device new-device s" packages" device-name get-node to packages new-device s" deblocker" device-name INSTANCE VARIABLE offset INSTANCE VARIABLE block-size INSTANCE VARIABLE max-transfer INSTANCE VARIABLE my-block INSTANCE VARIABLE adr INSTANCE VARIABLE len INSTANCE VARIABLE fail-count : open s" block-size" ['] $call-parent CATCH IF 2drop false EXIT THEN block-size ! s" max-transfer" ['] $call-parent CATCH IF 2drop false EXIT THEN max-transfer ! block-size @ alloc-mem my-block ! 0 offset ! true ; : close my-block @ block-size @ free-mem ; : seek ( lo hi -- status ) \ XXX: perhaps we should fail if the underlying lxjoin offset ! 0 ; : block+remainder ( -- block# remainder ) offset @ block-size @ u/mod swap ; : read-blocks ( addr block# #blocks -- actual ) s" read-blocks" $call-parent ; : read ( addr len -- actual ) dup >r len ! adr ! block+remainder dup IF ( block# offset-in-block ) >r my-block @ swap 1 read-blocks drop my-block @ r@ + adr @ block-size @ r> - len @ min dup >r move r> dup negate len +! dup adr +! offset +! ELSE 2drop THEN 0 fail-count ! BEGIN len @ block-size @ >= WHILE adr @ block+remainder drop len @ max-transfer @ min block-size @ / read-blocks dup 0= IF 1 fail-count +! fail-count @ 5 >= IF r> drop EXIT THEN ELSE 0 fail-count ! THEN block-size @ * dup negate len +! dup adr +! offset +! REPEAT len @ IF my-block @ block+remainder drop 1 read-blocks drop my-block @ adr @ len @ move THEN r> ; finish-device new-device false VALUE debug-disk-label? d# 65536 value max-prep-partition-blocks d# 4096 CONSTANT block-array-size s" disk-label" device-name 0 INSTANCE VALUE partition 0 INSTANCE VALUE part-offset 0 INSTANCE VALUE disk-chrp-boot 0 INSTANCE VALUE part-start 0 INSTANCE VALUE lpart-start 0 INSTANCE VALUE part-size 0 INSTANCE VALUE dos-logical-partitions 0 INSTANCE VALUE block-size 0 INSTANCE VALUE block 0 INSTANCE VALUE args 0 INSTANCE VALUE args-len 0 INSTANCE VALUE gpt-part-size 0 INSTANCE VALUE seek-pos INSTANCE VARIABLE block# \ variable to store logical sector# INSTANCE VARIABLE hit# \ partition counter INSTANCE VARIABLE success-flag 0ff constant END-OF-DESC 3 constant PARTITION-ID 48 constant VOL-PART-LOC STRUCT 1b8 field mbr>boot-loader /l field mbr>disk-signature /w field mbr>null 40 field mbr>partition-table /w field mbr>magic CONSTANT /mbr STRUCT /c field part-entry>active /c field part-entry>start-head /c field part-entry>start-sect /c field part-entry>start-cyl /c field part-entry>id /c field part-entry>end-head /c field part-entry>end-sect /c field part-entry>end-cyl /l field part-entry>sector-offset /l field part-entry>sector-count CONSTANT /partition-entry STRUCT 8 field gpt>signature 4 field gpt>revision 4 field gpt>header-size 4 field gpt>header-crc32 4 field gpt>reserved 8 field gpt>current-lba 8 field gpt>backup-lba 8 field gpt>first-lba 8 field gpt>last-lba 10 field gpt>disk-guid 8 field gpt>part-entry-lba 4 field gpt>num-part-entry 4 field gpt>part-entry-size 4 field gpt>part-array-crc32 1a4 field gpt>reserved CONSTANT /gpt-header STRUCT 10 field gpt-part-entry>part-type-guid 10 field gpt-part-entry>part-guid 8 field gpt-part-entry>first-lba 8 field gpt-part-entry>last-lba 8 field gpt-part-entry>attribute 48 field gpt-part-entry>part-name CONSTANT /gpt-part-entry : offset ( d.rel -- d.abs ) part-offset xlsplit d+ ; : seek ( pos.lo pos.hi -- status ) offset debug-disk-label? IF 2dup ." seek-parent: pos.hi=0x" u. ." pos.lo=0x" u. THEN s" seek" $call-parent debug-disk-label? IF dup ." status=" . cr THEN ; : read ( addr len -- actual ) debug-disk-label? IF 2dup swap ." read-parent: addr=0x" u. ." len=" .d THEN s" read" $call-parent debug-disk-label? IF dup ." actual=" .d cr THEN ; : read-sector ( sector-number -- ) block-size * 0 seek drop \ seek to sector block block-size read drop \ read sector ; : (.part-entry) ( part-entry ) cr ." part-entry>active: " dup part-entry>active c@ .d cr ." part-entry>start-head: " dup part-entry>start-head c@ .d cr ." part-entry>start-sect: " dup part-entry>start-sect c@ .d cr ." part-entry>start-cyl: " dup part-entry>start-cyl c@ .d cr ." part-entry>id: " dup part-entry>id c@ .d cr ." part-entry>end-head: " dup part-entry>end-head c@ .d cr ." part-entry>end-sect: " dup part-entry>end-sect c@ .d cr ." part-entry>end-cyl: " dup part-entry>end-cyl c@ .d cr ." part-entry>sector-offset: " dup part-entry>sector-offset l@-le .d cr ." part-entry>sector-count: " dup part-entry>sector-count l@-le .d cr ; : (.name) r@ begin cell - dup @ = UNTIL xt>name cr type space ; : init-block ( -- ) s" block-size" ['] $call-parent CATCH IF ABORT" parent has no block-size." THEN to block-size block-array-size alloc-mem dup block-array-size erase to block debug-disk-label? IF ." init-block: block-size=" block-size .d ." block=0x" block u. cr THEN ; : partition>part-entry ( partition -- part-entry ) 1- /partition-entry * block mbr>partition-table + ; : partition>start-sector ( partition -- sector-offset ) partition>part-entry part-entry>sector-offset l@-le ; : no-mbr? ( -- true|false ) 0 read-sector 1 partition>part-entry part-entry>id c@ ee = IF TRUE EXIT THEN \ GPT partition found block mbr>magic w@-le aa55 <> ; : no-gpt? ( -- true|false ) 0 read-sector 1 partition>part-entry part-entry>id c@ ee <> IF true EXIT THEN block mbr>magic w@-le aa55 <> ; : pc-extended-partition? ( part-entry-addr -- true|false ) part-entry>id c@ ( id ) dup 5 = swap ( true|false id ) dup f = swap ( true|false true|false id ) 85 = ( true|false true|false true|false ) or or ( true|false ) ; : count-dos-logical-partitions ( -- #logical-partitions ) no-mbr? IF 0 EXIT THEN 0 5 1 DO ( current ) i partition>part-entry ( current part-entry ) dup pc-extended-partition? IF part-entry>sector-offset l@-le ( current sector ) dup to part-start to lpart-start ( current ) BEGIN part-start read-sector \ read EBR 1 partition>start-sector IF 1+ THEN \ another logical partition 2 partition>start-sector ?dup IF lpart-start + to part-start false ELSE true THEN UNTIL ELSE drop THEN LOOP ; : (get-dos-partition-params) ( ext-part-start part-entry -- offset count active? id ) dup part-entry>sector-offset l@-le rot + swap ( offset part-entry ) dup part-entry>sector-count l@-le swap ( offset count part-entry ) dup part-entry>active c@ 80 = swap ( offset count active? part-entry ) part-entry>id c@ ( offset count active? id ) ; : find-dos-partition ( partition# -- false | offset count active? id true ) to partition 0 to part-start 0 to part-offset partition 0<= IF 0 to partition false EXIT THEN no-mbr? IF 0 to partition false EXIT THEN partition 4 <= IF \ Is this a primary partition? 0 partition partition>part-entry (get-dos-partition-params) true EXIT ELSE partition 4 - 0 5 1 DO ( logical-partition current ) i partition>part-entry ( log-part current part-entry ) dup pc-extended-partition? IF part-entry>sector-offset l@-le ( log-part current sector ) dup to part-start to lpart-start ( log-part current ) BEGIN part-start read-sector \ read EBR 1 partition>start-sector IF \ first partition entry 1+ 2dup = IF ( log-part current ) 2drop part-start 1 partition>part-entry (get-dos-partition-params) true UNLOOP EXIT THEN 2 partition>start-sector ?dup IF lpart-start + to part-start false ELSE true THEN ELSE true THEN UNTIL ELSE drop THEN LOOP 2drop false THEN ; : try-dos-partition ( -- okay? ) no-mbr? IF debug-disk-label? IF cr ." No DOS disk-label found." cr THEN false EXIT THEN count-dos-logical-partitions TO dos-logical-partitions debug-disk-label? IF ." Found " dos-logical-partitions .d ." logical partitions" cr ." Partition = " partition .d cr THEN partition 1 5 dos-logical-partitions + within 0= IF cr ." Partition # not 1-" 4 dos-logical-partitions + . cr false EXIT THEN partition find-dos-partition IF 2drop to part-size block-size * to part-offset true ELSE false THEN ; : has-iso9660-filesystem ( -- TRUE|FALSE ) 10 800 * 0 seek drop \ seek to sector block 800 read drop \ read sector block c@ 1 = block 1+ 5 s" CD001" str= and dup IF 800 to block-size THEN ; : fat-bootblock? ( addr -- flag ) dup c@ e9 = IF drop true EXIT THEN dup c@ eb = swap 2+ c@ 90 = and ; : load-from-dos-boot-partition ( addr -- size ) no-mbr? IF drop FALSE EXIT THEN \ read MBR and check for DOS disk-label magic count-dos-logical-partitions TO dos-logical-partitions debug-disk-label? IF ." Found " dos-logical-partitions .d ." logical partitions" cr ." Partition = " partition .d cr THEN 5 dos-logical-partitions + 1 DO i find-dos-partition IF ( addr offset count active? id ) 41 = and ( addr offset count prep-boot-part? ) IF ( addr offset count ) max-prep-partition-blocks min \ reduce load size swap ( addr count offset ) block-size * to part-offset 0 0 seek drop ( addr offset ) block-size * read ( size ) UNLOOP EXIT ELSE 2drop ( addr ) THEN THEN LOOP drop 0 ; 9E1A2D38 CONSTANT GPT-PREP-PARTITION-1 C612 CONSTANT GPT-PREP-PARTITION-2 4316 CONSTANT GPT-PREP-PARTITION-3 AA268B49521E5A8B CONSTANT GPT-PREP-PARTITION-4 : gpt-prep-partition? ( -- true|false ) block gpt-part-entry>part-type-guid dup l@-le GPT-PREP-PARTITION-1 <> IF drop false EXIT THEN dup 4 + w@-le GPT-PREP-PARTITION-2 <> IF drop false EXIT THEN dup 6 + w@-le GPT-PREP-PARTITION-3 <> IF drop false EXIT THEN 8 + x@ GPT-PREP-PARTITION-4 = ; EBD0A0A2 CONSTANT GPT-BASIC-DATA-PARTITION-1 B9E5 CONSTANT GPT-BASIC-DATA-PARTITION-2 4433 CONSTANT GPT-BASIC-DATA-PARTITION-3 87C068B6B72699C7 CONSTANT GPT-BASIC-DATA-PARTITION-4 : gpt-basic-data-partition? ( -- true|false ) block gpt-part-entry>part-type-guid dup l@-le GPT-BASIC-DATA-PARTITION-1 <> IF drop false EXIT THEN dup 4 + w@-le GPT-BASIC-DATA-PARTITION-2 <> IF drop false EXIT THEN dup 6 + w@-le GPT-BASIC-DATA-PARTITION-3 <> IF drop false EXIT THEN 8 + x@ GPT-BASIC-DATA-PARTITION-4 = ; 4546492050415254 CONSTANT GPT-SIGNATURE : get-gpt-partition ( -- true|false ) no-gpt? IF false EXIT THEN debug-disk-label? IF cr ." GPT partition found " cr THEN 1 read-sector block gpt>part-entry-lba x@-le block-size * to seek-pos block gpt>part-entry-size l@-le to gpt-part-size gpt-part-size block-array-size > IF cr ." GPT part size exceeds buffer allocated " cr false exit THEN block gpt>signature x@ GPT-SIGNATURE = ; : load-from-gpt-prep-partition ( addr -- size ) get-gpt-partition 0= IF false EXIT THEN block gpt>num-part-entry l@-le dup 0= IF false exit THEN 1+ 1 ?DO seek-pos 0 seek drop block gpt-part-size read drop gpt-prep-partition? IF debug-disk-label? IF ." GPT PReP partition found " cr THEN block gpt-part-entry>first-lba x@-le ( addr first-lba ) block gpt-part-entry>last-lba x@-le ( addr first-lba last-lba) over - 1+ ( addr first-lba blocks ) swap ( addr blocks first-lba ) block-size * to part-offset ( addr blocks ) 0 0 seek drop ( addr blocks ) block-size * read ( size ) UNLOOP EXIT THEN seek-pos gpt-part-size + to seek-pos LOOP false ; : try-gpt-dos-partition ( -- true|false ) get-gpt-partition 0= IF false EXIT THEN block gpt>num-part-entry l@-le dup 0= IF false EXIT THEN 1+ 1 ?DO seek-pos 0 seek drop block gpt-part-size read drop gpt-basic-data-partition? IF debug-disk-label? IF ." GPT BASIC DATA partition found " cr THEN block gpt-part-entry>first-lba x@-le ( first-lba ) dup to part-start ( first-lba ) block gpt-part-entry>last-lba x@-le ( first-lba last-lba ) over - 1+ ( first-lba s1 ) block-size * to part-size ( first-lba ) block-size * to part-offset ( ) 0 0 seek drop block block-size read drop block fat-bootblock? ( true|false ) UNLOOP EXIT THEN seek-pos gpt-part-size + to seek-pos LOOP false ; : parse-bootinfo-txt ( addr len -- str len ) 2dup s" " find-substr ( addr len pos1 ) 2dup = IF 3drop 0 0 EXIT THEN dup >r - swap r> + swap ( addr1 len1 ) 2dup s" &device;:" find-substr ( addr1 len1 posdev ) 2dup = IF 3drop 0 0 EXIT THEN 9 + \ Skip the "&device;:" string dup >r - swap r> + swap ( addr2 len2 ) 2dup s" " find-substr nip ( addr2 len3 ) debug-disk-label? IF ." Extracted boot loader from bootinfo.txt: '" 2dup type ." '" cr THEN ; : load-chrp-boot-file ( addr -- size ) my-parent instance>path disk-chrp-boot @ 1 = IF s" :1,\ppc\bootinfo.txt" $cat strdup ( addr str len ) ELSE s" :\ppc\bootinfo.txt" $cat strdup ( addr str len ) THEN open-dev dup 0= IF 2drop 0 EXIT THEN >r dup ( addr addr R:ihandle ) dup s" load" r@ $call-method ( addr addr size R:ihandle ) r> close-dev ( addr addr size ) parse-bootinfo-txt ( addr fnstr fnlen ) dup 0= IF 3drop 0 EXIT THEN 2dup 20 findchar IF >r 2dup r@ - 1- swap r@ + 1+ swap ( addr fnstr fnlen pstr plen R: offset ) encode-string s" bootargs" set-chosen drop r> THEN my-parent instance>path ( addr fnstr fnlen nstr nlen ) s" :" $cat 2swap $cat strdup ( addr str len ) 2dup encode-string s" bootpath" set-chosen open-dev dup 0= IF ." failed to load CHRP boot loader." 2drop 0 EXIT THEN >r s" load" r@ $call-method ( size R:ihandle ) r> close-dev ( size ) ; : load-from-boot-partition ( addr -- size ) debug-disk-label? IF ." Trying DOS boot " .s cr THEN dup load-from-dos-boot-partition ?dup 0 <> IF nip EXIT THEN debug-disk-label? IF ." Trying CHRP boot " .s cr THEN 1 disk-chrp-boot ! dup load-chrp-boot-file ?dup 0 <> IF nip EXIT THEN 0 disk-chrp-boot ! debug-disk-label? IF ." Trying GPT boot " .s cr THEN load-from-gpt-prep-partition ; : parse-partition ( -- okay? ) 0 to partition 0 to part-offset 0 to part-size my-args to args-len to args debug-disk-label? IF cr ." disk-label parse-partition: my-args=" my-args type cr THEN args-len 0 = IF true EXIT THEN my-args [char] , findchar 0= IF \ no comma? args c@ isdigit not IF \ ... and not a partition number? true EXIT \ ... then it's not a partition we can parse THEN ELSE drop THEN my-args [char] , split to args-len to args dup 0= IF 2drop true EXIT THEN \ no first argument base @ >r decimal $number r> base ! IF cr ." Not a partition #" false EXIT THEN to partition true ; : (interpose-filesystem) ( str len -- ) find-package IF args args-len rot interpose THEN ; : try-dos-files ( -- found? ) no-mbr? IF false EXIT THEN block fat-bootblock? 0= IF false EXIT THEN s" fat-files" (interpose-filesystem) true ; : try-ext2-files ( -- found? ) 2 read-sector \ read first superblock block d# 56 + w@-le \ fetch s_magic ef53 <> IF false EXIT THEN \ s_magic found? s" ext2-files" (interpose-filesystem) true ; : try-iso9660-files has-iso9660-filesystem 0= IF false exit THEN s" iso-9660" (interpose-filesystem) true ; : try-files ( -- found? ) args-len 0= IF true EXIT THEN try-dos-files IF true EXIT THEN try-ext2-files IF true EXIT THEN try-iso9660-files IF true EXIT THEN false ; : try-partitions ( -- found? ) try-dos-partition IF try-files EXIT THEN try-gpt-dos-partition IF try-files EXIT THEN false ; : close ( -- ) debug-disk-label? IF ." Closing disk-label: block=0x" block u. ." block-size=" block-size .d cr THEN block block-array-size free-mem ; : open ( -- true|false ) init-block parse-partition 0= IF close false EXIT THEN partition IF try-partitions ELSE try-files THEN dup 0= IF debug-disk-label? IF ." not found." cr THEN close THEN \ free memory again ; : load ( addr -- size ) debug-disk-label? IF ." load: " dup u. cr THEN args-len IF TRUE ABORT" Load done w/o filesystem" ELSE partition IF 0 0 seek drop part-size IF part-size max-prep-partition-blocks min \ Load size ELSE max-prep-partition-blocks THEN 200 * read ELSE has-iso9660-filesystem IF dup load-chrp-boot-file ?dup 0 > IF nip EXIT THEN THEN load-from-boot-partition dup 0= ABORT" No boot partition found" THEN THEN ; finish-device new-device s" fat-files" device-name INSTANCE VARIABLE bytes/sector INSTANCE VARIABLE sectors/cluster INSTANCE VARIABLE #reserved-sectors INSTANCE VARIABLE #fats INSTANCE VARIABLE #root-entries INSTANCE VARIABLE total-#sectors INSTANCE VARIABLE media-descriptor INSTANCE VARIABLE sectors/fat INSTANCE VARIABLE sectors/track INSTANCE VARIABLE #heads INSTANCE VARIABLE #hidden-sectors INSTANCE VARIABLE fat-type INSTANCE VARIABLE bytes/cluster INSTANCE VARIABLE fat-offset INSTANCE VARIABLE root-offset INSTANCE VARIABLE cluster-offset INSTANCE VARIABLE #clusters : seek s" seek" $call-parent ; : read s" read" $call-parent ; INSTANCE VARIABLE data INSTANCE VARIABLE #data : free-data data @ ?dup IF #data @ free-mem 0 data ! THEN ; : read-data ( offset size -- ) free-data dup #data ! alloc-mem data ! xlsplit seek -2 and ABORT" fat-files read-data: seek failed" data @ #data @ read #data @ <> ABORT" fat-files read-data: read failed" ; CREATE fat-buf 8 allot : read-fat ( cluster# -- data ) fat-buf 8 erase 1 #split fat-type @ * 2/ 2/ fat-offset @ + xlsplit seek -2 and ABORT" fat-files read-fat: seek failed" fat-buf 8 read 8 <> ABORT" fat-files read-fat: read failed" fat-buf 8c@ bxjoin fat-type @ dup >r 2* #split drop r> #split rot IF swap THEN drop ; INSTANCE VARIABLE next-cluster : read-cluster ( cluster# -- ) dup bytes/cluster @ * cluster-offset @ + bytes/cluster @ read-data read-fat dup #clusters @ >= IF drop 0 THEN next-cluster ! ; : read-dir ( cluster# -- ) ?dup 0= IF root-offset @ #root-entries @ 20 * read-data 0 next-cluster ! ELSE read-cluster THEN ; : .time ( x -- ) base @ >r decimal b #split 2 0.r [char] : emit 5 #split 2 0.r [char] : emit 2* 2 0.r r> base ! ; : .date ( x -- ) base @ >r decimal 9 #split 7bc + 4 0.r [char] - emit 5 #split 2 0.r [char] - emit 2 0.r r> base ! ; : .attr ( attr -- ) 6 0 DO dup 1 and IF s" RHSLDA" drop i + c@ ELSE bl THEN emit u2/ LOOP drop ; : .dir-entry ( adr -- ) dup 0b + c@ 8 and IF drop EXIT THEN \ volume label, not a file dup c@ e5 = IF drop EXIT THEN \ deleted file cr dup 1a + 2c@ bwjoin [char] # emit 4 0.r space \ starting cluster dup 18 + 2c@ bwjoin .date space dup 16 + 2c@ bwjoin .time space dup 1c + 4c@ bljoin base @ decimal swap a .r base ! space \ size in bytes dup 0b + c@ .attr space dup 8 BEGIN 2dup 1- + c@ 20 = over and WHILE 1- REPEAT type dup 8 + 3 BEGIN 2dup 1- + c@ 20 = over and WHILE 1- REPEAT dup IF [char] . emit type ELSE 2drop THEN drop ; : .dir-entries ( adr n -- ) 0 ?DO dup i 20 * + dup c@ 0= IF drop LEAVE THEN .dir-entry LOOP drop ; : .dir ( cluster# -- ) read-dir BEGIN data @ #data @ 20 / .dir-entries next-cluster @ WHILE next-cluster @ read-cluster REPEAT ; : str-upper ( str len adr -- ) \ Copy string to adr, uppercase -rot bounds ?DO i c@ upc over c! char+ LOOP drop ; CREATE dos-name b allot : make-dos-name ( str len -- ) dos-name b bl fill 2dup [char] . findchar IF 3dup 1+ /string 3 min dos-name 8 + str-upper nip THEN 8 min dos-name str-upper ; : (find-file) ( -- cluster file-len is-dir? true | false ) data @ BEGIN dup data @ #data @ + < WHILE dup dos-name b comp WHILE 20 + REPEAT dup 1a + 2c@ bwjoin swap dup 1c + 4c@ bljoin swap 0b + c@ 10 and 0<> true ELSE drop false THEN ; : find-file ( dir-cluster name len -- cluster file-len is-dir? true | false ) make-dos-name read-dir BEGIN (find-file) 0= WHILE next-cluster @ WHILE next-cluster @ read-cluster REPEAT false ELSE true THEN ; : find-path ( dir-cluster name len -- cluster file-len true | false ) dup 0= IF 3drop false ." empty name " EXIT THEN over c@ [char] \ = IF 1 /string RECURSE EXIT THEN [char] \ split 2>r find-file 0= IF 2r> 2drop false ." not found " EXIT THEN r@ 0<> <> IF 2drop 2r> 2drop false ." no dir<->file match " EXIT THEN r@ 0<> IF drop 2r> RECURSE EXIT THEN 2r> 2drop true ; : do-super ( -- ) 0 200 read-data data @ 0b + 2c@ bwjoin bytes/sector ! data @ 0d + c@ sectors/cluster ! bytes/sector @ sectors/cluster @ * bytes/cluster ! data @ 0e + 2c@ bwjoin #reserved-sectors ! data @ 10 + c@ #fats ! data @ 11 + 2c@ bwjoin #root-entries ! data @ 13 + 2c@ bwjoin total-#sectors ! data @ 15 + c@ media-descriptor ! data @ 16 + 2c@ bwjoin sectors/fat ! data @ 18 + 2c@ bwjoin sectors/track ! data @ 1a + 2c@ bwjoin #heads ! data @ 1c + 2c@ bwjoin #hidden-sectors ! total-#sectors @ 0= IF data @ 20 + 4c@ bljoin total-#sectors ! THEN sectors/fat @ 0= IF data @ 24 + 4c@ bljoin sectors/fat ! THEN total-#sectors @ #reserved-sectors @ - sectors/fat @ #fats @ * - #root-entries @ 20 * bytes/sector @ // - sectors/cluster @ / dup #clusters ! dup ff5 < IF drop c ELSE fff5 < IF 10 ELSE 20 THEN THEN fat-type ! base @ decimal base ! #reserved-sectors @ bytes/sector @ * fat-offset ! #fats @ sectors/fat @ * bytes/sector @ * fat-offset @ + root-offset ! #root-entries @ 20 * bytes/sector @ tuck // * root-offset @ + bytes/cluster @ 2* - cluster-offset ! ; INSTANCE VARIABLE file-cluster INSTANCE VARIABLE file-len INSTANCE VARIABLE current-pos INSTANCE VARIABLE pos-in-data : seek ( lo hi -- status ) lxjoin dup current-pos ! file-cluster @ read-cluster BEGIN dup #data @ >= WHILE #data @ - next-cluster @ dup 0= IF 2drop true EXIT THEN read-cluster REPEAT pos-in-data ! false ; : read ( adr len -- actual ) file-len @ current-pos @ - min \ can't go past end of file #data @ pos-in-data @ - min >r \ length for this transfer data @ pos-in-data @ + swap r@ move \ move the data r@ pos-in-data +! r@ current-pos +! pos-in-data @ #data @ = IF next-cluster @ ?dup IF read-cluster 0 pos-in-data ! THEN THEN r> ; : read ( adr len -- actual ) file-len @ min \ len cannot be greater than file size dup >r BEGIN dup WHILE 2dup read dup 0= ABORT" fat-files: read failed" /string ( tuck - >r + r> ) REPEAT 2drop r> ; : load ( adr -- len ) file-len @ read dup file-len @ <> ABORT" fat-files: failed loading file" ; : close free-data ; : open do-super 0 my-args find-path 0= IF close false EXIT THEN file-len ! file-cluster ! 0 0 seek 0= ; finish-device new-device s" rom-files" device-name INSTANCE VARIABLE length INSTANCE VARIABLE next-file INSTANCE VARIABLE buffer INSTANCE VARIABLE buffer-size INSTANCE VARIABLE file INSTANCE VARIABLE file-size INSTANCE VARIABLE found : open true 100 dup buffer-size ! alloc-mem buffer ! false found ! ; : close buffer @ buffer-size @ free-mem ; : read ( addr len -- actual ) s" read" $call-parent ; : seek ( lo hi -- status ) s" seek" $call-parent ; : .read-file-name ( offset -- str len ) 0 seek drop buffer @ buffer-size @ read drop buffer-size @ 1 - buffer @ + 0 swap c! buffer @ zcount ; : .print-info ( offset -- ) dup 2 spaces 6 0.r 2 spaces dup 8 + 0 seek drop length 8 read drop 6 length @ swap 0.r 2 spaces 20 + .read-file-name type cr ; : .list-header cr s" --offset---size-----file-name----" type cr ; : list .list-header 0 0 BEGIN + dup .print-info dup 0 seek drop next-file 8 read drop next-file @ dup 0= UNTIL 2drop ; : (find-file) ( name len -- offset | -1 ) 0 0 seek drop false found ! file-size ! file ! 0 0 BEGIN + dup 20 + .read-file-name file @ file-size @ str= IF true found ! THEN dup 0 seek drop next-file 8 read drop next-file @ dup 0= found @ or UNTIL drop found @ 0= IF drop -1 THEN ; : load ( addr -- size ) my-parent instance>args 2@ [char] \ left-parse-string 2drop (find-file) dup -1 = IF 2drop 0 ELSE 0 0 seek drop dup 8 + 0 seek drop here 8 read drop here @ ( dest-addr offset file-size ) over 18 + 0 seek drop here 8 read drop here @ ( dest-addr offset file-size data-offset ) rot + 0 seek drop ( dest-addr file-size ) read THEN ; finish-device new-device s" ext2-files" device-name INSTANCE VARIABLE first-block INSTANCE VARIABLE inode-size INSTANCE VARIABLE block-size INSTANCE VARIABLE inodes/group INSTANCE VARIABLE group-desc-size INSTANCE VARIABLE group-descriptors : seek s" seek" $call-parent ; : read s" read" $call-parent ; INSTANCE VARIABLE data INSTANCE VARIABLE #data INSTANCE VARIABLE indirect-block INSTANCE VARIABLE dindirect-block : free-data data @ ?dup IF #data @ free-mem 0 data ! THEN ; : read-data ( offset size -- ) free-data dup #data ! alloc-mem data ! xlsplit seek -2 and ABORT" ext2-files read-data: seek failed" data @ #data @ read #data @ <> ABORT" ext2-files read-data: read failed" ; : read-block ( block# -- ) block-size @ * block-size @ read-data ; INSTANCE VARIABLE inode INSTANCE VARIABLE file-len INSTANCE VARIABLE blocks INSTANCE VARIABLE #blocks INSTANCE VARIABLE ^blocks INSTANCE VARIABLE #blocks-left : blocks-read ( n -- ) dup negate #blocks-left +! 4 * ^blocks +! ; : read-indirect-blocks ( indirect-block# -- ) read-block data @ data off dup #blocks-left @ 4 * block-size @ min dup >r ^blocks @ swap move r> 2 rshift blocks-read block-size @ free-mem ; : read-double-indirect-blocks ( double-indirect-block# -- ) read-block data @ indirect-block ! data off BEGIN indirect-block @ l@-le dup 0 <> WHILE read-indirect-blocks 4 indirect-block +! \ point to next indirect block REPEAT drop \ drop 0, the invalid block number ; : read-triple-indirect-blocks ( triple-indirect-block# -- ) read-block data @ dindirect-block ! data off BEGIN dindirect-block @ l@-le dup 0 <> WHILE read-double-indirect-blocks 4 dindirect-block +! \ point to next double indirect block REPEAT drop \ drop 0, the invalid block number ; : read-block#s ( -- ) blocks @ ?dup IF #blocks @ 4 * free-mem THEN inode @ 4 + l@-le file-len ! file-len @ block-size @ // #blocks ! #blocks @ 4 * alloc-mem blocks ! blocks @ ^blocks ! #blocks @ #blocks-left ! #blocks-left @ c min \ # direct blocks inode @ 28 + over 4 * ^blocks @ swap move blocks-read #blocks-left @ IF inode @ 58 + l@-le read-indirect-blocks THEN #blocks-left @ IF inode @ 5c + l@-le read-double-indirect-blocks THEN #blocks-left @ IF inode @ 60 + l@-le read-triple-indirect-blocks THEN ; : read-inode ( inode# -- ) 1- inodes/group @ u/mod \ # in group, group # 20 * group-descriptors @ + 8 + l@-le block-size @ * \ # in group, inode table swap inode-size @ * + xlsplit seek drop inode @ inode-size @ read drop ; : .rwx ( bits last-char-if-special special? -- ) rot dup 4 and IF ." r" ELSE ." -" THEN dup 2 and IF ." w" ELSE ." -" THEN swap IF 1 and 0= IF upc THEN emit ELSE 1 and IF ." x" ELSE ." -" THEN drop THEN ; CREATE mode-chars 10 allot s" ?pc?d?b?-?l?s???" mode-chars swap move : .mode ( mode -- ) dup c rshift f and mode-chars + c@ emit dup 6 rshift 7 and over 800 and 73 swap .rwx dup 3 rshift 7 and over 400 and 73 swap .rwx dup 7 and swap 200 and 74 swap .rwx ; : .inode ( -- ) base @ >r decimal inode @ w@-le .mode \ file mode inode @ 1a + w@-le 5 .r \ link count inode @ 02 + w@-le 9 .r \ uid inode @ 18 + w@-le 9 .r \ gid inode @ 04 + l@-le 9 .r \ size r> base ! ; : do-super ( -- ) 400 400 read-data data @ 14 + l@-le first-block ! 400 data @ 18 + l@-le lshift block-size ! data @ 28 + l@-le inodes/group ! data @ 4c + l@-le 0= IF 80 inode-size ! ELSE data @ 58 + w@-le inode-size ! THEN data @ 20 + l@-le group-desc-size ! first-block @ 1+ block-size @ * group-desc-size @ read-data data @ group-descriptors ! data off ; INSTANCE VARIABLE current-pos : read ( adr len -- actual ) file-len @ current-pos @ - min \ can't go past end of file current-pos @ block-size @ u/mod 4 * blocks @ + l@-le read-block block-size @ over - rot min >r ( adr off r: len ) data @ + swap r@ move r> dup current-pos +! ; : read ( adr len -- actual ) dup >r BEGIN dup WHILE 2dup read dup 0= ABORT" ext2-files: read failed" /string REPEAT 2drop r> ; : seek ( lo hi -- status ) lxjoin dup file-len @ > IF drop true EXIT THEN current-pos ! false ; : load ( adr -- len ) file-len @ read dup file-len @ <> ABORT" ext2-files: failed loading file" ; : .name ( adr -- ) dup 8 + swap 6 + c@ type ; : read-dir ( inode# -- adr ) read-inode read-block#s file-len @ alloc-mem 0 0 seek ABORT" ext2-files read-dir: seek failed" dup file-len @ read file-len @ <> ABORT" ext2-files read-dir: read failed" ; : .dir ( inode# -- ) read-dir dup BEGIN 2dup file-len @ - > over l@-le tuck and WHILE cr dup 8 0.r space read-inode .inode space space dup .name dup 4 + w@-le + REPEAT 2drop file-len @ free-mem ; : (find-file) ( adr name len -- inode#|0 ) 2>r dup BEGIN 2dup file-len @ - > over l@-le and WHILE dup 8 + over 6 + c@ 2r@ str= IF 2r> 2drop nip l@-le EXIT THEN dup 4 + w@-le + REPEAT 2drop 2r> 2drop 0 ; : find-file ( inode# name len -- inode#|0 ) 2>r read-dir dup 2r> (find-file) swap file-len @ free-mem ; : find-path ( inode# name len -- inode#|0 ) dup 0= IF 3drop 0 ." empty name " EXIT THEN over c@ [char] \ = IF 1 /string ." slash " RECURSE EXIT THEN [char] \ split 2>r find-file ?dup 0= IF 2r> 2drop false ." not found " EXIT THEN r@ 0<> IF 2r> ." more... " RECURSE EXIT THEN 2r> 2drop ." got it " ; : close inode @ inode-size @ free-mem group-descriptors @ group-desc-size @ free-mem free-data blocks @ ?dup IF #blocks @ 4 * free-mem THEN ; : open 0 data ! 0 blocks ! 0 #blocks ! do-super inode-size @ alloc-mem inode ! my-args nip 0= IF 0 0 ELSE 2 my-args find-path ?dup 0= IF close false EXIT THEN THEN read-inode read-block#s 0 0 seek 0= ; finish-device new-device s" obp-tftp" device-name INSTANCE VARIABLE ciregs-buffer : open ( -- okay? ) ciregs-size alloc-mem ciregs-buffer ! true ; : load ( addr -- size ) ciregs ciregs-buffer @ ciregs-size move s" bootargs" get-chosen 0= IF 0 0 THEN >r >r s" bootpath" get-chosen 0= IF 0 0 THEN >r >r my-parent ihandle>phandle node>path encode-string s" bootpath" set-chosen (u.) s" netboot " 2swap $cat s" 60000000 " $cat 6B8 alloc-mem dup >r (u.) $cat s" " $cat huge-tftp-load @ IF s" 1 " ELSE s" 0 " THEN $cat s" 1432 " $cat my-args $cat (client-exec) dup 0< IF drop 0 THEN ciregs-buffer @ ciregs ciregs-size move r> r> r> over IF s" bootpath" set-chosen ELSE 2drop THEN r> r> over IF s" bootargs" set-chosen ELSE 2drop THEN dup 6B8 encode-bytes s" bootp-response" s" /chosen" find-node set-property 6B8 free-mem ; : close ( -- ) ciregs-buffer @ ciregs-size free-mem ; : ping ( -- ) s" ping " my-args $cat (client-exec) ; finish-device new-device s" iso-9660" device-name 0 VALUE iso-debug-flag : iso-debug-print ( str len -- ) iso-debug-flag IF type cr ELSE 2drop THEN ; 0 VALUE path-tbl-size 0 VALUE path-tbl-addr 0 VALUE root-dir-size 0 VALUE vol-size 0 VALUE logical-blk-size 0 VALUE path-table 0 VALUE count INSTANCE VARIABLE dir-addr INSTANCE VARIABLE data-buff INSTANCE VARIABLE #data INSTANCE VARIABLE ptable INSTANCE VARIABLE file-loc INSTANCE VARIABLE file-size INSTANCE VARIABLE cur-file-offset INSTANCE VARIABLE self INSTANCE VARIABLE index : seek ( pos.lo pos.hi -- status ) s" seek" $call-parent ; : read ( addr len -- actual ) s" read" $call-parent ; : free-data ( -- ) data-buff @ ( data-buff ) ?DUP IF #data @ free-mem 0 data-buff ! 0 #data ! THEN ; : read-data ( offset size -- ) dup #data @ > IF free-data dup dup ( offset size size size ) #data ! alloc-mem data-buff ! ( offset size ) THEN swap xlsplit ( size pos.lo pos.hi ) seek -2 and ABORT" seek failed." data-buff @ over read ( size actual ) <> ABORT" read failed." ; : extract-vol-info ( -- ) 10 800 * 800 read-data data-buff @ 88 + l@-be to path-tbl-size \ read path table size data-buff @ 94 + l@-be to path-tbl-addr \ read big-endian path table data-buff @ a2 + l@-be dir-addr ! \ gather of root directory info data-buff @ 0aa + l@-be to root-dir-size \ get volume info data-buff @ 54 + l@-be to vol-size \ size in blocks data-buff @ 82 + l@-be to logical-blk-size path-tbl-size alloc-mem dup TO path-table path-tbl-size erase path-tbl-addr 800 * xlsplit seek drop path-table path-tbl-size read drop \ pathtable in-system-memory copy ; : file-name ( str len -- str' len' ) 2dup [char] ; findchar IF nip \ Omit the trailing ";1" revision of ISO9660 file name 2dup + 1- ( str newlen endptr ) c@ [CHAR] . = IF 1- ( str len' ) \ Remove trailing dot THEN THEN ; : dup3 ( num -- num num num ) dup dup dup ; : get-next-record ( rec-addr -- next-rec-offset ) dup3 ( rec-addr rec-addr rec-addr rec-addr ) self @ 1 + self ! ( rec-addr rec-addr rec-addr rec-addr ) c@ 1 AND IF ( rec-addr rec-addr rec-addr ) c@ + 9 ( rec-addr rec-addr' rec-len ) ELSE c@ + 8 ( rec-addr rec-addr' rec-len ) THEN + swap - ( next-rec-offset ) ; : path-table-search ( str len -- TRUE | FALSE ) path-table path-tbl-size + path-table ptable @ + DO ( str len ) 2dup I 6 + w@-be index @ = ( str len str len ) -rot I 8 + I c@ iso-debug-flag IF ." ISO: comparing path name '" 4dup type ." ' with '" type ." '" cr THEN string=ci and IF ( str len ) s" Directory Matched!! " iso-debug-print ( str len ) self @ index ! ( str len ) I 2 + l@-be dir-addr ! I dup ( str len rec-addr ) get-next-record + path-table - ptable ! ( str len ) 2drop TRUE UNLOOP EXIT ( TRUE ) THEN I get-next-record ( str len next-rec-offset ) +LOOP 2drop FALSE ( FALSE ) s" Invalid path / directory " iso-debug-print ; : search-file-dir ( str len -- TRUE | FALSE ) dir-addr @ 800 * dir-addr ! ( str len ) dir-addr @ 100 read-data ( str len ) data-buff @ 0e + l@-be dup >r ( str len rec-len ) 100 > IF ( str len ) s" size dir record" iso-debug-print ( str len ) dir-addr @ r@ read-data ( str len ) THEN r> data-buff @ + data-buff @ DO ( str len ) I 19 + c@ 2 and 0= I c@ 0<> and IF ( str len ) 2dup ( str len str len ) I 21 + I 20 + c@ ( str len str len str' len' ) iso-debug-flag IF ." ISO: comparing file name '" 4dup type ." ' with '" type ." '" cr THEN file-name string=ci IF ( str len ) s" File found!" iso-debug-print ( str len ) I 6 + l@-be 800 * ( str len file-loc ) file-loc ! ( str len ) I 0e + l@-be file-size ! ( str len ) 2drop TRUE ( TRUE ) UNLOOP EXIT THEN THEN I c@ ?dup 0= IF 800 I 7ff AND - iso-debug-flag IF ." skipping " dup . ." bytes at end of sector" cr THEN THEN +LOOP 2drop FALSE ( FALSE ) s" file not found" iso-debug-print ; : search-path ( str len -- FALSE|TRUE ) 0 ptable ! 1 self ! 1 index ! dup ( str len len ) 0= IF 3drop FALSE ( FALSE ) s" Empty path name " iso-debug-print EXIT ( FALSE ) THEN OVER c@ ( str len char ) [char] \ = IF ( str len ) swap 1 + swap 1 - BEGIN ( str len ) [char] \ split ( str len str' len ' ) dup 0 = IF ( str len str' len ' ) 2drop search-file-dir EXIT ( TRUE | FALSE ) ELSE 2swap path-table-search invert IF ( str' len ' ) 2drop FALSE EXIT ( FALSE ) THEN THEN AGAIN ELSE BEGIN [char] \ split dup 0 = IF ( str len str' len' ) 2drop search-file-dir EXIT ( TRUE | FALSE ) ELSE 2swap path-table-search invert IF ( str' len ' ) 2drop FALSE EXIT ( FALSE ) THEN THEN AGAIN THEN ; 0 VALUE loc : load ( addr -- len ) dup to loc ( addr ) file-loc @ xlsplit seek drop file-size @ read ( file-size ) iso-debug-flag IF s" Bytes returned from read:" type dup . cr THEN dup file-size @ <> ABORT" read failed!" ; : close ( -- ) free-data count 1 - dup to count 0 = IF path-table path-tbl-size free-mem 0 TO path-table THEN ; : open ( -- TRUE | FALSE ) 0 data-buff ! 0 #data ! 0 ptable ! 0 file-loc ! 0 file-size ! 0 cur-file-offset ! 1 self ! 1 index ! count 0 = IF s" extract-vol-info called " iso-debug-print extract-vol-info THEN count 1 + to count my-args search-path IF file-loc @ xlsplit seek drop TRUE ( TRUE ) ELSE close FALSE ( FALSE ) THEN 0 cur-file-offset ! s" opened ISO9660 package" iso-debug-print ; : seek ( pos.lo pos.hi -- status ) lxjoin dup cur-file-offset ! ( offset ) file-loc @ + xlsplit ( pos.lo pos.hi ) s" seek" $call-parent ( status ) ; : read ( addr len -- actual ) file-size @ cur-file-offset @ - ( addr len remainder-of-file ) min ( addr len|remainder-of-file ) s" read" $call-parent ( actual ) dup cur-file-offset @ + cur-file-offset ! ( actual ) cur-file-offset @ ( offset actual ) xlsplit seek drop ( actual ) ; finish-device finish-device : open true ; : close ; 20000 VALUE size : ibm,client-architecture-support ( vec -- err? ) size alloc-mem ( vec memaddr ) swap over size ( memaddr vec memaddr size ) hv-cas 0= IF ( memaddr ) dup l@ 1 >= IF \ Version number >= 1 " /" find-node set-node dup 4 + fdt-init fdt-check-header fdt-struct fdt-fix-cas-node fdt-fix-cas-success NOT ELSE FALSE THEN ELSE TRUE THEN >r size free-mem r> ; finish-device 370 cp : check-boot-menu s" qemu,boot-menu" get-chosen IF decode-int 1 = IF ." Press F12 for boot menu." cr cr THEN 2drop THEN ; check-boot-menu 380 cp 371 cp STRUCT /l field rtas>token /l field rtas>nargs /l field rtas>nret /l field rtas>args0 /l field rtas>args1 /l field rtas>args2 /l field rtas>args3 /l field rtas>args4 /l field rtas>args5 /l field rtas>args6 /l field rtas>args7 /l C * field rtas>args /l field rtas>bla CONSTANT /rtas-control-block CREATE rtas-cb /rtas-control-block allot rtas-cb /rtas-control-block erase 0 VALUE rtas-base 0 VALUE rtas-size 0 VALUE rtas-entry 0 VALUE rtas-node 372 cp : find-qemu-rtas ( -- ) " /rtas" find-device get-node to rtas-node " linux,rtas-base" rtas-node get-package-property IF device-end EXIT THEN drop l@ to rtas-base " linux,rtas-base" delete-property " rtas-size" rtas-node get-package-property IF device-end EXIT THEN drop l@ to rtas-size " linux,rtas-entry" rtas-node get-package-property IF rtas-base to rtas-entry ELSE drop l@ to rtas-entry " linux,rtas-entry" delete-property THEN 0 rtas-base dup rtas-size + check-and-patch-sc1 device-end ; find-qemu-rtas 373 cp : enter-rtas ( -- ) rtas-cb rtas-base 0 rtas-entry call-c drop ; : rtas-get-token ( str len -- token | 0 ) rtas-node get-package-property IF 0 ELSE drop l@ THEN ; : rtas-power-off ( x y -- status ) [ s" power-off" rtas-get-token ] LITERAL rtas-cb rtas>token l! 2 rtas-cb rtas>nargs l! 1 rtas-cb rtas>nret l! rtas-cb rtas>args0 l! rtas-cb rtas>args1 l! enter-rtas rtas-cb rtas>args2 l@ ; : power-off ( -- ) 0 0 rtas-power-off ; : rtas-system-reboot ( -- status ) [ s" system-reboot" rtas-get-token ] LITERAL rtas-cb rtas>token l! 0 rtas-cb rtas>nargs l! 1 rtas-cb rtas>nret l! rtas-cb rtas>args0 l! enter-rtas rtas-cb rtas>args1 l@ ; : rtas-start-cpu ( pid loc r3 -- status ) [ s" start-cpu" rtas-get-token ] LITERAL rtas-cb rtas>token l! 3 rtas-cb rtas>nargs l! 1 rtas-cb rtas>nret l! rtas-cb rtas>args2 l! rtas-cb rtas>args1 l! rtas-cb rtas>args0 l! 0 rtas-cb rtas>args3 l! enter-rtas rtas-cb rtas>args3 l@ ; : rtas-set-tce-bypass ( unit enable -- ) " ibm,set-tce-bypass" rtas-get-token rtas-cb rtas>token l! 2 rtas-cb rtas>nargs l! 0 rtas-cb rtas>nret l! rtas-cb rtas>args1 l! rtas-cb rtas>args0 l! enter-rtas ; : rtas-quiesce ( -- ) " quiesce" rtas-get-token rtas-cb rtas>token l! 0 rtas-cb rtas>nargs l! 0 rtas-cb rtas>nret l! enter-rtas ; 0 value puid : rtas-do-config-@ ( config-addr size -- value) " ibm,read-pci-config" rtas-get-token rtas-cb rtas>token l! 4 rtas-cb rtas>nargs l! 2 rtas-cb rtas>nret l! ( addr size ) rtas-cb rtas>args3 l! puid ffffffff and rtas-cb rtas>args2 l! puid 20 rshift rtas-cb rtas>args1 l! ( addr ) rtas-cb rtas>args0 l! enter-rtas rtas-cb rtas>args4 l@ dup IF drop ffffffff ELSE drop rtas-cb rtas>args5 l@ THEN ; : rtas-do-config-! ( value config-addr size ) " ibm,write-pci-config" rtas-get-token rtas-cb rtas>token l! 5 rtas-cb rtas>nargs l! 1 rtas-cb rtas>nret l! ( value addr size ) rtas-cb rtas>args3 l! puid ffffffff and rtas-cb rtas>args2 l! puid 20 rshift rtas-cb rtas>args1 l! ( value addr ) rtas-cb rtas>args0 l! ( value ) rtas-cb rtas>args4 l! enter-rtas rtas-cb rtas>args5 l@ dup IF ." RTAS write config err " . cr ELSE drop THEN ; : rtas-config-b@ ( config-addr -- value ) 1 rtas-do-config-@ ff and ; : rtas-config-b! ( value config-addr -- ) 1 rtas-do-config-! ; : rtas-config-w@ ( config-addr -- value ) 2 rtas-do-config-@ ffff and ; : rtas-config-w! ( value config-addr -- ) 2 rtas-do-config-! ; : rtas-config-l@ ( config-addr -- value ) 4 rtas-do-config-@ ffffffff and ; : rtas-config-l! ( value config-addr -- ) 4 rtas-do-config-! ; : of-start-cpu rtas-start-cpu ; ' power-off to halt ' rtas-system-reboot to reboot rtas-node set-node : open true ; : close ; : instantiate-rtas ( adr -- entry ) dup rtas-base swap rtas-size move dup rtas-entry rtas-base - + 2dup hv-rtas-update dup 0 <> IF dup -2 <> IF ." HV-RTAS-UPDATE error: " . cr ELSE drop THEN ELSE drop THEN nip ; device-end 374 cp 390 cp STRUCT /n FIELD vd>base /l FIELD vd>type CONSTANT /vd-len : virtio-setup-vd ( vdstruct -- ) >r s" class-code" get-node get-property 0= IF 2drop s" 10 config-l@ translate-my-address 3 not AND" evaluate ( io-base ) r@ vd>base ! 0 r@ vd>type l! ELSE ." unsupported virtio interface!" cr 1 r@ vd>type l! THEN r> drop ; 3f0 cp : strequal ( str1 len1 str2 len2 -- flag ) rot dup rot = IF comp 0= ELSE 2drop drop 0 THEN ; 400 cp " /" find-device 480 cp new-device s" mmu" 2dup device-name device-type 0 0 s" translations" property : open true ; : close ; finish-device device-end 4c0 cp : fixup-tbfreq " /cpus/@0" find-device " timebase-frequency" get-node get-package-property IF 2drop ELSE decode-int to tb-frequency 2drop THEN device-end ; fixup-tbfreq 4d0 cp include fbuffer.fs 500 cp : populate-vios ( -- ) ." Populating /vdevice methods" cr " /vdevice" find-device get-node child BEGIN dup 0 <> WHILE dup set-node dup " compatible" rot get-package-property 0 = IF drop dup from-cstring 2dup " hvterm1" strequal IF " vio-hvterm.fs" included THEN 2dup " IBM,v-scsi" strequal IF " vio-vscsi.fs" included THEN 2dup " IBM,l-lan" strequal IF " vio-veth.fs" included THEN 2dup " qemu,spapr-nvram" strequal IF " rtas-nvram.fs" included THEN 2drop THEN peer REPEAT drop device-end ; populate-vios 580 cp 5a0 cp VARIABLE pci-next-mem \ prefetchable memory mapped VARIABLE pci-max-mem VARIABLE pci-next-mmio \ non-prefetchable memory VARIABLE pci-max-mmio VARIABLE pci-next-io \ I/O space VARIABLE pci-max-io VARIABLE pci-next-mem64 \ prefetchable 64-bit memory mapped VARIABLE pci-max-mem64 0 VALUE pci-bus-number 0 VALUE pci-device-number 0 VALUE pci-device-slots here 100 allot CONSTANT pci-device-vec 0 VALUE pci-device-vec-len 0 VALUE pci-hotplug-enabled : next-pci-mem ( addr -- addr ) pci-next-mem ; : next-pci-mmio ( addr -- addr ) pci-next-mmio ; : next-pci-io ( addr -- addr ) pci-next-io ; : int2str ( int len -- str len ) swap s>d rot <# 0 ?DO # LOOP #> ; : pci-addr2bus ( addr -- busnr ) 10 rshift FF and ; : pci-addr2dev ( addr -- dev ) B rshift 1F and ; : pci-addr2fn ( addr -- dev ) 8 rshift 7 and ; : pci-bus2addr ( busnr devnr -- addr ) B lshift swap 10 lshift + ; : pci-addr-out ( addr -- ) dup pci-addr2bus 2 0.r space FFFF and 4 0.r ; : pci-dump ( addr -- ) 10 0 DO dup cr i 4 * + dup pci-addr-out space rtas-config-l@ 8 0.r LOOP drop cr ; : pci-vendor@ ( addr -- id ) rtas-config-l@ FFFF and ; : pci-device@ ( addr -- id ) rtas-config-l@ 10 rshift ; : pci-status@ ( addr -- status ) 4 + rtas-config-l@ 10 rshift ; : pci-revision@ ( addr -- id ) 8 + rtas-config-b@ ; : pci-class@ ( addr -- class ) 8 + rtas-config-l@ 8 rshift ; : pci-cache@ ( addr -- size ) C + rtas-config-b@ ; : pci-htype@ ( addr -- type ) E + rtas-config-b@ ; : pci-sub-vendor@ ( addr -- sub-id ) 2C + rtas-config-l@ FFFF and ; : pci-sub-device@ ( addr -- sub-id ) 2C + rtas-config-l@ 10 rshift FFFF and ; : pci-interrupt@ ( addr -- interrupt ) 3D + rtas-config-b@ ; : pci-min-grant@ ( addr -- min-gnt ) 3E + rtas-config-b@ ; : pci-max-lat@ ( addr -- max-lat ) 3F + rtas-config-b@ ; : pci-capabilities? ( addr -- 0|1 ) pci-status@ 4 rshift 1 and ; : pci-cap-next ( cap-addr -- next-cap-off ) rtas-config-b@ FC and ; : pci-cap-next-addr ( cap-addr -- next-cap-addr ) 1+ dup pci-cap-next dup IF swap -100 and + ELSE nip THEN ; : pci-cap-dump ( addr -- ) cr dup pci-capabilities? IF 33 + BEGIN pci-cap-next-addr dup 0<> WHILE dup pci-addr-out s" : " type dup rtas-config-b@ 2 0.r cr REPEAT s" end found " ELSE s" capabilities not enabled!" THEN type cr drop ; : pci-cap-find ( addr id -- capp-addr|0 ) swap dup pci-capabilities? IF 33 + BEGIN pci-cap-next-addr dup 0<> IF dup rtas-config-b@ 2 pick = ELSE true THEN UNTIL nip ELSE 2drop 0 THEN ; : pci-express? ( addr -- 0|1 ) 10 pci-cap-find 0<> ; : pci-x? ( addr -- 0|1 ) 07 pci-cap-find 0<> ; : pci-config-ext? ( addr -- 0|1 ) pci-express? ; : pci-device-disable ( -- ) my-space 4 + dup rtas-config-l@ 7 invert and swap rtas-config-l! ; : pci-master-enable ( -- ) my-space 4 + dup rtas-config-l@ 4 or swap rtas-config-l! ; : pci-master-disable ( -- ) my-space 4 + dup rtas-config-l@ 4 invert and swap rtas-config-l! ; : pci-mem-enable ( -- ) my-space 4 + dup rtas-config-w@ 2 or swap rtas-config-w! ; : pci-io-enable ( -- ) my-space 4 + dup rtas-config-w@ 1 or swap rtas-config-w! ; : pci-enable ( -- ) my-space 4 + dup rtas-config-w@ 7 or swap rtas-config-w! ; : pci-error-enable ( -- ) my-space 4 + dup rtas-config-w@ 140 or swap rtas-config-w! ; : pci-out ( addr char -- ) 15 spaces over pci-addr-out s" (" type emit s" ) : " type dup pci-vendor@ 4 0.r space pci-device@ 4 0.r 4 spaces ; : pci-irq-line@ ( addr -- irq-pin ) 3C + rtas-config-b@ ; : pci-irq-line! ( pin addr -- ) 3C + rtas-config-b! ; : pci-bus-prim! ( nr addr -- ) 18 + dup rtas-config-l@ FFFFFF00 and rot + swap rtas-config-l! ; : pci-bus-prim@ ( addr -- nr ) 18 + rtas-config-l@ FF and ; : pci-bus-scnd! ( nr addr -- ) 18 + dup rtas-config-l@ FFFF00FF and rot 8 lshift + swap rtas-config-l! ; : pci-bus-scnd@ ( addr -- nr ) 18 + rtas-config-l@ 8 rshift FF and ; : pci-bus-subo! ( nr addr -- ) 18 + dup rtas-config-l@ FF00FFFF and rot 10 lshift + swap rtas-config-l! ; : pci-bus-subo@ ( addr -- nr ) 18 + rtas-config-l@ 10 rshift FF and ; : pci-bus! ( subo scnd prim addr -- ) swap rot 8 lshift + rot 10 lshift + swap 18 + dup rtas-config-l@ FF000000 and rot + swap rtas-config-l! ; : pci-bus@ ( addr -- subo scnd prim ) 18 + rtas-config-l@ dup 10 rshift FF and swap dup 8 rshift FF and swap FF and ; : pci-reset-2nd ( addr -- ) 1C + dup rtas-config-l@ FFFF0000 or swap rtas-config-l! ; : pci-vec ( -- ) cr s" device-vec(" type pci-device-vec-len dup 2 0.r s" ):" type 1+ 0 DO pci-device-vec i + c@ space 2 0.r LOOP cr ; : pci-var-out ( -- ) s" mem:" type pci-next-mem @ 16 0.r cr s" mmio:" type pci-next-mmio @ 16 0.r cr s" io:" type pci-next-io @ 16 0.r cr ; : pci-set-slot ( addr -- ) pci-addr2dev dup \ calc slot number pci-device-vec-len \ the end of the vector pci-device-vec + c! \ and update the vector 80000000 swap rshift \ calc bit position of the device slot pci-device-slots or \ set this bit TO pci-device-slots \ and write it back ; : pci-bridge-set-mmio-base ( addr -- ) pci-next-mmio @ 100000 #aligned \ read the current Value and align to 1MB boundary dup 100000 + pci-next-mmio ! \ and write back with 1MB for bridge 10 rshift \ mmio-base reg is only the upper 16 bits pci-max-mmio @ 1- FFFF0000 and or \ and Insert mmio Limit (set it to max) swap 20 + rtas-config-l! \ and write it into the bridge ; : pci-bridge-set-mmio-limit ( addr -- ) pci-next-mmio @ 100000 #aligned \ fetch current value and align to 1MB dup pci-next-mmio ! \ and write it back 1- FFFF0000 and \ make it one less and keep upper 16 bits over 20 + rtas-config-l@ 0000FFFF and \ fetch original value or swap 20 + rtas-config-l! \ and write it into the Reg ; : pci-bridge-set-mem-base ( addr -- ) pci-next-mem @ 100000 #aligned \ read the current Value and align to 1MB boundary dup 100000 + pci-next-mem ! \ and write back with 1MB for bridge over 24 + rtas-config-w@ \ check if 64bit support 1 and IF \ IF 64 bit support pci-next-mem64 @ 100000000 #aligned \ | read the current Value of 64-bit and align to 4GB boundary dup 100000000 + pci-next-mem64 x! \ | and write back with 1GB for bridge 2 pick swap \ | 20 rshift \ | keep upper 32 bits swap 28 + rtas-config-l! \ | and write it into the Base-Upper32-bits pci-max-mem64 @ 20 rshift \ | fetch max Limit address and keep upper 32 bits 2 pick 2C + rtas-config-l! \ | and set the Limit THEN \ FI 10 rshift \ keep upper 16 bits pci-max-mem @ 1- FFFF0000 and or \ and Insert mmem Limit (set it to max) swap 24 + rtas-config-l! \ and write it into the bridge ; : pci-bridge-set-mem-limit ( addr -- ) pci-next-mem @ 100000 #aligned \ read the current Value and align to 1MB boundary dup pci-next-mem ! \ and write it back 1- \ make limit one less than boundary over 24 + rtas-config-w@ \ check if 64bit support 1 and IF \ IF 64 bit support pci-next-mem64 @ 100000000 #aligned \ | Reat current value of 64-bar and align at 4GB dup pci-next-mem64 x! \ | and write it back 1- \ | make limite one less than boundary 2 pick swap \ | 20 rshift \ | keep upper 32 bits swap 2C + rtas-config-l! \ | and write it into the Limit-Upper32-bits THEN \ FI FFFF0000 and \ keep upper 16 bits over 24 + rtas-config-l@ 0000FFFF and \ fetch original Value or swap 24 + rtas-config-l! \ and write it into the bridge ; : pci-bridge-set-io-base ( addr -- ) pci-next-io @ 1000 #aligned \ read the current Value and align to 4KB boundary dup 1000 + pci-next-io ! \ and write back with 4K for bridge over 1C + rtas-config-l@ \ check if 32bit support 1 and IF \ IF 32 bit support 2dup 10 rshift \ | keep upper 16 bits pci-max-io @ FFFF0000 and or \ | insert upper 16 bits of Max-Limit swap 30 + rtas-config-l! \ | and write it into the Base-Upper16-bits THEN \ FI 8 rshift 000000FF and \ keep upper 8 bits pci-max-io @ 1- 0000FF00 and or \ insert upper 8 bits of Max-Limit over rtas-config-l@ FFFF0000 and \ fetch original Value or swap 1C + rtas-config-l! \ and write it into the bridge ; : pci-bridge-set-io-limit ( addr -- ) pci-next-io @ 1000 #aligned \ read the current Value and align to 4KB boundary dup pci-next-io ! \ and write it back 1- \ make limit one less than boundary over 1D + rtas-config-b@ \ check if 32bit support 1 and IF \ IF 32 bit support 2dup FFFF0000 and \ | keep upper 16 bits over 30 + rtas-config-l@ \ | fetch original Value or swap 30 + rtas-config-l! \ | and write it into the Limit-Upper16-bits THEN \ FI 0000FF00 and \ keep upper 8 bits over 1C + rtas-config-l@ FFFF00FF and \ fetch original Value or swap 1C + rtas-config-l! \ and write it into the bridge ; : pci-bridge-set-bases ( addr -- ) dup pci-bridge-set-mmio-base dup pci-bridge-set-mem-base pci-bridge-set-io-base ; : pci-bridge-set-limits ( addr -- ) dup pci-bridge-set-mmio-limit dup pci-bridge-set-mem-limit pci-bridge-set-io-limit ; DEFER func-pci-probe-bus DEFER func-pci-bridge-range-props : pci-bridge-probe ( addr -- ) dup pci-bridge-set-bases \ SetUp all Base Registers dup func-pci-bridge-range-props \ Setup temporary "range pci-bus-number 1+ TO pci-bus-number \ increase number of busses found pci-device-vec-len 1+ TO pci-device-vec-len \ increase the device-slot vector depth dup \ stack config-addr for pci-bus! FF swap \ Subordinate Bus Number ( for now to max to open all subbusses ) pci-bus-number swap \ Secondary Bus Number ( the new busnumber ) dup pci-addr2bus swap \ Primary Bus Number ( the current bus ) pci-bus! \ and set them into the bridge pci-enable \ enable mem/IO transactions dup pci-bus-scnd@ func-pci-probe-bus \ and probe the secondary bus dup pci-bus-number swap pci-bus-subo! \ set SubOrdinate Bus Number to current number of busses pci-device-vec-len 1- TO pci-device-vec-len \ decrease the device-slot vector depth dup pci-bridge-set-limits \ SetUp all Limit Registers drop \ forget the config-addr ; : pci-device-setup ( addr -- ) drop \ since the config-addr is coded in my-space, drop it here s" pci-device.fs" included \ and setup the device as node in the device tree ; : pci-bridge-setup ( addr -- ) drop \ since the config-addr is coded in my-space, drop it here s" pci-bridge.fs" included \ and setup the bridge as node in the device tree ; : pci-add-device ( addr -- ) new-device \ create a new device-tree node dup set-space \ set the config addr for this device tree entry dup pci-set-slot \ set the slot bit dup pci-htype@ \ read HEADER-Type 7f and \ Mask bit 7 - multifunction device CASE 0 OF pci-device-setup ENDOF \ | set up the device 1 OF pci-bridge-setup ENDOF \ | set up the bridge dup OF dup pci-htype@ pci-out ENDOF ENDCASE finish-device \ and close the device-tree node ; : pci-setup-device ( addr -- ) dup pci-htype@ \ read HEADER-Type 80 and IF 8 ELSE 1 THEN \ check for multifunction 0 DO \ LOOP over all possible functions (either 8 or only 1) dup i 8 lshift + \ calc device-function-config-addr dup pci-vendor@ \ check if valid function FFFF = IF drop \ non-valid so forget the address ELSE pci-device-number 1+ \ increase the number of devices TO pci-device-number \ and store it pci-add-device \ and add the device to the device tree and set it up THEN LOOP \ next function drop \ forget the device-addr ; : pci-probe-device ( busnr devicenr -- ) pci-bus2addr \ calc pci-address dup pci-vendor@ \ fetch Vendor-ID FFFF = IF \ check if valid drop \ if not forget it ELSE pci-setup-device \ if valid setup the device THEN ; : pci-probe-bus ( busnr -- ) 0 TO pci-device-slots \ reset slot array to unpoppulated 20 0 DO dup i pci-probe-device LOOP drop ; ' pci-probe-bus TO func-pci-probe-bus : pci-probe-all ( bus-max bus-min -- ) \ Check all busses from bus-min up to bus-max if needed 0 TO pci-device-vec-len \ reset the device-slot vector DO i TO pci-bus-number \ set current Busnumber 0 TO pci-device-number \ reset Device Number pci-bus-number pci-probe-bus \ and probe this bus pci-device-number 0 > IF LEAVE THEN \ if we found a device we're done LOOP \ else next bus ; : (probe-pci-host-bridge) ( bus-max bus-min -- ) 0d emit ." Adapters on " puid 10 0.r cr \ print the puid we're looking at ( bus-max bus-min ) pci-probe-all \ and walk the bus pci-device-number 0= IF \ IF no devices found 15 spaces \ | indent the output ." None" cr \ | tell the world our result THEN \ FI ; : probe-pci-host-bridge ( bus-max bus-min mmio-max mmio-base mem-max mem-base io-max io-base my-puid -- ) puid >r TO puid \ save puid and set the new pci-next-io ! \ save the next io-base address pci-max-io ! \ save the max io-space address pci-next-mem ! \ save the next mem-base address pci-max-mem ! \ save the max mem-space address pci-next-mmio ! \ save the next mmio-base address pci-max-mmio ! \ save the max mmio-space address (probe-pci-host-bridge) r> TO puid \ restore puid ; 0 VALUE pci-net-num 0 VALUE pci-disk-num 0 VALUE pci-cdrom-num : pci-set-alias ( str-addr str-len num -- ) $cathex strdup \ create alias name get-node node>path \ get path string set-alias \ and set the alias ; : unknown-enet ( -- pci-net-num ) pci-net-num dup 1+ TO pci-net-num ; : pci-alias-net ( config-addr -- ) drop \ forget the config address pci-net-num dup 1+ TO pci-net-num \ increase the pci-net-num s" net" rot pci-set-alias \ create the alias ; : pci-alias-disk ( config-addr -- ) drop \ forget the config address pci-disk-num dup 1+ TO pci-disk-num \ increase the pci-disk-num s" disk" rot pci-set-alias \ create the alias ; : pci-alias-cdrom ( config-addr -- ) drop \ forget the config address pci-cdrom-num dup 1+ TO pci-cdrom-num \ increase the pci-cdrom-num s" cdrom" rot pci-set-alias \ create the alias ; : pci-alias ( config-addr -- ) dup pci-class@ 10 rshift CASE 01 OF pci-alias-disk ENDOF 02 OF pci-alias-net ENDOF dup OF drop ENDOF ENDCASE ; : pci-gen-irq-map-one ( prop-addr prop-len slot pin -- prop-addr prop-len ) 2dup + 4 mod ( prop-addr prop-len slot pin parentpin ) >r >r ( prop-addr prop-len slot R: swizzledpin pin ) B lshift encode-int+ ( prop-addr prop-len R: swizzledpin pin ) 0 encode-64+ r> encode-int+ ( prop-addr prop-len R: swizzledpin ) get-parent encode-int+ get-node >space pci-addr2dev B lshift ( prop-addr prop-len parent-slot R: swizzledpin ) encode-int+ 0 encode-64+ r> encode-int+ ( prop-addr prop-len R: ) ; : pci-gen-irq-entry ( prop-addr prop-len config-addr -- prop-addr prop-len ) pci-addr2dev 4 mod ( prop-addr prop-len slot ) -rot ( slot prop-addr prop-len ) 5 1 DO 2 pick i ( slot prop-addr prop-len slot pin ) pci-gen-irq-map-one LOOP rot drop ; : pci-set-irq-line ( config-addr -- ) drop ; : pci-msi-prop ( addr -- ) 5 pci-cap-find ( capaddr ) ?dup IF 2+ rtas-config-w@ ( msi-control ) 1 rshift 7 and ( msi-control:3:1 ) dup 6 < IF 1 swap lshift ( vectors# ) encode-int " ibm,req#msi" property ELSE ." Invalid MSI vectors number " . cr THEN THEN ; : pci-msix-prop ( addr -- ) 11 pci-cap-find ( capaddr ) ?dup IF 2+ rtas-config-w@ ( msix-control ) 7ff and ( msix-control:10:0 ) 1+ ( vectors# ) ?dup IF encode-int " ibm,req#msi-x" property THEN THEN ; : pci-set-capabilities ( config-addr -- ) dup pci-msi-prop dup pci-msix-prop drop ; : pci-class-name-00 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 01 OF s" display" ENDOF dup OF s" unknown-legacy-device" ENDOF ENDCASE ; : pci-class-name-01 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" scsi" ENDOF 01 OF s" ide" ENDOF 02 OF s" fdc" ENDOF 03 OF s" ipi" ENDOF 04 OF s" raid" ENDOF 05 OF s" ata" ENDOF 06 OF s" sata" ENDOF 07 OF s" sas" ENDOF dup OF s" mass-storage" ENDOF ENDCASE ; : pci-class-name-02 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" ethernet" ENDOF 01 OF s" token-ring" ENDOF 02 OF s" fddi" ENDOF 03 OF s" atm" ENDOF 04 OF s" isdn" ENDOF 05 OF s" worldfip" ENDOF 05 OF s" picmg" ENDOF dup OF s" network" ENDOF ENDCASE ; : pci-class-name-03 ( addr -- str len ) pci-class@ FFFF and CASE 0000 OF s" vga" ENDOF 0001 OF s" 8514-compatible" ENDOF 0100 OF s" xga" ENDOF 0200 OF s" 3d-controller" ENDOF dup OF s" display" ENDOF ENDCASE ; : pci-class-name-04 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" video" ENDOF 01 OF s" sound" ENDOF 02 OF s" telephony" ENDOF dup OF s" multimedia-device" ENDOF ENDCASE ; : pci-class-name-05 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" memory" ENDOF 01 OF s" flash" ENDOF dup OF s" memory-controller" ENDOF ENDCASE ; : pci-class-name-06 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" host" ENDOF 01 OF s" isa" ENDOF 02 OF s" eisa" ENDOF 03 OF s" mca" ENDOF 04 OF s" pci" ENDOF 05 OF s" pcmcia" ENDOF 06 OF s" nubus" ENDOF 07 OF s" cardbus" ENDOF 08 OF s" raceway" ENDOF 09 OF s" semi-transparent-pci" ENDOF 0A OF s" infiniband" ENDOF dup OF s" unkown-bridge" ENDOF ENDCASE ; : pci-class-name-07 ( addr -- str len ) pci-class@ FFFF and CASE 0000 OF s" serial" ENDOF 0001 OF s" 16450-serial" ENDOF 0002 OF s" 16550-serial" ENDOF 0003 OF s" 16650-serial" ENDOF 0004 OF s" 16750-serial" ENDOF 0005 OF s" 16850-serial" ENDOF 0006 OF s" 16950-serial" ENDOF 0100 OF s" parallel" ENDOF 0101 OF s" bi-directional-parallel" ENDOF 0102 OF s" ecp-1.x-parallel" ENDOF 0103 OF s" ieee1284-controller" ENDOF 01FE OF s" ieee1284-device" ENDOF 0200 OF s" multiport-serial" ENDOF 0300 OF s" modem" ENDOF 0301 OF s" 16450-modem" ENDOF 0302 OF s" 16550-modem" ENDOF 0303 OF s" 16650-modem" ENDOF 0304 OF s" 16750-modem" ENDOF 0400 OF s" gpib" ENDOF 0500 OF s" smart-card" ENDOF dup OF s" communication-controller" ENDOF ENDCASE ; : pci-class-name-08 ( addr -- str len ) pci-class@ FFFF and CASE 0000 OF s" interrupt-controller" ENDOF 0001 OF s" isa-pic" ENDOF 0002 OF s" eisa-pic" ENDOF 0010 OF s" io-apic" ENDOF 0020 OF s" iox-apic" ENDOF 0100 OF s" dma-controller" ENDOF 0101 OF s" isa-dma" ENDOF 0102 OF s" eisa-dma" ENDOF 0200 OF s" timer" ENDOF 0201 OF s" isa-system-timer" ENDOF 0202 OF s" eisa-system-timer" ENDOF 0300 OF s" rtc" ENDOF 0301 OF s" isa-rtc" ENDOF 0400 OF s" hot-plug-controller" ENDOF 0500 OF s" sd-host-conrtoller" ENDOF dup OF s" system-periphal" ENDOF ENDCASE ; : pci-class-name-09 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" keyboard" ENDOF 01 OF s" pen" ENDOF 02 OF s" mouse" ENDOF 03 OF s" scanner" ENDOF 04 OF s" gameport" ENDOF dup OF s" input-controller" ENDOF ENDCASE ; : pci-class-name-0A ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" dock" ENDOF dup OF s" docking-station" ENDOF ENDCASE ; : pci-class-name-0B ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" 386" ENDOF 01 OF s" 486" ENDOF 02 OF s" pentium" ENDOF 10 OF s" alpha" ENDOF 20 OF s" powerpc" ENDOF 30 OF s" mips" ENDOF 40 OF s" co-processor" ENDOF dup OF s" cpu" ENDOF ENDCASE ; : pci-class-name-0C ( addr -- str len ) pci-class@ FFFF and CASE 0000 OF s" firewire" ENDOF 0100 OF s" access-bus" ENDOF 0200 OF s" ssa" ENDOF 0300 OF s" usb-uhci" ENDOF 0310 OF s" usb-ohci" ENDOF 0320 OF s" usb-ehci" ENDOF 0330 OF s" usb-xhci" ENDOF 0380 OF s" usb" ENDOF 03FE OF s" usb-device" ENDOF 0400 OF s" fibre-channel" ENDOF 0500 OF s" smb" ENDOF 0600 OF s" infiniband" ENDOF 0700 OF s" ipmi-smic" ENDOF 0701 OF s" ipmi-kbrd" ENDOF 0702 OF s" ipmi-bltr" ENDOF 0800 OF s" sercos" ENDOF 0900 OF s" canbus" ENDOF dup OF s" serial-bus" ENDOF ENDCASE ; : pci-class-name-0D ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" irda" ENDOF 01 OF s" consumer-ir" ENDOF 10 OF s" rf-controller" ENDOF 11 OF s" bluetooth" ENDOF 12 OF s" broadband" ENDOF 20 OF s" enet-802.11a" ENDOF 21 OF s" enet-802.11b" ENDOF dup OF s" wireless-controller" ENDOF ENDCASE ; : pci-class-name-0E ( addr -- str len ) pci-class@ 8 rshift FF and CASE dup OF s" intelligent-io" ENDOF ENDCASE ; : pci-class-name-0F ( addr -- str len ) pci-class@ 8 rshift FF and CASE 01 OF s" satelite-tv" ENDOF 02 OF s" satelite-audio" ENDOF 03 OF s" satelite-voice" ENDOF 04 OF s" satelite-data" ENDOF dup OF s" satelite-devoce" ENDOF ENDCASE ; : pci-class-name-10 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" network-encryption" ENDOF 01 OF s" entertainment-encryption" ENDOF dup OF s" encryption" ENDOF ENDCASE ; : pci-class-name-11 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" dpio" ENDOF 01 OF s" counter" ENDOF 10 OF s" measurement" ENDOF 20 OF s" managment-card" ENDOF dup OF s" data-processing-controller" ENDOF ENDCASE ; : pci-class-name ( addr -- str len ) dup pci-class@ 10 rshift CASE 00 OF pci-class-name-00 ENDOF 01 OF pci-class-name-01 ENDOF 02 OF pci-class-name-02 ENDOF 03 OF pci-class-name-03 ENDOF 04 OF pci-class-name-04 ENDOF 05 OF pci-class-name-05 ENDOF 06 OF pci-class-name-06 ENDOF 07 OF pci-class-name-07 ENDOF 08 OF pci-class-name-08 ENDOF 09 OF pci-class-name-09 ENDOF 0A OF pci-class-name-0A ENDOF 0B OF pci-class-name-0B ENDOF 0C OF pci-class-name-0C ENDOF 0C OF pci-class-name-0D ENDOF 0C OF pci-class-name-0E ENDOF 0C OF pci-class-name-0F ENDOF 0C OF pci-class-name-10 ENDOF 0C OF pci-class-name-11 ENDOF dup OF drop s" unknown" ENDOF ENDCASE ; : pci-bar-size@ ( bar-addr -- bar-size ) -1 over rtas-config-l! rtas-config-l@ ; : pci-bar-size-mem@ ( bar-addr -- mem-size ) pci-bar-size@ -10 and invert 1+ FFFFFFFF and ; : pci-bar-size-io@ ( bar-addr -- io-size ) pci-bar-size@ -4 and invert 1+ FFFFFFFF and ; : pci-bar-size ( bar-addr -- bar-size-raw ) dup rtas-config-l@ swap \ fetch original Value ( bval baddr ) -1 over rtas-config-l! \ make BAR show size ( bval baddr ) dup rtas-config-l@ \ and fetch the size ( bval baddr bsize ) -rot rtas-config-l! \ restore Value ; : pci-bar-size-mem32 ( bar-addr -- bar-size ) pci-bar-size \ fetch raw size -10 and invert 1+ \ calc size FFFFFFFF and \ keep lower 32 bits ; : pci-bar-size-rom ( bar-addr -- bar-size ) pci-bar-size \ fetch raw size FFFFF800 and invert 1+ \ calc size FFFFFFFF and \ keep lower 32 bits ; : pci-bar-size-mem64 ( bar-addr -- bar-size ) dup pci-bar-size \ fetch raw size lower 32 bits swap 4 + pci-bar-size \ fetch raw size upper 32 bits 20 lshift + \ and put them together -10 and invert 1+ \ calc size ; : pci-bar-size-io ( bar-addr -- bar-size ) pci-bar-size \ fetch raw size -4 and invert 1+ \ calc size FFFFFFFF and \ keep lower 32 bits ; : pci-bar-code@ ( bar-addr -- 0|1..4|5 ) rtas-config-l@ dup \ fetch the BaseAddressRegister 1 and IF \ IO BAR ? 2 and IF 0 ELSE 1 THEN \ only '01' is valid ELSE \ Memory BAR ? F and CASE 0 OF 2 ENDOF \ Memory 32 Bit Non-Prefetchable 8 OF 3 ENDOF \ Memory 32 Bit Prefetchable 4 OF 4 ENDOF \ Memory 64 Bit Non-Prefetchable C OF 5 ENDOF \ Memory 64 Bit Prefechtable dup OF 0 ENDOF \ Not a valid BarType ENDCASE THEN ; : assign-var ( size var -- al-mem ) 2dup @ \ ( size var size cur-mem ) read current free mem swap #aligned \ ( size var al-mem ) align the mem to the size dup 2swap -rot + \ ( al-mem var new-mem ) add size to aligned mem swap ! \ ( al-mem ) set variable to new mem ; : assign-bar-value32 ( bar size var -- 4 ) over IF \ IF size > 0 assign-var \ | ( bar al-mem ) set variable to next mem swap rtas-config-l! \ | ( -- ) set the bar to al-mem ELSE \ ELSE 2drop drop \ | clear stack THEN \ FI 4 \ size of the base-address-register ; : assign-bar-value64 ( bar size var -- 8 ) over IF \ IF size > 0 assign-var \ | ( bar al-mem ) set variable to next mem swap \ | ( al-mem addr ) calc config-addr of this bar 2dup rtas-config-l! \ | ( al-mem addr ) set the Lower part of the bar to al-mem 4 + swap 20 rshift \ | ( al-mem>>32 addr ) prepare the upper part of the al-mem swap rtas-config-l! \ | ( -- ) and set the upper part of the bar ELSE \ ELSE 2drop drop \ | clear stack THEN \ FI 8 \ size of the base-address-register ; : assign-mem64-bar ( bar-addr -- 8 ) dup pci-bar-size-mem64 \ fetch size pci-next-mem64 @ 0 = IF \ Check if we have 64-bit memory range pci-next-mem ELSE pci-next-mem64 THEN assign-bar-value64 \ and set it all ; : assign-mem32-bar ( bar-addr -- 4 ) dup pci-bar-size-mem32 \ fetch size pci-next-mem \ var to change assign-bar-value32 \ and set it all ; : assign-mmio64-bar ( bar-addr -- 8 ) dup pci-bar-size-mem64 \ fetch size pci-next-mem64 @ 0 = IF \ Check if we have 64-bit memory range pci-next-mmio ELSE pci-next-mem64 \ for board-qemu we will use same range THEN assign-bar-value64 \ and set it all ; : assign-mmio32-bar ( bar-addr -- 4 ) dup pci-bar-size-mem32 \ fetch size pci-next-mmio \ var to change assign-bar-value32 \ and set it all ; : assign-io-bar ( bar-addr -- 4 ) dup pci-bar-size-io \ fetch size pci-next-io \ var to change assign-bar-value32 \ and set it all ; : assign-rom-bar ( bar-addr -- ) dup pci-bar-size-rom \ fetch size dup IF \ IF size > 0 over >r \ | save bar addr for enable pci-next-mmio \ | var to change assign-bar-value32 \ | and set it drop \ | forget the BAR length r@ rtas-config-l@ \ | fetch BAR 1 or r> rtas-config-l! \ | and enable the ROM ELSE \ ELSE 2drop \ | clear stack THEN ; : assign-bar ( bar-addr -- reg-size ) dup pci-bar-code@ \ calc BAR type dup IF \ IF >0 CASE \ | CASE Setup the right type 1 OF assign-io-bar ENDOF \ | - set up an IO-Bar 2 OF assign-mmio32-bar ENDOF \ | - set up an 32bit MMIO-Bar 3 OF assign-mem32-bar ENDOF \ | - set up an 32bit MEM-Bar (prefetchable) 4 OF assign-mmio64-bar ENDOF \ | - set up an 64bit MMIO-Bar 5 OF assign-mem64-bar ENDOF \ | - set up an 64bit MEM-Bar (prefetchable) ENDCASE \ | ESAC ELSE \ ELSE ABORT \ | Throw an exception THEN \ FI ; : assign-all-device-bars ( configaddr -- ) 28 10 DO \ BARs start at 10 and end at 27 dup i + \ calc config-addr of the BAR assign-bar \ and set it up +LOOP \ add 4 or 8 to the index and loop 30 + assign-rom-bar \ set up the ROM if available ; : assign-all-bridge-bars ( configaddr -- ) 18 10 DO \ BARs start at 10 and end at 17 dup i + \ calc config-addr of the BAR assign-bar \ and set it up +LOOP \ add 4 or 8 to the index and loop 38 + assign-rom-bar \ set up the ROM if available ; : gen-mem64-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 8 ) dup pci-bar-size-mem64 \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch lower 32 bits ( paddr plen baddr val.lo R: size) over 4 + rtas-config-l@ \ | fetch upper 32 bits ( paddr plen baddr val.lo val.hi R: size) 20 lshift + -10 and >r \ | calc 64 bit value and save it ( paddr plen baddr R: size val ) 83000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 8 \ sizeof(BAR) = 8 Bytes ; : gen-pmem64-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 8 ) dup pci-bar-size-mem64 \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch lower 32 bits ( paddr plen baddr val.lo R: size) over 4 + rtas-config-l@ \ | fetch upper 32 bits ( paddr plen baddr val.lo val.hi R: size) 20 lshift + -10 and >r \ | calc 64 bit value and save it ( paddr plen baddr R: size val ) C3000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 8 \ sizeof(BAR) = 8 Bytes ; : gen-mem32-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 ) dup pci-bar-size-mem32 \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size) -10 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val ) 82000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ sizeof(BAR) = 4 Bytes ; : gen-pmem32-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 ) dup pci-bar-size-mem32 \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size) -10 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val ) C2000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ sizeof(BAR) = 4 Bytes ; : gen-io-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 ) dup pci-bar-size-io \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size) -4 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val ) 81000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ sizeof(BAR) = 4 Bytes ; : gen-rom-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len ) dup pci-bar-size-rom \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size) FFFFF800 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val ) 82000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI ; : pci-add-assigned-address ( prop-addr prop-len bar-addr -- prop-addr prop-len bsize ) dup pci-bar-code@ \ calc BAR type ( paddr plen baddr btype) CASE \ CASE for the BAR types ( paddr plen baddr ) 0 OF drop 4 ENDOF \ - not a valid type so do nothing 1 OF gen-io-bar-prop ENDOF \ - IO-BAR 2 OF gen-mem32-bar-prop ENDOF \ - MEM32 3 OF gen-pmem32-bar-prop ENDOF \ - MEM32 prefetchable 4 OF gen-mem64-bar-prop ENDOF \ - MEM64 5 OF gen-pmem64-bar-prop ENDOF \ - MEM64 prefetchable ENDCASE \ ESAC ( paddr plen bsize ) ; : pci-device-assigned-addresses-prop ( addr -- ) encode-start \ provide mem for property ( addr paddr plen ) 2 pick 30 + gen-rom-bar-prop \ assign the rom bar 28 10 DO \ we have 6 possible BARs 2 pick i + \ calc BAR address ( addr paddr plen bar-addr ) pci-add-assigned-address \ and generate the props for the BAR +LOOP \ increase Index by returned len s" assigned-addresses" property drop \ and write it into the device tree ; : pci-bridge-assigned-addresses-prop ( addr -- ) encode-start \ provide mem for property 2 pick 38 + gen-rom-bar-prop \ assign the rom bar 18 10 DO \ we have 2 possible BARs 2 pick i + \ ( addr paddr plen current-addr ) pci-add-assigned-address \ and generate the props for the BAR +LOOP \ increase Index by returned len s" assigned-addresses" property drop \ and write it into the device tree ; : pci-bridge-gen-range ( paddr plen base limit type -- paddr plen ) >r over - \ calc size ( paddr plen base size R:type ) dup 0< IF \ IF Size < 0 ( paddr plen base size R:type ) 2drop r> drop \ | forget values ( paddr plen ) ELSE \ ELSE 1+ swap 2swap \ | adjust stack ( size base paddr plen R:type ) r@ encode-int+ \ | Child type ( size base paddr plen R:type ) 2 pick encode-64+ \ | Child address ( size base paddr plen R:type ) r> encode-int+ \ | Parent type ( size base paddr plen ) rot encode-64+ \ | Parent address ( size paddr plen ) rot encode-64+ \ | Encode size ( paddr plen ) THEN \ FI ; : pci-bridge-gen-mmio-range ( addr prop-addr prop-len -- addr prop-addr prop-len ) 2 pick 20 + rtas-config-l@ \ fetch Value ( addr paddr plen val ) dup 0000FFF0 and 10 lshift \ calc base-address ( addr paddr plen val base ) swap 000FFFFF or \ calc limit-address ( addr paddr plen base limit ) 02000000 pci-bridge-gen-range \ and generate it ( addr paddr plen ) ; : pci-bridge-gen-mem-range ( addr prop-addr prop-len -- addr prop-addr prop-len ) 2 pick 24 + rtas-config-l@ \ fetch Value ( addr paddr plen val ) dup 000FFFFF or \ calc limit Bits 31:0 ( addr paddr plen val limit.31:0 ) swap 0000FFF0 and 10 lshift \ calc base Bits 31:0 ( addr paddr plen limit.31:0 base.31:0 ) 4 pick 28 + rtas-config-l@ \ fetch upper Basebits ( addr paddr plen limit.31:0 base.31:0 base.63:32 ) 20 lshift or swap \ and calc Base ( addr paddr plen base.63:0 limit.31:0 ) 4 pick 2C + rtas-config-l@ \ fetch upper Limitbits ( addr paddr plen base.63:0 limit.31:0 limit.63:32 ) 20 lshift or \ and calc Limit ( addr paddr plen base.63:0 limit.63:0 ) 42000000 pci-bridge-gen-range \ and generate it ( addr paddr plen ) ; : pci-bridge-gen-io-range ( addr prop-addr prop-len -- addr prop-addr prop-len ) 2 pick 1C + rtas-config-l@ \ fetch Value ( addr paddr plen val ) dup 0000F000 and 00000FFF or \ calc Limit Bits 15:0 ( addr paddr plen val limit.15:0 ) swap 000000F0 and 8 lshift \ calc Base Bits 15:0 ( addr paddr plen limit.15:0 base.15:0 ) 4 pick 30 + rtas-config-l@ \ fetch upper Bits ( addr paddr plen limit.15:0 base.15:0 val ) dup FFFF and 10 lshift rot or \ calc Base ( addr paddr plen limit.15:0 val base.31:0 ) -rot FFFF0000 and or \ calc Limit ( addr paddr plen base.31:0 limit.31:0 ) 01000000 pci-bridge-gen-range \ and generate it ( addr paddr plen ) ; : pci-bridge-range-props ( addr -- ) encode-start \ provide mem for property pci-bridge-gen-mmio-range \ generate the non prefetchable Memory Entry pci-bridge-gen-mem-range \ generate the prefetchable Memory Entry pci-bridge-gen-io-range \ generate the IO Entry dup IF \ IF any space present (propsize>0) s" ranges" property \ | write it into the device tree ELSE \ ELSE s" " s" ranges" property 2drop \ | forget the properties THEN \ FI drop \ forget the address ; : pci-bridge-interrupt-map ( -- ) encode-start \ create the property ( paddr plen ) get-node child \ find the first child ( paddr plen handle ) BEGIN dup WHILE \ Loop as long as the handle is non-zero ( paddr plen handle ) dup >r >space \ Get the my-space ( paddr plen addr R: handle ) pci-gen-irq-entry \ and Encode the interrupt settings ( paddr plen R: handle) r> peer \ Get neighbour ( paddr plen handle ) REPEAT \ process next childe node ( paddr plen handle ) drop \ forget the null ( paddr plen ) s" interrupt-map" property \ and set it ( -- ) 1 encode-int s" #interrupt-cells" property \ encode the cell# f800 encode-int 0 encode-int+ 0 encode-int+ \ encode the bit mask for config addr (Dev only) 7 encode-int+ s" interrupt-map-mask" property \ encode IRQ#=7 and generate property ; : encode-mem32-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 4 ) dup pci-bar-size-mem32 \ calc BAR-size ( not changing the BAR ) dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize ) >r 02000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | encode size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ BAR-Len = 4 (32Bit) ; : encode-pmem32-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 4 ) dup pci-bar-size-mem32 \ calc BAR-size ( not changing the BAR ) dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize ) >r 42000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | encode size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ BAR-Len = 4 (32Bit) ; : encode-mem64-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 8 ) dup pci-bar-size-mem64 \ calc BAR-size ( not changing the BAR ) dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize ) >r 03000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | encode size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 8 \ BAR-Len = 8 (64Bit) ; : encode-pmem64-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 8 ) dup pci-bar-size-mem64 \ calc BAR-size ( not changing the BAR ) dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize ) >r 43000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | encode size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 8 \ BAR-Len = 8 (64Bit) ; : encode-rom-bar ( prop-addr prop-len configaddr -- prop-addr prop-len ) dup pci-bar-size-rom \ fetch raw BAR-size dup IF \ IF BAR is used >r 02000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | calc and encode the size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI ; : encode-io-bar ( prop-addr prop-len BAR-addr BAR-value -- prop-addr prop-len 4 ) dup pci-bar-size-io \ calc BAR-size ( not changing the BAR ) dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize ) >r 01000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | encode size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ BAR-Len = 4 (32Bit) ; : encode-bar ( prop-addr prop-len bar-addr -- prop-addr prop-len bar-len ) dup pci-bar-code@ \ calc BAR type CASE \ CASE for the BAR types ( paddr plen baddr val ) 0 OF drop 4 ENDOF \ - not a valid type so do nothing 1 OF encode-io-bar ENDOF \ - IO-BAR 2 OF encode-mem32-bar ENDOF \ - MEM32 3 OF encode-pmem32-bar ENDOF \ - MEM32 prefetchable 4 OF encode-mem64-bar ENDOF \ - MEM64 5 OF encode-pmem64-bar ENDOF \ - MEM64 prefetchable ENDCASE \ ESAC ( paddr plen blen ) ; : pci-reg-props ( configaddr -- ) dup encode-int \ configuration space ( caddr paddr plen ) 0 encode-64+ \ make the rest 0 0 encode-64+ \ encode the size as 0 2 pick pci-htype@ \ fetch Header Type ( caddr paddr plen type ) 1 and IF \ IF Bridge ( caddr paddr plen ) 18 10 DO \ | loop over all BARs 2 pick i + \ | calc bar-addr ( caddr paddr plen baddr ) encode-bar \ | encode this BAR ( caddr paddr plen blen ) +LOOP \ | increase LoopIndex by the BARlen 2 pick 38 + \ | calc ROM-BAR for a bridge ( caddr paddr plen baddr ) encode-rom-bar \ | encode the ROM-BAR ( caddr paddr plen ) ELSE \ ELSE ordinary device ( caddr paddr plen ) 28 10 DO \ | loop over all BARs 2 pick i + \ | calc bar-addr ( caddr paddr plen baddr ) encode-bar \ | encode this BAR ( caddr paddr plen blen ) +LOOP \ | increase LoopIndex by the BARlen 2 pick 30 + \ | calc ROM-BAR for a device ( caddr paddr plen baddr ) encode-rom-bar \ | encode the ROM-BAR ( caddr paddr plen ) THEN \ FI ( caddr paddr plen ) s" reg" property \ and store it into the property drop ; : pci-common-props ( addr -- ) dup pci-class-name device-name dup pci-vendor@ encode-int s" vendor-id" property dup pci-device@ encode-int s" device-id" property dup pci-revision@ encode-int s" revision-id" property dup pci-class@ encode-int s" class-code" property 3 encode-int s" #address-cells" property 2 encode-int s" #size-cells" property dup pci-config-ext? IF 1 encode-int s" ibm,pci-config-space-type" property THEN dup pci-status@ dup 9 rshift 3 and encode-int s" devsel-speed" property dup 7 rshift 1 and IF 0 0 s" fast-back-to-back" property THEN dup 6 rshift 1 and IF 0 0 s" 66mhz-capable" property THEN 5 rshift 1 and IF 0 0 s" udf-supported" property THEN dup pci-cache@ ?dup IF encode-int s" cache-line-size" property THEN pci-interrupt@ ?dup IF encode-int s" interrupts" property THEN ; : pci-device-props ( addr -- ) dup pci-common-props dup pci-min-grant@ encode-int s" min-grant" property dup pci-max-lat@ encode-int s" max-latency" property dup pci-sub-device@ ?dup IF encode-int s" subsystem-id" property THEN dup pci-sub-vendor@ ?dup IF encode-int s" subsystem-vendor-id" property THEN dup pci-device-assigned-addresses-prop pci-reg-props pci-hotplug-enabled IF dup dup pci-addr2bus 8 lshift swap pci-addr2dev 3 lshift or 40000000 + encode-int s" ibm,my-drc-index" property dup dup pci-addr2bus 20 * swap pci-addr2dev + a base ! s" Slot " rot $cathex hex encode-string s" ibm,loc-code" property THEN ; : pci-bridge-props ( addr -- ) dup pci-bus@ encode-int s" primary-bus" property encode-int s" secondary-bus" property encode-int s" subordinate-bus" property dup pci-bus@ drop encode-int rot encode-int+ s" bus-range" property pci-device-slots encode-int s" slot-names" property dup pci-bridge-range-props dup pci-bridge-assigned-addresses-prop s" interrupt-map" get-node get-property IF pci-bridge-interrupt-map ELSE 2drop THEN pci-reg-props ; : pci-bridge-generic-setup ( addr -- ) pci-device-slots >r \ save the slot array on return stack dup pci-common-props \ set the common properties before scanning the bus s" pci" device-type \ the type is allways "pci" dup pci-bridge-probe \ find all device connected to it dup assign-all-bridge-bars \ set up all memory access BARs dup pci-set-irq-line \ set the interrupt pin dup pci-set-capabilities \ set up the capabilities pci-bridge-props \ and generate all properties r> TO pci-device-slots \ and reset the slot array ; DEFER func-pci-device-props : pci-device-generic-setup ( config-addr -- ) dup assign-all-device-bars \ calc all BARs dup pci-set-irq-line \ set the interrupt pin dup pci-set-capabilities \ set up the capabilities dup func-pci-device-props \ and generate all properties drop \ forget the config-addr ; ' pci-device-props TO func-pci-device-props ' pci-bridge-range-props TO func-pci-bridge-range-props : populate-pci-busses ( -- ) " /" find-device get-node child BEGIN dup 0 <> WHILE dup set-node dup " name" rot get-package-property 0 = IF drop dup from-cstring 2dup s" pci" strequal IF s" pci-phb.fs" included THEN 2drop THEN peer REPEAT drop device-end ; populate-pci-busses 600 cp : check-patch-kernel-sc1 ( -- ) ciregs >r4 @ dup 1000000 + dup 2000000 < IF 0 ELSE dup 2000000 - THEN swap check-and-patch-sc1 ; ' check-patch-kernel-sc1 add-quiesce-xt ' rtas-quiesce add-quiesce-xt 640 cp 690 cp 6a0 cp 6a8 cp 6b0 cp 6b8 cp 6c0 cp s" /cpus/@0" open-dev encode-int s" cpu" set-chosen s" /memory@0" open-dev encode-int s" memory" set-chosen 6e0 cp 700 cp s" /openprom" find-device s" SLOF," slof-build-id here swap rmove here slof-build-id nip $cat encode-string s" model" property 0 0 s" relative-addressing" property device-end s" /aliases" find-device : open true ; : close ; device-end s" /mmu" open-dev encode-int s" mmu" set-chosen VARIABLE chosen-memory-ih 0 chosen-memory-ih ! : (chosen-memory-ph) ( -- phandle ) chosen-memory-ih @ ?dup 0= IF s" memory" get-chosen IF decode-int nip nip dup chosen-memory-ih ! ihandle>phandle ELSE 0 THEN ELSE ihandle>phandle THEN ; : (set-available-prop) ( prop plen -- ) s" available" (chosen-memory-ph) ?dup 0<> IF set-property ELSE cr ." Can't find chosen memory node - " ." no available property created" cr 2dup 2dup THEN ; : update-available-property ( available-ptr -- ) dup >r available>size@ 0= r@ available AVAILABLE-SIZE /available * + >= or IF available r> available - encode-bytes (set-available-prop) ELSE r> /available + RECURSE THEN ; : update-available-property available update-available-property ; : claim ( [ addr ] len align -- base ) claim update-available-property ; : release ( addr len -- ) release update-available-property ; update-available-property : input ( dev-str dev-len -- ) open-dev ?dup IF s" stdin" get-chosen IF decode-int nip nip ?dup IF close-dev THEN THEN encode-int s" stdin" set-chosen THEN ; : output ( dev-str dev-len -- ) open-dev ?dup IF s" stdout" get-chosen IF decode-int nip nip ?dup IF close-dev THEN THEN encode-int s" stdout" set-chosen THEN ; : io ( dev-str dev-len -- ) 2dup input output ; 1 BUFFER: (term-io-char-buf) : term-io-key ( -- char ) s" stdin" get-chosen IF decode-int nip nip dup 0= IF 0 EXIT THEN >r BEGIN (term-io-char-buf) 1 s" read" r@ $call-method 0 > UNTIL (term-io-char-buf) c@ r> drop ELSE [ ' key behavior compile, ] THEN ; ' term-io-key to key : term-io-key? ( -- true|false ) s" stdin" get-chosen IF decode-int nip nip dup 0= IF drop 0 EXIT THEN \ return false and exit if no stdin set >r \ store ihandle on return stack s" device_type" r@ ihandle>phandle ( propstr len phandle ) get-property ( true | data dlen false ) IF false ELSE 1 - \ remove 1 from length to ignore null-termination char 2dup s" serial" str= IF 2drop serial-key? r> drop EXIT THEN \ call serial-key, cleanup return-stack, exit 2dup s" keyboard" str= IF 2drop ( ) s" key-available?" r@ ihandle>phandle find-method IF drop s" key-available?" r@ $call-method ELSE false THEN r> drop EXIT \ cleanup return-stack, exit THEN 2drop r> drop false EXIT \ unknown device_type cleanup return-stack, return false THEN ELSE false THEN ; ' term-io-key? to key? 800 cp 51 CONSTANT nvram-partition-type-cpulog 60 CONSTANT nvram-partition-type-sas 61 CONSTANT nvram-partition-type-sms 6e CONSTANT nvram-partition-type-debug 6f CONSTANT nvram-partition-type-history 70 CONSTANT nvram-partition-type-common 7f CONSTANT nvram-partition-type-freespace a0 CONSTANT nvram-partition-type-linux : rztype ( str len -- ) \ stop at zero byte, read with nvram-c@ 0 DO dup i + nvram-c@ ?dup IF ( str char ) emit ELSE ( str ) drop UNLOOP EXIT THEN LOOP ; create tmpStr 500 allot : rzcount ( zstr -- str len ) dup tmpStr >r BEGIN dup nvram-c@ dup r> dup 1+ >r c! WHILE char+ REPEAT r> drop over - swap drop tmpStr swap ; : calc-header-cksum ( offset -- cksum ) dup nvram-c@ 10 2 DO over I + nvram-c@ + LOOP wbsplit + nip ; : bad-header? ( offset -- flag ) dup 2+ nvram-w@ ( offset length ) 0= IF ( offset ) drop true EXIT ( ) THEN dup calc-header-cksum ( offset checksum' ) swap 1+ nvram-c@ ( checksum ' checksum ) <> ( flag ) ; : .header ( offset -- ) cr ( offset ) dup bad-header? IF ( offset ) ." BAD HEADER -- trying to print it anyway" cr THEN space ( offset ) dup nvram-c@ 2 0.r ( offset ) space space ( offset ) dup 2+ nvram-w@ 10 * 5 .r ( offset ) space space ( offset ) 4 + 0c rztype ( ) ; : .headers ( -- ) cr cr ." Type Size Name" cr ." ========================" 0 BEGIN ( offset ) dup nvram-c@ ( offset type ) WHILE dup .header ( offset ) dup 2+ nvram-w@ 10 * + ( offset offset' ) dup nvram-size < IF ( offset ) ELSE drop EXIT ( ) THEN REPEAT drop ( ) cr cr ; : reset-nvram ( -- ) internal-reset-nvram ; : dump-partition ['] nvram-c@ 1 (dump) ; : type-no-zero ( addr len -- ) 0 DO dup I + dup nvram-c@ 0= IF drop ELSE nvram-c@ emit THEN LOOP drop ; : type-no-zero-part ( from-str cnt-str addr len ) 0 DO dup i + dup nvram-c@ 0= IF drop ELSE 3 pick 0= 3 pick 0 > AND IF dup 1 type-no-zero THEN nvram-c@ a = IF 2 pick 0= IF over 1- 0 max rot drop swap THEN 2 pick 1- 0 max 3 roll drop rot rot THEN THEN LOOP drop ; : (dmesg-prepare) ( base-addr -- base-addr' addr len act-off ) 10 - \ go back to header dup 14 + nvram-l@ dup >r ( base-addr act-off ) ( R: act-off ) over over over + swap 10 + nvram-w@ + >r ( base-addr act-off ) ( R: act-off nvram-act-addr ) over 2 + nvram-w@ 10 * swap - over swap ( base-addr base-addr start-size ) ( R: act-off nvram-act-addr ) r> swap rot 10 + nvram-w@ - r> ; : .dmesg ( base-addr -- ) (dmesg-prepare) >r cr type-no-zero ( base-addr ) ( R: act-off ) dup 10 + nvram-w@ + r> type-no-zero ; : .dmesg-part ( from-str cnt-str base-addr -- ) (dmesg-prepare) >r >r >r -rot r> r> cr type-no-zero-part rot ( base-addr ) ( R: act-off ) dup 10 + nvram-w@ + r> type-no-zero-part ; : dmesg-part ( from-str cnt-str -- left-from-str left-cnt-str ) 2dup s" ibm,CPU0log" get-named-nvram-partition IF 2drop EXIT THEN drop .dmesg-part nip nip ; : dmesg2 ( -- ) s" ibm,CPU1log" get-named-nvram-partition IF ." No log partition." cr EXIT THEN drop .dmesg ; : dmesg ( -- ) s" ibm,CPU0log" get-named-nvram-partition IF ." No log partition." cr EXIT THEN drop .dmesg ; 880 cp wordlist CONSTANT envvars : listenv ( -- ) get-current envvars set-current words set-current ; : create-env ( "name" -- ) get-current envvars set-current CREATE set-current ; : env-int ( n -- ) 1 c, align , DOES> char+ aligned @ ; : env-bytes ( a len -- ) 2 c, align dup , here swap dup allot move DOES> char+ aligned dup @ >r cell+ r> ; : env-string ( str len -- ) 3 c, align dup , here over allot swap move DOES> char+ aligned dup @ >r cell+ r> ; : env-flag ( f -- ) 4 c, c, DOES> char+ c@ 0<> ; : env-secmode ( sm -- ) 5 c, c, DOES> char+ c@ ; : default-int ( n "name" -- ) create-env env-int ; : default-bytes ( a len "name" -- ) create-env env-bytes ; : default-string ( a len "name" -- ) create-env env-string ; : default-flag ( f "name" -- ) create-env env-flag ; : default-secmode ( sm "name" -- ) create-env env-secmode ; : set-option ( option-name len option len -- ) 2swap encode-string 2swap s" /options" find-node dup IF set-property ELSE drop 2drop 2drop THEN ; : findenv ( name len -- adr def-adr type | 0 ) 2dup envvars voc-find dup 0<> IF ( ABORT" not a configuration variable" ) link> >body char+ >r (find-order) link> >body dup char+ swap c@ r> swap ELSE nip nip THEN ; : test-flag ( param len -- true | false ) 2dup s" true" string=ci -rot s" false" string=ci or ; : test-secmode ( param len -- true | false ) 2dup s" none" string=ci -rot 2dup s" command" string=ci -rot s" full" string=ci or or ; : test-int ( param len -- true | false ) $dh-number IF false ELSE drop true THEN ; : findtype ( param len name len -- param len name len type ) 2dup findenv \ try to find type of envvar dup IF \ found a type? nip nip EXIT THEN drop 2swap 2dup test-flag IF 4 -rot \ boolean type ELSE 2dup test-secmode IF 5 -rot \ secmode type ELSE 2dup test-int IF 1 -rot \ integer type ELSE 2dup test-string IF 3 ELSE 2 THEN \ 3 = string, 2 = default to bytes -rot THEN THEN THEN rot >r 2swap r> ; : $setenv ( param len name len -- ) 4dup set-option findtype -rot $CREATE CASE 1 OF $dh-number IF 0 THEN env-int ENDOF \ XXX: wants decimal and 0x... 2 OF env-bytes ENDOF 3 OF env-string ENDOF 4 OF evaluate env-flag ENDOF 5 OF evaluate env-secmode ENDOF \ XXX: recognize none, command, full ENDCASE ; : (printenv) ( adr type -- ) CASE 1 OF aligned @ . ENDOF 2 OF aligned dup cell+ swap @ swap . . ENDOF 3 OF aligned dup @ >r cell+ r> type ENDOF 4 OF c@ IF ." true" ELSE ." false" THEN ENDOF 5 OF c@ . ENDOF \ XXX: print symbolically ENDCASE ; : .printenv-header ( -- ) cr s" ---environment variable--------current value-------------default value------" type cr ; DEFER old-emit 0 VALUE emit-counter : emit-and-count emit-counter 1 + to emit-counter old-emit ; : .enable-emit-counter 0 to emit-counter ['] emit behavior to old-emit ['] emit-and-count to emit ; : .disable-emit-counter ['] old-emit behavior to emit ; : .spaces ( number-of-spaces -- ) dup 0 > IF spaces ELSE drop space THEN ; : .print-one-env ( name len -- ) 3 .spaces 2dup dup -rot type 1c swap - .spaces findenv rot over .enable-emit-counter (printenv) .disable-emit-counter 1a emit-counter - .spaces (printenv) ; : .print-all-env .printenv-header envvars cell+ BEGIN @ dup WHILE dup link> >name name>string .print-one-env cr REPEAT drop ; : printenv parse-word dup 0= IF 2drop .print-all-env ELSE findenv dup 0= ABORT" not a configuration variable" rot over cr ." Current: " (printenv) cr ." Default: " (printenv) THEN ; : (set-default) ( def-xt -- ) dup >name name>string $CREATE dup >body c@ >r execute r> CASE 1 OF env-int ENDOF 2 OF env-bytes ENDOF 3 OF env-string ENDOF 4 OF env-flag ENDOF 5 OF env-secmode ENDOF ENDCASE ; true default-flag auto-boot? s" " default-string boot-device s" " default-string boot-file s" boot" default-string boot-command s" " default-string diag-device s" " default-string diag-file false default-flag diag-switch? true default-flag fcode-debug? s" " default-string input-device s" " default-string nvramrc s" " default-string oem-banner false default-flag oem-banner? 0 0 default-bytes oem-logo false default-flag oem-logo? s" " default-string output-device 200 default-int screen-#columns 200 default-int screen-#rows 0 default-int security-#badlogins 0 default-secmode security-mode s" " default-string security-password 0 default-int selftest-#megs false default-flag use-nvramrc? false default-flag direct-serial? true default-flag real-mode? default-load-base default-int load-base VARIABLE nvoff \ offset in envvar partition : (nvupdate-one) ( adr type -- "value" ) CASE 1 OF aligned @ (.d) ENDOF 2 OF drop 0 0 ENDOF 3 OF aligned dup @ >r cell+ r> ENDOF 4 OF c@ IF s" true" ELSE s" false" THEN ENDOF 5 OF c@ (.) ENDOF \ XXX: print symbolically ENDCASE ; : nvupdate-one ( def-xt -- ) >r nvram-partition-type-common get-nvram-partition ( part.addr part.len FALSE|TRUE R: def-xt ) ABORT" No valid NVRAM." r> ( part.addr part.len def-xt ) >name name>string ( part.addr part.len var.a var.l ) 2dup findenv nip (nvupdate-one) internal-add-env drop ; : (nvupdate) ( -- ) nvram-partition-type-common get-nvram-partition ABORT" No valid NVRAM." erase-nvram-partition drop envvars cell+ BEGIN @ dup WHILE dup link> nvupdate-one REPEAT drop ; : nvupdate ( -- ) ." nvupdate is obsolete." cr ; : set-default parse-word envvars voc-find dup 0= ABORT" not a configuration variable" link> (set-default) ; : (set-defaults) envvars cell+ BEGIN @ dup WHILE dup link> (set-default) REPEAT drop ; (set-defaults) : set-defaults (set-defaults) (nvupdate) ; : setenv parse-word ( skipws ) 0d parse -leading 2swap $setenv (nvupdate) ; : get-nv ( -- ) nvram-partition-type-common get-nvram-partition ( addr offset not-found | not-found ) \ find partition header IF ." No NVRAM common partition, re-initializing..." cr internal-reset-nvram (nvupdate) nvram-partition-type-common get-nvram-partition IF ." NVRAM seems to be broken." cr EXIT THEN THEN drop ( addr ) \ throw away offset BEGIN dup rzcount dup \ make string from offset and make condition WHILE ( offset offset length ) 2dup [char] = split \ Split string at equal sign (=) 2swap ( offset offset length param len name len ) $setenv \ Set envvar nip \ throw away old string begin + 1+ \ calc new offset REPEAT 2drop drop \ cleanup ; get-nv : check-for-nvramrc ( -- ) use-nvramrc? IF s" Executing following code from nvramrc: " s" nvramrc" evaluate $cat nvramlog-write-string-cr s" (!) Executing code specified in nvramrc" type cr s" SLOF Setup = " type .enable-emit-counter s" nvramrc" evaluate ['] evaluate CATCH IF 2drop emit-counter 0 DO 8 emit LOOP s" (!) Code in nvramrc triggered exception. " 2dup nvramlog-write-string type cr 12 spaces s" Aborting nvramrc execution" 2dup nvramlog-write-string-cr type cr s" SLOF Setup = " type THEN .disable-emit-counter THEN ; : (nv-findalias) ( alias-ptr alias-len -- pos ) here 0 s" devalias " string-cat 3 pick 3 pick string-cat s" " string-cat s" nvramrc" evaluate 2swap find-substr nip nip ; : (nv-build-real-entry) ( name-ptr name-len dev-ptr dev-len -- str-ptr str-len ) 2swap here 0 s" devalias " string-cat 2swap string-cat s" " string-cat 2swap string-cat 0d char-cat 0a char-cat ; : (nv-build-null-entry) ( name-ptr name-len dev-ptr dev-len -- str-ptr str-len ) 4drop here 0 ; : (nv-build-nvramrc) ( name-str name-len dev-str dev-len xt-build-entry -- ) 4 pick 4 pick (nv-findalias) dup s" nvramrc" evaluate nip >= IF drop execute s" nvramrc" evaluate string-cat dup allot s" nvramrc" $setenv ELSE \ if our alias is still defined in nvramrc 5 pick 5 pick 5 pick 5 pick 5 pick execute nip over + s" nvramrc" evaluate 3 pick string-at 2dup find-nextline string-at nip + alloc-mem 0 s" nvramrc" evaluate drop 3 pick string-cat rot >r >r >r execute r> r> 2swap string-cat ( mem, len ) ( R: alias-pos ) s" nvramrc" evaluate r> string-at 2dup find-nextline string-at string-cat 2dup s" nvramrc" $setenv free-mem THEN ; : $nvalias ( name-str name-len dev-str dev-len -- ) 4dup ['] (nv-build-real-entry) (nv-build-nvramrc) set-alias s" true" s" use-nvramrc?" $setenv (nvupdate) ; : nvalias ( "alias-name< >device-specifier" -- ) parse-word parse-word dup 0<> IF $nvalias ELSE 2drop 2drop cr " Usage: nvalias (""alias-name< >device-specifier"" -- )" type cr THEN ; : $nvunalias ( name-str name-len -- ) s" " ['] (nv-build-null-entry) (nv-build-nvramrc) (nvupdate) ; : nvunalias ( "alias-name< >" -- ) parse-word $nvunalias ; : diagnostic-mode? ( -- diag-switch? ) diag-switch? ; check-for-nvramrc 890 cp defer set-boot-device defer add-boot-device 8 CONSTANT MAX-ALIAS : add-boot-aliases ( str -- ) 2dup add-boot-device ( $str ) MAX-ALIAS 1 DO 2dup i $cathex 2dup ( $str $strN $strN ) find-alias 0 > IF ( $str $strN false | $result ) drop strdup add-boot-device ( $str ) ELSE 2drop THEN LOOP 2drop ; : qemu-read-bootlist ( -- ) " qemu,boot-list" get-chosen IF s" boot-device" $setenv EXIT THEN 0 0 set-boot-device " qemu,boot-device" get-chosen not IF " boot-device" evaluate swap drop 0= IF " disk" add-boot-aliases " cdrom" add-boot-aliases " net" add-boot-aliases THEN EXIT THEN 0 ?DO dup i + c@ CASE 0 OF ENDOF [char] a OF ENDOF [char] b OF ENDOF [char] c OF " disk" add-boot-aliases ENDOF [char] d OF " cdrom" add-boot-aliases ENDOF [char] n OF " net" add-boot-aliases ENDOF ENDCASE cr LOOP drop ; ' qemu-read-bootlist to read-bootlist 8a0 cp 0 VALUE debug-client-interface? VOCABULARY client-voc \ We store all client-interface callable words here. 6789 CONSTANT sc-exit 4711 CONSTANT sc-yield VARIABLE client-callback \ Address of client's callback function : client-data ciregs >r3 @ ; : nargs client-data la1+ l@ ; : nrets client-data la1+ la1+ l@ ; : client-data-to-stack client-data 3 la+ nargs 0 ?DO dup l@ swap la1+ LOOP drop ; : stack-to-client-data client-data nargs nrets + 2 + la+ nrets 0 ?DO tuck l! /l - LOOP drop ; : call-client ( args len client-entry -- ) >r ciregs >r7 ! ciregs >r6 ! client-entry-point @ ciregs >r5 ! cistack ciregs >r1 ! r> jump-client drop BEGIN client-data-to-stack client-data l@ zcount ALSO client-voc $find PREVIOUS dup 0= >r IF CATCH ?dup IF dup CASE sc-exit OF drop r> drop EXIT ENDOF sc-yield OF drop r> drop EXIT ENDOF ENDCASE THROW THEN stack-to-client-data ELSE cr type ." NOT FOUND" THEN r> ciregs >r3 ! ciregs >r4 @ jump-client UNTIL ; : flip-stack ( a1 ... an n -- an ... a1 ) ?dup IF 1 ?DO i roll LOOP THEN ; : (callback) ( "service-name<>" "arguments" -- ) client-callback @ \ client-callback points to the function prolog dup 8 + @ ciregs >r2 ! \ Set up the TOC pointer (???) @ call-client ; \ Resolve the function's address from the prolog ' (callback) to callback : (continue-client) s" " \ make call-client happy, client won't use the string anyways. ciregs >r4 @ call-client ; ' (continue-client) to continue-client : string-to-buffer ( str len buf len -- len' ) 2dup erase rot min dup >r move r> ; ALSO client-voc DEFINITIONS : exit sc-exit THROW ; : yield sc-yield THROW ; : test ( zstr -- missing? ) zcount debug-client-interface? IF ." ci: test " 2dup type cr THEN ALSO client-voc $find PREVIOUS IF drop FALSE ELSE 2drop TRUE THEN ; : finddevice ( zstr -- phandle ) zcount debug-client-interface? IF ." ci: finddevice " 2dup type cr THEN 2dup " /memory" str= IF 2drop " /memory@0" THEN find-node dup 0= IF drop -1 THEN ; : getprop ( phandle zstr buf len -- len' ) >r >r zcount rot ( str-adr str-len phandle R: len buf ) debug-client-interface? IF ." ci: getprop " 3dup . ." '" type ." '" THEN get-property debug-client-interface? IF dup IF ." ** not found **" THEN cr THEN 0= IF r> swap dup r> min swap >r move r> ELSE r> r> 2drop -1 THEN ; : getproplen ( phandle zstr -- len ) zcount rot get-property 0= IF nip ELSE -1 THEN ; : setprop ( phandle zstr buf len -- size|-1 ) dup >r \ save len encode-bytes ( phandle zstr prop-addr prop-len ) 2swap zcount rot ( prop-addr prop-len name-addr name-len phandle ) current-node @ >r \ save current node set-node \ change to specified node property \ set property r> set-node \ restore original node r> \ always return size, because we can not fail. ; : canon ( zstr buf len -- len' ) 2dup erase >r >r zcount >r dup c@ [char] / = IF r> r> swap r> over >r min move r> ELSE r> find-alias ?dup 0= IF r> r> 2drop -1 ELSE dup -rot r> swap r> min move THEN THEN ; : nextprop ( phandle zstr buf -- flag ) \ -1 invalid, 0 end, 1 ok >r zcount rot next-property IF r> zplace 1 ELSE r> drop 0 THEN ; : open ( zstr -- ihandle ) zcount debug-client-interface? IF ." ci: open " 2dup type cr THEN open-dev ; : close ( ihandle -- ) debug-client-interface? IF ." ci: close " dup . cr THEN s" stdin" get-chosen IF decode-int nip nip over = IF close-dev quiesce ELSE close-dev THEN ELSE close-dev THEN ; : write ( ihandle str len -- len' ) rot s" write" rot ['] $call-method CATCH IF 2drop 3drop -1 THEN ; : read ( ihandle str len -- len' ) rot s" read" rot ['] $call-method CATCH IF 2drop 3drop -1 THEN ; : seek ( ihandle hi lo -- status ) swap rot s" seek" rot ['] $call-method CATCH IF 2drop 3drop -1 THEN ; : claim ( addr len align -- base ) debug-client-interface? IF ." ci: claim " .s cr THEN dup IF rot drop ['] claim CATCH IF 2drop -1 THEN ELSE ['] claim CATCH IF 3drop -1 THEN THEN ; : release ( addr len -- ) debug-client-interface? IF ." ci: release " .s cr THEN release ; : instance-to-package ( ihandle -- phandle ) ihandle>phandle ; : package-to-path ( phandle buf len -- len' ) 2>r node>path 2r> string-to-buffer ; : instance-to-path ( ihandle buf len -- len' ) 2>r instance>path 2r> string-to-buffer ; : instance-to-interposed-path ( ihandle buf len -- len' ) 2>r instance>qpath 2r> string-to-buffer ; : call-method ( str ihandle arg ... arg -- result return ... return ) nargs flip-stack zcount debug-client-interface? IF ." ci: call-method " 2dup type cr THEN rot ['] $call-method CATCH nrets 0= IF drop ELSE \ if called with 0 return args do not return the catch result dup IF nrets 1 ?DO -444 LOOP THEN nrets flip-stack THEN ; : test-method ( phandle str -- missing? ) zcount debug-client-interface? IF ." ci: test-method " 2dup type cr THEN rot find-method dup IF nip THEN 0= ; : milliseconds milliseconds ; : start-cpu ( phandle addr r3 -- ) >r >r s" reg" rot get-property 0= IF drop l@ ELSE true ABORT" start-cpu called with invalid phandle" THEN r> r> of-start-cpu drop ; : quiesce ( -- ) debug-client-interface? IF ." ci: quiesce" cr THEN quiesce ; : boot ( zstr -- ) zcount debug-client-interface? IF ." ci: boot " 2dup type cr THEN " boot " 2swap $cat " boot-command" $setenv (nvupdate) reset-all ; : interpret ( ... zstr -- result ... ) zcount debug-client-interface? IF ." ci: interpret " 2dup type cr THEN ['] evaluate CATCH ; : set-callback ( newfunc -- oldfunc ) client-callback @ swap client-callback ! ; PREVIOUS DEFINITIONS false value elf-claim? 0 value last-claim 0 VALUE cur-brk : elf-claim-segment ( addr size -- errorcode ) 2dup elf-claim? IF >r here last-claim , to last-claim \ Setup ptr to last claim dup , r> dup , ( addr size ) 0 ['] claim CATCH IF ." Memory for ELF file is already in use!" cr true ABORT" Memory for ELF file already in use " THEN drop ELSE 2drop THEN + to cur-brk 0 ; : elf-load-claim ( file-addr destaddr -- claim-list entry imagetype ) true to elf-claim? 0 to last-claim dup -1 = IF \ If destaddr == -1 then load to addr from ELF header drop ['] elf-load-file CATCH IF false to elf-claim? ABORT THEN ELSE ['] elf-load-file-to-addr CATCH IF false to elf-claim? ABORT THEN THEN >r last-claim swap false to elf-claim? r> ; : elf-release ( claim-list -- ) BEGIN dup cell+ ( claim-list claim-list-addr ) dup @ swap cell+ @ ( claim-list claim-list-addr claim-list-sz ) release ( claim-list ) @ dup 0= ( Next-element ) UNTIL drop ; CREATE bootdevice 2 cells allot bootdevice 2 cells erase CREATE bootargs 2 cells allot bootargs 2 cells erase CREATE load-list 2 cells allot load-list 2 cells erase : start-elf ( arg len entry -- ) msr@ 7fffffffffffffff and 2000 or ciregs >srr1 ! call-client ; : start-elf64 ( arg len entry r2 -- ) msr@ 2000 or ciregs >srr1 ! ciregs >r2 ! call-client \ entry point is pointer to .opd ; : set-bootpath s" disk" find-alias dup IF ELSE drop s" boot-device" evaluate find-alias THEN dup IF strdup ELSE 0 THEN encode-string s" bootpath" set-chosen ; : set-netbootpath s" net" find-alias ?dup IF strdup encode-string s" bootpath" set-chosen THEN ; : set-bootargs skipws 0 parse dup 0= IF 2drop s" boot-file" evaluate THEN encode-string s" bootargs" set-chosen ; : .(client-exec) ( arg len -- rc ) s" snk" romfs-lookup 0<> IF paflof-start f00000 + elf-load-file-to-addr drop \ FIXME - check this for LE, currently its BE only dup @ swap 8 + @ \ populate entry r2 start-elf64 client-data ELSE 2drop false THEN ; ' .(client-exec) to (client-exec) : .client-exec ( arg len -- rc ) set-bootargs (client-exec) ; ' .client-exec to client-exec : netflash ( -- rc ) s" netflash 2000000 " (parse-line) $cat set-netbootpath client-exec ; : netsave ( "addr len {filename}[,params]" -- rc ) (parse-line) dup 0> IF s" netsave " 2swap $cat set-netbootpath client-exec ELSE cr ." Usage: netsave addr len [bootp|dhcp,]filename[,siaddr][,ciaddr][,giaddr][,bootp-retries][,tftp-retries][,use_ci]" cr 2drop THEN ; : ping ( "{device-path:[device-args,]server-ip,[client-ip],[gateway-ip][,timeout]}" -- ) my-self >r current-node @ >r \ Save my-self (parse-line) open-dev dup IF dup to my-self dup ihandle>phandle set-node dup s" ping" rot ['] $call-method CATCH IF cr ." Not a pingable device" cr 3drop THEN swap close-dev ELSE cr ." Usage: ping device-path:[device-args,]server-ip,[client-ip],[gateway-ip][,timeout]" cr drop THEN r> set-node r> to my-self \ Restore my-self ; 8a8 cp CREATE version-str 10 ALLOT 0 value temp-ptr : dump-display-buffer disp-ptr to temp-ptr " SLOF **********************************************************************" terminal-write drop cr version-str get-print-version version-str @ \ start version-str 8 + @ \ end over - terminal-write drop " Press 's' to enter Open Firmware." terminal-write drop cr cr temp-ptr disp-size > IF temp-ptr disp-size MOD dup prevga-disp-buf + swap disp-size swap - terminal-write drop temp-ptr disp-size MOD prevga-disp-buf swap 1 - terminal-write drop ELSE prevga-disp-buf temp-ptr terminal-write drop THEN ; : enable-framebuffer-output ( -- ) s" screen" find-alias ?dup IF open-dev close-node false to store-prevga? s" display-emit" $find IF to emit dump-display-buffer ELSE 2drop THEN THEN ; enable-framebuffer-output 8b0 cp usb-scan 8c0 cp romfs-base 400000 0 ' claim CATCH IF ." claim failed!" cr 2drop THEN drop 8d0 cp : set-default-console s" linux,stdout-path" get-chosen IF decode-string ." Using default console: " 2dup type cr io 2drop ELSE ." No console specified " " screen" find-alias dup IF nip THEN " keyboard" find-alias dup IF nip THEN AND IF ." using screen & keyboard" cr " screen" output " keyboard" input ELSE " hvterm" find-alias IF drop ." using hvterm" cr " hvterm" io ELSE " /openprom" find-node ?dup IF set-node ." and no default found, creating dev-null" cr " dev-null.fs" included " devnull-console" io 0 set-node THEN THEN THEN THEN ; set-default-console 8e0 cp 0 VALUE direct-ram-boot-base 0 VALUE direct-ram-boot-size : (boot-ram) direct-ram-boot-size 0<> IF ." Booting from memory..." cr s" go-args 2@ " evaluate direct-ram-boot-base 0 s" true state-valid ! " evaluate s" disable-watchdog go-64" evaluate THEN ; 8e8 cp : check-boot-from-ram s" qemu,boot-kernel" get-chosen IF decode-int -rot decode-int -rot ( n1 n2 p s ) decode-int -rot decode-int -rot ( n1 n2 n3 n4 p s ) 2drop swap 20 << or to direct-ram-boot-size swap 20 << or to direct-ram-boot-base ." Detected RAM kernel at " direct-ram-boot-base . ." (" direct-ram-boot-size . ." bytes) " s" boot-command" $create " (boot-ram)" env-string THEN ; check-boot-from-ram 8ff cp : (boot) ( -- ) s" Executing following boot-command: " boot-command $cat nvramlog-write-string-cr s" boot-command" evaluate \ get boot command ['] evaluate catch ?dup IF \ and execute it ." boot attempt returned: " abort"-str @ count type cr nip nip \ drop string from 1st evaluate throw THEN ; : (function-key) ( -- n ) key? IF key CASE 50 OF 1 ENDOF 7e OF 1 ENDOF dup OF 0 ENDOF ENDCASE THEN ; : (esc-sequence) ( -- n ) key? IF key CASE 4f OF (function-key) ENDOF 5b OF key key (function-key) ENDOF dup OF 0 ENDOF ENDCASE THEN ; : (s-pressed) ( -- ) s" An 's' has been pressed. Entering Open Firmware Prompt" nvramlog-write-string-cr ; : (boot?) ( -- ) of-prompt? not auto-boot? and IF (boot) THEN ; false VALUE (sms-loaded?) false value (sms-available?) s" sms.fs" romfs-lookup IF true to (sms-available?) drop THEN (sms-available?) [IF] s" /packages" find-device new-device s" sms" device-name : open true ; : close ; finish-device device-end \ leave /packages : sms-init-nvram ( -- ) nvram-partition-type-sms get-nvram-partition IF cr ." Could not find SMS partition in NVRAM - " nvram-partition-type-sms s" SMS" d# 1024 new-nvram-partition ABORT" Failed to create SMS NVRAM partition" 2dup erase-nvram-partition drop 2dup s" lang" s" 1" internal-set-env drop 2dup s" tftp-retries" s" 5" internal-set-env drop 2dup s" tftp-blocksize" s" 512" internal-set-env drop 2dup s" bootp-retries" s" 255" internal-set-env drop 2dup s" client" s" 000.000.000.000" internal-set-env drop 2dup s" server" s" 000.000.000.000" internal-set-env drop 2dup s" gateway" s" 000.000.000.000" internal-set-env drop 2dup s" netmask" s" 255.255.255.000" internal-set-env drop 2dup s" net-protocol" s" 0" internal-set-env drop 2dup s" net-flags" s" 0" internal-set-env drop 2dup s" net-device" s" 0" internal-set-env drop 2dup s" net-client-name" s" " internal-set-env drop 2dup s" scsi-spinup" s" 6" internal-set-env drop 2dup s" scsi-id-0" s" 7" internal-set-env drop 2dup s" scsi-id-1" s" 7" internal-set-env drop 2dup s" scsi-id-2" s" 7" internal-set-env drop 2dup s" scsi-id-3" s" 7" internal-set-env drop ." created" cr THEN s" sms-nvram-partition" $2constant ; sms-init-nvram : sms-add-env ( "name" "value" -- ) sms-nvram-partition 2rot 2rot internal-add-env drop ; : sms-set-env ( "name" "value" -- ) sms-nvram-partition 2rot 2rot internal-set-env drop ; : sms-get-env ( "name" -- "value" TRUE | FALSE) sms-nvram-partition 2swap internal-get-env ; : sms-get-net-device ( -- n ) s" net-device" sms-get-env IF $dnumber IF 0 THEN ELSE 0 THEN ; : sms-set-net-device ( n -- ) (.d) s" net-device" 2swap sms-set-env ; : sms-get-net-flags ( -- n ) s" net-flags" sms-get-env IF $dnumber IF 0 THEN ELSE 0 THEN ; : sms-set-net-flags ( n -- ) (.d) s" net-flags" 2swap sms-set-env ; : sms-get-net-protocol ( -- n ) s" net-protocol" sms-get-env IF $dnumber IF 0 THEN ELSE 0 THEN ; : sms-set-net-protocol ( n -- ) (.d) s" net-protocol" 2swap sms-set-env ; : sms-get-lang ( -- n ) s" lang" sms-get-env IF $dnumber IF 1 THEN ELSE 1 THEN ; : sms-set-lang ( n -- ) (.d) s" lang" 2swap sms-set-env ; : sms-get-bootp-retries ( -- n ) s" bootp-retries" sms-get-env IF $dnumber IF 255 THEN ELSE 255 THEN ; : sms-set-bootp-retries ( n -- ) (.d) s" bootp-retries" 2swap sms-set-env ; : sms-get-tftp-retries ( -- n ) s" tftp-retries" sms-get-env IF $dnumber IF 5 THEN ELSE 5 THEN ; : sms-set-tftp-retries ( n -- ) (.d) s" tftp-retries" 2swap sms-set-env ; : sms-get-tftp-blocksize ( -- n ) s" tftp-blocksize" sms-get-env IF $dnumber IF 5 THEN ELSE 5 THEN ; : sms-set-tftp-blocksize ( n -- ) (.d) s" tftp-blocksize" 2swap sms-set-env ; : sms-get-client ( -- FALSE | n1 n2 n3 n4 TRUE ) s" client" sms-get-env IF (ipaddr) ELSE false THEN ; : sms-set-client ( n1 n2 n3 n4 -- ) (ipformat) s" client" 2swap sms-set-env ; : sms-get-server ( -- FALSE | n1 n2 n3 n4 TRUE ) s" server" sms-get-env IF (ipaddr) ELSE false THEN ; : sms-set-server ( n1 n2 n3 n4 -- ) (ipformat) s" server" 2swap sms-set-env ; : sms-get-gateway ( -- FALSE | n1 n2 n3 n4 TRUE ) s" gateway" sms-get-env IF (ipaddr) ELSE false THEN ; : sms-set-gateway ( n1 n2 n3 n4 -- ) (ipformat) s" gateway" 2swap sms-set-env ; : sms-get-subnet ( -- FALSE | n1 n2 n3 n4 TRUE ) s" netmask" sms-get-env IF (ipaddr) ELSE false THEN ; : sms-set-subnet ( n1 n2 n3 n4 -- ) (ipformat) s" netmask" 2swap sms-set-env ; : sms-get-client-name ( -- FALSE | addr len TRUE ) s" net-client-name" sms-get-env ; : sms-set-client-name ( addr len -- ) s" net-client-name" 2swap sms-set-env ; : sms-get-scsi-spinup ( -- n ) s" scsi-spinup" sms-get-env IF $dnumber IF 6 THEN ELSE 6 THEN ; : sms-set-scsi-spinup ( n -- ) (.d) s" scsi-spinup" 2swap sms-set-env ; : sms-get-scsi-id ( n -- id ) s" scsi-id-" rot (.) $cat sms-get-env IF $dnumber IF 6 THEN ELSE 6 THEN ; : sms-set-scsi-id ( id n -- ) swap (.d) rot s" scsi-id-" rot (.) $cat sms-set-env ; : sms-get-net-boot-file ( -- addr len ) s" net" sms-get-net-device (.) $cat s" :dhcp," $cat sms-get-server IF (ipformat) $cat THEN s" ," $cat sms-get-client-name IF $cat THEN s" ," $cat sms-get-client IF (ipformat) $cat THEN s" ," $cat sms-get-gateway IF (ipformat) $cat THEN s" ," $cat sms-get-bootp-retries dup ff <> IF (.) $cat ELSE drop THEN s" ," $cat sms-get-tftp-retries (.) $cat dup IF strdup ( s" :" 2swap $cat strdup ) THEN ; ' sms-get-net-boot-file to furnish-boot-file : $sms-node s" /packages/sms" ; : (sms-init-package) ( -- true|false ) (sms-loaded?) ?dup IF EXIT THEN $sms-node ['] find-device catch IF 2drop false EXIT THEN s" sms.fs" [COMPILE] included device-end true dup to (sms-loaded?) ; : (sms-evaluate) ( addr len -- ) (sms-init-package) not IF cr ." SMS is not available." cr 2drop exit THEN s" Entering SMS ..." type disable-watchdog reset-dual-emit 2>r $sms-node find-device 2r> evaluate device-end vpd-boot-import ; : sms-start ( -- ) s" sms-start" (sms-evaluate) ; : sms-fru-replacement ( -- ) s" sms-fru-replacement" (sms-evaluate) ; [ELSE] : sms-start ( -- ) cr ." SMS is not available." cr ; : sms-fru-replacement ( -- ) cr ." SMS FRU replacement is not available." cr ; [THEN] TRUE VALUE use-load-watchdog? 1 value my-boot-dev 1 value digit-val 0 value boot-dev-no : boot-selected 1 to my-boot-dev BEGIN parse-word dup WHILE boot-dev-no my-boot-dev = IF s" boot " 2swap $cat ['] evaluate catch ?dup IF \ and execute it ." boot attempt returned: " abort"-str @ count type cr throw THEN 0 0 load-list 2! UNLOOP EXIT ELSE 2drop THEN my-boot-dev 1 + to my-boot-dev REPEAT 2drop 0 0 load-list 2! (boot) ; : boot-start BEGIN key? WHILE key drop REPEAT decimal BEGIN parse-word dup WHILE my-boot-dev (u.) s" . " $cat type 2dup type ." : " de-alias type cr my-boot-dev 1 + to my-boot-dev REPEAT 2drop 0 0 load-list 2! cr BEGIN KEY dup emit dup isdigit IF dup 30 - to digit-val boot-dev-no a * digit-val + to boot-dev-no THEN d = UNTIL boot-dev-no my-boot-dev < IF s" boot-selected " s" $bootdev" evaluate $cat strdup evaluate ELSE ." Invalid choice!" cr THEN hex ; : boot-menu-start ." Select boot device:" cr cr s" boot-start " s" $bootdev" evaluate $cat strdup evaluate ; : boot-menu-enabled? ( -- true|false ) s" qemu,boot-menu" get-chosen IF decode-int 1 = IF 2drop TRUE EXIT THEN 2drop THEN FALSE ; : f12-pressed? 34 = >r 32 = r> and IF TRUE ELSE FALSE THEN ; : start-it ( -- ) key? IF key CASE [char] s OF (s-pressed) ENDOF 1b OF (esc-sequence) CASE 1 OF console-clean-fifo f12-pressed? boot-menu-enabled? and IF boot-menu-start ELSE (boot?) THEN ENDOF dup OF (boot?) ENDOF ENDCASE ENDOF dup OF (boot?) ENDOF ENDCASE ELSE (boot?) THEN disable-watchdog FALSE to use-load-watchdog? .banner ; ." " \ Clear last checkpoint 0 VALUE load-size 0 VALUE go-entry VARIABLE state-valid false state-valid ! CREATE go-args 2 cells allot go-args 2 cells erase : $bootargs bootargs 2@ ?dup IF ELSE s" diagnostic-mode?" evaluate and IF s" diag-file" evaluate ELSE s" boot-file" evaluate THEN THEN ; : $bootdev ( -- device-name len ) bootdevice 2@ dup IF s" " $cat THEN s" diagnostic-mode?" evaluate IF s" diag-device" evaluate ELSE s" boot-device" evaluate THEN $cat \ prepend bootdevice setting from vpd-bootlist strdup ?dup 0= IF disable-watchdog drop true ABORT" No boot device!" THEN ; : set-boot-args ( str len -- ) dup IF strdup ELSE nip dup THEN bootargs 2! ; : (set-boot-device) ( str len -- ) ?dup IF 1+ strdup 1- ELSE drop 0 0 THEN bootdevice 2! ; ' (set-boot-device) to set-boot-device : (add-boot-device) ( str len -- ) \ Concatenate " str" to "bootdevice" bootdevice 2@ ?dup IF $cat-space ELSE drop THEN set-boot-device ; ' (add-boot-device) to add-boot-device 0 value claim-list : no-go ( -- ) -64 boot-exception-handler ABORT ; defer go ( -- ) : go-32 ( -- ) state-valid @ IF 0 ciregs >r3 ! 0 ciregs >r4 ! go-args 2@ go-entry start-elf client-data claim-list elf-release 0 to claim-list THEN -6d boot-exception-handler ABORT ; : go-64 ( args len entry r2 -- ) 0 ciregs >r3 ! 0 ciregs >r4 ! start-elf64 client-data claim-list elf-release 0 to claim-list ; : set-le ( -- ) 1 ciregs >r13 ! ; : set-be ( -- ) 0 ciregs >r13 ! ; : go-64-be ( -- ) state-valid @ IF set-be go-args 2@ go-entry @ go-entry 8 + @ go-64 THEN -6d boot-exception-handler ABORT ; : go-32-be set-be go-32 ; : go-32-lev1 set-le go-32 ; : go-64-lev1 state-valid @ IF go-args 2@ go-entry @ xbflip go-entry 8 + @ xbflip set-le go-64 THEN -6d boot-exception-handler ABORT ; : go-64-lev2 state-valid @ IF go-args 2@ go-entry 0 set-le go-64 THEN -6d boot-exception-handler ABORT ; : load-elf-init ( arg len file-addr -- success ) false state-valid ! \ Not valid anymore ... claim-list IF \ Release claimed mem claim-list elf-release 0 to claim-list \ from last load THEN true swap -1 ( arg len true file-addr -1 ) elf-load-claim ( arg len true claim-list entry elftype ) CASE 1 OF ['] go-32-be ENDOF ( arg len true claim-list entry go ) 2 OF ['] go-64-be ENDOF ( arg len true claim-list entry go ) 3 OF ['] go-64-lev1 ENDOF ( arg len true claim-list entry go ) 4 OF ['] go-64-lev2 ENDOF ( arg len true claim-list entry go ) 5 OF ['] go-32-lev1 ENDOF ( arg len true claim-list entry go ) dup OF ['] no-go to go 2drop 3drop false EXIT ENDOF ( false ) ENDCASE to go to go-entry to claim-list dup state-valid ! -rot 2 pick IF go-args 2! ELSE 2drop THEN ; : init-program ( -- ) $bootargs get-load-base ['] load-elf-init CATCH ?dup IF boot-exception-handler 2drop 2drop false \ Could not claim ELSE IF 0 ciregs 2dup >r3 ! >r4 ! \ Valid (ELF ) Image THEN THEN ; : do-load ( devstr len -- img-size ) \ Device method wrapper use-load-watchdog? IF 4ec set-watchdog THEN my-self >r current-node @ >r \ Save my-self ." Trying to load: " $bootargs type ." from: " 2dup type ." ... " 2dup open-dev dup IF dup to my-self dup ihandle>phandle set-node -rot ( ihandle devstr len ) encode-string s" bootpath" set-chosen $bootargs encode-string s" bootargs" set-chosen get-load-base s" load" 3 pick ['] $call-method CATCH IF -67 boot-exception-handler 3drop drop false ELSE dup 0> IF init-program ELSE false state-valid ! drop 0 \ Could not load THEN THEN swap close-dev device-end dup to load-size ELSE -68 boot-exception-handler 3drop false THEN r> set-node r> to my-self \ Restore my-self ; : parse-load ( "{devlist}" -- success ) \ Parse-execute boot-device list cr BEGIN parse-word dup WHILE de-alias do-load dup 0< IF drop 0 THEN IF state-valid @ IF ." Successfully loaded" cr THEN true 0d parse strdup load-list 2! EXIT THEN REPEAT 2drop 0 0 load-list 2! false ; : load ( "{params}"} -- success ) \ Client interface to load parse-word 0d parse -leading 2swap ?dup IF de-alias set-boot-device ELSE drop THEN set-boot-args s" parse-load " $bootdev $cat strdup evaluate ; : load-next ( -- success ) \ Continue after go failed load-list 2@ ?dup IF s" parse-load " 2swap $cat strdup evaluate ELSE drop false THEN ; : noload false ; ' no-go to go : (go-and-catch) ( -- ) get-load-base c@ 5c = get-load-base 1+ c@ 20 = AND IF load-size alloc-mem ( allocated-addr ) ?dup 0= IF ." alloc-mem failed." cr EXIT THEN load-size >r >r ( R: allocate-addr load-size ) get-load-base r@ load-size move \ Move away from load-base r@ load-size evaluate \ Run the script r> r> free-mem EXIT THEN ['] go behavior CATCH IF -69 boot-exception-handler THEN ; read-bootlist : boot load 0= IF -65 boot-exception-handler EXIT THEN disable-watchdog (go-and-catch) BEGIN load-next WHILE disable-watchdog (go-and-catch) REPEAT .banner ; : load load 0= IF -65 boot-exception-handler THEN ; : yaboot ." Use 'boot disk' instead " ; : netboot ( -- rc ) ." Use 'boot net' instead " ; : netboot-arg ( arg-string -- rc ) s" boot net " 2swap $cat (parse-line) $cat evaluate ; : netload ( -- rc ) (parse-line) load-base-override >r flash-load-base to load-base-override s" load net:" strdup 2swap $cat strdup evaluate r> to load-base-override load-size ; : neteval ( -- ) FLASH-LOAD-BASE netload evaluate ; cr .( Welcome to Open Firmware) cr cr .( Copyright (c) char ) emit .( 2004, 2011 IBM Corporation All rights reserved.) cr .( This program and the accompanying materials are made available) cr .( under the terms of the BSD License available at) cr .( http://www.opensource.org/licenses/bsd-license.php) cr cr ' start-it CATCH drop cr ." Ready!" X`hx  Ht8ssst(stsstttXthttttx0vvuvxuuvh@PPXp  6P7PGNUTnYqr!AGCC: (GNU) 4.8.3 20140911 (Red Hat 4.8.3-7).symtab.strtab.shstrtab.rela.slof.loader.rela.text.rela.opd.got.rela.data.comment.note.GNU-stack.bss d5h2j -7Xp=mm 8)BzzLzzG+LR0,[k Yp(  * mz  uz  y!m@H@(r5zXh<z8DEaSppl 0 {wHxXp(cd crzw yp,&m7nCrXSxh_mplkxPspL PuXdnsH qy<ozhs8rHq'z$/wx@^M RqXbzXlq{r|q0 Pztoe oqH,yHo((/o@yxJqhL^]f_s@er8dxHHuHlm_lx8qw 8` yln2m 8s(JzHLR\_gwxox8xx yheyhXsXrxq8 pH| n# `2p\AmPsa aqwTyq(Xpuhtyw q qph@w( w0.m<xIr(Qb\xht8zocm`\pxmsPoHo pdu8- A Jy8Qx(ey(s }shud!pX4 @oXt xyy bqx(sx5xl@qlNr\pq    wtH8xc| cn  q s $x ,( 8x Gc\ Urp b  jc {qt l   wh  e w m0 y p$ p8 /v8 Au Qx YyP `z($ hr py ~xH v0  n x mP ot r y o m0< r -m ;_ Dxd Ozxt X  iy sp@ mPp p8t np x w.patch_broken_sc1e1k_mac_setupengineusb_hcd_initprintfvsprintfio_printhex16virtio_get_host_featuresthe_data_stackget_partitionincrease_nvram_partition_sizevirtio_get_vring_descbootmsg_warningstderr_databootmsg_nvupdatep9_clunkmemmovenvram_write_qwordhv_casvirtio_vring_sizeSLOF_dma_map_outcall_clientusb_devpool_getreset_nvramSLOF_usleepadd_envvirtioblk_shutdownhash_tableusb_key_availableSLOF_bm_freeusb_hid_initthe_client_stackvirtionet_closememcpyelf_forth_claimputsusb_dev_populate_pipep9_statp9_transactiontolowernvram_read_dwordromfs_lookupctrlvirtioscsi_initvsnprintfvirtio_9p_initusb_put_pipep9_reg_transportthe_pocketsstrtoul_slof_textelf_load_filekeycodes_shift_USdevpoolelf_byteswap_header64virtioscsi_sendhv_logical_ci_loadelf_load_file_to_addrpatch_broken_sc1e1k_closevirtioscsi_shutdown.call_cwriteLogBytekeycodes_alt_GRp9_readclear_nvram_partitionusb_hid_kbd_exitSLOF_alloc_memc_romfs_lookupdelete_nvram_partitionvirtionet_readfree_nvram_buffervqhv_logical_ci_storeclient_entry_pointwriteusb_transfer_bulkfprintf_start_OFio_putcharnvram_read_qwordelf_byteswap_header32nvram_debugheadlibveth_readkeycodes_ctrle1k_openusb_hid_exitusb_get_pipevirtio_9p_loadvirtiodevvirtio_get_vring_usedSLOF_bm_allocator_initepapr_ima_sizevirtioblk_readSLOF_dma_allocsetup_new_devicethe_comp_bufferget_nvram_bufferstrncmpvirtio_9p_shutdownvirtioblk_initusb_read_keybstrncpynvram_write_bytethe_return_stackp9_attachvirtio_queue_notifynvram_read_wordepapr_magicnvram_read_byteSLOF_dma_freelibveth_openp9_openbootmsg_cp.hv_hascharusb_ehci_registerelf_get_eflags_64bootmsg_checklevelSLOF_msleepvirtio_set_qaddrSLOF_dma_map_inusb_msc_resetrecoveryelf_load_segments32elf_load_segments64virtio_get_configusb_hid_kbd_initthe_exception_framethe_heapmemsetnew_nvram_partitionlibveth_writefdt_startusb_msc_initusb_hub_init.call_client_binary_OF_fsi_startvirtio_reset_devicethe_memelf_get_base_addr32rphv_hascharhv_send_crqe1k_readGET_WRNG_LVLvirtionet_openusb_msc_exithv_putcharreset_buffersusb_send_ctrl__virtio_read_configprint_version_endset_leds_binary_OF_fsi_endspnvram_write_dwordusb_ohci_registerhv_getcharbootmsg_debugcpdpprint_msgSLOF_bm_allockbd_bufferp9_versionusb_transfer_ctrlset_envstdout_dataget_nvram_sizebootmsg_errorusb_hcd_exitthe_tibbootmsg_setlevelvirtionet_write_slof_text_endromfs_basenvram_write_word.client_entry_pointkeycodes_std_USerase_nvramwriteLogByte_wrapperhv_logical_memopvirtio_get_qsizevirtio_set_statususb_xhci_registerslof_usb_handledel_envstrlentoupperp9_walklibveth_closeget_print_bannernvram_initprint_versioncall_cget_envSLOF_alloc_mem_alignedelf_get_base_addr64usb_hcd_registerhv_send_logical_lanelf_relocate64asm_coutusb_poll_intrSLOF_free_memio_printhv_genericvfprintfthe_client_framee1k_writevirtio_set_guest_featuresSLOF_GetTimervirtio_get_vring_availbm_find_bitswipe_nvramnvramlog_printfvv&f*f:;>;J;N;RV\ &&,* . 96 9H,G X X X X F2J0b2022020022 0220 0@22@@202"0F2pJ0pV2b02022p00p 2 2 "0 &0 J2 N92 V0 Z90 ~2 2 0 0 2 2 0 0 2 (2 0 (0 2 j2 &0 *j0 N2 RW2 Z0 ^W0 2 2 0 @ 2 2 0 @ 2 2 0 0 "2 &2 .0 20 Z2 ^v2 f0 jv0 2 f2 0 f0 2 0 2 2 0 0 ^2 j0 2 0 2 0 2 0 2 &0 n2 r0 2 0 2 0 20:2F0j2v0202020*22260N0r2~020220022002262>0B0n2r2z0~r20r02r20r0202 200F2R020202062B0r2~02020&2.0b2n0202020"2*0N2Z020202020B2J020202"0j2v020202*0b2n022002020J2V02200"2*0V2b0~202020202020b2f02020"2.0x 2020 2*0$2$0 2$20$020 H0  b$2 n$0 2 0  2 0 ! 2!0!$ !B2!N0!x !2!0! !2!0! "2"&0"P "n2"z0"A "2"0"R "2#0#A #62#B0#lR #2#0#A #2#0#R $2$0$0A $N2$Z0$R $2$0$ %2% 0%4 %R2%^0% %2%0% %2%0&C &.2&:0&H &f2&r0& &2&0& &2'0'4 'N2'Z0'hn '2'0'# '2'0(g (2(*0(\6 (2(0(m (2(0(b )2)"0)04 )N2)Z0)pE )2)0)@ *2*0*8 *v2*~0*) *2*0*O *2+0+ +D +h} + +2+0+ +2+0, ,2,*0,8' ,V2,^0,p` ,2,0,o ,2,0,% ,2- 0- -62-B0-P -n2-z0- -2-0- -2-0.LU .j2.v0.{ .2.0. .2/ 0/, /F2/R0/ /2/0/ /2/00 0D 0^20b+20j00n+00< 02000+20+00B 1*21201Dw 1b21n01|u 121011 12101Y 2 2202(q 2N22Z02l 22202 22202 323&03< 32303* 3 3 4B24N04 52505L 5 5 5[ 52506(* 6D 6l 6 62606* 7 7D* 7` 7" 72707* 8 8@ 828082808 82909 9:29F09 9290:2:0:>2:J0:n2:z0:2:0:2:0:2:0;2;0;B2;J0;Z2;f0;t ;2;0; ;2<0<4  2>0>:2>F0>j2>r0>2>0>2>0>2?0?*2?60?Z2?f0?2?0?2?0?2?0?2?0@"2@.0@R2@Z0@2@0@2@0@2@0@2@0A2A"0AJ2AV0Ay A2A0A B2B0B4] BR2B^0B B2B0B_ B2C 0C D C:2CF0C C2C0C2C0C D2D0D>2DJ0DlJ D2D0DN E2E0EB2EN0E|* E E* E F FR2F^0F2F0F2F0F2F0F2F0G2G&0GJ2GV0Gz2G0G2G0G2G0G2G0G2G0H2H&0HB2HJ0HZ2Hb0H2H0M$2M$0N N O2O0O O O P P PZ2Pb0Pt P P P2P0P P Q Q QZ2(Qb0(Ql Q Q Q Q28Q08Q R R R( RlL R2HR0HR R R S SX Sj2XSp Sz0XS S S S T T&2hT, T60hTD TP Td T2xT0xT T T T U2U"0U4 U@ UT Uh U2U0U U U U V62V>0VH V\ Vh V| V2V0V V V W YJ2YR0YT Y^2Yb0Yd Y2XY2`Y2Y0XY0`Y0Y Z< ZT Zb2PZf0PZh [$L [T \d ]2`]0`] ^2 ^2 _2 ` X `@X `\X `xX `X `X `X `X aX a X a<X aXX atX aX aX aX aX bX b bX bX bX bX bX cX c X c(X c0 c8X c@ cHX cPX c` ch ct c c c d4? dZ e e` e|~ e f( fD f` fx f f g4 gd g h h iR2iV0iX ll l m22m60m8 nF2HnJ2(nZ0Hn^0(oj2mon0mp r t2xt0xt u u u0 uD xJxNxRxVx| xxxxxxz { { | |0       \   8 \ |   d 22 @ 02020t   &2*0, 2200V 20,    d xt V2(^0(0(     208 h t 2(0(2(20(0, \ l ~20  s 2808  62P>0P@ T. f2hn0hp   z I 62:0< L \ v2~0    0d t  4    0 @ ` |   DL \* vc2c0 Q2Q0  $ 8    (L 2,"0,, <t R2V0X h 20 20   Bc2Jc0P \ Q2Q02,0,$* 62,:0,J0,jc2rc0t 2 0  N2.V0.` jQ2rQ0c2"c0$t R2PV0PX 2Ҩ@Ҩ2Ұ@Ұ2Ҹ@Ҹ2@2Ҹ@Ҹ 2@ 22Ҹ0@ҸJ2N2ҨR0V@ҨZ2Ҹ^2Ҩb@Ҹf0Ҩ p 2p0p *2.08 >2F0  *  / 2@.2208l   $ *220  *   ( <* L /  20l/  2020l  2Ҹ@Ҹ`*  2Ҹ@Ҹ/ 2@4 >2F0/ 2@< V2^0/ 2@*  20/  2@n>2r>0 L B>2J>02200 z\2~\020 \2\020 20 2200 L  `  b2f2j0n0p a 0a Pa  pK t- 7  7 h p x a  l    h 8 x 20 00 22H60H8 Hx * 2200 20 x < L X f2hj2n0hr0t 2 020v2~0<   x  h  8 L ` h  20H 2 20 0 `  x  x  2`2x28 0`0x08  2808   p è  r2v0x 20 20 B2F2J0N0P x Ŋ2Ŏ2Œ0Ŗ0Ř <h T l Ƅ Ǩ  22@00@  2X2h0X "0hL ^2b0d Ȁ    x ɼ v2pz0p| ʈL ʬ h 20  x  h ˔ $! 22608 la ̔ ̨ Ͱ L Δ ή20β2Hζ00κ0H   i , Ў2В0Д 20 20 Ѡ   dh ӄ N2 V0 X dL |   Ph h xh Ր ը (h @ X *2 60  ؄ ، ؤi  Z2 ^0 ` ٚ2 ٞ0 ٠ ٮ2 ٲ0 ٴ  x 2 X0 X  x 2 "0 $ ^2b0n0v2 z2 `~0 ڂ0 `ڄ   0x L \x x ۈx ۤ ۴x  ܴ  D h  , D t  D p ߆2 ߎ0 ߐ ߰    x 2 0   2 82 p0 80 p   2 "0 $  , P  2 P0 P 2 82 "0 8&0 ( :2 p>0 p@ R2 Z0 \ 20 R2 0^0 0l x  2 0    2 0 22 >0 b2j@2@202200202260b^2f^0"2&=2*0.=02262:@>@F2J0^2b0v32z3020JH2NH0   X    h 20-   2 `2 H0 `0 H 7 "2*00x t (~2200 (22002020 (  2  0  @ xH P |   x     $i < 2 0  @ l   J2 N0 P  20  R2 V0 X     l  x h 8 L  x    h  @  P    D 8     8 D   ( h 8 H i    2*0T  * n0"2 &0 (  2 2 0 0    Hh  d x $ H (2 (0 (  (2 `0 ` ! x        x ( d  x   2 0  L   ! h $ 8  ( 4 (     x !2(! 0(! !Z2 !^0 !` !2 !0 ! !h " $8 $L X$\ X$ $x $ $2x$0x$ %&2 %*0 %p %2$%0$%2 %0 &$ &t &z2$&~0$&2$&0$' 2('0('L 'r2('z0(' '2$'0$'2('0(( (2$(0$(B2 (F0 (J2((N0((R2$(V0$(Z20(^@0(r2$(v0$( (2$(0$(2((0() )22$)60$)V2 )Z0 ) )2$)0$* *(u *\ *b2 *v0 *~2$*0$* * +V2 +Z0 +\ 8+b2$+f0$+l 8+~2$+0$+ ,H ,d ,j2$,r0$,2(,0(-4 - -2(-0(- .2$.0$.( 8.22.:0.H H.2$.0$.2(.0(. /2$/0$/62 /:0 / /2$/0$/2(/0(0 0B2$0J0$0f2 0j0 0 02$00$1 2(10(1L 1r2$1v2 1z0$1~0 12810812810824 2l 22$20$32 30 3T 3hu 3 3l 4 4 52 5F0 5 6"2$6*@$6, 6d 6 6 7 7  H7< X72$70$72 70 8P 8 8 8 8 8 X9 :` :2$:0$:2 :0 :28:08;$ ;L ; ;28;08< < <&2$<.0$<@ Xw ><w >2P>0P> ? w ?Xw ?p ?l @2P@0P@pw @ @l A A A B4q B@ Bhq Bq B C0 C@ Chw Ck Cw D q D(P D< D D El Ex E Ek Ew Fw F,w F`q Fl Fq Fq FP G q G,q G" GL H* H*2XH>0XHF2\HJ2XHN0\HR0XHT H^2`Hn@`Hv2hHz@hH| H2pH@pHL H2`H2xH@`H@xH2hH@hI IT I2I0I I2`I@`I I2pI@pI I2xI@xJ J Jr20Jv00Jx J2J0J J K K2`K@`K K*2pK.@pK< KF2xKJ@xK\ K2\K2XK2`K0\K0XK0`L0 LL L* M4 Mr2Mz0M| N2֐N0֐NF2֘NN@֘Nr2֘Nz@֘O2֐O0֐O P"2֐P&@֐P2P0P P2֘P@֘Q22֘QB@֘Q~2֘Q@֘Q2Q0R2R0R2֘R"@֘R&2֐R2@֐R~2֘R@֘R2֐R0֐RL R R R2֘R@֘R2֘S@֘ST S 8S T VD V2V0V V2֘V@֘W2֘W@֘W, W62֘W>@֘WR2֘WZ@֘Wn2֘Wv@֘W2֘W@֘W2֘W@֘W2֘W2֐W@֘W0֐X HX X, HX4 XT Xl X2֘X@֘X2֐X0֐YB2֐YJ0֐Y* Y Z2֘Z@֘Z2֘Z@֘Z2֐Z0֐[(* [N2֘[V@֘\.2\60\b2֘\j@֘\r2֐\@֐\ \ 8\2\0`@5 ` `2`0a aB2aJ0aX alT av2a~0aT a5 bT bZ2bb0b2Xb0Xb2Xb0XcL c: e2e:0f2df0dg: g hD h h i i i j@ jP j j n&n3n&n3nF&n3m&m3m&m3m & m(3m0&m83m@&@mH3mP&MmX3m`&Mmh3mp&NPmx3m&Nm3m&O@m3m&Om3m&PPm3m&Pm3m&Q0m3m&Qm3m&Rm3n&Sn3n&Sn3n &T n(3n0&Tn83n@&U0nH3nP&U`nX3n`&Unh3np&Unx3n&Vn3n&Xn3n&Yn3n&Zn3o&ao3o&bo 3o(&co03o8&e o@3oH&eoP3oX&go`3oh&h0op3ox&hPo3o&io3o&ko3o&lo3o&po3o&ro3o&ro3o&so3o&wp3p&x`p3p&xp 3p(&xp03p8&ypp@3pH&ypP3pX&zpp`3ph&zpp3px&zp3p&{p3p&{p3p&|p3p&|pp3p&}p3p&~p3p&p3p&q3q&@q3q&Pq 3q(&Pq03q8&q@3qH&qP3qX&q`3qh&qp3qx&q3q&q3q&q3q& q3q&q3q&q3q&@q3q&q3q&r3r&r3r&r 3r(&r03r8&r@3rH&prP3rX&`r`3rh&@rp3rx&r3r&@r3r&r3r&`r3r&r3r&r3r&0r3r&r3r&s3s&s3s&s 3s(&s03s8&s@3sH&sP3sX& s`3sh&sp3sx&s3s&Ps3s&s3s&s3s&s3s&s3s&s3s&`s3s& t3t& t3t&t 3t(&t03t8&@t@3tH&tP3tX&0t`3th&@tp3tx&Pt3t&t3t&Ѐt3t& t3t&@t3t&@t3t&ېt3t&@t3t&u3u&u3u&`u 3u(&u03u8&u@3uH&uP3uX&`u`3uh&up3ux&Pu3u&u3u&`u3u&u3u&u3u&u3u&u3u&u3u&v3v&v3v&0v 3v(&v03v8&v@3vH&0vP3vX&`v`3vh&vp3vx&pv3v&v3v&0v3v&pv3v&"v3v&# v3v&#v3v&$v3v&&@w3w&&pw3w&&w 3w(&'0w03w8&'w@3wH&)wP3wX&,w`3wh&,wp3wx&-w3w&-w3w&.@w3w&.w3w&/pw3w&/w3w&/w3w&0w3w&3x3x&4 x3x&4@x 3x(&4x03x8&5x@3xH&7`xP3xX&7x`3xh&:xp3xx&;x3x&;x3x&;x3x&<x3x&>x3x&?x3x&@x3x&Bx3x&Ey3y&Hy3y&Iy 3y(&Jy03y8&Ky@3yH&O0yP3yX&Oy`3yh&PPyp3yx&Ty3y&Vy3y&X`y3y&Yy3y&Zy3y&[0y3y&\y3y&\y3y&\z3z&]0z3z&]z 3z(&]z03z8&^ z@3zH&^pzP3zX&^z`3zh&_0zp3zx&_z3z&`@z3z&az3z&bz3z&iz3@&X& `&{h& `p&&x&Jp&h&JH&&O`&&&&J(&P&&H&|H&I@&0& &&h&8&8&(&0&8&p@&P&hX&8h&8p&&&&&& <&`8& &`P&X& &0(&0&HH&HP&``&|h&x&&&&&&&L&&&& &08&@&PX& `&px& X&& && L&& l&& && &( & (&@8& 8@&XP& hX&ph& p&& && && (&& p&& &&&& &0(&00&H@&lH&``&h&xx&D&&&&&&&&4&&p&&&( &(&@8&$@&XP&`X&ph&p&&&&&& &&L&&&&&&&0(& 0&HH&@P&`h&p&&&&&&h&&&&&&&( &`(&@8&@&XP&X&ph&Hp&&&& &&T&&&&& &(&88&@&XP&X&ph&p&& &&&& \&&&&|& & &0& \@& PP& \`& pp& \& & \& & \& & \& & \&!& \ &!00& \@&!PP& \`&!pp& \&!& \&!& \&!& \&!& \&"& \(&"88& \H&"XX& \h&"xx& \&"& &"&&0&"& &"(&&0&"& &"H&&0&#(& 0&"h8&@&0H&#HX& `&"h&p&0x&#x& &"&&0&#& &"&&0&#& &#(&&0&$&  &#X(&0&08&$8H& P&#X&`&0h&$hx& &"&&0&$& &"(&&0&$& &"H&&0&$& &"h& &0(&%(8& @&"H&P&0X&%Xh& p&$x&0&%& &%h&0&%& &"&&0&%& &"&&0&&&  &"(&00&&8@& H&#P&0X&&`h& p&#x&0&&& &$x&0&&& &&%&h&&&%&&0&&&  &(&%0&h8&h@&H&P&8`&8h&p&0x&'0& &h&&h&0&'& &&&0&'& &&&0&((& 0& 8&@& H&P& X&`&0h&(Hx& & && &&0&(& &&&0&(& &&&&0&) & (&0&8&0@&)@P& X& `&Xh&0p&)p& &&&&&0&)& &&&&&0&)& &&)& &)(&00&* @& H&P&X&*0`&h&p&*0x&0&*`& &h&'&&)&& &&&'&&&)& & &0&08&*H& P&hX&'`&p&x&)&&&& &&&'&&&& &&&0&+h&  &(&)0&8&@&H&P&0X&,8h& p&x&&&)&&&0&,& &&&&&&)&&&0&,& &-80& 8& @&H&0P&-P`& h& p&x&0&-& & & &0&-& &&0&-& &&0&.& &  &0(&.08& @& `H&hP&0X&.Xh& p&.hx&0&.& \&.& \&.& &&&0&.& &&&0 &/ 0& 8&/@&PH&0P&/P`& h&8p&Px&0&/& &&P&0&/& & &/`&0&/& & &/&0&0 & (& 0&/8&0@&0@P& X& `&/h&0p&0p& &/0&P&0&0& &&P&0&0& &)&h&)&/&&( &.(&0&/8&H&.P&X&.`&0h&1& & &&1&0&1& &-`&& &&&-`&&0&1& & &-(&0&8@&H&PP&X&-`&0h&20x& &&-&&8&&P&&-&0&2& & &&&0&3&  &h(& 0&@&3H&0P&38`& h&((p&x&&&&0&3& &((&/&&&&0&3& &&0&4 (& 0& 8&@&0H&4HX& `& h&p&0x&4x& & &&0&4& & &&0&4& &4X& `&8&0&5 & (&0&8&@&0H&5@X& `&hh& p&0x&5x& &.h&&3&h&P&&&&0&5& &h& &&5 &0(&68& @&H&P&hX&`&h&hp&x&&&&&0&6X& &&6h&&&0&6& &5&6&0&7 & (&0&h8& @&H&1P&X&h&p&6hx&&0&7@& & &)&8& &h&7P&&&0&7& &((&h &(&0&3H8&@&3HH&7P&X& `&p&5x&0&8(& &&h& &&1&&&&0&P&&& &P&& &(&0&08&8H& P&8`& h&hp&8x&&&&0&9h& &&&&6 &&3H&9x&& &&3& & (&8&3@&H&3P&X&0`&9p& x&h&&((&h& &&9&&0 &&8&&4&&&&&&& &0(&:8& @& H&P&9xX&0`&;Xp& x&&5&&:&0&;& &;&)P&0&;& &;&&0&<& & &88(&0&:8&0@&<0P& X&<@`&)Ph&0p&Hx& &! &&P&0&>& &!@&&P&0&>& &>&&>&&>&0 &?0& 8&<@&H&>P&0X&?Ph& p&=x&&>&0&?& &!`&&P&0&?& &=h&&?&0&?& &= &(&*00&8&?@&0H&@0X& `&>h&p&>x&&?&0&@x& &>&&*0&&@&0&@& &?&&?&&?&0 &A0& 8&=h@&@@H&P&@@X&?`&0h&AP& &"&4&&"&3&8&0&A& &&&&&0&A& & &(&0&8&@&H&P&X&`&h&0p&B0& &&&&(&&0&B& &'&&&&&0&B&`&C0(& 0&.8&@&H&0P&CH`& h&.p&x&&0&C& &&h&8&/&&8&&0&C& &h&% &(&0&8&0@&D(P& X&h`&h&p&x&%&&0&Dp& &5P&&B&&?`&B&&"(&&0&D(& 0&5P8&H&BP&X&?`&Bh&(p&"Hx&&0&E@& &5P&&B&&@@&B&(&"H&&0&E(& 0&5P8&H&BP&@X&A``&Bh&Xp&"hx&&0&F@& &5P&&B&@&@&B&X&"h&&0&F(& 0&5P8&H&BP&@X&@`&Bh&Xp&"hx&ˆ&0&G@ &¨&G¸& &8&G&0&G& &8&G&0&H0& @&HHX& h&Hpx& À&@È&Ð&H`Ø&à&è&pð&H`ø&&P&&H`&&&& &0&H& &' &0&H`8&@&H&P&H`X&`&h&p&x&XĀ&Ĉ&Đ&0Ę&I0Ĩ& İ& `ĸ&I@&0&I& &I& &J& (&J8@& P&JX`& h&J(p&JHx&ŀ&0ň&JŘ& Ũ&J& &X&&&J(&J&&JH&& &&&Jp&0 &J0& \@&KPP& \`&Kpp& \ƀ&KƐ& \Ơ&KƸ& \&K& <&K& <&L&  &5P(&8&B@&H&LP&`&0h&L8x& ǀ&KLj&Lǐ&Kǘ&LǠ&0Ǩ&LǸ& &K`&L&0&L& & &&L& &0(&M8& @&hH&%P&X&`&0h&MXx& Ȁ&hȈ&Ȑ&4XȘ&Ƞ&hȨ&Ȱ&ȸ&h&&0&M& &h&8&8&1&(&88&@&0H&NX& `&hh&8x&8Ɉ&1ɐ&ɠ&8ɰ&ɸ&0&Nx& <&N& <&O& < &O00& @&OPP& X&O@`&O`h&p&0x&Opʈ& ʐ&Jpʘ&Pʠ&ʰ&Jʸ&O& &J&&.&&Jp& `&8&&.& &80&I@8&0@&OP& `&Ppx& ˀ&!ˈ&Pː&˘&0ˠ&P˰& ˸&!@&P&&0&P& &! &P&&0&Q & (&0&8@&H&0P&Q@h& p&hx&8̈&/̐&̠&8̰&̸&8&&0&Q& &h&&;h&&& &9x(&0&08&RH& P&QPX&h`&h&0p&Rh̀& ͈&QP͐&h͘&͠&4ͨ&'Ͱ&͸&&&0&R& & &&8&R&0 &S0& 8&P@&H&RP&)X&Q`&Rh&0p&SP΀& Έ&S`ΐ&((Θ&PΠ&ΰ&&0&S& &(&QP&h&&'&&0&S(& 0&Rx8&h@&H&3HP& X&S`&h&Sp&Tx&0π&THϐ& Ϙ&PϠ&Ϩ&;hϰ&ϸ&Q&R&0&T& &T&h&&&0 &U0& 8&@&QPH&hP&X&'`&h&0p&UPЀ& Ј&RxА&UИ&U`Р&0Ш&Uи& &TX&LH&L&0&U& &U&0&V&  &U(&LH0&L8&0@&V8P& X&`&TXh&)p&((x&р&ѐ&ј&Ѡ&MѨ&Ѹ&&LH&0&Vp& &&U&)&((&& &(&0&M8&H&P&LHX&0`&Wp& x&PҀ&҈&Ґ&PҘ&UҠ&PҨ&Ұ&0Ҹ&W& &P&&&P&U&P&&0&W & (&@0&h8& @&P&X&`& h&x&@Ӏ&Bӈ&Ӑ&4Ә&Ӡ&UӨ&Ӹ&0&X@& &&U&0&X& &&N&h &80&8@&1H&X&8h&p&8Ԁ&Ԉ&hԐ&)Ԙ& Ԡ&Ԩ&1԰&&)P&.&&&.&0&Y & &h &P(&8&@&H&P&PX&`&Y0h&x&Հ&Ո&Ր&՘&ՠ&Pը&հ&40ո&&P&&7&)&&& &6&&%&&4 &0&8&0@&Z(X& `&hh&Pp&ր&ֈ&֐&.֘&֠&֨&hְ&ָ&&8&8&h&&&%&&4&h&P &0&8&@&H&.P&X&`&h& p& x&׀&׈&Z@א&)Pט&Pנ&װ&׸&&&3&.&&&&&.&0&[p & (&0&8&&@&H&0P&]@`& h&p&x&"؀&]P؈&0ؐ&]ؠ& ب&ذ&ظ&"&]P&0&]& &&&"(&]P&0&^ & (&0&(8&"H@&]PH&0P&^@`& h&p&Xx&"hـ&]Pو&0ِ&^٠& ٨&ٰ&"ٸ&4&8&& &]&&0&^& &(( &(&%0&8&&H@&5PH&X&h`&h&Bp&x&%ڀ& ڈ&&Hڐ&ڠ&ڨ&0ڰ&_0& &&&4X&&H&]P&_@&0&_&  &0(&@& H&P&`X`& h&`pp&%x&0ۀ&`ۘ& ۠& &`8& @&`H&aP`& h&%p&0x&ax܈& ܐ&%ܘ&hܠ&ܨ&4Xܰ&&ܸ&A&0&a& &a&a&0&a& &% &Mh(&00&b(@& P&b`h& <x&b݈& ݐ&^ݘ&ݠ&`ݨ&ݰ&]ݸ&bp&& &]&_&^&0&b& &bp&&a &b@(&b0&bp8&@&`H&P&0X&c p&x&cވ& <ޘ&cް& ޸&h&&&((&&a&b@&c&&(& &(&0&8&H&)P&.X&0`&cx& ߀&ah߈&hߐ&ߘ&`ߠ&0ߨ&߸&((&&&%&&c&'&&)P&)P&& &(&0&&8&H&P&)X& `&0h&d& &d&h&&a&h&a&&&.&0&e& &((&e&& &)P(&)P0&.8&H&.P&0X&fp& \&f& &f&8&0 &0&f& &`&&%&h&&f&P& &(&00&fH& P&X& `&p&x&B&&&&h&K`&8&&/`&&8&&B&B&)P&)P&.& &0&8&@&.H&0P&g``& h&p&J(x&J&&&O`&&J&&&((&&gx&&)P&h& &&&h&J &B(&00&h@& H&J(P&O`X&`&hh&Jp&x&/&&&J&&&&K`&/`&& &J&B&&&&0&i`0& 8&ip@&K`H&hP&0X&jHp& &j& &x&j&&8&&&j&& &&h&8&8& &(& 0&j8&@&0H&jX& `&jh&p&hx&h&&&5P&&h&*0&&%&B&&&&&&0&kx&  &j`(&0&8&0@&l8P& X&8h&hp&(x&0&lp& &J&&4&J&&K&h&(&0&l& &m& &m  &CX(&00&m0@& H&8X&m `&h&0p&m`& &m &&&&8&I@&0&m& &]&0&n& &j` &b(&P0& 8&n@&mpH&0P&n0h& p&^x&&P& &n&mp&0&n& &m&P&0&n&c0&m@&0&n& &m&8(&h0&P8&'H@&nH&hP&]X&5P`&p&Bx&&]&&^&0&o(& &m &&&o8&P&Mh&n&&8&h &h(&0&j8&h@&H&P&hX&`&h&0p&o& &o&((&& &&&&0&p& &m &&&o&P&LH&n &(&88&h@&LHH&0P&p`& h&8x&h&LH&0&q& &&%&h&&n&&0&q& &r&  &m (&0& 8&m @&BH&X&`&h&r(p&x&&&&&q& &0&r8& & `&m &B&m &&&&q&&r(& &&(&0&8&P@&0H&r`& h&p&x&%&&&&0&sx& &rH&P&&n&& &n&0&s& &rH&P &(&n0&8& @&nH&0P&t(`& h&mp&sx&r&0&t& &m&P&&n&& &n&&s&0&t& &rH& &0 &u 8& @&mH&PP&X&n`&'h&x&4&&t&&r&0&uP& &m&4X&&P&&n&P&8&n&t8&P &(&n0&8&0@&uP& X&m`&h&tp&x&0&vp& &&%&&n&0&v& &rH&&0&v& &m&P &(&n0&v8&r@&0H&w(X& `&mh&Pp&x&n&v&r&0&wx& &m&t8&&0&w& &m&w8&t&0&x& (&x8@& H&xHP&X&'`&p&hx&&&&&&&&&&&n&xH&&0&xX& &rH&xH& &(&P0&h8&n@& H&xHP&X&0`&y p& x&rH&xH&&P&&n&&&xH&& &n&0&y& &m&P&&n&xp &r(&00&z@& H&mP&PX&`&nh&xpp&rx&0&z`& &m&P&&n&xH&&&xH&&n&0&z& &m&P& &n(&xH0&8&@&xHH&P&nX&0`&{ x& &&J(&&JH&&&Jp&&O`&&&J&&&&0&{&  &(&0&J8&@&H&O`P&X&`&&h&Jpp&x&JH&&&&&J(&&0&|0&|&|&}8&}@X& <h&}h& &}& & `&&&}&0&}& & &&&}&0&~(& 0&}8&H&P&X&XP`&h&p&0x&~@& &h&8&8&&P&}X&Mh&LH&L(&&&h&8 &8(&8&@&H&}P&0X&~p& x&L&h&P&&~X&P&|&&h& `&8&&P&}&Mh&LH& &h(&88&8@&P&HX&`&Mhh&LHp&x&&~&L(&0&& &((&e&&f&&)P&)P&P&&n &((&0&((8&[@&P&LHX&8h&I@p&Px&8&n&n&(&0&& &((&e&&&)P&)P&P&&((&[&(&LH0&8@&I@H&P&(X&`&0h&& & &J&&j`&h&&m &&&&&&&(&0 &p0& 8&@&0H&P`& h&p&&H&&8&I@&&0&x& &o8&P&&n&0& &(@& H&jP&X&P`&@h&hp&x&4X&&&h&&h&&4X&&&h&&&&&&h&&0&P & (&j`0&f 8&P@&P&pX&.`&h&p&0x&@& & &&m@&J&@&U&8&L&L&O&&L&P&&H&h &(&8&H&0P&h& <x&& <&& <&& &&((&&&5P& &(&0&8&@&H&P&X&`&((h&Kp&gxx&&)P&h&&&&4X&&&&&0&& &j`&&0 &8& @&bH&PP& X&n`&Ph&`Hp&%x&n&c0&0&P& &j`&h&0&& &&%&bp&&b&%&&0 &0& 8&P@&H&nP&0X&Pp& x&j`&b&P& \&n&n&c0&0&& &j`&b&P& &n&n&c0&0&(& 0&j`8&b@&PH& P&nX& `&nh&c0p&0x&@& &j`&b&P& &n&]P&c0&0&& &j`&b&P& <&n&P &I(&n0&c08&0@&P& X&j``&bh&Pp& Lx&n&P&n&c0&0&p& & &0&& &&0&& &j`&b &P(& 0&n8&@&]H&P&c0X&0`&(x& &P&8&n&n&0&& &P&n&0&& &j`&((&e&P &0&p8&.@&H&P&fX&P`&p&Px&P&n&n&P&n&n&(&0&& &lH&&0&&  &P &P &P &n &n (&0 0& @&  H&h P&Mh X&e `& p&) x& &. & &f & &3 & &. & &0 &` &  &P &m  & & &P && &n (&n 0& 8&% @& H&0 P& h&  p&% x& &0 & &  &  &&p & &0 & &  &  &&p & &0 & &  &c0 &0 (&( @&  H&bp P& X&b `&n h&0 p&X &  &j` &P & & &P & & &P & &0 & &  &j` &P & & &P & & (&P 0& 8&0 @& P&  X&j` `&P h& p& x&Q & & &P & &0 &p & & & & & & &@ (&8 @& H&X `& h&x &  & &# & & l & &  & &  &&!4&( &!(&@8&!@&XP&"X&ph&"Lp&&"&&#&&#P&&#&&$, &(@&$dH&Ph&$p&x&$&&%L&&%&&%&0&'8&@X&'L`&h&'&&&&&&&&&&&(& 8&(t@&H`&(h&p&(&&)8&&)\&&)& &)(&8@&)H&X`&*h&x&*T&&*&&*&&*&&+4& (&+l0&@P&+X&`x&+&&,h&&,&&,&&-D&0&-8&@X&.8`&h&-&&.\&&.&&/(&&0& (&/`0&@H&0LP&`h&/p&&0&&/&&0&&3&&3&(0&38&HX&1`&h&1&&2@&&3&&B<&0&B8&@X&3`&h&4&&5&&C@&&A8&&A &08&A@&PX&B `&px&>&&?&&?H&&?&&@&&@P &08&@@&PX&@`&px&6&&6&&78&&7&&DP&&FX& &E &80&F8&PH&CP&h`&Eh&x&EH&&D&&Ex&&D&&D&&E&&6&( &>(&@8&>P@&XP&=X&ph&>p&&=&&=&&<&&> &&.8!|N ```./A\/A49 8`}>.8!|N ```jH`K8`N ``8`K```+AL`xc$" }I.|i/A0||!cHI`8!p|N 8`N ```|xj 9*+!@H+A`xc$B }*.|j/Ac|H)`8!p|N /8pAp88px 9} 9D|3x|"8 H ``` @9)A(B@$ + @ @9)@}&HPy% |3xKH8!p8`|N 8`N ```|x !Ka8!p|c|N ```|x !K8!p|c|N ```|x !KQ8!p|c|N ```|!H`8!p|N |!Aa|}x"!Q;; ;C```xH``xA_+ ;>@@}P{z CxHI`8xx | Ha`<iH``;?+ A@@T9Y/ }YA}*KxxK`8!8` !A|aN 8!8y|c!A|aN `||!A8pK}8pH`8!|N ||!A8pK=8pH`8!|N |mB| B|B| @xc|cxN `|3x|;x|& x|B`|\}( |!BA@8H|BB€8B0*K8|A@!N |!|3x|;xK !|N "0!K|?;ex!qH``@/A<88e 8H `/|d@xc 8K`|}yAxH `/|dxA;f`:g{ z 8ap:pH=`9 8ap!t9 !x{ 9 z !p|AH I`x8K/|qxA>88L8ap:fH`z 9 8ap!t!x|pH `99!=89g8L:a8ap;!{ aHa`8apptx|H `a>>:g;xz :g; z1 A88L8apH`!8apptx!|H !`88L8apH`a8apptx|aH `88L8apH`8apptxa|H `!88L8ap}J!}JH1`!8apptx|!A!H M`y /A/A !ydy(~x9i9|e:yk xcd/)y ,xG@A +A}FA@:k9J~i9 ``` y)} KxB+A|3x9@A(:o~iHyJ|SxB}*J@@@@@A+}J@PA/xd8|:x A88|9 `y)} KxB}*J288L8apH`8ap|ptxA!H `88L8ap{ H}`8apa|ptxA!H `88L8apHA`8apptx|H m`ax@8!px|!Aa!AaN ``FyJ}JCx}*J@@At|P|b/|AK``8xd}:}&8.y)})CxK9 K9 Ktx8K|qxKPH@A|P|b/|A`K@``||x!K=8!|dxx|K|!Aa!?9 |x88L;f{ 8ap!!HU`9 8ap|p!t!xH}`/A$>>:f`:fX;z z { x; ;;@HH```H`8apptx|H `!x/}?KxA!88L8ap{ !H`8app!tx|AH`!88L8ap/Al8adxKa8! |!AaN 8! 8`|!AaN  ``||~x8L|#x8!8ap;H`=B="9Jf`9)gؑAp9@At!9@9 8ap!Ax|H`!/@|/xA@x8HU`8`8!|N ```88H`8!8`|N 8`K```|Aa|#x|+x88L!|zx?b;{fh;{{ 8apHE`="8ap9)fxap!|txHi`="=B8ʊ@/A@88L8ap?H`=";f`9)g;{ 8ap!9!!|ptxH`8L88apH`="8ap9)g|!9!!ptxH`8`K֥`8`K֕`8`Kօ`88L8apH!`="8ap9)haptx!|HE`/A88L8apH`="8ap9)f蓡|!ptxH`/AH8ap88LH`="8ap9)hptx|!AH`K`=B="88Lʊ8@8apH=`="8ap9)g|!p9 !t9 !xHU`!=B8`*D8!Aa|N ```8`K```=B*D/M |="=B8@8Lʊ8!18apHa`="8ap9)g |!p9 !tH`8!|N ```+|exAx+A@+A8`N ```8`<8D"/8`L x N 8`<8D"/8`xc L x N ```8`<8D"/8`xc L x N +|ix|#xAd+A<+A8`N ``8`@8}%Kxx D"8`N `8`@8}%KxD"8`N ``8`@8}%Kxx D"8`N 肀P|!A(|N!A(8!|N |N <8犸=G */A,} 8`P@M }#KxN ```|;x} 8`P@@N ``="9I= a)jy)e)Sxca)}#Hy#|cN =B9*iN `|vN ```|v|cN ||dy 9^9 `` })BBy*y) })Ry*}*J})HU)>H@>y*@y*@Љ> /A/A/@^~/A/A/@^mI/v@X>/@L=0> HH@8/A09 8`(H|``=@= aJP@A8?8`!A|aN ``="0?0 ܡ>;HA88`8?!A|aN ="0 > H@B,> H@y*@l^U)8~x})R%/A(/@8|8~0x H`K8|8~0x HY`8`K```+@|!Aa|#x!Q$/@ࣄ/@=0$?0H;H@|{x/A/@K`88HM`/@ȁ/At=8@Ad}]J @A<`H}]J @A9)}I0UJJ }*HP8@y) @```8`8!!A|aN ```/@<8`8!!A|aN `=;] 88*;)ZJ;: #xH`K`x8|ex#xK9`K`9 < :9 :9 :|dx88z Hy`&x88z*Ha`0cx$x8*K`8`K``<;8h0x8HY`|zy@x88H`>/A;<&8xxH`BcxxK`]B^8`Kx``8`N ```/=0|#xM |8E99@|x8*8T!p8q!8p9 r!89 vx!89 8atvA|AzA!yH`9.9A} 9 })BBy*y) })R8py*x}*J8p})H!KM8!|N ``="0iN ``|x +!@$|#x/"A+"@T/Am'/@$/5@t88j|H `8!p|ct|N ``/D@<$/C@088|H `8!p|N ``8!p8`|N ```HOQ`8!p|ct|N `88j|H<`8!p|ct|N ```+L #/L ||+x!HUM`8!p|N ``9 #N ```8`N ```N |a|+x|{x|#x|+x;!a```?}]Pxx})tU(28,}JJx //*A\AlAH`?})t9)JJ?}]Pxx})tU(28,}JJx //*@?;y?Kd/>Atx8!a|N ```<x8lH~`8!8`a|N 8K|A!a!1|+x|wx|#x|#xH~`+:A\; 09@(;(;c?1;{R{e 8x;H-`9@4}?}_.9@I; xxH}`xH~5`+8cxi }]JA9;}K.{ 885|x`K1`888apH`H+U`x88p|fxxH,9`A(=B19*0xe~x)Ii}IIN!A(8!|!AaN `; 9@;KK.:8z |~ijx`85KM`="1|޸xx 88K`K0 /A="1i޸8`N ``|;:l|#x|zx~xx|+x|3xH{`<x8h8H}`/A<x8h@H}`;?x;hHxH}`/AxxH}y`;?x;hPxH}]`/xA,x?H}A`;hXx|}Pxx xH}%`/xA$xH} `|}Pxc @|ix@ xy< 9<+AxxxH|-`9 ;<~xxHz`xHz`+Axx```?P;{ }Cx+.x{ ,+ ?A8A4;?;P}Cx+.{ x{ ,+ ?@ЙGA;H{u`?|x/@|=1'H޸/AT+A>; 9 =B1x~x*Hy`;xHy`/CxA@xexKK`K`H@```>,AA$>/ AAtK`/@CxK]`>++q(A8`8!!|AaN ``PAK=`/A!;9~x{9 :$AxHA`/@p<Hqi`!8||HP|Hs`}_خ=}*J}?ٮ=^}*J>8!a|N ```|aA|#x|x|+x|3x!ad/AdC9 +@,H```} CxH@@8}_H+A|/9 y A}_@9)})Ry) H@A;@@X|]/A8+@p8!8`Aa|N ;@A|`&Tc8!Aa|N |/Ap_P@A+A\8H,``}Cx(@@@}_(P@+ AA,/9y A}_@9%})Ry% (@AȈ|Dx8Hq`<Z9)})R<:9)K9 `<K8`xxFxKK|a!A|+x!A|~x8|#xx8Hp`<x8sP8HqA`/@;;;;@;=```@@l}>}^I}>/4A+4@/BAD+B@/]A/AL/CA*9)@A``|`&Tc8!!|AaN `/A+A4/A|/@=*=*9)K/A,/2@T*=*9)K`/5A/6@$*=*9)K`:8|#x|"Hom`}>}=JI}>9)Kx`8!8`!|AaN ``*J;U)@.}IKx=K*9 +Aԙ=*9)K``*=*9)K;K`*= *9)K:8|x|"HnM`}>}=JI}>9)KX`*=*9)K8`8!8`!|AaN  ```|?1<;|~x8sP8}8!qHm}`^8`9*y) +A98`} H6q'@,8!|N ```>85  ]/;A9@4]=;>2/A 9 2;?9 ?>?>6/@89@|3x9 ``9)y) +}GRyJ @/AD9 7_?|3x;9 `9 /A ?;y  +@>B/@Љ>C/@|>]/A(9 ];?9 ?9 ?9 ?9 8!?8`|N 9 6;?9 ?>?K9 C;?xHh`x8cxi 8?}%KxHk}`?9)JKD9 B;?xHhU`x8cxi 8?}%KxHk5`?9)JK|?18;8H|}xx;!QHj`="1=B1 9 =B1*KЉ`8|dx8~8Hj`888apHjQ`8apqvsK8~848D8CK`="18xx 88HK`xx8HK`8!|N ```|9 Aa=B1?1?b!a#||x;;;{iP;@*})t```/)}#Kx/AA`HkM`dx/xAHHh%`dx/xAHh `x;|P|~48ap{ HgI`}!88 8apIpHm `Ti>|c4+A؁<4U)@.|i|?})t/.@D?/;})t/)}#Kx@88!kA|c4a|Tc~xcN ```x8apHd`8ap;HeI`88 8apHlA`Ti>|c4+@8``8!A8`a|N ``|!Aa?1?B;!A;Zl;9 |yx|#xx;~:Dx!pHd`DxcxHd`=1x(KA9 =B1*;@K=`KU`xK`>// Ad@@8`8!!Aa|N ```K`/A;Z{Z!AKx?/@?/A =1(?8q*@cxHc`/@=1(/A!p=1?Hx88_Hb`8!8`!Aa|N ```>KX``8apK /A4!pK``x88Hbi`K<```xdx8p8K1`/@>/@(8`Kx```8`Kd```|?18H;|}x8x;!QHd`="1=B1< 8l9  8=B1*Ha`Kʵ`8|dx88Hd`=B18*8=B18ap*Hdm`=B18ap*9@A!pK8848D8CK`="1=B1x88HK!`xx8HK`8!|N ```|!Aa|#x||x|+x!888aHc`?/@;<x8sP8Hc`/@{ x;[8{Z DxK/Ax!/@܉!/AP=1?1H;/Ax/@@+A+@h9 8`>>9 >H_=1?;,x?1H=B1*=1;?ܑ(H_`/A0="1/@ 8~x8@H``8`;lxH_`/A$8~x8H``9 =B1*h9 =1(8`8!!Aa|N ```8at88l8K/@8`8!!8`Aa|N +A8`8!!Aa|N ``9;8apxEx!Ham`!/A/AD/@\8at88l8K/A@!8ap88x K/@K``_?=1;,x?1H=B1*H]`;/A=1H/A;lxH]`/@?=1=B1(9 *="1iKб`=B1j/A/x@P8H`Y`!/A!/@܉!/Axa88KQ`8`K`exH` `K8~x8@H^%`^8K0?88Hx>!>H_`9 ^>^KŁ`8|dx8~8H_`888apH_I`9 888at!H_m`888apAH_U`8apAAqAvAsAAA͛AKy848D8C8~KU`8x88x 8HK`xx8HKȑ`9 8`>K``8at88,8@K1Kx``8~x8H\`9 =B1*hK```!ʁ_/^?A>^A8~8HZ`/A$8~8HZ`9 =1(K;^<Cx8lHZ`!q)/A;?l#xHZ`/ACx$x8H[`xK;<x8lHZE`!9)U)>+@P^/@Dx8,8@H[`^8K(aKέ`aK`K``````||x|+x|#x8(x!A8apH\`/_9 !p!vAw@;8{ 9 ;`D})RB99An} `` })BB8!y*y) })R|y#}#J}#Hxc N 9 K``||~x8`!Ha`|yA$9 38??8 8H[`8!x|N ```||~y!Ax=B19*/@ H````8/AHxx8H[`/@8!8`|N ```8!8`|N ``|A!a|#x|+x|zx!188;(8apHZ`9<+A?b1;;{x88HZ`/A4?+AL+:A8apHY`?(/|~xAT|= x9 =8ap8xHZi`/Al/Axdx8HZE`/@xdx8HZ)`/@>/A@{ ;~(;>6K`8x`|excxK%`xx#xHY`8Cxdx|K`8!!Aa|N `="1x8HY1`?+@xxxbK,#Aİ.K``8ap{ K;~(;>6|}xK`8x`|ex8K=`K8ap{ Ky;~(;>6|}xK`Cx8p;~(H`88cx{ HX-`K5`8x`;>6|excxK`xx#xHX1`K%`K=`H````CxK`K5`/AK$xx8HW`K``xxxbK*KL`8`K,``8`}xH]Y`8p8|~x8cHWq`>9@x^9)>HQ`KT`9 ?.K``|a|x;|#x;`{ !Qc/A+AHX`/Ax8:HR`|}yAP4+{ Ax8apxHT`}!ip8ap88HZ`+|jApxyJ"}Ii+:AD;/{ @T8!}#a|N ``;;K8!8`a|N ``x88apHS`8aptHR`K``="1iN ``||}x8d|#x|+x!qK/A +'@?/A\/:A$8!8`|N 8<xxH`8!|N 8(xKe`8!|N `|= `|;x|x8c!#9 #|3x8HTA`x88HT-`8!|N ||dx|x8!q8axHS`888a}HS`9 8x!{8ap9 8!|HS`ap8!|N ```||~x8`@!HY%`88|xHS`_= xy)}IKx?K8!|cxx|N ``=B19*)/A8I@@H,``I@A)8/@8`N 8`N ```|8`(!HX1`8!p|N ```|!qa8`@HW`|yA888HQ`K`K|$ x8dq8HQ`8!x|N ```||y!qAK/A 8!8`|N `|$ x9 $px8HQ`/@P=B19*I/A=B18!9*x8`I9 8?8|N `8`@HV`|iyAd=@=aJyyJ I_ I _I_IK KhKt```||#x|x8`@!qHV-`/<1|}xeAhx8HP9`<1;f?;zK}="1<18="198=@8="1aJe8="1}Cx80= FUk~y)ƙe<1<1(8&'9 'K<1="18(<1<19 9E 9&x;H `H `/@TKI`Ka`H`Kq`/@ xK `H e`/A9>y>!@8!|N K`Ke8|dxxHN`K```|8!HN`8!p|c4|Tc~|ctN |a|#x||x88cx!1;;HM`x8:HI`|y@HX/}>|xA@88:HI`9>P/@/;;|x@/@08`8!a|N `A/@/A<x8iXHL-`|yxA<8i`HIQ`/@49 8!Й;8`a|N P{ +AHxx8apHK`89 8>pK|yA { |c8|{HL`8ap8Ky|eyAcx8x HL`xK/@KdxKAK```|!A9 ?"?B??a|#x!Q;$;c;;9i;Zix;ih;hXH8``HU`@xx;AxHG`@Ahx//'@0Dxx|;x@$xxHF`K``xxHU `K```?x;i`xxHI`|~y}?P}*/A}_R;A*/:@}=P9@})/}]I@<x8iXHF1`>;/AD?;iH```>/A xx8HG`/AxxHE`<x8iHFm`/@ <x8iXHF```8!!A|aN <x8hXHEU`K$```|88|x?1; !8apHIe`=B19 * =B19 *!=B19 *"K`="18.88|fx8a~K`8#8a8.8"KŁ`x89 8a!HI%`9@ 9 A9@!A!K`8|dx8aHH`9 9@!Ʊ!9 A!9@9 8~A±!9@9 ;x8dAı!K`8!p|N |:="1?(;;sTx!qKm9 =B*sTK-`KE`xK `>/+ AT@08!8`|N ```K`/A;{!AK8!8`|N `|Aa|x!a#/@9 =B*sT;8`HM`/;;@;`||xA(/AP/A/8`A,8! a|N `9 x! h! lH`|}yA^.=1;89(?]{ƈT^0]^4] ^-UG0yJUH02|;x}JCxI;/ApH``/@<8ax88HB`?y)Gy)A_?H@@_*yJhR})/}>@D_/@8x8HA`_*yJhR})/}>A9 =B1*08`8! a|N ```x9>(8;8a h!xHA1`8a hH%`|yAx88HA `?/At;(x8xH@`xx8|K `9 8`?K4K1`8x8 8:;|fx8aK`8x88aH@}`ƛK=`8|dx8aH@Y`!9@88AU)~9@a)`8a!9 A!ƛH?`K`8|dx8aH?`K`8|dx8aH?`A(=19(08x8H)Ii}IIN!A(8! a8`|N ```axK9`|{yAlKy`/A\K`|dyAL8{8(H?1`cxK`K,``x8xHy`/AxH`8`Kl8a hxH`|}xH%`K,```|iyAX<19F( /A(=18`9H *9@((I(N <1*8 (8`'N 8`N ||}x8`0|#x!qHC`|yA<808H=`x8xH=`8x8H=`8!x|N ``|=B19*(|~x!/@HD(/A88xK`/A8!x|N 8!8`|N ``|iyAX<19F /A(=18`9H *9@( I N <1*8 8`'N 8`N |8`|#x!HBE`|yA888H=B|4/ s`A/A8U(>/A/A<@8`I9JI8!Aa|N 9 <L```8!8`Aa|N `> U*>+Ad=y)9H,}*J}IR}IN D$DD`<4 8} A\m&/A@@AdA=B18`*x9@֐<1Gh^ I ```8!9 A=1a|(N ```{ ; J@@?;iH@x8H.`,#A8c8H.`,#A;@@xxH/`x8xx H2`/@xH/`88 8c|H4`<1xc 9#gd+A<cxs`8K8`K=" s`9 =B1*d;8x8y H1`=1(@/A/;;Ahx8 8FxK`9 <1?9 ? 9 ? A(9'0cxxx)Ii}IIN!A(9 8`<0K ```cx9 8<,K8`K`=B s`K`9 =1(h8`K```9 <1'h8`K```9 =B1*h8`K```9 =1(h8`Kp```9 <1'h8`KP```9 =B1*h8`K0K`8 8;0;C|fx8xK`Kl``4=19@(x<1쀑I=B1*`}'^}*J9)@@X9 =1(h8`K=18`(xI9JIKl`8/A<+A44K|`="18iX8 x |c:H/`=B cxs`K1<1>d<1G`9 H9)})R'`@\4mI/@<8/@9 8`<0KcxK<1=B1'x t<18`I9t9JIK=B1x*H8!88;;!K`K<s`K`="1 cih=B19 *N ``||#x<1<1fH<1p/=19`<1H@=B1쀑jh<19@<1x!qFdgg8@/A}%?1<;88i8?H7`/@8<1db8!|N 9 8`ב?0KH5i`;{sd; ;--;xxH5=`H?u`/?/AtA0AA@}:8K`CxxK`|~yA/@;xxH4`H?`/?/@/[Ax8.H `|~yA8~8.H `/Ax8/H `|~yA89}DP8ap}J}QH]`Cx8p8p8K5`/A8x8apKM`cx8H`xH`8!x!Aa|N ``8]H `,#A}>P8/x}:H `|yyAѮ8~xK‘`/A,8cxH y`xH]`8!x!Aa|N `x|N ``8!8`|N ;K|Aa?|x;d;!Q;iP;@#/)}#Kx+AAH `x/xAHu`x|}yxAH]`x|P|}48ap+ { xAXH`}!Ip88 8ap;H Q`{ +A {?+.@P?;KD8`8!Aa|N `x8 8apH`8apyH`Kh`k0c|cK`````||}x8!aJ8iI!A|aN 8`K#U)>#N |/!!AA(/A 8H9`8!p|N 8`K||#x8|+xx`}%Kx!H `8!p|N |?|kx8s!}d[x8!AH !`8!|N #/L 9)#N ```/ A,9#+@ / A|c4Tc~|cN `8`N ```||x!q#/A/Ax#}*A/OA}P}DR/@8PK-`|c/Ax/O@t_9 ?j8!|N ``8p8K-u`/@Xap8!|N ```8`?9@}IK```9)})Kt`8`Kp```|!Aa|}x!A|+x;d;;; ;$/AX``9IUH>+)A$+Ax}!xpK;x~ xK/A}!)p8apKm`/A:8ap889IZKQ`~Kd@9>+A}!xpKq;x~ xK /AKx```9)U*>+ AK`]}!)p/ALxK8apK`/@D8!8`!|AaN ``]}!)p/A,xKK ]}!)p/AxKK]}!ip/AxKKxKK ``||#x!Q$/A(|}x;;H?;/A+%@9Ao9H\``+iAl+xAd+XA\+pAT+cAL+sAD+%A+OA4+oA,|;x}&Kx?8|+d@``9|:}x}B8p8'ppK]/@$?;;/@,``8!x|N ;K``K="8isK||#x|+x|~x}%Kx8@!A8apH`8p|x~{ K$`8!x|N |9E="+ 9)r|+xI!aiApaxA @|x|#x@=B1*H/#A$9@-I9 =B1*H#9)#9Ap8!}J8`I?9)?|N ```8!8`|N ```+xK9Ap?8!8`P}J讙I?9)?|N |a|~x|+x|#x8 8!a|3x|;x}CxK`/|cA9 ``9)})/@y) })H@T})P/})@D9)y* >9J}IH`````>9)>B8!8`a|N 9 Kx|!Aa!Aapx!>b|zx|#x|+x|3x|gx; :: : 0;a@:@x{1:sr>/A8}Z8P@,+%A';>/p8p@9 'ap8!@p|zPx|!A|ca!AaN ``9A9H\`+iAl+uAd+xA\+XAT+pAL+cAD+sA<+%A+OA,+oA$|3x*8>|+d@`99Ap}|2} B& ( !+0A+.: ;A/A:;}9IUH>+)A+)@9I+ Ad}A;*p{ <KP`<9\+lA}\Sx:K`<9\+hA}\Sx:K`V8}!9J)p~ P6xP9A,!p9-z$ }3R)}H8Ap9JAp}{x8 ~x98pcxKcx}{x8 K<K`}!cx8p88 8 9)pK<ApAp9JApKz$}A}3J8)~x98pcxH8*p}{xKacx}{x8K<Kx`z$}A}3J8)~x98pcxH8*p}{xKcx}{x8K<K(`|< x:0<K<:K`<:K`9';!p9 %'pKDCan not open "%s" because file descriptor list is full Can not open socket, no parent instance Can not open socket, no parent package Can not open socket, no MAC address Can not open socket, file descriptor list is full my-parent/rtas Could not open /rtas rtas-size Size of rtas (%x) too small to make sense Failed to allocated memory for RTAS Could not open /rtas instantiate-rtasinstantiate-rtas failed read-pci-configibm,read-pci-configwrite-pci-configibm,write-pci-configget-time-of-dayassigned-addressesreggetpropfinddevice/chosen/aliasesnetbootpathtestinterpretclosewritereadseekpeerchildparentinstance-to-packageopenclaimreleasecall-methodrtas-read-vpdrtas-write-vpdset-ledwrite-mm-logyieldset-callbackbootmsg-warningbootmsg-errorname#address-cells#size-cellsrangeslocal-mac-addressstdinstdout/cpustimebase-frequency:////@/: ERROR: Can't resolve domain name (DNS server is not presented)! Giving up after %d DNS requests ERROR: Bad URL! ERROR: Bad host name! %02d Giving up after %d bootp requests bla.::::1%s%x%02x%s%x00:0:0:::0%d KBytesblksizeoctet%d Receiving data: Repeating TFTP read request... Lost ACK packets: %d %03d Aborted Giving up after %d DHCP requests  Bootloader 1.6 E3000: (net) Could not read MAC addressbootpdhcpipv6 Requesting IP address via BOOTP: Requesting IP address via DHCPv4: Requesting information via DHCPv6: Requesting IP address via DHCP: E3001: (net) Could not get IP address%d.%d.%d.%d E3002: (net) ARP request to TFTP server (%d.%d.%d.%d) failedE3008: (net) Can't obtain TFTP server IP address Requesting file "%s" via TFTP from %d.%d.%d.%d Requesting file "%s" via TFTP from %s TFTP: Received %s (%d KBytes) (net) unknown TFTP errorE3004: (net) TFTP buffer of %d bytes is too small for %sE3009: (net) file not found: %sE3010: (net) TFTP access violationE3011: (net) illegal TFTP operationE3012: (net) unknown TFTP transfer IDE3013: (net) no such TFTP userE3017: (net) TFTP blocksize negotiation failedE3018: (net) file exceeds maximum TFTP transfer sizeE3005: (net) ICMP ERROR "net unreachablehost unreachableprotocol unreachableport unreachablefragmentation needed and DF setsource route failedE3014: (net) TFTP error occurred after %d bad packets receivedE3015: (net) TFTP error occurred after missing %d responsesE3016: (net) TFTP error missing block %d, expected block was %dE3006: (net) Could not initialize network device Reading MAC address from device: %02x:%02x:%02x:%02x:%02x:%02x unable to allocate memory, parsing failed tftp:// tftp missing in %s missing ] in %s missing filename in %s wrong format IPV6 address in %s missing . seperator in %s missing domain in %s DNS failed for IPV6 ping device-path:[device-args,]server-ip,[client-ip],[gateway-ip][,timeout] E3000: Could not read MAC address E3006: Could not initialize network device %02x:%02x:%02x:%02x:%02x:%02x DHCP: Could not get ip address Own IP address: Ping to %d.%d.%d.%d success failed Reading MAC address from device: netbootpingUnknown client application called argv[%d] %s No such callback function 0123456789ABCDEF^cSc2tP2tP`0`P p       ` p ``@ppp   p !"'(*+0. ./p00<0P011 1@1`114@445<0 B`EFFGH@HpHHJL0LQTWXZ^P`b d0fhnopPqtvvwxxy yyz`{}`}0pPpP`p0`@``@ŀ`ȠP0@`ΐՐհ p`ؐ0`2uIH`GCC: (GNU) 4.8.3 20140911 (Red Hat 4.8.3-7).symtab.strtab.shstrtab.rela.text.rodata.rela.data.rela.opd.rela.got.bss.comment.note.GNU-stack ( "&83@.޸0> 9#@HXC(M1eIR02uP,[DDk `  @ `  2uP %; 2s@IDP`n(hD 2s `488xh4 ( x8*ht88<?(DhpQ 2s[lsH}X8(ltxHt,(4hh 2uI(4 <X4Scp4h8xxH X$h8p@X(X 2s@/;@BXtY`dl0dq\yl 2t XHt HdHt 2t(x|xtxt"h'|3@; 2t0C(8JV[ 2t8@hrhz@Hd8  2tx(,dDl"D4HBX4Mh0Udu\  h$0 2t|x%X1xAJPHZeHpPw`$0<L `XhlX 2tHDxt .LC3._start_kernel.callback_entrycall_client_interfaceall_dhcpv6_llstrcpyset_ipv4_routerhandle_dhcpv6translate_address_devprintfvsprintflast_router_prom_entryrecvhandle_arpget_arg_ptrset_timersend_ipv4get_sec_tickshandle_udpfd_arraymac2eui64._exitneighbor_creatertas_tokenof_finddevicememcpypingneighbor_addfirst_ip6set_ipv4_addressmallocrtas_callvsnprintfip6_create_ll_addressset_mac_addressof_getpropof_set_callbackhandle_udp_dunstrtoulhandle_dnsof_call_method_3handle_ipv4socketof_glue_init__client_endstr_to_ipv6tb_freqip6_create_prefix_info_callback_entrysendget_mac_addressget_timerisxdigitstdin_datapong_ipv4strtolfill_udphdrip6_prefix2addrrouter_addwritestrcatof_writehandle_tftp_dunof_get_macof_readall_routers_llsend_router_solicitationhandle_dhcp_startof_instance_to_packagestrstripv6_to_strreadnetbootstrncmpof_closefirst_neighborstrncpystrcasecmptftpget_args_count_rtasparse_tftp_argsmemcmpfirst_routerdhcpv6find_neighborstrtoiphandle_ipv6of_opendhcpv4sbrkhandle_tftpip6_cmpsend_ipmemsetfill_ip6hdrmainall_nodes_llsend_ipv6getchardns_get_ipunknown_prefixdhcpexception_stack_framestrcmplast_ip6handle_icmpv6send_neighbour_solicitation__client_startsprintfrtas_call_entrypre_open_ihbootpdhcp_send_releaserouter_createsend_etherargncpyhandle_tcp_dunget_ipv6_addressmalloc_alignedstdout_data._callback_entryisdigit.call_client_interfaceof_interpret_1ip6_stateset_ipv4_netmaskbootmsg_errorwrite_mm_logip6addr_add_gotis_ra_receivedfind_routerof_glue_releasecallback_exitping_ipv4handle_tcpfill_iphdrstrlendns_inittoupper.rtas_call_entrystrchrset_ipv6_addressrtas_argsfill_ethhdrrtas_initlast_neighborreceive_ethervfprintffree._entry ( n2r@2 20 @5 2@N  62 >@ c 20 2 @ f2 n@ 20 O I B2F0H v28z08| 2h0h 20 2 @ DU 2 @ J 2 @ 8G  R `E E  ( #    k     8, @, j?8 r?0 x   ?0 2 0 "  2@ @@ "2  *0  0-  P  dc  z2 0 2  2 0   20 00   2 0   2` 0`   22 60 8  j2@ r@@ -   X 2H @H 2@ @@ y >2@F@@Py | X20! 2 0 20! 2$0$20! 2(0(20! 2,0,2000! 20002$@$>2 B@ p) ) 2,@,2(@(<) ) 20@0() 2@0@i 2`0` 2X0XB2hN0h`i j2xr0x i 2`20`0 i  \i f2n0 i 2`20`0i  20( i 20 i 2"04 i 20 0i :2B0d i 20 xi 2`0` i 2&08 i 20 i 2&08 i 20 i 2h&0h8 i 20  i *220T i 2 0  @i J2(R0(t i 28"08D i 2H0H `i j2Xr0X i 2`0`  (i  22p :0p H  i  2x 0x ! i !*2!20!L !i !2!0! "f2`"j2"n0`"r0"i " " "2"0"i # #62#>0#`i #| #2#2#0#0#i # #i $( $<i $h $i $ &i &, &Di &l &i & ' ' ( (F2(Z0(li ( (2`(2X(0`(0X(i ( )0i )X ) *@i *J2`*N2*R0`*V0* *# *# +j2h+n0h+|i +2x+0x+ +28+2@+@8+0@+2`+i +2+0`+0, ,(i ,22,:0,\ ,lz ,|z ,z ,i ,2,0, ,i ,2,0- -(i -22-:0-X -` -j28-n2@-z@8-~0@-i -2-0- -2D-0D."2D.&0D.>2@.B28.J0@.R@8.`i .j2 .r0 . 0 ?P0R20V00820801821801j201n001# 1i 1201002202 002(i 2@ 2^2 2f0 2l] 2~20200323 03] 3,] 3P] 3 33 4b 4P; 4# 4# 4205005205 005205005&205*005Ti 5nh25vh05z25~06r20C6v00C620C620600C600620C600C62(60(7] 7 < 7@ 7T# 7l~ 72072(70070(8i 8< 8F20C8J00C8X# 8p# 8|< 8 8~ 8208208008008208009i 9"20C9200C94i 9<< 9T 9l# 9v20I9z00I9| 9 9= 9 :20C:00C:20C:00C:*20:.20:200:600::2(:>0(:20:00:20:2:00;0;20C;20C;00C;00C;Di <220C<600C<8 N20C>b00C>20C>00C?^20?f00?00?20I?20?00I?00@220I@600I@# @ @20I@00I@# A A|# A B/ B8 B20CB20B00CB00B< B] D(i D0< DH DP< D# D# D~ D20D00D] E# E,# E@~ E20E00Fi Fd F20F00G 1 GPM Gf G HH I# I2I0I JT Jz21OJ~01OJi J J KB K$# K, KHj KVh2KZh0KB K21UL01UL L:21UL>01ULV21ULZ01ULh# L21OL01OL2L0L L28M08MP M2@M"0@M$P M22HM:0HM@P MXP Mf2PMn0PMtP M2XMP M0XMP MP NW N  N, NW N21UN01UO21WO01WO O O< O@ OH O= O O2O0O PH PR2PV0PX Px P2P0P P P2XP0XPP P P# Q>2`QB0`QD Q# Qi Rn21XRv01XR R21WR01WR21OR01OS  S@s Ss S21WS01WS# S TV2TZ2Tb0Tf0Tr2@Tt T~21YT@1YT T0@Ti T TB U U < U4# UH U|i U U U V= V0 VB2VJ0VP V< V] W21YW @1YW# W8 WF2HWJ0HWT W# X# X# Z8# Z HZi Z2Z0[] \# ]# ^b21Y^f2^j01Y^r0^# `d `# ` `# a21Ya 01Ya$i a.21Z a221Z a601Z a:01Z aB21ZaF01ZaH< a\# api a xaB a21_a01_a a bB21_bF21_bN2Pb^01_bf0Pbn01_b bP bP bW cA c c cA dR21YdV2d^01Ydf0d d d21ad@1ad d21ad01ad d d e0= ej21aen01ae e21ae01ae21_e01_e f f8 f`o f21Yf01Yfi f21Z f21Z f2f01Z f0g01Z g21Zg01Zg g< g0# g:21_gB01_gJ21ZgR01ZgTi g^21agf01agx xgB g21_g21ag01_g01ag g h@i hZ2hb0hh] h hh21ah21Yh01ah01Yi21_i21Yi01_i21ai"01ai&21ai*01Yi201ai4 iF21aiJ01ai`W ix iW i21ahi01ahi21ai01aj Xj# j Xj hk 21_k21Yk01_k21ak"01ak$ k.01Yk:21ak>01akP kf21akj21akn01akv01akz21_k~01_k' k21ak@1ak# k k# l W l8i lP< ld# lxi l# l# l xlB m m  mP XmlW mz21ahm~01ahm m m21am01am2m0n n n<W nR2nZ0n\ nW n n o# o( p# pn&2pr&0p] qT# qj21bqr01bq] q` q] q] r] r@< r\ rp# r~ r21br@1br# r s s(< sD sX s|v si s< s s# s s t t = t,# tP tx( t# t% u(> u@ utW uA vLW v\ v21bv@1bv wu wL w# w# x # x4# xX# x( xi x y"&2y&&0y( y( z# z < z z(# zx z] z&2z&0zt2zt0{( {X {( {21b{@1b{# {21b{@1b{m2{m0{ {2{l2{0{ 2{l0| 0|K2|K0|h2|h0|621b|:@1b|>21b|B@1b|d |j^2|n2|r^0|vV2|z2|~0|V0|0|L | | | |= | | }$< },+ }<# }p] }i } ~ ~2X~0X~P ~2`~0`~s  W 8 X# h #  22x2h2X00x0h"0X0x LF F x 20P &2X.0X0F J2N0xT F 20s 2X0X 2X 0X F J21b N01b \i f21b n01b r21b!z01b!~21b"01b"  2 0j B # < # dm 21b(2@1b(0 20   0= 20( `W j21b(v@1b(\ 21b(@1b(<# T zK2K0 j < # h2h0R21b0V@1b0i  j # (< <# Jh2Nh0# # P f2n0# H# v21b0z01b0# ` # # 8~ P pj # < # i  #  <  # .h22h0C p 9 #   %  } ,D Z^2^^0n2v020( i # $# n^2r^0g  V2V02&0B2J0( # # V2V0Dg 21b801b82200 2021b8 01b82&0<x t 2021b801b8i 21c@ 01c@4B Nh2Vh0 j 21cH@1cH f2n21b8r0v01b8z20i 21c@01c@2021cH@1cH    <B N21cHR@1cH\ t# ~21cH@1cH  #   #   0# >h2Bh020     4j B21cHJ@1cHN2V0\ l |  21cH@1cH 21cX@1cX21b801b821c`*@1c`4 8 @ R2 ^0 2,0,21cx@1cx21ch01ch21c01c2 0 0 P h] | 0 21cd01cd2 0  2 0 21cd01cdi 21c@01c@0B >h2Zh0 2 0 21ch01ch21ch01ch21ch01ch621ch:01chV21chZ01chv21chz01ch j 21cx@1cx21c01c21c`01c`21ch01ch21cx@1cxR21cXZ@1cXh# r2 ~0  21cd01cd21c`01c`01c` 21cx21ct@1cx01ct21ct01ct21cH@1cH8 F2 J0 b21chj01chn21cv01c21c01c21cH@1cH21cp01cp21c@21c01c@21ch01c01ch21cx21cd@1cx01cd21b8201b8"0*2,x 62:0>0@ P V21cXZ@1cX\ f2j0l v21cHz@1cH  =  ( 0 @ z21cX@1cX  , 22608 N21c`R@1c`20 2 0 2(2$0( 0$4 <n l |_  n 2000 ,d B2hF0hH ld 2@0@ 20  # <A TA lA A A 20 2p0p i 4  n @ H P= p4 2 0  , i Z 2$ 0$P# Z2$^0$t] ] # 2$0$] ] ' &2$*@$:2>0P b2 j0 l |   i 0# :2$>0$^2xf0x2@0@ q 2$0$2$ 2$0$0$DY f2n0t 20 q 2$@$20 ] { ( D] ^2b0d |q 2 X 0 X x  ( < ^2$`W j2$r0$z0$20 2$@$Y |  2"0$X D N2$V0$    ( 62$:0$d t7 i  i i 2P0P  Q *2x20x4 P] l] ~2$@$ a i   ^2f0hX z20X 2$0$A #  i Di Xi xi A ] # ]  # 8] T# l] # ] #   a ,i < h xa i  i  4 X h7 i   7 i  8i Ti li z2h0h 20x    20   4 F2N0P ` l  2 (0 (x 202 0 x   ( 8 B2 pF0 pLx X b2 @f0 @lx |    2 0 x  2 0 x  2 X0 Xx  2 H0 H x 0 :2 >0 Dx R2Z0\ n2 v0 |x    20x    2 &0 (x 8 D X j2 r0 t    2 0     2  0    ( < N2 xV0 xX h t  2 P0 P    2 (0 (    ( W 2 H0 HT     D \o tQ     7 ( 4 r2 Pz0 P  2 0  2 0  2 0   2 0   "2 *0 0 < J2 R0 X d r2 hz0 h  i Z ( 8a X ha  i 2P0P 4 2 0  , 4# >2B0D P' ^2b0t # 2 0      @ = .2H20H4 b2@f0@h q 2 0   a   a , L `A r28v08x  a 2 0   2 0  *2 h.0 h0 ÄW 2P&0PD \P tP ĜW A ,W < Ś2Ţ0Ŭ Ŷ2ź0ż 20 V:2^:0l. z2x~0xƀs ƞ2Ƣ0Ƥs ƶ2ƺ0Ƽ 20 0$ DS x nj   XT  ( 21d01de ,e r21dԂ@1d @* z2ւ0ְ ׸R  R 2 0 X H X  Hڄ Xڤ>  X H A <> X Xp Hۄ X۴ X H   X  H4 XT p X܈ Hܠ A   X  H4 Xh X| Hݔ A  X HX 8`  8 8 8 84 h X?2?0 X* E z2021eH01eH21eH01eHl 0 &2Z02 0 0  d      ` p   &1d&1d&3&`3&03&3&`3 &(30&83@&H3P&X3`&h3p&Px3&3&3&3&p3&3&3&3&3&3(& 038& `@3H& P3X& p`3h&p3x&3&3&3& 3&3&`3&3&`3&3&3&@ 3(&038&p@3H&P3X&p`3h&p3x&p3&3&3&3&3&3& 3&3&p3&3&  3(&!038&&@3H&'P3X&)`3h&*0p3x&- 3&-3&.p3&3&3&/P3&/3&03&0 3&0@ 3(&0`038&0@3H&0P3X&3@`3h&3p3x&33&43&;03&;P3&;p3&<03&ata \ base address for command-block 0 VALUE >ata1 \ base address for control block true VALUE no-timeout \ flag that no timeout occurred 0c CONSTANT #cdb-bytes \ command descriptor block (12 bytes) 800 CONSTANT atapi-size 200 CONSTANT ata-size : ata-ctrl! 2 >ata1 + io-c! ; \ device control reg : ata-astat@ 2 >ata1 + io-c@ ; \ read alternate status : ata-data@ 0 >ata + io-w@ ; \ data reg : ata-data! 0 >ata + io-w! ; \ data reg : ata-err@ 1 >ata + io-c@ ; \ error reg : ata-feat! 1 >ata + io-c! ; \ feature reg : ata-cnt@ 2 >ata + io-c@ ; \ sector count reg : ata-cnt! 2 >ata + io-c! ; \ sector count reg : ata-lbal! 3 >ata + io-c! ; \ lba low reg : ata-lbal@ 3 >ata + io-c@ ; \ lba low reg : ata-lbam! 4 >ata + io-c! ; \ lba mid reg : ata-lbam@ 4 >ata + io-c@ ; \ lba mid reg : ata-lbah! 5 >ata + io-c! ; \ lba high reg : ata-lbah@ 5 >ata + io-c@ ; \ lba high reg : ata-dev! 6 >ata + io-c! ; \ device reg : ata-dev@ 6 >ata + io-c@ ; \ device reg : ata-cmd! 7 >ata + io-c! ; \ command reg : ata-stat@ 7 >ata + io-c@ ; \ status reg 00 CONSTANT cmd#nop \ ATA and ATAPI 08 CONSTANT cmd#device-reset \ ATAPI only (mandatory) 20 CONSTANT cmd#read-sector \ ATA and ATAPI 90 CONSTANT cmd#execute-device-diagnostic \ ATA and ATAPI a0 CONSTANT cmd#packet \ ATAPI only (mandatory) a1 CONSTANT cmd#identify-packet-device \ ATAPI only (mandatory) ec CONSTANT cmd#identify-device \ ATA and ATAPI : set-regs ( n -- ) dup 01 and \ only Chan 0 or Chan 1 allowed 3 lshift dup 10 + config-l@ -4 and to >ata 14 + config-l@ -4 and to >ata1 02 ata-ctrl! \ disable interrupts 02 and IF 10 ELSE 00 THEN ata-dev! ; ata-size VALUE block-size 80000 VALUE max-transfer \ Arbitrary, really CREATE sector d# 512 allot CREATE packet-cdb #cdb-bytes allot CREATE return-buffer atapi-size allot scsi-open \ add scsi functions : show-regs cr cr ." alt. Status: " ata-astat@ . cr ." Status : " ata-stat@ . cr ." Device : " ata-dev@ . cr ." Error-Reg : " ata-err@ . cr ." Sect-Count : " ata-cnt@ . cr ." LBA-Low : " ata-lbal@ . cr ." LBA-Med : " ata-lbam@ . cr ." LBA-High : " ata-lbah@ . ; : status-check ( -- ) ata-stat@ dup 01 and \ is 'check' flag set ? IF cr ." - ATAPI-Status: " . ata-err@ \ retrieve sense code dup 60 = \ sense code = 6 ? IF ." ( media changed or reset )" \ 'unit attention' drop \ drop err-reg content ELSE dup ." (Err : " . \ show err-reg content space rshift 4 .sense-text \ show text string 29 emit THEN cr ELSE drop \ remove unused status THEN ; : wait-for-ready get-msecs \ start timer BEGIN ata-stat@ 80 and 0<> \ busy flag still set ? no-timeout and WHILE \ yes dup get-msecs swap - \ calculate timer difference FFFF AND \ reduce to 65.5 seconds d# 5000 > \ difference > 5 seconds ? IF false to no-timeout THEN REPEAT drop ; : wait-for-status ( val mask -- ) get-msecs \ initial timer value (start) >r BEGIN 2dup \ val mask ata-stat@ and <> \ expected status ? no-timeout and \ and no timeout ? WHILE get-msecs r@ - \ calculate timer difference FFFF AND \ mask-off overflow bits d# 5000 > \ 5 seconds exceeded ? IF false to no-timeout \ set global flag THEN REPEAT r> \ clean return stack 3drop ; : cut-string ( saddr nul -- ) swap over + swap 1 rshift \ bytecount -> wordcount 0 do /w - dup ( addr -- addr addr ) w@ ( addr addr -- addr nuw ) dup ( addr nuw -- addr nuw nuw ) 2020 = IF drop 0 ELSE LEAVE THEN over w! LOOP drop drop ; : show-model ( dev# chan# -- ) 2dup ." CH " . \ channel 0 / 1 0= IF ." / MA" \ Master / Slave ELSE ." / SL" THEN swap 2 * + ." (@" . ." ) : " \ device number sector 1 + c@ 80 AND 0= IF ." ATA-Drive " ELSE ." ATAPI-Drive " THEN 22 emit \ start string display with " sector d# 54 + \ string starts 54 bytes from buffer start dup d# 40 \ and is 40 chars long cut-string \ remove all trailing spaces BEGIN dup w@ wbflip wbsplit dup 0<> \ first char IF emit dup 0<> \ second char IF emit wa1+ \ increment address for next false ELSE \ second char = EndOfString drop true THEN ELSE \ first char = EndOfString drop drop true THEN UNTIL \ end of string detected drop 22 emit \ end string display sector c@ \ get lower byte of first doublet 80 AND \ check bit 7 IF ." (removable media)" THEN sector 1 + c@ 80 AND 0= IF \ is this an ATA drive ? sector d# 120 + \ get word 60 + 61 rl@-le \ read 32-bit as little endian value d# 512 \ standard ATA block-size swap .capacity-text ( block-size #blocks -- ) THEN sector d# 98 + \ goto word 49 w@ wbflip 200 and 0= IF cr ." ** LBA is not supported " THEN sector c@ \ get lower byte of first doublet 03 AND 01 = \ we use 12-byte packet commands (=00b) IF cr ." packet size = 16 ** not supported ! **" THEN no-timeout not \ any timeout occurred so far ? IF cr ." ** timeout **" THEN ; : pio-sector ( addr -- ) 100 0 DO ata-data@ over w! wa1+ LOOP drop ; : pio-sector ( addr -- ) wait-for-ready pio-sector ; : pio-sectors ( n addr -- ) swap 0 ?DO dup pio-sector 200 + LOOP drop ; : lba! lbsplit 0f and 40 or \ always set LBA-mode + LBA (27..24) ata-dev@ 10 and or \ add current device-bit (DEV) ata-dev! \ set LBA (27..24) ata-lbah! \ set LBA (23..16) ata-lbam! \ set LBA (15..8) ata-lbal! \ set LBA (7..0) ; : read-sectors ( lba count addr -- ) >r dup >r ata-cnt! lba! 20 ata-cmd! r> r> pio-sectors ; : read-sectors ( lba count addr dev-nr -- ) set-regs ( lba count addr ) \ Set ata regs BEGIN >r dup 100 > WHILE over 100 r@ read-sectors >r 100 + r> 100 - r> 20000 + REPEAT r> read-sectors ; : ata-read-blocks ( addr block# #blocks dev# -- #read ) swap dup >r swap >r rot r> ( addr block# #blocks dev # R: #blocks ) read-sectors r> ( R: #read ) ; : set-lba ( block-length -- ) lbsplit ( quad -- b1.lo b2 b3 b4.hi ) drop \ skip upper two bytes drop ata-lbah! ata-lbam! ; : read-pio-block ( buff-addr -- buff-addr-new ) ata-lbah@ 8 lshift \ get block length High ata-lbam@ or \ get block length Low 1 rshift \ bcount -> wcount dup 0> IF \ any data to transfer? 0 DO \ words to read dup \ buffer-address ata-data@ swap w! \ write 16-bits wa1+ \ address of next entry LOOP ELSE drop ( buff-addr wcount -- buff-addr ) THEN wait-for-ready ; : send-atapi-packet ( req-buffer -- ) >r ( R: req-buffer ) atapi-size set-lba \ set regs to length limit 00 ata-feat! cmd#packet ata-cmd! \ A0 = ATAPI packet command 48 C8 wait-for-status ( val mask -- ) \ BSY:0 DRDY:1 DRQ:1 6 0 do packet-cdb i 2 * + \ transfer command block (12 bytes) w@ ata-data! \ 6 doublets PIO transfer to device loop \ copy packet to data-reg status-check ( -- ) \ status err bit set ? -> display wait-for-ready ( -- ) \ busy released ? BEGIN ata-stat@ 08 and 08 = WHILE \ Data-Request-Bit set ? r> \ get last target buffer address read-pio-block \ only if from device requested >r \ start of next block REPEAT r> \ original value drop \ return clean ; : atapi-packet-io ( -- ) return-buffer atapi-size erase \ clear return buffer return-buffer send-atapi-packet \ send 'packet-cdb' , get 'return-buffer' ; : atapi-test ( -- true|false ) packet-cdb scsi-build-test-unit-ready \ command-code: 00 atapi-packet-io ( ) \ send CDB, get return-buffer ata-stat@ 1 and IF false ELSE true THEN ; : atapi-sense ( -- ascq asc sense-key ) d# 252 packet-cdb scsi-build-request-sense ( alloc-len cdb -- ) atapi-packet-io ( ) \ send CDB, get return-buffer return-buffer scsi-get-sense-data ( cdb-addr -- ascq asc sense-key ) ; : atapi-read-blocks ( address block# #blocks dev# -- #read-blocks ) set-regs ( address block# #blocks ) dup >r ( address block# #blocks ) packet-cdb scsi-build-read-10 ( address block# #blocks cdb -- ) send-atapi-packet ( address -- ) r> \ return requested number of blocks ; : atapi-read-capacity ( -- ) packet-cdb scsi-build-read-cap-10 \ fill block with command atapi-packet-io ( ) \ send CDB, get return-buffer return-buffer scsi-get-capacity-10 ( cdb -- block-size #blocks ) .capacity-text ( block-size #blocks -- ) status-check ( -- ) ; : atapi-read-capacity-ext ( -- ) packet-cdb scsi-build-read-cap-16 \ fill block with command atapi-packet-io ( ) \ send CDB, get return-buffer return-buffer scsi-get-capacity-16 ( cdb -- block-size #blocks ) .capacity-text ( block-size #blocks -- ) status-check ( -- ) ; : wait-for-media-ready ( -- true|false ) get-msecs \ initial timer value (start) >r BEGIN atapi-test \ unit ready? false if not not no-timeout and WHILE atapi-sense ( -- ascq asc sense-key ) 02 = \ sense key 2 = media error IF \ check add. sense code 3A = \ asc: device not ready ? IF false to no-timeout ." empty (" . 29 emit \ show asc qualifier ELSE drop \ discard asc qualifier THEN \ medium not present, abort waiting ELSE drop \ discard asc drop \ discard ascq THEN get-msecs r@ - \ calculate timer difference FFFF AND \ mask-off overflow bits d# 5000 > \ 5 seconds exceeded ? IF false to no-timeout \ set global flag THEN REPEAT r> drop no-timeout ; 2 CONSTANT #chan 2 CONSTANT #dev : #totaldev #dev #chan * ; CREATE read-blocks-xt #totaldev cells allot read-blocks-xt #totaldev cells erase : dev-read-blocks ( address block# #blocks dev# -- #read-blocks ) dup cells read-blocks-xt + @ execute ; : read-ident ( -- true|false ) false 00 ata-lbal! \ clear previous signature 00 ata-lbam! 00 ata-lbah! cmd#identify-device ata-cmd! wait-for-ready \ first try ATA, ATAPI aborts command ata-stat@ CF and 48 = IF drop true \ cmd accepted, this is a ATA d# 512 set-lba \ set LBA to sector-length ELSE \ ATAPI sends signature instead ata-lbam@ 14 = IF \ cylinder low = 14 ? ata-lbah@ EB = IF \ cylinder high = EB ? cmd#device-reset ata-cmd! wait-for-ready \ only supported by ATAPI cmd#identify-packet-device ata-cmd! wait-for-ready \ first try ata ata-stat@ CF and 48 = IF drop true \ replace flag THEN THEN THEN THEN dup IF ata-stat@ 8 AND IF \ data requested (as expected) ? sector read-pio-block drop \ discard address end ELSE drop false THEN THEN no-timeout not IF \ check without any timeout ? drop false \ no, detection discarded THEN ; scsi-close \ remove scsi commands from word list : find-disks ( -- ) #chan 0 DO \ check 2 channels (primary & secondary) #dev 0 DO \ check 2 devices per channel (master / slave) i 2 * j + set-regs \ set base address and dev-register for register access ata-stat@ 7f and 7f <> \ Check, if device is connected IF true to no-timeout \ preset timeout-flag read-ident ( -- true|false ) IF i j show-model \ print manufacturer + device string sector 1+ c@ C0 and 80 = \ Check for ata or atapi IF wait-for-media-ready \ wait up to 5 sec if not ready no-timeout and IF atapi-read-capacity atapi-size to block-size \ ATAPI: 2048 bytes 80000 to max-transfer ['] atapi-read-blocks i 2 * j + cells read-blocks-xt + ! s" cdrom" strdup i 2 * j + s" generic-disk.fs" included ELSE ." -" \ show hint for not registered THEN ELSE ata-size to block-size \ ATA: 512 bytes 80000 to max-transfer ['] ata-read-blocks i 2 * j + cells read-blocks-xt + ! s" disk" strdup i 2 * j + s" generic-disk.fs" included THEN cr THEN THEN i 2 * j + 200 + cp LOOP LOOP ; find-disks 430fbuffer.fs0 VALUE line# 0 VALUE column# false VALUE inverse? false VALUE inverse-screen? 18 VALUE #lines 50 VALUE #columns false VALUE cursor false VALUE saved-cursor defer draw-character \ 2B inited by display driver defer reset-screen \ 2B inited by display driver defer toggle-cursor \ 2B inited by display driver defer erase-screen \ 2B inited by display driver defer blink-screen \ 2B inited by display driver defer invert-screen \ 2B inited by display driver defer insert-characters \ 2B inited by display driver defer delete-characters \ 2B inited by display driver defer insert-lines \ 2B inited by display driver defer delete-lines \ 2B inited by display driver defer draw-logo \ 2B inited by display driver : nop-toggle-cursor ( nop ) ; ' nop-toggle-cursor to toggle-cursor : (cursor-off) ( -- ) cursor dup to saved-cursor IF toggle-cursor false to cursor THEN ; : (cursor-on) ( -- ) cursor dup to saved-cursor 0= IF toggle-cursor true to cursor THEN ; : restore-cursor ( -- ) saved-cursor dup cursor <> IF toggle-cursor to cursor ELSE drop THEN ; ' (cursor-off) to cursor-off ' (cursor-on) to cursor-on false VALUE esc-on false VALUE csi-on defer esc-process 0 VALUE esc-num-parm 0 VALUE esc-num-parm2 0 VALUE saved-line# 0 VALUE saved-column# : get-esc-parm ( default -- value ) esc-num-parm dup 0> IF nip ELSE drop THEN 0 to esc-num-parm ; : get-esc-parm2 ( default -- value ) esc-num-parm2 dup 0> IF nip ELSE drop THEN 0 to esc-num-parm2 ; : set-esc-parm ( newdigit -- ) [char] 0 - esc-num-parm a * + to esc-num-parm ; : reverse-cursor ( oldpos -- newpos) dup IF 1 get-esc-parm - THEN ; : advance-cursor ( bound oldpos -- newpos) tuck > IF 1 get-esc-parm + THEN ; : erase-in-line #columns column# - dup 0> IF delete-characters ELSE drop THEN ; : terminal-line++ ( -- ) line# 1+ dup #lines = IF 1- 0 to line# 1 delete-lines THEN to line# ; 0 VALUE dang 0 VALUE blipp false VALUE stopcsi 0 VALUE term-background 7 VALUE term-foreground : set-term-color dup d# 30 d# 39 between IF dup d# 30 - to term-foreground THEN dup d# 40 d# 49 between IF dup d# 40 - to term-background THEN 0 = IF 0 to term-background 7 to term-foreground THEN term-foreground term-background <= to inverse? ; : ansi-esc ( char -- ) csi-on IF dup [char] 0 [char] 9 between IF set-esc-parm ELSE true to stopcsi CASE [char] A OF line# reverse-cursor to line# ENDOF [char] B OF #lines line# advance-cursor to line# ENDOF [char] C OF #columns column# advance-cursor to column# ENDOF [char] D OF column# reverse-cursor to column# ENDOF [char] E OF ( FIXME: Cursor Next Line - No idea what does it mean ) #lines line# advance-cursor to line# ENDOF [char] f OF 1 get-esc-parm2 to line# column# get-esc-parm to column# ENDOF [char] H OF 1 get-esc-parm2 to line# column# get-esc-parm to column# ENDOF [char] ; OF false to stopcsi 0 get-esc-parm to esc-num-parm2 ENDOF [char] ? OF false to stopcsi ENDOF ( FIXME: Ignore that for now ) [char] l OF ENDOF ( FIXME: ?25l should hide cursor ) [char] h OF ENDOF ( FIXME: ?25h should show cursor ) [char] J OF #lines line# - dup 0> IF line# 1+ to line# delete-lines line# 1- to line# ELSE drop THEN erase-in-line ENDOF [char] K OF erase-in-line ENDOF [char] L OF 1 get-esc-parm insert-lines ENDOF [char] M OF 1 get-esc-parm delete-lines ENDOF [char] @ OF 1 get-esc-parm insert-characters ENDOF [char] P OF 1 get-esc-parm delete-characters ENDOF [char] m OF 0 get-esc-parm set-term-color ENDOF [char] p OF inverse-screen? IF false to inverse-screen? inverse? 0= to inverse? invert-screen THEN ENDOF [char] q OF inverse-screen? 0= IF true to inverse-screen? inverse? 0= to inverse? invert-screen THEN ENDOF [char] u OF saved-line# to line# saved-column# to column# ENDOF dup dup to dang OF blink-screen ENDOF ENDCASE stopcsi IF false to csi-on false to esc-on 0 to esc-num-parm 0 to esc-num-parm2 THEN THEN ELSE CASE [char] 7 OF line# to saved-line# column# to saved-column# ENDOF [char] 8 OF saved-line# to line# saved-column# to column# ENDOF [char] [ OF true to csi-on ENDOF dup dup OF false to esc-on to blipp ENDOF ENDCASE csi-on 0= IF false to esc-on THEN 0 to esc-num-parm 0 to esc-num-parm2 THEN ; ' ansi-esc to esc-process CREATE twtracebuf 4000 allot twtracebuf 4000 erase twtracebuf VALUE twbp 0 VALUE twbc 0 VALUE twtrace-enabled? : twtrace twbc 4000 = IF 0 to twbc twtracebuf to twbp THEN dup twbp c! twbp 1+ to twbp twbc 1+ to twbc ; : terminal-write ( addr len -- actual-len ) cursor-off tuck bounds ?DO i c@ twtrace-enabled? IF twtrace THEN esc-on IF esc-process ELSE CASE 1B OF true to esc-on ENDOF carret OF 0 to column# ENDOF linefeed OF terminal-line++ ENDOF bell OF blink-screen ENDOF 9 ( TAB ) OF column# 7 + -8 and dup #columns < IF to column# ELSE drop THEN ENDOF B ( VT ) OF line# ?dup IF 1- to line# THEN ENDOF C ( FF ) OF 0 to line# 0 to column# erase-screen ENDOF bs OF column# 1- dup 0< IF line# IF line# 1- to line# drop #columns 1- ELSE drop column# THEN THEN to column# ( bl draw-character ) ENDOF dup OF i c@ draw-character column# 1+ dup #columns >= IF drop 0 terminal-line++ THEN to column# ENDOF ENDCASE THEN LOOP restore-cursor ; 0 VALUE char-height 0 VALUE char-width 0 VALUE fontbytes CREATE display-emit-buffer 20 allot defer dis-old-emit ' emit behavior to dis-old-emit : display-write terminal-write ; : display-emit dup dis-old-emit display-emit-buffer tuck c! 1 terminal-write drop ; : is-install ( 'open -- ) s" defer vendor-open to vendor-open" eval s" : open deadbeef vendor-open dup deadbeef = IF drop true ELSE nip THEN ;" eval s" defer write ' display-write to write" eval s" : draw-logo ['] draw-logo CATCH IF 2drop 2drop THEN ;" eval s" : reset-screen ['] reset-screen CATCH drop ;" eval ; : is-remove ( 'close -- ) s" defer close to close" eval ; : is-selftest ( 'selftest -- ) s" defer selftest to selftest" eval ; STRUCT cell FIELD font>addr cell FIELD font>width cell FIELD font>height cell FIELD font>advance cell FIELD font>min-char cell FIELD font>#glyphs CONSTANT /font CREATE default-font-ctrblk /font allot default-font-ctrblk dup font>addr 0 swap ! dup font>width 8 swap ! dup font>height -10 swap ! dup font>advance 1 swap ! dup font>min-char 20 swap ! font>#glyphs 7f swap ! : display-default-font ( str len -- ) romfs-lookup dup 0= IF drop EXIT THEN 600 <> IF ." Only support 60x8x16 fonts ! " drop EXIT THEN default-font-ctrblk font>addr ! ; s" default-font.bin" display-default-font : .scan-lines ( height -- scanlines ) dup 0>= IF 1- ELSE negate THEN ; : set-font ( addr width height advance min-char #glyphs -- ) default-font-ctrblk /font + /font 0 DO 1 cells - dup >r ! r> 1 cells +LOOP drop default-font-ctrblk dup font>height @ abs to char-height dup font>width @ to char-width font>advance @ to fontbytes ; : >font ( char -- addr ) dup default-font-ctrblk dup >r font>min-char @ dup r@ font>#glyphs + within IF r@ font>min-char @ - r@ font>advance @ * r@ font>height @ .scan-lines * r> font>addr @ + ELSE drop r> font>addr @ THEN ; : default-font ( -- addr width height advance min-char #glyphs ) default-font-ctrblk /font 0 DO dup cell+ >r @ r> 1 cells +LOOP drop ; 0 VALUE frame-buffer-adr 0 VALUE screen-height 0 VALUE screen-width 0 VALUE screen-depth 0 VALUE screen-line-bytes 0 VALUE window-top 0 VALUE window-left 0 VALUE .sc : screen-#rows ( -- rows ) .sc IF screen-height char-height / ELSE true to .sc s" screen-#rows" eval false to .sc THEN ; : screen-#columns ( -- columns ) .sc IF screen-width char-width / ELSE true to .sc s" screen-#columns" eval false to .sc THEN ; : fb8-background inverse? ; : fb8-foreground inverse? invert ; : fb8-lines2bytes ( #lines -- #bytes ) char-height * screen-line-bytes * ; : fb8-columns2bytes ( #columns -- #bytes ) char-width * screen-depth * ; : fb8-line2addr ( line# -- addr ) char-height * window-top + screen-line-bytes * frame-buffer-adr + window-left screen-depth * + ; : fb8-erase-block ( addr len ) fb8-background rfill ; 0 VALUE .ab CREATE bitmap-buffer 400 4 * allot : active-bits ( -- new ) .ab dup 8 > IF 8 - to .ab 8 ELSE char-width to .ab ?dup 0= IF recurse THEN THEN ; : fb8-char2bitmap ( font-height font-addr -- bitmap-buffer ) bitmap-buffer >r char-height rot 0> IF r> char-width 2dup fb8-erase-block + >r 1- THEN r> -rot char-width to .ab fontbytes * bounds ?DO i c@ active-bits 0 ?DO dup 80 and IF fb8-foreground ELSE fb8-background THEN ( fb-addr fbyte colr ) 2 pick ! 1 lshift swap screen-depth + swap LOOP drop LOOP drop bitmap-buffer ; : fb8-draw-logo ( line# addr width height -- ) ." fb8-draw-logo ( " .s ." )" cr 2drop 2drop ; : fb8-toggle-cursor ( -- ) line# fb8-line2addr column# fb8-columns2bytes + char-height 2 - screen-line-bytes * + 2 0 ?DO dup char-width screen-depth * invert-region screen-line-bytes + LOOP drop ; : fb8-draw-character ( char -- ) >r default-font over + r@ -rot between IF 2swap 3drop r> >font fb8-char2bitmap ( bitmap-buf ) line# fb8-line2addr column# fb8-columns2bytes + ( bitmap-buf fb-addr ) char-height 0 ?DO 2dup char-width screen-depth * mrmove screen-line-bytes + >r char-width screen-depth * + r> LOOP 2drop ELSE 2drop r> 3drop THEN ; : fb8-insert-lines ( n -- ) fb8-lines2bytes >r line# fb8-line2addr dup dup r@ + #lines line# - fb8-lines2bytes r@ - rmove r> fb8-erase-block ; : fb8-delete-lines ( n -- ) fb8-lines2bytes >r line# fb8-line2addr dup dup r@ + swap #lines fb8-lines2bytes r@ - dup >r rmove r> + r> fb8-erase-block ; : fb8-insert-characters ( n -- ) line# fb8-line2addr column# fb8-columns2bytes + >r #columns column# - 2dup >= IF nip dup 0> IF fb8-columns2bytes r> ELSE r> 2drop EXIT THEN ELSE fb8-columns2bytes swap fb8-columns2bytes tuck - over r@ tuck + rot char-height 0 ?DO 3dup rmove -rot screen-line-bytes tuck + -rot + swap rot LOOP 3drop r> THEN char-height 0 ?DO dup 2 pick fb8-erase-block screen-line-bytes + LOOP 2drop ; : fb8-delete-characters ( n -- ) line# fb8-line2addr column# fb8-columns2bytes + >r #columns column# - 2dup >= IF nip dup 0> IF fb8-columns2bytes r> ELSE r> 2drop EXIT THEN ELSE fb8-columns2bytes swap fb8-columns2bytes tuck - over r@ + 2dup + r> swap >r rot char-height 0 ?DO 3dup rmove -rot screen-line-bytes tuck + -rot + swap rot LOOP 3drop r> over - THEN char-height 0 ?DO dup 2 pick fb8-erase-block screen-line-bytes + LOOP 2drop ; : fb8-reset-screen ( -- ) ( Left as no-op by design ) ; : fb8-erase-screen ( -- ) frame-buffer-adr screen-height screen-line-bytes * fb8-erase-block ; : fb8-invert-screen ( -- ) frame-buffer-adr screen-height screen-line-bytes * invert-region ; : fb8-blink-screen ( -- ) fb8-invert-screen fb8-invert-screen ; : fb8-install ( width height #columns #lines -- ) 1 to screen-depth 2swap to screen-height to screen-width screen-width to screen-line-bytes screen-#rows min to #lines screen-#columns min to #columns screen-height char-height #lines * - 2/ to window-top screen-width char-width #columns * - 2/ to window-left ['] fb8-toggle-cursor to toggle-cursor ['] fb8-draw-character to draw-character ['] fb8-insert-lines to insert-lines ['] fb8-delete-lines to delete-lines ['] fb8-insert-characters to insert-characters ['] fb8-delete-characters to delete-characters ['] fb8-erase-screen to erase-screen ['] fb8-blink-screen to blink-screen ['] fb8-invert-screen to invert-screen ['] fb8-reset-screen to reset-screen ['] fb8-draw-logo to draw-logo ; : fb-install ( width height #columns #lines depth -- ) >r fb8-install r> to screen-depth screen-width screen-depth * to screen-line-bytes ; : fb8-set-tokens ( -- ) ['] is-install 0 11C set-token ['] is-remove 0 11D set-token ['] is-selftest 0 11E set-token ['] #lines 0 150 set-token ['] #columns 0 151 set-token ['] line# 0 152 set-token ['] column# 0 153 set-token ['] inverse? 0 154 set-token ['] inverse-screen? 0 155 set-token ['] draw-character 0 157 set-token ['] reset-screen 0 158 set-token ['] toggle-cursor 0 159 set-token ['] erase-screen 0 15A set-token ['] blink-screen 0 15B set-token ['] invert-screen 0 15C set-token ['] insert-characters 0 15D set-token ['] delete-characters 0 15E set-token ['] insert-lines 0 15F set-token ['] delete-lines 0 160 set-token ['] draw-logo 0 161 set-token ['] frame-buffer-adr 0 162 set-token ['] screen-height 0 163 set-token ['] screen-width 0 164 set-token ['] window-top 0 165 set-token ['] window-left 0 166 set-token ['] default-font 0 16A set-token ['] set-font 0 16B set-token ['] char-height 0 16C set-token ['] char-width 0 16D set-token ['] >font 0 16E set-token ['] fontbytes 0 16F set-token ['] fb8-draw-character 0 180 set-token ['] fb8-reset-screen 0 181 set-token ['] fb8-toggle-cursor 0 182 set-token ['] fb8-erase-screen 0 183 set-token ['] fb8-blink-screen 0 184 set-token ['] fb8-invert-screen 0 185 set-token ['] fb8-insert-characters 0 186 set-token ['] fb8-delete-characters 0 187 set-token ['] fb8-insert-lines 0 188 set-token ['] fb8-delete-lines 0 189 set-token ['] fb8-draw-logo 0 18A set-token ['] fb8-install 0 18B set-token ; fb8-set-tokens : fb8-dump-bitmap cr char-height 0 ?do char-width 0 ?do dup c@ if ." @" else ." ." then 1+ loop cr loop drop ; : fb8-dump-char >font -b swap fb8-char2bitmap fb8-dump-bitmap ; 0graphics.fs: draw-rectangle ( adr x y w h -- ) frame-buffer-adr 0= IF 4drop drop EXIT THEN 0 ?DO 4dup drop ( adr x y w adr x y ) i + screen-width * + screen-depth * ( adr x y w adr offs ) frame-buffer-adr + ( adr x y w adr fb_adr ) over 3 pick screen-depth * i * + ( adr x y w adr fb_adr src ) swap 3 pick screen-depth * ( adr x y w adr src fb_adr len ) rmove \ copy line ( adr x y w adr ) drop ( adr x y w ) LOOP 4drop ; : fill-rectangle ( col x y w h -- ) frame-buffer-adr 0= IF 4drop drop EXIT THEN 0 ?DO 4dup drop ( col x y w col x y ) i + screen-width * + screen-depth * ( col x y w col offs ) frame-buffer-adr + ( col x y w col adr ) 2 pick screen-depth * 2 pick ( col x y w col adr len col ) rfill \ draw line ( col x y w col ) drop ( col x y w ) LOOP 4drop ; : read-rectangle ( adr x y w h -- ) frame-buffer-adr 0= IF 4drop drop EXIT THEN 0 ?DO 4dup drop ( adr x y w adr x y ) i + screen-width * + screen-depth * ( adr x y w adr offs ) frame-buffer-adr + ( adr x y w adr fb_adr ) over 3 pick screen-depth * i * + ( adr x y w adr fb_adr dst ) 3 pick ( adr x y w adr fb_adr dst w ) rmove \ copy line ( adr x y w adr ) drop ( adr x y w ) LOOP 4drop ; : dimensions ( -- width height ) screen-width screen-height ; : init-default-palette 100 10 DO i i i i color! LOOP 00 00 00 0 color! 00 00 aa 1 color! 00 aa 00 2 color! 00 aa aa 3 color! aa 00 00 4 color! aa 00 aa 5 color! aa 55 00 6 color! aa aa aa 7 color! 55 55 55 8 color! 55 55 ff 9 color! 55 ff 55 a color! 55 ff ff b color! ff 55 55 c color! ff 55 ff d color! ff ff 55 e color! ff ff ff f color! ; 0generic-disk.fsnew-device set-unit ( str len ) 2dup device-name s" 0 pci-alias-" 2swap $cat evaluate s" block" device-type s" block-size" $call-parent CONSTANT block-size s" max-transfer" $call-parent CONSTANT max-transfer : read-blocks ( addr block# #blocks -- #read ) my-unit s" dev-read-blocks" $call-parent ; INSTANCE VARIABLE deblocker : open ( -- okay? ) 0 0 s" deblocker" $open-package dup deblocker ! dup IF s" disk-label" find-package IF my-args rot interpose THEN THEN 0<> ; : close ( -- ) deblocker @ close-package ; : seek ( pos.lo pos.hi -- status ) s" seek" deblocker @ $call-method ; : read ( addr len -- actual ) s" read" deblocker @ $call-method ; finish-device H 0dma-function.fs: dma-alloc ( size -- virt ) my-phandle TO calling-child s" dma-alloc" my-phandle parent $call-static 0 TO calling-child ; : dma-free ( virt size -- ) my-phandle TO calling-child s" dma-free" my-phandle parent $call-static 0 TO calling-child ; : dma-map-in ( virt size cacheable? -- devaddr ) my-phandle TO calling-child s" dma-map-in" my-phandle parent $call-static 0 TO calling-child ; : dma-map-out ( virt devaddr size -- ) my-phandle TO calling-child s" dma-map-out" my-phandle parent $call-static 0 TO calling-child ; i0pci-device.fsget-node CONSTANT my-phandle s" my-puid" my-phandle parent $call-static CONSTANT my-puid : config-b@ puid >r my-puid TO puid my-space + rtas-config-b@ r> TO puid ; : config-w@ puid >r my-puid TO puid my-space + rtas-config-w@ r> TO puid ; : config-l@ puid >r my-puid TO puid my-space + rtas-config-l@ r> TO puid ; : config-b! puid >r my-puid TO puid my-space + rtas-config-b! r> TO puid ; : config-w! puid >r my-puid TO puid my-space + rtas-config-w! r> TO puid ; : config-l! puid >r my-puid TO puid my-space + rtas-config-l! r> TO puid ; : config-dump puid >r my-puid TO puid my-space pci-dump r> TO puid ; : open puid >r \ save the old puid my-puid TO puid \ set up the puid to the devices Hostbridge pci-master-enable \ And enable Bus Master, IO and MEM access again. pci-mem-enable \ enable mem access pci-io-enable \ enable io access r> TO puid \ restore puid true ; : close puid >r \ save the old puid my-puid TO puid \ set up the puid pci-device-disable \ and disable the device r> TO puid \ restore puid ; s" dma-function.fs" included : devicefile ( -- str len ) s" pci-device_" my-space pci-vendor@ 4 int2str $cat s" _" $cat my-space pci-device@ 4 int2str $cat s" .fs" $cat ; : classfile ( -- str len ) s" pci-class_" my-space pci-class@ 10 rshift 2 int2str $cat s" .fs" $cat ; : setup ( -- ) devicefile romfs-lookup ?dup IF evaluate ELSE classfile romfs-lookup ?dup IF evaluate ELSE my-space pci-class-name type 2a emit cr my-space pci-device-generic-setup THEN THEN ; pci-device-disable pci-error-enable my-space 44 pci-out \ config-addr ascii('D') setup s0pci-bridge.fsget-node CONSTANT my-phandle s" my-puid" my-phandle parent $call-static CONSTANT my-puid pci-bus-number 1+ CONSTANT my-bus s" pci-config-bridge.fs" included s" dma-function.fs" included : filename ( -- str len ) s" pci-bridge_" my-space pci-vendor@ 4 int2str $cat s" _" $cat my-space pci-device@ 4 int2str $cat s" .fs" $cat ; : setup ( -- ) filename romfs-lookup ?dup IF evaluate ELSE my-space pci-class-name type 2a emit cr my-space pci-bridge-generic-setup my-space pci-reset-2nd THEN ; pci-device-disable pci-error-enable my-space 42 pci-out \ config-addr ascii('B') setup pci-master-enable pci-mem-enable pci-io-enable 8pci-properties.fs: pci-class-name-00 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 01 OF s" display" ENDOF dup OF s" unknown-legacy-device" ENDOF ENDCASE ; : pci-class-name-01 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" scsi" ENDOF 01 OF s" ide" ENDOF 02 OF s" fdc" ENDOF 03 OF s" ipi" ENDOF 04 OF s" raid" ENDOF 05 OF s" ata" ENDOF 06 OF s" sata" ENDOF 07 OF s" sas" ENDOF dup OF s" mass-storage" ENDOF ENDCASE ; : pci-class-name-02 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" ethernet" ENDOF 01 OF s" token-ring" ENDOF 02 OF s" fddi" ENDOF 03 OF s" atm" ENDOF 04 OF s" isdn" ENDOF 05 OF s" worldfip" ENDOF 05 OF s" picmg" ENDOF dup OF s" network" ENDOF ENDCASE ; : pci-class-name-03 ( addr -- str len ) pci-class@ FFFF and CASE 0000 OF s" vga" ENDOF 0001 OF s" 8514-compatible" ENDOF 0100 OF s" xga" ENDOF 0200 OF s" 3d-controller" ENDOF dup OF s" display" ENDOF ENDCASE ; : pci-class-name-04 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" video" ENDOF 01 OF s" sound" ENDOF 02 OF s" telephony" ENDOF dup OF s" multimedia-device" ENDOF ENDCASE ; : pci-class-name-05 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" memory" ENDOF 01 OF s" flash" ENDOF dup OF s" memory-controller" ENDOF ENDCASE ; : pci-class-name-06 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" host" ENDOF 01 OF s" isa" ENDOF 02 OF s" eisa" ENDOF 03 OF s" mca" ENDOF 04 OF s" pci" ENDOF 05 OF s" pcmcia" ENDOF 06 OF s" nubus" ENDOF 07 OF s" cardbus" ENDOF 08 OF s" raceway" ENDOF 09 OF s" semi-transparent-pci" ENDOF 0A OF s" infiniband" ENDOF dup OF s" unkown-bridge" ENDOF ENDCASE ; : pci-class-name-07 ( addr -- str len ) pci-class@ FFFF and CASE 0000 OF s" serial" ENDOF 0001 OF s" 16450-serial" ENDOF 0002 OF s" 16550-serial" ENDOF 0003 OF s" 16650-serial" ENDOF 0004 OF s" 16750-serial" ENDOF 0005 OF s" 16850-serial" ENDOF 0006 OF s" 16950-serial" ENDOF 0100 OF s" parallel" ENDOF 0101 OF s" bi-directional-parallel" ENDOF 0102 OF s" ecp-1.x-parallel" ENDOF 0103 OF s" ieee1284-controller" ENDOF 01FE OF s" ieee1284-device" ENDOF 0200 OF s" multiport-serial" ENDOF 0300 OF s" modem" ENDOF 0301 OF s" 16450-modem" ENDOF 0302 OF s" 16550-modem" ENDOF 0303 OF s" 16650-modem" ENDOF 0304 OF s" 16750-modem" ENDOF 0400 OF s" gpib" ENDOF 0500 OF s" smart-card" ENDOF dup OF s" communication-controller" ENDOF ENDCASE ; : pci-class-name-08 ( addr -- str len ) pci-class@ FFFF and CASE 0000 OF s" interrupt-controller" ENDOF 0001 OF s" isa-pic" ENDOF 0002 OF s" eisa-pic" ENDOF 0010 OF s" io-apic" ENDOF 0020 OF s" iox-apic" ENDOF 0100 OF s" dma-controller" ENDOF 0101 OF s" isa-dma" ENDOF 0102 OF s" eisa-dma" ENDOF 0200 OF s" timer" ENDOF 0201 OF s" isa-system-timer" ENDOF 0202 OF s" eisa-system-timer" ENDOF 0300 OF s" rtc" ENDOF 0301 OF s" isa-rtc" ENDOF 0400 OF s" hot-plug-controller" ENDOF 0500 OF s" sd-host-conrtoller" ENDOF dup OF s" system-periphal" ENDOF ENDCASE ; : pci-class-name-09 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" keyboard" ENDOF 01 OF s" pen" ENDOF 02 OF s" mouse" ENDOF 03 OF s" scanner" ENDOF 04 OF s" gameport" ENDOF dup OF s" input-controller" ENDOF ENDCASE ; : pci-class-name-0A ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" dock" ENDOF dup OF s" docking-station" ENDOF ENDCASE ; : pci-class-name-0B ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" 386" ENDOF 01 OF s" 486" ENDOF 02 OF s" pentium" ENDOF 10 OF s" alpha" ENDOF 20 OF s" powerpc" ENDOF 30 OF s" mips" ENDOF 40 OF s" co-processor" ENDOF dup OF s" cpu" ENDOF ENDCASE ; : pci-class-name-0C ( addr -- str len ) pci-class@ FFFF and CASE 0000 OF s" firewire" ENDOF 0100 OF s" access-bus" ENDOF 0200 OF s" ssa" ENDOF 0300 OF s" usb-uhci" ENDOF 0310 OF s" usb-ohci" ENDOF 0320 OF s" usb-ehci" ENDOF 0330 OF s" usb-xhci" ENDOF 0380 OF s" usb" ENDOF 03FE OF s" usb-device" ENDOF 0400 OF s" fibre-channel" ENDOF 0500 OF s" smb" ENDOF 0600 OF s" infiniband" ENDOF 0700 OF s" ipmi-smic" ENDOF 0701 OF s" ipmi-kbrd" ENDOF 0702 OF s" ipmi-bltr" ENDOF 0800 OF s" sercos" ENDOF 0900 OF s" canbus" ENDOF dup OF s" serial-bus" ENDOF ENDCASE ; : pci-class-name-0D ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" irda" ENDOF 01 OF s" consumer-ir" ENDOF 10 OF s" rf-controller" ENDOF 11 OF s" bluetooth" ENDOF 12 OF s" broadband" ENDOF 20 OF s" enet-802.11a" ENDOF 21 OF s" enet-802.11b" ENDOF dup OF s" wireless-controller" ENDOF ENDCASE ; : pci-class-name-0E ( addr -- str len ) pci-class@ 8 rshift FF and CASE dup OF s" intelligent-io" ENDOF ENDCASE ; : pci-class-name-0F ( addr -- str len ) pci-class@ 8 rshift FF and CASE 01 OF s" satelite-tv" ENDOF 02 OF s" satelite-audio" ENDOF 03 OF s" satelite-voice" ENDOF 04 OF s" satelite-data" ENDOF dup OF s" satelite-devoce" ENDOF ENDCASE ; : pci-class-name-10 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" network-encryption" ENDOF 01 OF s" entertainment-encryption" ENDOF dup OF s" encryption" ENDOF ENDCASE ; : pci-class-name-11 ( addr -- str len ) pci-class@ 8 rshift FF and CASE 00 OF s" dpio" ENDOF 01 OF s" counter" ENDOF 10 OF s" measurement" ENDOF 20 OF s" managment-card" ENDOF dup OF s" data-processing-controller" ENDOF ENDCASE ; : pci-class-name ( addr -- str len ) dup pci-class@ 10 rshift CASE 00 OF pci-class-name-00 ENDOF 01 OF pci-class-name-01 ENDOF 02 OF pci-class-name-02 ENDOF 03 OF pci-class-name-03 ENDOF 04 OF pci-class-name-04 ENDOF 05 OF pci-class-name-05 ENDOF 06 OF pci-class-name-06 ENDOF 07 OF pci-class-name-07 ENDOF 08 OF pci-class-name-08 ENDOF 09 OF pci-class-name-09 ENDOF 0A OF pci-class-name-0A ENDOF 0B OF pci-class-name-0B ENDOF 0C OF pci-class-name-0C ENDOF 0C OF pci-class-name-0D ENDOF 0C OF pci-class-name-0E ENDOF 0C OF pci-class-name-0F ENDOF 0C OF pci-class-name-10 ENDOF 0C OF pci-class-name-11 ENDOF dup OF drop s" unknown" ENDOF ENDCASE ; : pci-bar-size@ ( bar-addr -- bar-size ) -1 over rtas-config-l! rtas-config-l@ ; : pci-bar-size-mem@ ( bar-addr -- mem-size ) pci-bar-size@ -10 and invert 1+ FFFFFFFF and ; : pci-bar-size-io@ ( bar-addr -- io-size ) pci-bar-size@ -4 and invert 1+ FFFFFFFF and ; : pci-bar-size ( bar-addr -- bar-size-raw ) dup rtas-config-l@ swap \ fetch original Value ( bval baddr ) -1 over rtas-config-l! \ make BAR show size ( bval baddr ) dup rtas-config-l@ \ and fetch the size ( bval baddr bsize ) -rot rtas-config-l! \ restore Value ; : pci-bar-size-mem32 ( bar-addr -- bar-size ) pci-bar-size \ fetch raw size -10 and invert 1+ \ calc size FFFFFFFF and \ keep lower 32 bits ; : pci-bar-size-rom ( bar-addr -- bar-size ) pci-bar-size \ fetch raw size FFFFF800 and invert 1+ \ calc size FFFFFFFF and \ keep lower 32 bits ; : pci-bar-size-mem64 ( bar-addr -- bar-size ) dup pci-bar-size \ fetch raw size lower 32 bits swap 4 + pci-bar-size \ fetch raw size upper 32 bits 20 lshift + \ and put them together -10 and invert 1+ \ calc size ; : pci-bar-size-io ( bar-addr -- bar-size ) pci-bar-size \ fetch raw size -4 and invert 1+ \ calc size FFFFFFFF and \ keep lower 32 bits ; : pci-bar-code@ ( bar-addr -- 0|1..4|5 ) rtas-config-l@ dup \ fetch the BaseAddressRegister 1 and IF \ IO BAR ? 2 and IF 0 ELSE 1 THEN \ only '01' is valid ELSE \ Memory BAR ? F and CASE 0 OF 2 ENDOF \ Memory 32 Bit Non-Prefetchable 8 OF 3 ENDOF \ Memory 32 Bit Prefetchable 4 OF 4 ENDOF \ Memory 64 Bit Non-Prefetchable C OF 5 ENDOF \ Memory 64 Bit Prefechtable dup OF 0 ENDOF \ Not a valid BarType ENDCASE THEN ; : assign-var ( size var -- al-mem ) 2dup @ \ ( size var size cur-mem ) read current free mem swap #aligned \ ( size var al-mem ) align the mem to the size dup 2swap -rot + \ ( al-mem var new-mem ) add size to aligned mem swap ! \ ( al-mem ) set variable to new mem ; : assign-bar-value32 ( bar size var -- 4 ) over IF \ IF size > 0 assign-var \ | ( bar al-mem ) set variable to next mem swap rtas-config-l! \ | ( -- ) set the bar to al-mem ELSE \ ELSE 2drop drop \ | clear stack THEN \ FI 4 \ size of the base-address-register ; : assign-bar-value64 ( bar size var -- 8 ) over IF \ IF size > 0 assign-var \ | ( bar al-mem ) set variable to next mem swap \ | ( al-mem addr ) calc config-addr of this bar 2dup rtas-config-l! \ | ( al-mem addr ) set the Lower part of the bar to al-mem 4 + swap 20 rshift \ | ( al-mem>>32 addr ) prepare the upper part of the al-mem swap rtas-config-l! \ | ( -- ) and set the upper part of the bar ELSE \ ELSE 2drop drop \ | clear stack THEN \ FI 8 \ size of the base-address-register ; : assign-mem64-bar ( bar-addr -- 8 ) dup pci-bar-size-mem64 \ fetch size pci-next-mem64 @ 0 = IF \ Check if we have 64-bit memory range pci-next-mem ELSE pci-next-mem64 THEN assign-bar-value64 \ and set it all ; : assign-mem32-bar ( bar-addr -- 4 ) dup pci-bar-size-mem32 \ fetch size pci-next-mem \ var to change assign-bar-value32 \ and set it all ; : assign-mmio64-bar ( bar-addr -- 8 ) dup pci-bar-size-mem64 \ fetch size pci-next-mem64 @ 0 = IF \ Check if we have 64-bit memory range pci-next-mmio ELSE pci-next-mem64 \ for board-qemu we will use same range THEN assign-bar-value64 \ and set it all ; : assign-mmio32-bar ( bar-addr -- 4 ) dup pci-bar-size-mem32 \ fetch size pci-next-mmio \ var to change assign-bar-value32 \ and set it all ; : assign-io-bar ( bar-addr -- 4 ) dup pci-bar-size-io \ fetch size pci-next-io \ var to change assign-bar-value32 \ and set it all ; : assign-rom-bar ( bar-addr -- ) dup pci-bar-size-rom \ fetch size dup IF \ IF size > 0 over >r \ | save bar addr for enable pci-next-mmio \ | var to change assign-bar-value32 \ | and set it drop \ | forget the BAR length r@ rtas-config-l@ \ | fetch BAR 1 or r> rtas-config-l! \ | and enable the ROM ELSE \ ELSE 2drop \ | clear stack THEN ; : assign-bar ( bar-addr -- reg-size ) dup pci-bar-code@ \ calc BAR type dup IF \ IF >0 CASE \ | CASE Setup the right type 1 OF assign-io-bar ENDOF \ | - set up an IO-Bar 2 OF assign-mmio32-bar ENDOF \ | - set up an 32bit MMIO-Bar 3 OF assign-mem32-bar ENDOF \ | - set up an 32bit MEM-Bar (prefetchable) 4 OF assign-mmio64-bar ENDOF \ | - set up an 64bit MMIO-Bar 5 OF assign-mem64-bar ENDOF \ | - set up an 64bit MEM-Bar (prefetchable) ENDCASE \ | ESAC ELSE \ ELSE ABORT \ | Throw an exception THEN \ FI ; : assign-all-device-bars ( configaddr -- ) 28 10 DO \ BARs start at 10 and end at 27 dup i + \ calc config-addr of the BAR assign-bar \ and set it up +LOOP \ add 4 or 8 to the index and loop 30 + assign-rom-bar \ set up the ROM if available ; : assign-all-bridge-bars ( configaddr -- ) 18 10 DO \ BARs start at 10 and end at 17 dup i + \ calc config-addr of the BAR assign-bar \ and set it up +LOOP \ add 4 or 8 to the index and loop 38 + assign-rom-bar \ set up the ROM if available ; : gen-mem64-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 8 ) dup pci-bar-size-mem64 \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch lower 32 bits ( paddr plen baddr val.lo R: size) over 4 + rtas-config-l@ \ | fetch upper 32 bits ( paddr plen baddr val.lo val.hi R: size) 20 lshift + -10 and >r \ | calc 64 bit value and save it ( paddr plen baddr R: size val ) 83000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 8 \ sizeof(BAR) = 8 Bytes ; : gen-pmem64-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 8 ) dup pci-bar-size-mem64 \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch lower 32 bits ( paddr plen baddr val.lo R: size) over 4 + rtas-config-l@ \ | fetch upper 32 bits ( paddr plen baddr val.lo val.hi R: size) 20 lshift + -10 and >r \ | calc 64 bit value and save it ( paddr plen baddr R: size val ) C3000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 8 \ sizeof(BAR) = 8 Bytes ; : gen-mem32-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 ) dup pci-bar-size-mem32 \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size) -10 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val ) 82000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ sizeof(BAR) = 4 Bytes ; : gen-pmem32-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 ) dup pci-bar-size-mem32 \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size) -10 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val ) C2000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ sizeof(BAR) = 4 Bytes ; : gen-io-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 ) dup pci-bar-size-io \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size) -4 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val ) 81000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ sizeof(BAR) = 4 Bytes ; : gen-rom-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len ) dup pci-bar-size-rom \ fetch BAR Size ( paddr plen baddr bsize ) dup IF \ IF Size > 0 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size) FFFFF800 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val ) 82000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val ) r> encode-64+ \ | Encode assigned addr ( paddr plen R: size ) r> encode-64+ \ | Encode size ( paddr plen ) ELSE \ ELSE 2drop \ | don't do anything THEN \ FI ; : pci-add-assigned-address ( prop-addr prop-len bar-addr -- prop-addr prop-len bsize ) dup pci-bar-code@ \ calc BAR type ( paddr plen baddr btype) CASE \ CASE for the BAR types ( paddr plen baddr ) 0 OF drop 4 ENDOF \ - not a valid type so do nothing 1 OF gen-io-bar-prop ENDOF \ - IO-BAR 2 OF gen-mem32-bar-prop ENDOF \ - MEM32 3 OF gen-pmem32-bar-prop ENDOF \ - MEM32 prefetchable 4 OF gen-mem64-bar-prop ENDOF \ - MEM64 5 OF gen-pmem64-bar-prop ENDOF \ - MEM64 prefetchable ENDCASE \ ESAC ( paddr plen bsize ) ; : pci-device-assigned-addresses-prop ( addr -- ) encode-start \ provide mem for property ( addr paddr plen ) 2 pick 30 + gen-rom-bar-prop \ assign the rom bar 28 10 DO \ we have 6 possible BARs 2 pick i + \ calc BAR address ( addr paddr plen bar-addr ) pci-add-assigned-address \ and generate the props for the BAR +LOOP \ increase Index by returned len s" assigned-addresses" property drop \ and write it into the device tree ; : pci-bridge-assigned-addresses-prop ( addr -- ) encode-start \ provide mem for property 2 pick 38 + gen-rom-bar-prop \ assign the rom bar 18 10 DO \ we have 2 possible BARs 2 pick i + \ ( addr paddr plen current-addr ) pci-add-assigned-address \ and generate the props for the BAR +LOOP \ increase Index by returned len s" assigned-addresses" property drop \ and write it into the device tree ; : pci-bridge-gen-range ( paddr plen base limit type -- paddr plen ) >r over - \ calc size ( paddr plen base size R:type ) dup 0< IF \ IF Size < 0 ( paddr plen base size R:type ) 2drop r> drop \ | forget values ( paddr plen ) ELSE \ ELSE 1+ swap 2swap \ | adjust stack ( size base paddr plen R:type ) r@ encode-int+ \ | Child type ( size base paddr plen R:type ) 2 pick encode-64+ \ | Child address ( size base paddr plen R:type ) r> encode-int+ \ | Parent type ( size base paddr plen ) rot encode-64+ \ | Parent address ( size paddr plen ) rot encode-64+ \ | Encode size ( paddr plen ) THEN \ FI ; : pci-bridge-gen-mmio-range ( addr prop-addr prop-len -- addr prop-addr prop-len ) 2 pick 20 + rtas-config-l@ \ fetch Value ( addr paddr plen val ) dup 0000FFF0 and 10 lshift \ calc base-address ( addr paddr plen val base ) swap 000FFFFF or \ calc limit-address ( addr paddr plen base limit ) 02000000 pci-bridge-gen-range \ and generate it ( addr paddr plen ) ; : pci-bridge-gen-mem-range ( addr prop-addr prop-len -- addr prop-addr prop-len ) 2 pick 24 + rtas-config-l@ \ fetch Value ( addr paddr plen val ) dup 000FFFFF or \ calc limit Bits 31:0 ( addr paddr plen val limit.31:0 ) swap 0000FFF0 and 10 lshift \ calc base Bits 31:0 ( addr paddr plen limit.31:0 base.31:0 ) 4 pick 28 + rtas-config-l@ \ fetch upper Basebits ( addr paddr plen limit.31:0 base.31:0 base.63:32 ) 20 lshift or swap \ and calc Base ( addr paddr plen base.63:0 limit.31:0 ) 4 pick 2C + rtas-config-l@ \ fetch upper Limitbits ( addr paddr plen base.63:0 limit.31:0 limit.63:32 ) 20 lshift or \ and calc Limit ( addr paddr plen base.63:0 limit.63:0 ) 42000000 pci-bridge-gen-range \ and generate it ( addr paddr plen ) ; : pci-bridge-gen-io-range ( addr prop-addr prop-len -- addr prop-addr prop-len ) 2 pick 1C + rtas-config-l@ \ fetch Value ( addr paddr plen val ) dup 0000F000 and 00000FFF or \ calc Limit Bits 15:0 ( addr paddr plen val limit.15:0 ) swap 000000F0 and 8 lshift \ calc Base Bits 15:0 ( addr paddr plen limit.15:0 base.15:0 ) 4 pick 30 + rtas-config-l@ \ fetch upper Bits ( addr paddr plen limit.15:0 base.15:0 val ) dup FFFF and 10 lshift rot or \ calc Base ( addr paddr plen limit.15:0 val base.31:0 ) -rot FFFF0000 and or \ calc Limit ( addr paddr plen base.31:0 limit.31:0 ) 01000000 pci-bridge-gen-range \ and generate it ( addr paddr plen ) ; : pci-bridge-range-props ( addr -- ) encode-start \ provide mem for property pci-bridge-gen-mmio-range \ generate the non prefetchable Memory Entry pci-bridge-gen-mem-range \ generate the prefetchable Memory Entry pci-bridge-gen-io-range \ generate the IO Entry dup IF \ IF any space present (propsize>0) s" ranges" property \ | write it into the device tree ELSE \ ELSE s" " s" ranges" property 2drop \ | forget the properties THEN \ FI drop \ forget the address ; : pci-bridge-interrupt-map ( -- ) encode-start \ create the property ( paddr plen ) get-node child \ find the first child ( paddr plen handle ) BEGIN dup WHILE \ Loop as long as the handle is non-zero ( paddr plen handle ) dup >r >space \ Get the my-space ( paddr plen addr R: handle ) pci-gen-irq-entry \ and Encode the interrupt settings ( paddr plen R: handle) r> peer \ Get neighbour ( paddr plen handle ) REPEAT \ process next childe node ( paddr plen handle ) drop \ forget the null ( paddr plen ) s" interrupt-map" property \ and set it ( -- ) 1 encode-int s" #interrupt-cells" property \ encode the cell# f800 encode-int 0 encode-int+ 0 encode-int+ \ encode the bit mask for config addr (Dev only) 7 encode-int+ s" interrupt-map-mask" property \ encode IRQ#=7 and generate property ; : encode-mem32-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 4 ) dup pci-bar-size-mem32 \ calc BAR-size ( not changing the BAR ) dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize ) >r 02000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | encode size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ BAR-Len = 4 (32Bit) ; : encode-pmem32-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 4 ) dup pci-bar-size-mem32 \ calc BAR-size ( not changing the BAR ) dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize ) >r 42000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | encode size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ BAR-Len = 4 (32Bit) ; : encode-mem64-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 8 ) dup pci-bar-size-mem64 \ calc BAR-size ( not changing the BAR ) dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize ) >r 03000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | encode size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 8 \ BAR-Len = 8 (64Bit) ; : encode-pmem64-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 8 ) dup pci-bar-size-mem64 \ calc BAR-size ( not changing the BAR ) dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize ) >r 43000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | encode size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 8 \ BAR-Len = 8 (64Bit) ; : encode-rom-bar ( prop-addr prop-len configaddr -- prop-addr prop-len ) dup pci-bar-size-rom \ fetch raw BAR-size dup IF \ IF BAR is used >r 02000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | calc and encode the size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI ; : encode-io-bar ( prop-addr prop-len BAR-addr BAR-value -- prop-addr prop-len 4 ) dup pci-bar-size-io \ calc BAR-size ( not changing the BAR ) dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize ) >r 01000000 or encode-int+ \ | save size and encode BAR addr 0 encode-64+ \ | make mid and lo zero r> encode-64+ \ | encode size ELSE \ ELSE 2drop \ | don't do anything THEN \ FI 4 \ BAR-Len = 4 (32Bit) ; : encode-bar ( prop-addr prop-len bar-addr -- prop-addr prop-len bar-len ) dup pci-bar-code@ \ calc BAR type CASE \ CASE for the BAR types ( paddr plen baddr val ) 0 OF drop 4 ENDOF \ - not a valid type so do nothing 1 OF encode-io-bar ENDOF \ - IO-BAR 2 OF encode-mem32-bar ENDOF \ - MEM32 3 OF encode-pmem32-bar ENDOF \ - MEM32 prefetchable 4 OF encode-mem64-bar ENDOF \ - MEM64 5 OF encode-pmem64-bar ENDOF \ - MEM64 prefetchable ENDCASE \ ESAC ( paddr plen blen ) ; : pci-reg-props ( configaddr -- ) dup encode-int \ configuration space ( caddr paddr plen ) 0 encode-64+ \ make the rest 0 0 encode-64+ \ encode the size as 0 2 pick pci-htype@ \ fetch Header Type ( caddr paddr plen type ) 1 and IF \ IF Bridge ( caddr paddr plen ) 18 10 DO \ | loop over all BARs 2 pick i + \ | calc bar-addr ( caddr paddr plen baddr ) encode-bar \ | encode this BAR ( caddr paddr plen blen ) +LOOP \ | increase LoopIndex by the BARlen 2 pick 38 + \ | calc ROM-BAR for a bridge ( caddr paddr plen baddr ) encode-rom-bar \ | encode the ROM-BAR ( caddr paddr plen ) ELSE \ ELSE ordinary device ( caddr paddr plen ) 28 10 DO \ | loop over all BARs 2 pick i + \ | calc bar-addr ( caddr paddr plen baddr ) encode-bar \ | encode this BAR ( caddr paddr plen blen ) +LOOP \ | increase LoopIndex by the BARlen 2 pick 30 + \ | calc ROM-BAR for a device ( caddr paddr plen baddr ) encode-rom-bar \ | encode the ROM-BAR ( caddr paddr plen ) THEN \ FI ( caddr paddr plen ) s" reg" property \ and store it into the property drop ; : pci-common-props ( addr -- ) dup pci-class-name device-name dup pci-vendor@ encode-int s" vendor-id" property dup pci-device@ encode-int s" device-id" property dup pci-revision@ encode-int s" revision-id" property dup pci-class@ encode-int s" class-code" property 3 encode-int s" #address-cells" property 2 encode-int s" #size-cells" property dup pci-config-ext? IF 1 encode-int s" ibm,pci-config-space-type" property THEN dup pci-status@ dup 9 rshift 3 and encode-int s" devsel-speed" property dup 7 rshift 1 and IF 0 0 s" fast-back-to-back" property THEN dup 6 rshift 1 and IF 0 0 s" 66mhz-capable" property THEN 5 rshift 1 and IF 0 0 s" udf-supported" property THEN dup pci-cache@ ?dup IF encode-int s" cache-line-size" property THEN pci-interrupt@ ?dup IF encode-int s" interrupts" property THEN ; : pci-device-props ( addr -- ) dup pci-common-props dup pci-min-grant@ encode-int s" min-grant" property dup pci-max-lat@ encode-int s" max-latency" property dup pci-sub-device@ ?dup IF encode-int s" subsystem-id" property THEN dup pci-sub-vendor@ ?dup IF encode-int s" subsystem-vendor-id" property THEN dup pci-device-assigned-addresses-prop pci-reg-props pci-hotplug-enabled IF dup dup pci-addr2bus 8 lshift swap pci-addr2dev 3 lshift or 40000000 + encode-int s" ibm,my-drc-index" property dup dup pci-addr2bus 20 * swap pci-addr2dev + a base ! s" Slot " rot $cathex hex encode-string s" ibm,loc-code" property THEN ; : pci-bridge-props ( addr -- ) dup pci-bus@ encode-int s" primary-bus" property encode-int s" secondary-bus" property encode-int s" subordinate-bus" property dup pci-bus@ drop encode-int rot encode-int+ s" bus-range" property pci-device-slots encode-int s" slot-names" property dup pci-bridge-range-props dup pci-bridge-assigned-addresses-prop s" interrupt-map" get-node get-property IF pci-bridge-interrupt-map ELSE 2drop THEN pci-reg-props ; : pci-bridge-generic-setup ( addr -- ) pci-device-slots >r \ save the slot array on return stack dup pci-common-props \ set the common properties before scanning the bus s" pci" device-type \ the type is allways "pci" dup pci-bridge-probe \ find all device connected to it dup assign-all-bridge-bars \ set up all memory access BARs dup pci-set-irq-line \ set the interrupt pin dup pci-set-capabilities \ set up the capabilities pci-bridge-props \ and generate all properties r> TO pci-device-slots \ and reset the slot array ; DEFER func-pci-device-props : pci-device-generic-setup ( config-addr -- ) dup assign-all-device-bars \ calc all BARs dup pci-set-irq-line \ set the interrupt pin dup pci-set-capabilities \ set up the capabilities dup func-pci-device-props \ and generate all properties drop \ forget the config-addr ; ' pci-device-props TO func-pci-device-props ( 8pci-config-bridge.fs: config-xt ( config-addr xt -- data ) puid >r \ Safe puid my-puid TO puid \ Set my-puid swap dup ffff00 AND 0= IF \ Has bus-device-function been specified? my-space OR \ No: use my-space instead THEN swap execute \ Execute the rtas-config-xx function r> TO puid \ Restore previous puid ; : config-b@ ( config-addr -- data ) ['] rtas-config-b@ config-xt ; : config-w@ ( config-addr -- data ) ['] rtas-config-w@ config-xt ; : config-l@ ( config-addr -- data ) ['] rtas-config-l@ config-xt ; : config-b! ( data config-addr -- ) ['] rtas-config-b! config-xt ; : config-w! ( data config-addr -- ) ['] rtas-config-w! config-xt ; : config-l! ( data config-addr -- ) ['] rtas-config-l! config-xt ; : config-dump puid >r my-puid TO puid my-space pci-dump r> TO puid ; : decode-unit ( addr len -- phys.lo ... phys.hi ) 2 hex-decode-unit \ decode string B lshift swap \ shift the devicenumber to the right spot 8 lshift or \ add the functionnumber my-bus 10 lshift or \ add the busnumber 0 0 rot \ make phys.lo = 0 = phys.mid ; : encode-unit ( phys.lo ... phys.hi -- unit-str unit-len ) nip nip \ forget the both zeros dup 8 rshift 7 and swap \ calc Functionnumber B rshift 1F and \ calc Devicenumber over IF \ IF Function!=0 2 hex-encode-unit \ | create string with DevNum,FnNum ELSE \ ELSE nip 1 hex-encode-unit \ | create string with only DevNum THEN \ FI ; : map-in ( phys.lo phys.mid phys.hi size -- virt ) drop nip nip ( phys.hi ) dup FF AND dup 10 28 WITHIN NOT swap 30 <> AND IF cr ." phys.hi = " . cr ABORT" map-in with illegal config space address" THEN 00FFFFFF AND \ Need only bus-dev-fn+register bits dup config-l@ ( phys.hi' bar.lo ) dup 7 AND 4 = IF \ Is it a 64-bit BAR? swap 4 + config-l@ lxjoin \ Add upper part of 64-bit BAR ELSE nip THEN F NOT AND \ Clear indicator bits ; : map-out ( virt size -- ) 2drop ; : dma-alloc ( ... size -- virt ) alloc-mem ; : dma-free ( virt size -- ) free-mem ; : dma-map-in ( ... virt size cacheable? -- devaddr ) 2drop ; : dma-map-out ( virt devaddr size -- ) 2drop drop ; : dma-sync ( virt devaddr size -- ) 2drop drop ; : open true ; : close ; 0update_flash.fsfalse value flash-new : update-flash-help ( -- ) cr ." update-flash tool to flash host FW " cr ." -f : Flash from file (e.g. net:\boot_rom.bin)" cr ." -l : Flash from load-base" cr ." -d : Flash from old load base (used by drone)" cr ." -c : Flash from temp to perm" cr ." -r : Flash from perm to temp" cr ; : flash-read-temp ( -- success? ) get-flashside 1 = IF flash-addr get-load-base over flash-image-size rmove true ELSE false THEN ; : flash-read-perm ( -- success? ) get-flashside 0= IF flash-addr get-load-base over flash-image-size rmove true ELSE false THEN ; : flash-switch-side ( side -- success? ) set-flashside 0<> IF s" Cannot change flashside" type cr false ELSE true THEN ; : flash-ensure-temp ( -- success? ) get-flashside 0= IF cr ." Cannot flash perm! Switching to temp side!" 1 flash-switch-side ELSE true THEN ; : update-flash ( "text" ) get-flashside >r \ Save old flashside parse-word ( str len ) \ Parse first string drop dup c@ ( str first-char ) [char] - <> IF update-flash-help r> 2drop EXIT THEN 1+ c@ ( second-char ) CASE [char] f OF parse-word cr s" do-load" evaluate flash-ensure-temp TO flash-new ENDOF [char] l OF flash-ensure-temp ENDOF [char] d OF flash-load-base get-load-base 200000 move flash-ensure-temp ENDOF [char] c OF flash-read-temp 0= flash-new or IF ." Cannot commit temp, need to boot on temp first " cr false ELSE 0 flash-switch-side THEN ENDOF [char] r OF flash-read-perm 0= IF ." Cannot commit perm, need to boot on perm first " cr false ELSE 1 flash-switch-side THEN ENDOF dup OF false ENDOF ENDCASE 0= IF update-flash-help r> drop EXIT THEN get-load-base flash-write 0= IF ." Flash write failed !! " cr THEN r> set-flashside drop \ Restore old flashside ; 00xmodem.fs01 CONSTANT XM-SOH \ Start of header 04 CONSTANT XM-EOT \ End-of-transmission 06 CONSTANT XM-ACK \ Acknowledge 15 CONSTANT XM-NAK \ Neg. acknowledge 0 VALUE xm-retries \ Retry count 0 VALUE xm-block# : xmodem-get-byte ( timeout -- byte|-1 ) d# 1000 * 0 DO key? IF key UNLOOP EXIT THEN 1 ms LOOP -1 ; : xmodem-rx-packet ( address -- success? ) 1 xmodem-get-byte \ Get block number dup 0 < IF 2drop false EXIT \ Timeout THEN 1 xmodem-get-byte \ Get neg. block number dup 0 < IF 3drop false EXIT \ Timeout THEN rot 0 ( blk# ~blk# address chksum ) 80 0 DO 1 xmodem-get-byte dup 0 < IF ( blk# ~blk# address chksum byte ) 3drop 2drop UNLOOP FALSE EXIT THEN dup 3 pick c! ( blk# ~blk# address chksum byte ) + swap 1+ swap ( blk# ~blk# address+1 chksum' ) LOOP 0ff and 1 xmodem-get-byte <> IF 3drop FALSE EXIT THEN drop ( blk# ~blk# ) over xm-block# <> IF 2drop FALSE EXIT THEN ( blk# ~blk# ) ff xor = ; : (xmodem-load) ( address -- bytes ) 1 to xm-block# 0 to xm-retries dup BEGIN d# 10 xmodem-get-byte dup >r CASE XM-SOH OF dup xmodem-rx-packet IF XM-ACK emit 80 + ( start-addr next-addr R: rx-byte ) 0 to xm-retries \ Reset retry count xm-block# 1+ ff and to xm-block# \ Increase current block# ELSE XM-NAK emit xm-retries 1+ to xm-retries \ Increase retry count THEN ENDOF XM-EOT OF XM-ACK emit ENDOF dup OF XM-NAK emit xm-retries 1+ to xm-retries \ Increase retry count ENDOF ENDCASE r> XM-EOT = xm-retries d# 10 >= OR UNTIL ( start-address end-address ) swap - ( bytes received ) ; : xmodem-load ( -- bytes ) cr ." Waiting for start of XMODEM upload..." cr get-load-base (xmodem-load) ; 0scsi-disk.fsnew-device s" disk" device-name s" block" device-type false VALUE scsi-disk-debug? scsi-open : execute-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len -- ... ) " execute-scsi-command" $call-parent ; : retry-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len #retries -- ... ) " retry-scsi-command" $call-parent ; 0 INSTANCE VALUE block-size 0 INSTANCE VALUE max-transfer 0 INSTANCE VALUE max-block-num 0 INSTANCE VALUE is_cdrom INSTANCE VARIABLE deblocker CREATE scratch 100 allot CREATE cdb 10 allot : dump-scsi-error ( sense-buf sense-len stat name namelen -- ) ." SCSI-DISK: " my-self instance>path type ." ," type ." failed" cr ." SCSI-DISK: Status " dup . .status-text 0<> IF ." Sense " scsi-get-sense-data dup . .sense-text ." ASC " . ." ASCQ " . cr ELSE drop THEN ; : read-blocks ( addr block# #blocks -- #read ) scsi-disk-debug? IF ." SCSI-DISK: read-blocks " .s cr THEN 2dup + max-block-num > IF ." SCSI-DISK: Access beyond end of device ! " cr drop dup max-block-num > IF drop drop 0 EXIT THEN dup max-block-num swap - THEN dup block-size * ( addr block# #blocks len ) >r rot r> ( block# #blocks addr len ) 2swap ( addr len block# #blocks ) dup >r cdb scsi-build-read-10 ( addr len ) r> -rot ( #blocks addr len ) scsi-dir-read cdb scsi-param-size 10 retry-scsi-command dup 0<> IF " read-blocks" dump-scsi-error -65 throw ELSE drop THEN ; : (inquiry) ( size -- buffer | NULL ) dup cdb scsi-build-inquiry scratch swap scsi-dir-read cdb scsi-param-size 10 retry-scsi-command 0= IF scratch ELSE 2drop 0 THEN ; : inquiry ( -- buffer | NULL ) scsi-disk-debug? IF ." SCSI-DISK: inquiry " .s cr THEN d# 36 (inquiry) 0= IF 0 EXIT THEN scratch inquiry-data>add-length c@ 5 + (inquiry) ; : read-capacity ( -- blocksize #blocks ) scsi-disk-debug? IF ." SCSI-DISK: read-capacity " .s cr THEN scratch 10 erase cdb scsi-build-read-cap-10 scratch scsi-length-read-cap-10-data scsi-dir-read cdb scsi-param-size 1 retry-scsi-command dup 0<> IF " read-capacity" dump-scsi-error 0 0 EXIT THEN drop scratch scsi-get-capacity-10 1 + ; 100 CONSTANT test-unit-retries : test-unit-ready ( true | [ ascq asc sense-key false ] ) scsi-disk-debug? IF ." SCSI-DISK: test-unit-ready " .s cr THEN cdb scsi-build-test-unit-ready 0 0 0 cdb scsi-param-size test-unit-retries retry-scsi-command 0= IF true EXIT THEN 0= IF drop 0 0 4 false EXIT THEN scsi-get-sense-data false ; : start-stop-unit ( state# -- true | false ) scsi-disk-debug? IF ." SCSI-DISK: start-stop-unit " .s cr THEN cdb scsi-build-start-stop-unit 0 0 0 cdb scsi-param-size 10 retry-scsi-command 0= IF true ELSE 2drop false THEN ; : compare-sense ( ascq asc key ascq2 asc2 key2 -- true | false ) 3 pick = ( ascq asc key ascq2 asc2 keycmp ) swap 4 pick = ( ascq asc key ascq2 keycmp asccmp ) rot 5 pick = ( ascq asc key keycmp asccmp ascqcmp ) and and nip nip nip ; 0 CONSTANT CDROM-READY 1 CONSTANT CDROM-NOT-READY 2 CONSTANT CDROM-NO-DISK 3 CONSTANT CDROM-TRAY-OPEN 4 CONSTANT CDROM-INIT-REQUIRED 5 CONSTANT CDROM-TRAY-MAYBE-OPEN : cdrom-try-close-tray ( -- ) scsi-const-load start-stop-unit drop ; : cdrom-must-close-tray ( -- ) scsi-const-load start-stop-unit not IF ." Tray open !" cr -65 throw THEN ; : get-media-event ( -- true | false ) scsi-disk-debug? IF ." SCSI-DISK: get-media-event " .s cr THEN cdb scsi-build-get-media-event scratch scsi-length-media-event scsi-dir-read cdb scsi-param-size 1 retry-scsi-command 0= IF true ELSE 2drop false THEN ; : cdrom-status ( -- status ) test-unit-ready IF CDROM-READY EXIT THEN scsi-disk-debug? IF ." TestUnitReady sense: " 3dup . . . cr THEN 3dup 1 4 2 compare-sense IF 3drop CDROM-NOT-READY EXIT THEN get-media-event IF scratch w@ 4 >= IF scratch 2 + c@ 04 = IF scratch 5 + c@ dup 02 and 0<> IF drop 3drop CDROM-READY EXIT THEN dup 01 and 0<> IF drop 3drop CDROM-TRAY-OPEN EXIT THEN drop 3drop CDROM-NO-DISK EXIT THEN THEN THEN 3dup 2 4 2 compare-sense IF 3drop CDROM-INIT-REQUIRED EXIT THEN over 4 = over 2 = and IF 3drop CDROM-READY EXIT THEN over 3a = IF 3drop CDROM-NO-DISK EXIT THEN 3drop CDROM-TRAY-MAYBE-OPEN ; : prep-cdrom ( -- ready? ) 5 0 DO cdrom-status CASE CDROM-READY OF UNLOOP true EXIT ENDOF CDROM-NO-DISK OF ." No medium !" cr UNLOOP false EXIT ENDOF CDROM-TRAY-OPEN OF cdrom-must-close-tray ENDOF CDROM-INIT-REQUIRED OF cdrom-try-close-tray ENDOF CDROM-TRAY-MAYBE-OPEN OF cdrom-try-close-tray ENDOF ENDCASE d# 1000 ms LOOP ." Drive not ready !" cr false ; : prep-disk ( -- ready? ) test-unit-ready not IF ." SCSI-DISK: Disk not ready ! " ." Sense " dup .sense-text ." [" . ." ]" ." ASC " . ." ASCQ " . cr false EXIT THEN true ; : open ( -- true | false ) scsi-disk-debug? IF ." SCSI-DISK: open [" .s ." ] unit is " my-unit . . ." [" .s ." ]" cr THEN my-unit " set-address" $call-parent inquiry dup 0= IF drop false EXIT THEN scsi-disk-debug? IF ." ---- inquiry: ----" cr dup 100 dump cr ." ------------------" cr THEN dup inquiry-data>peripheral c@ e0 and 0 <> IF ." SCSI-DISK: Unsupported PQ != 0" cr false EXIT THEN inquiry-data>peripheral c@ CASE 5 OF true to is_cdrom ENDOF 7 OF true to is_cdrom ENDOF ENDCASE scsi-disk-debug? IF is_cdrom IF ." SCSI-DISK: device treated as CD-ROM" cr ELSE ." SCSI-DISK: device treated as disk" cr THEN THEN is_cdrom IF prep-cdrom ELSE prep-disk THEN not IF false EXIT THEN " max-transfer" $call-parent to max-transfer read-capacity to max-block-num to block-size max-block-num 0= block-size 0= OR IF ." SCSI-DISK: Failed to get disk capacity!" cr FALSE EXIT THEN scsi-disk-debug? IF ." Capacity: " max-block-num . ." blocks of " block-size . cr THEN 0 0 " deblocker" $open-package dup deblocker ! dup IF " disk-label" find-package IF my-args rot interpose THEN THEN 0<> ; : close ( -- ) deblocker @ close-package ; : seek ( pos.lo pos.hi -- status ) s" seek" deblocker @ $call-method ; : read ( addr len -- actual ) s" read" deblocker @ $call-method ; scsi-close finish-device ^8scsi-host-helpers.fs: check-retry-sense? ( sense-buf sense-len -- retry? ) 8 < IF -1 EXIT THEN dup sense-data>response-code c@ 7e and 70 = IF dup sense-data>sense-key c@ e0 and IF drop -1 EXIT THEN THEN scsi-get-sense-data? IF ( ascq asc sense-key ) dup 2 < IF 3drop 0 EXIT THEN dup 2 = swap 6 = or nip nip IF 1 EXIT THEN THEN -1 ; 0 INSTANCE VALUE rcmd-buf-addr 0 INSTANCE VALUE rcmd-buf-len 0 INSTANCE VALUE rcmd-dir 0 INSTANCE VALUE rcmd-cmd-addr 0 INSTANCE VALUE rcmd-cmd-len : retry-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len #retries -- ... ) >r \ stash #retries to rcmd-cmd-len to rcmd-cmd-addr to rcmd-dir to rcmd-buf-len to rcmd-buf-addr 0 \ dummy status & sense r> \ retreive #retries ( stat #retries ) 0 DO 0<> IF 2drop THEN rcmd-buf-addr rcmd-buf-len rcmd-dir rcmd-cmd-addr rcmd-cmd-len execute-scsi-command ( [ sense-buf sense-len ] stat ) dup 0= IF LEAVE THEN dup -1 = IF LEAVE THEN dup 2 = IF ( sense-buf sense-len stat ) >r \ stash stat ( sense-buf sense len ) 2dup check-retry-sense? ( sense-buf sense-len retry? ) r> swap \ unstash stat ( sense-buf sense-len stat retry? ) CASE 0 OF 3drop 0 LEAVE ENDOF \ Swallow error, return 0 -1 OF LEAVE ENDOF \ No retry ENDCASE ELSE \ Anything other than busy -> exit dup 8 <> IF LEAVE THEN THEN a ms LOOP ; CREATE sector d# 512 allot CREATE cdb 10 allot : (inquiry) ( size -- buffer | NULL ) dup cdb scsi-build-inquiry sector swap scsi-dir-read cdb scsi-param-size 10 retry-scsi-command 0= IF sector ELSE 2drop 0 THEN ; : inquiry ( -- buffer | NULL ) d# 36 (inquiry) 0= IF 0 EXIT THEN sector inquiry-data>add-length c@ 5 + (inquiry) ; : report-luns ( -- [ sector ] true | false ) 200 cdb scsi-build-report-luns sector 200 scsi-dir-read cdb scsi-param-size 10 retry-scsi-command 0= IF sector true ELSE drop false THEN ; : make-disk-alias ( $name srplun -- ) >r 2dup r> -rot ( $name srplun $name) find-alias 0<> IF 4drop exit THEN get-node node>path 20 allot " /disk@" string-cat ( $name srplun npath npathl ) rot base @ >r hex (u.) r> base ! string-cat ( $name $diskpath ) set-alias ; l8scsi-probe-helpers.fs: wrapped-inquiry ( -- true | false ) inquiry 0= IF false EXIT THEN sector inquiry-data>peripheral c@ e0 and 0 = ; : scsi-read-lun ( addr -- lun true | false ) dup c@ C0 AND CASE 40 OF w@-be 3FFF AND TRUE ENDOF 0 OF w@-be TRUE ENDOF dup dup OF ." Unsupported LUN format = " . cr FALSE ENDOF ENDCASE ; : vscsi-report-luns ( -- array ndev ) dev-max-target 3 << alloc-mem dup 0 ( devarray devcur ndev ) dev-max-target 0 DO i 0 dev-generate-srplun (set-target) report-luns nip IF sector l@ ( devarray devcur ndev size ) sector 8 + swap ( devarray devcur ndev lunarray size ) dup 8 + dup alloc-mem ( devarray devcur ndev lunarray size size+ mem ) dup rot 0 fill ( devarray devcur ndev lunarray size mem ) dup >r swap move r> ( devarray devcur ndev mem ) dup sector l@ 3 >> 0 ?DO ( devarray devcur ndev mem memcur ) dup dup scsi-read-lun IF j swap dev-generate-srplun swap x! 8 + ELSE 2drop THEN LOOP drop rot ( devarray ndev mem devcur ) dup >r x! r> 8 + ( devarray ndev devcur ) swap 1 + ELSE dev-max-target 1 = IF 16 alloc-mem ( devarray devcur ndev mem ) dup 16 0 fill ( devarray devcur ndev mem ) dup 0 0 dev-generate-srplun swap x! ( devarray devcur ndev mem ) rot x! ( devarray ndev ) 1 + UNLOOP EXIT THEN THEN LOOP nip ; : make-media-alias ( $name srplun -- ) >r get-next-alias ?dup IF r> make-disk-alias ELSE r> drop THEN ; : scsi-find-disks ( -- ) ." SCSI: Looking for devices" cr vscsi-report-luns 0 ?DO dup x@ BEGIN dup x@ dup 0= IF drop TRUE ELSE (set-target) wrapped-inquiry IF ." " current-target (u.) type ." " sector inquiry-data>peripheral c@ CASE 0 OF ." DISK : " " disk" current-target make-media-alias ENDOF 5 OF ." CD-ROM : " " cdrom" current-target make-media-alias ENDOF 7 OF ." OPTICAL : " " cdrom" current-target make-media-alias ENDOF e OF ." RED-BLOCK: " " disk" current-target make-media-alias ENDOF dup dup OF ." ? (" . 8 emit 29 emit 5 spaces ENDOF ENDCASE sector .inquiry-text cr THEN 8 + FALSE THEN UNTIL drop 8 + LOOP drop ; NN0scsi-support.fsvocabulary scsi-words \ create new word list named 'scsi-words' also scsi-words definitions \ place next definitions into new list false value scsi-param-debug \ common debugging flag d# 0 value scsi-param-size \ length of CDB processed last h# 0 value scsi-param-control \ control word for CDBs as defined in SAM-4 d# 0 value scsi-param-errors \ counter for detected errors : scsi-inc-errors scsi-param-errors 1 + to scsi-param-errors ; 00 CONSTANT scsi-cmd-test-unit-ready STRUCT /c FIELD test-unit-ready>operation-code \ 00h 4 FIELD test-unit-ready>reserved \ unused /c FIELD test-unit-ready>control \ control byte as specified in SAM-4 CONSTANT scsi-length-test-unit-ready : scsi-build-test-unit-ready ( cdb -- ) dup scsi-length-test-unit-ready erase ( cdb ) scsi-param-control swap test-unit-ready>control c! ( ) scsi-length-test-unit-ready to scsi-param-size \ update CDB length ; a0 CONSTANT scsi-cmd-report-luns STRUCT /c FIELD report-luns>operation-code \ a0h 1 FIELD report-luns>reserved \ unused /c FIELD report-luns>select-report \ report select byte 3 FIELD report-luns>reserved2 \ unused /l FIELD report-luns>alloc-length \ report length 1 FIELD report-luns>reserved3 \ unused /c FIELD report-luns>control \ control byte CONSTANT scsi-length-report-luns : scsi-build-report-luns ( alloc-len cdb -- ) dup scsi-length-report-luns erase \ 12 bytes CDB scsi-cmd-report-luns over ( alloc-len cdb cmd cdb ) report-luns>operation-code c! ( alloc-len cdb ) scsi-param-control over report-luns>control c! ( alloc-len cdb ) report-luns>alloc-length l! \ size of Data-In Buffer scsi-length-report-luns to scsi-param-size \ update CDB length ; 03 CONSTANT scsi-cmd-request-sense STRUCT /c FIELD request-sense>operation-code \ 03h 3 FIELD request-sense>reserved \ unused /c FIELD request-sense>allocation-length \ buffer-length for data response /c FIELD request-sense>control \ control byte as specified in SAM-4 CONSTANT scsi-length-request-sense : scsi-build-request-sense ( alloc-len cdb -- ) >r ( alloc-len ) ( R: -- cdb ) r@ scsi-length-request-sense erase ( alloc-len ) scsi-cmd-request-sense r@ ( alloc-len cmd cdb ) request-sense>operation-code c! ( alloc-len ) dup d# 252 > \ buffer length too big ? IF scsi-inc-errors drop d# 252 \ replace with 252 ELSE dup d# 18 < \ allocated buffer too small ? IF scsi-inc-errors drop 0 \ reject return data THEN THEN ( alloclen ) r@ request-sense>allocation-length c! ( ) scsi-param-control r> request-sense>control c! ( alloc-len cdb ) ( R: cdb -- ) scsi-length-request-sense to scsi-param-size \ update CDB length ; 70 CONSTANT scsi-response(request-sense-0) 71 CONSTANT scsi-response(request-sense-1) STRUCT /c FIELD sense-data>response-code \ 70h (current errors) or 71h (deferred errors) /c FIELD sense-data>obsolete /c FIELD sense-data>sense-key \ D3..D0 = sense key, D7 = EndOfMedium /l FIELD sense-data>info /c FIELD sense-data>alloc-length \ <= 244 (for max size) /l FIELD sense-data>command-info /c FIELD sense-data>asc \ additional sense key /c FIELD sense-data>ascq \ additional sense key qualifier /c FIELD sense-data>unit-code 3 FIELD sense-data>key-specific /c FIELD sense-data>add-sense-bytes \ start of appended extra bytes CONSTANT scsi-length-sense-data : scsi-get-sense-data ( addr -- ascq asc sense-key ) >r ( R: -- addr ) r@ sense-data>response-code c@ 7f and 72 >= IF r@ 3 + c@ ( ascq ) r@ 2 + c@ ( ascq asc ) r> 1 + c@ 0f and ( ascq asc sense-key ) ELSE r@ sense-data>ASCQ c@ ( ascq ) r@ sense-data>ASC c@ ( ascq asc ) r> sense-data>sense-key c@ 0f and ( ascq asc sense-key ) ( R: addr -- ) THEN ; : scsi-get-sense-data? ( addr -- false | ascq asc sense-key true ) dup sense-data>response-code c@ 7e AND dup 70 = swap 72 = or \ Response code (some devices have MSB set) IF scsi-get-sense-data TRUE ELSE drop FALSE \ drop addr THEN ; : scsi-get-sense-ID? ( addr -- false | ascq asc sense-key true ) dup sense-data>response-code c@ 7e AND 70 = \ Response code (some devices have MSB set) IF scsi-get-sense-data ( ascq asc sense-key ) 10 lshift ( ascq asc sense-key16 ) swap 8 lshift or ( ascq sense-key+asc ) swap or \ 24-bit sense-ID ( sense-key+asc+ascq ) TRUE ELSE drop FALSE \ drop addr THEN ; 12 CONSTANT scsi-cmd-inquiry STRUCT /c FIELD inquiry>operation-code \ 0x12 /c FIELD inquiry>reserved \ + EVPD-Bit (vital product data) /c FIELD inquiry>page-code \ page code for vital product data (if used) /w FIELD inquiry>allocation-length \ length of Data-In-Buffer /c FIELD inquiry>control \ control byte as specified in SAM-4 CONSTANT scsi-length-inquiry : scsi-build-inquiry ( alloc-len cdb -- ) dup scsi-length-inquiry erase \ 6 bytes CDB scsi-cmd-inquiry over ( alloc-len cdb cmd cdb ) inquiry>operation-code c! ( alloc-len cdb ) scsi-param-control over inquiry>control c! ( alloc-len cdb ) inquiry>allocation-length w! \ size of Data-In Buffer scsi-length-inquiry to scsi-param-size \ update CDB length ; STRUCT /c FIELD inquiry-data>peripheral \ qualifier and device type /c FIELD inquiry-data>reserved1 /c FIELD inquiry-data>version \ supported SCSI version (1,2,3) /c FIELD inquiry-data>data-format /c FIELD inquiry-data>add-length \ total block length - 4 /c FIELD inquiry-data>flags1 /c FIELD inquiry-data>flags2 /c FIELD inquiry-data>flags3 d# 8 FIELD inquiry-data>vendor-ident \ vendor string d# 16 FIELD inquiry-data>product-ident \ device string /l FIELD inquiry-data>product-revision \ revision string d# 20 FIELD inquiry-data>vendor-specific \ optional params CONSTANT scsi-length-inquiry-data 25 CONSTANT scsi-cmd-read-capacity-10 \ command code STRUCT \ SCSI 10-byte CDB structure /c FIELD read-cap-10>operation-code /c FIELD read-cap-10>reserved1 /l FIELD read-cap-10>lba /w FIELD read-cap-10>reserved2 /c FIELD read-cap-10>reserved3 /c FIELD read-cap-10>control CONSTANT scsi-length-read-cap-10 : scsi-build-read-cap-10 ( cdb -- ) dup scsi-length-read-cap-10 erase ( cdb ) scsi-cmd-read-capacity-10 over ( cdb cmd cdb ) read-cap-10>operation-code c! ( cdb ) scsi-param-control swap read-cap-10>control c! ( ) scsi-length-read-cap-10 to scsi-param-size \ update CDB length ; STRUCT /l FIELD read-cap-10-data>max-lba /l FIELD read-cap-10-data>block-size CONSTANT scsi-length-read-cap-10-data : scsi-get-capacity-10 ( addr -- block-size #blocks ) >r ( addr -- ) ( R: -- addr ) r@ read-cap-10-data>block-size l@ ( block-size ) r> read-cap-10-data>max-lba l@ ( block-size #blocks ) ( R: addr -- ) ; 9e CONSTANT scsi-cmd-read-capacity-16 \ command code STRUCT \ SCSI 16-byte CDB structure /c FIELD read-cap-16>operation-code /c FIELD read-cap-16>service-action /l FIELD read-cap-16>lba-high /l FIELD read-cap-16>lba-low /l FIELD read-cap-16>allocation-length \ should be 32 /c FIELD read-cap-16>reserved /c FIELD read-cap-16>control CONSTANT scsi-length-read-cap-16 : scsi-build-read-cap-16 ( cdb -- ) >r r@ ( R: -- cdb ) scsi-length-read-cap-16 erase ( ) scsi-cmd-read-capacity-16 ( code ) r@ read-cap-16>operation-code c! ( ) 10 r@ read-cap-16>service-action c! d# 32 \ response size 32 bytes r@ read-cap-16>allocation-length l! ( ) scsi-param-control r> read-cap-16>control c! ( R: cdb -- ) scsi-length-read-cap-16 to scsi-param-size \ update CDB length ; STRUCT /l FIELD read-cap-16-data>max-lba-high \ upper quadlet of Max-LBA /l FIELD read-cap-16-data>max-lba-low \ lower quadlet of Max-LBA /l FIELD read-cap-16-data>block-size \ logical block length in bytes /c FIELD read-cap-16-data>protect \ type of protection (4 bits) /c FIELD read-cap-16-data>exponent \ logical blocks per physical blocks /w FIELD read-cap-16-data>lowest-aligned \ first LBA of a phsy. block 10 FIELD read-cap-16-data>reserved \ 16 reserved bytes CONSTANT scsi-length-read-cap-16-data \ results in 32 : scsi-get-capacity-16 ( addr -- block-size #blocks ) >r ( R: -- addr ) r@ read-cap-16-data>block-size l@ ( block-size ) r@ read-cap-16-data>max-lba-high l@ ( block-size #blocks-high ) d# 32 lshift ( block-size #blocks-upper ) r> read-cap-16-data>max-lba-low l@ + ( block-size #blocks ) ( R: addr -- ) ; 5a CONSTANT scsi-cmd-mode-sense-10 STRUCT /c FIELD mode-sense-10>operation-code /c FIELD mode-sense-10>res-llbaa-dbd-res /c FIELD mode-sense-10>pc-page-code \ page code + page control /c FIELD mode-sense-10>sub-page-code 3 FIELD mode-sense-10>reserved2 /w FIELD mode-sense-10>allocation-length /c FIELD mode-sense-10>control CONSTANT scsi-length-mode-sense-10 : scsi-build-mode-sense-10 ( alloc-len subpage page cdb -- ) >r ( alloc-len subpage page ) ( R: -- cdb ) r@ scsi-length-mode-sense-10 erase \ 10 bytes CDB scsi-cmd-mode-sense-10 ( alloc-len subpage page cmd ) r@ mode-sense-10>operation-code c! ( alloc-len subpage page ) 10 r@ mode-sense-10>res-llbaa-dbd-res c! \ long LBAs accepted r@ mode-sense-10>pc-page-code c! ( alloc-len subpage ) r@ mode-sense-10>sub-page-code c! ( alloc-len ) r@ mode-sense-10>allocation-length w! ( ) scsi-param-control r> mode-sense-10>control c! ( R: cdb -- ) scsi-length-mode-sense-10 to scsi-param-size \ update CDB length ; STRUCT /w FIELD mode-sense-10-data>head-length /c FIELD mode-sense-10-data>head-medium /c FIELD mode-sense-10-data>head-param /c FIELD mode-sense-10-data>head-longlba /c FIELD mode-sense-10-data>head-reserved /w FIELD mode-sense-10-data>head-descr-len CONSTANT scsi-length-mode-sense-10-data : .mode-sense-data ( addr -- ) cr dup mode-sense-10-data>head-length w@ ." Mode Length: " .d space dup mode-sense-10-data>head-medium c@ ." / Medium Type: " .d space dup mode-sense-10-data>head-longlba c@ ." / Long LBA: " .d space mode-sense-10-data>head-descr-len w@ ." / Descr. Length: " .d ; 08 CONSTANT scsi-cmd-read-6 STRUCT /c FIELD read-6>operation-code \ 08h /c FIELD read-6>block-address-msb \ upper 5 bits /w FIELD read-6>block-address \ lower 16 bits /c FIELD read-6>length \ number of blocks to read /c FIELD read-6>control \ CDB control CONSTANT scsi-length-read-6 : scsi-build-read-6 ( block# #blocks cdb -- ) >r ( block# #blocks ) ( R: -- cdb ) r@ scsi-length-read-6 erase \ 6 bytes CDB scsi-cmd-read-6 r@ read-6>operation-code c! ( block# #blocks ) dup d# 255 > \ #blocks exceeded limit ? IF scsi-inc-errors drop 1 \ replace with any valid number THEN r@ read-6>length c! \ set #blocks to read dup 1fffff > \ check address upper limit IF scsi-inc-errors drop \ remove original block# 1fffff \ replace with any valid address THEN dup d# 16 rshift r@ read-6>block-address-msb c! \ set upper 5 bits ffff and r@ read-6>block-address w! \ set lower 16 bits scsi-param-control r> read-6>control c! ( R: cdb -- ) scsi-length-read-6 to scsi-param-size \ update CDB length ; 28 CONSTANT scsi-cmd-read-10 STRUCT /c FIELD read-10>operation-code /c FIELD read-10>protect /l FIELD read-10>block-address \ logical block address (32bits) /c FIELD read-10>group /w FIELD read-10>length \ transfer length (16-bits) /c FIELD read-10>control CONSTANT scsi-length-read-10 : scsi-build-read-10 ( block# #blocks cdb -- ) >r ( block# #blocks ) ( R: -- cdb ) r@ scsi-length-read-10 erase \ 10 bytes CDB scsi-cmd-read-10 r@ read-10>operation-code c! ( block# #blocks ) r@ read-10>length w! ( block# ) r@ read-10>block-address l! ( ) scsi-param-control r> read-10>control c! ( R: cdb -- ) scsi-length-read-10 to scsi-param-size \ update CDB length ; a8 CONSTANT scsi-cmd-read-12 STRUCT /c FIELD read-12>operation-code \ code: a8 /c FIELD read-12>protect \ RDPROTECT, DPO, FUA, FUA_NV /l FIELD read-12>block-address \ lba /l FIELD read-12>length \ transfer length (32bits) /c FIELD read-12>group \ group number /c FIELD read-12>control CONSTANT scsi-length-read-12 : scsi-build-read-12 ( block# #blocks cdb -- ) >r ( block# #blocks ) ( R: -- cdb ) r@ scsi-length-read-12 erase \ 12 bytes CDB scsi-cmd-read-12 r@ read-12>operation-code c! ( block# #blocks ) r@ read-12>length l! ( block# ) r@ read-12>block-address l! ( ) scsi-param-control r> read-12>control c! ( R: cdb -- ) scsi-length-read-12 to scsi-param-size \ update CDB length ; : scsi-build-read? ( block# #blocks cdb -- length ) over ( block# #blocks cdb #blocks ) fffe > \ tx-length (#blocks) exceeds 16-bit limit ? IF scsi-build-read-12 ( block# #blocks cdb -- ) scsi-length-read-12 ( length ) ELSE ( block# #blocks cdb ) scsi-build-read-10 ( block# #blocks cdb -- ) scsi-length-read-10 ( length ) THEN ; 1b CONSTANT scsi-cmd-start-stop-unit STRUCT /c FIELD start-stop-unit>operation-code /c FIELD start-stop-unit>immed /w FIELD start-stop-unit>reserved /c FIELD start-stop-unit>pow-condition /c FIELD start-stop-unit>control CONSTANT scsi-length-start-stop-unit f1 CONSTANT scsi-const-active-power \ param used for start-stop-unit f2 CONSTANT scsi-const-idle-power \ param used for start-stop-unit f3 CONSTANT scsi-const-standby-power \ param used for start-stop-unit 3 CONSTANT scsi-const-load \ param used for start-stop-unit 2 CONSTANT scsi-const-eject \ param used for start-stop-unit 1 CONSTANT scsi-const-start 0 CONSTANT scsi-const-stop : scsi-build-start-stop-unit ( state# cdb -- ) >r ( state# ) ( R: -- cdb ) r@ scsi-length-start-stop-unit erase \ 6 bytes CDB scsi-cmd-start-stop-unit r@ start-stop-unit>operation-code c! dup 3 > IF 4 lshift \ shift to upper nibble THEN ( state ) r@ start-stop-unit>pow-condition c! ( ) scsi-param-control r> start-stop-unit>control c! ( R: cdb -- ) scsi-length-start-stop-unit to scsi-param-size \ update CDB length ; 2b CONSTANT scsi-cmd-seek STRUCT /c FIELD seek>operation-code /c FIELD seek>reserved1 /l FIELD seek>lba 3 FIELD seek>reserved2 /c FIELD seek>control CONSTANT scsi-length-seek : scsi-build-seek ( lba cdb -- ) >r ( lba ) ( R: -- cdb ) r@ scsi-length-seek erase \ 10 bytes CDB scsi-cmd-seek r@ seek>operation-code c! r> seek>lba l! ( ) ( R: cdb -- ) scsi-length-seek to scsi-param-size \ update CDB length ; STRUCT /w FIELD media-event-data-len /c FIELD media-event-nea-class /c FIELD media-event-supp-class /l FIELD media-event-data CONSTANT scsi-length-media-event : scsi-build-get-media-event ( cdb -- ) dup c erase ( cdb ) 4a over c! ( cdb ) 01 over 1 + c! 10 over 4 + c! 08 over 8 + c! drop ; : .sense-text ( scode -- ) case 0 OF s" OK" ENDOF 1 OF s" RECOVERED ERR" ENDOF 2 OF s" NOT READY" ENDOF 3 OF s" MEDIUM ERROR" ENDOF 4 OF s" HARDWARE ERR" ENDOF 5 OF s" ILLEGAL REQUEST" ENDOF 6 OF s" UNIT ATTENTION" ENDOF 7 OF s" DATA PROTECT" ENDOF 8 OF s" BLANK CHECK" ENDOF 9 OF s" VENDOR SPECIFIC" ENDOF a OF s" COPY ABORTED" ENDOF b OF s" ABORTED COMMAND" ENDOF d OF s" VOLUME OVERFLOW" ENDOF e OF s" MISCOMPARE" ENDOF dup OF s" UNKNOWN" ENDOF endcase 5b emit type 5d emit ; : .status-text ( stat -- ) case 00 OF s" GOOD" ENDOF 02 OF s" CHECK CONDITION" ENDOF 04 OF s" CONDITION MET" ENDOF 08 OF s" BUSY" ENDOF 18 OF s" RESERVATION CONFLICT" ENDOF 28 OF s" TASK SET FULL" ENDOF 30 OF s" ACA ACTIVE" ENDOF 40 OF s" TASK ABORTED" ENDOF dup OF s" UNKNOWN" ENDOF endcase 5b emit type 5d emit ; : .dec3-2 ( prenum postnum -- ) swap base @ >r \ save actual base setting decimal \ show decimal values 4 .r 2e emit dup 9 <= IF 30 emit THEN .d \ 3 pre-decimal, right aligned r> base ! \ restore base ; : .capacity-text ( block-size #blocks -- ) scsi-param-debug \ debugging flag set ? IF \ show additional info 2dup cr ." LBAs: " .d \ highest logical block number ." / Block-Size: " .d ." / Total Capacity: " THEN * \ calculate total capacity dup d# 1000000000000 >= \ check terabyte limit IF d# 1000000000000 /mod swap d# 10000000000 / \ limit remainder to two digits .dec3-2 ." TB" \ show terabytes as xxx.yy ELSE dup d# 1000000000 >= \ check gigabyte limit IF d# 1000000000 /mod swap d# 10000000 / .dec3-2 ." GB" \ show gigabytes as xxx.yy ELSE dup d# 1000000 >= IF d# 1000000 /mod \ check mega byte limit swap d# 10000 / .dec3-2 ." MB" \ show megabytes as xxx.yy ELSE dup d# 1000 >= \ check kilo byte limit IF d# 1000 /mod swap d# 10 / .dec3-2 ." kB" ELSE .d ." Bytes" THEN THEN THEN THEN ; : .inquiry-text ( addr -- ) 22 emit \ enclose text with " dup inquiry-data>vendor-ident 8 type space dup inquiry-data>product-ident 10 type space inquiry-data>product-revision 4 type 22 emit ; : scsi-supp-init ( -- ) false to scsi-param-debug \ no debug strings h# 0 to scsi-param-size h# 0 to scsi-param-control \ common CDB control byte d# 0 to scsi-param-errors \ local errors (param limits) ; true CONSTANT scsi-dir-read false CONSTANT scsi-dir-write 0 VALUE scsi-context \ addr of word list on top : scsi-init ( -- ) also scsi-words \ append scsi word-list context to scsi-context \ save for close process scsi-supp-init \ preset all scsi-param-xxx values scsi-param-debug IF space ." SCSI-SUPPORT OPENED" cr .wordlists THEN ; : scsi-close ( -- ) scsi-param-debug IF space ." Closing SCSI-SUPPORT .. " cr THEN context scsi-context = \ scsi word list still active ? IF scsi-param-errors 0<> \ any errors occurred ? IF cr ." ** WARNING: " scsi-param-errors .d ." SCSI Errors occurred ** " cr THEN previous \ remove scsi word list on top 0 to scsi-context \ prevent from being misinterpreted ELSE cr ." ** WARNING: Trying to close non-open SCSI-SUPPORT (1) ** " cr THEN scsi-param-debug IF .wordlists THEN ; s" scsi-init" $find drop \ return execution pointer, when included previous \ remove scsi word list from search path definitions \ place next definitions into previous list @8default-font.bin(($$~$$~$$*(( *0H0 0@  8DD@"THT" |(||00 @8DDDDDDDD88DD @x8DD8@@@HH~~@@@xx @@@xDDD8~B 8DDD8DDDD88DDD<D800000000 @ @@ ~~  "$BNRN@@$$$$~BBBB|BBB||BBB|<"`@@@@`"<xDBBBBBBDx~@@@~~@@@~~@@@~~@@@@r my-puid TO puid rtas-config-b@ r> TO puid ; : config-w@ puid >r my-puid TO puid rtas-config-w@ r> TO puid ; : config-l@ puid >r my-puid TO puid rtas-config-l@ r> TO puid ; : config-b! puid >r my-puid TO puid rtas-config-b! r> TO puid ; : config-w! puid >r my-puid TO puid rtas-config-w! r> TO puid ; : config-l! puid >r my-puid TO puid rtas-config-l! r> TO puid ; : map-in ( phys.lo phys.mid phys.hi size -- virt ) phb-debug? IF cr ." map-in called: " .s cr THEN drop nip nip ( phys.hi ) dup FF AND dup 10 28 WITHIN NOT swap 30 <> AND IF cr ." phys.hi = " . cr ABORT" map-in with illegal config space address" THEN 00FFFFFF AND \ Need only bus-dev-fn+register bits dup config-l@ ( phys.hi' bar.lo ) dup 7 AND 4 = IF \ Is it a 64-bit BAR? swap 4 + config-l@ lxjoin \ Add upper part of 64-bit BAR ELSE nip THEN F NOT AND \ Clear indicator bits translate-my-address phb-debug? IF ." map-in done: " .s cr THEN ; : map-out ( virt size -- ) phb-debug? IF ." map-out called: " .s cr THEN 2drop ; : dma-alloc ( size -- virt ) phb-debug? IF cr ." dma-alloc called: " .s cr THEN fff + fff not and \ Align size to next 4k boundary alloc-mem dup fff and IF ." Warning: dma-alloc got unaligned memory!" cr THEN ; : dma-free ( virt size -- ) phb-debug? IF cr ." dma-free called: " .s cr THEN fff + fff not and \ Align size to next 4k boundary free-mem ; 0 VALUE dma-window-liobn \ Logical I/O bus number 0 VALUE dma-window-base \ Start address of window 0 VALUE dma-window-size \ Size of the window 0 VALUE bm-handle \ Bitmap allocator handle 0 VALUE my-virt 0 VALUE my-size 0 VALUE dev-addr 0 VALUE tmp-dev-addr : (init-dma-window-vars) ( -- ) s" ibm,dma-window" calling-child get-property IF s" ibm,dma-window" calling-child parent get-property ABORT" no dma-window property available" THEN decode-int TO dma-window-liobn decode-64 TO dma-window-base decode-64 TO dma-window-size 2drop bm-handle 0= IF dma-window-base dma-window-size 1000 bm-allocator-init to bm-handle dma-window-base 0= IF bm-handle 1000 bm-alloc drop THEN THEN ; : (clear-dma-window-vars) ( -- ) 0 TO dma-window-liobn 0 TO dma-window-base 0 TO dma-window-size ; : dma-virt2dev ( virt -- devaddr ) dma-window-size mod dma-window-base + ; : dma-map-in ( virt size cachable? -- devaddr ) phb-debug? IF cr ." dma-map-in called: " .s cr THEN (init-dma-window-vars) drop ( virt size ) to my-size to my-virt bm-handle my-size bm-alloc to dev-addr dev-addr 0 < IF ." Bitmap allocation Failed " dev-addr . FALSE EXIT THEN dev-addr to tmp-dev-addr my-virt my-size bounds dup >r ( v+s virt R: virt ) swap fff + fff not and \ Align end to next 4k boundary swap fff not and ( v+s' virt' R: virt ) ?DO dma-window-liobn \ liobn tmp-dev-addr \ ioba i 3 OR \ Make a read- & writeable TCE hv-put-tce ABORT" H_PUT_TCE failed" tmp-dev-addr 1000 + to tmp-dev-addr 1000 +LOOP r> drop my-virt FFF and dev-addr or (clear-dma-window-vars) ; : dma-map-out ( virt devaddr size -- ) phb-debug? IF cr ." dma-map-out called: " .s cr THEN (init-dma-window-vars) to my-size to dev-addr to my-virt dev-addr fff not and to dev-addr dev-addr to tmp-dev-addr my-virt my-size ( virt size ) bounds ( v+s virt ) swap fff + fff not and \ Align end to next 4k boundary swap fff not and ( v+s' virt' ) ?DO dma-window-liobn \ liobn tmp-dev-addr \ ioba i \ Lowest bits not set => invalid TCE hv-put-tce ABORT" H_PUT_TCE failed" tmp-dev-addr 1000 + to tmp-dev-addr 1000 +LOOP bm-handle dev-addr my-size bm-free (clear-dma-window-vars) ; : dma-sync ( virt devaddr size -- ) phb-debug? IF cr ." dma-sync called: " .s cr THEN 3drop ; : open true ; : close ; : phb-parse-ranges ( -- ) 0 pci-next-io ! 0 pci-max-io ! 0 pci-next-mem ! 0 pci-max-mem ! 0 pci-next-mmio ! 0 pci-max-mmio ! 0 pci-next-mem64 ! 0 pci-max-mem64 ! s" ranges" get-node get-property 0<> ABORT" ranges property not found" BEGIN dup WHILE decode-int \ Decode phys.hi 3000000 AND \ Filter out address space in phys.hi CASE 1000000 OF \ I/O space? decode-64 dup >r pci-next-io ! \ Decode PCI base address decode-64 drop \ Forget the parent address decode-64 r> + pci-max-io ! \ Decode size & calc max address pci-next-io @ 0= IF pci-next-io @ 10 + pci-next-io ! \ BARs must not be set to zero THEN ENDOF 2000000 OF \ 32-bit memory space? decode-64 pci-next-mem ! \ Decode mem base address decode-64 drop \ Forget the parent address decode-64 2 / dup >r \ Decode and calc size/2 pci-next-mem @ + dup pci-max-mem ! \ and calc max mem address dup pci-next-mmio ! \ which is the same as MMIO base r> + pci-max-mmio ! \ calc max MMIO address ENDOF 3000000 OF \ 64-bit memory space? decode-64 pci-next-mem64 ! decode-64 drop \ Forget the parent address decode-64 pci-max-mem64 ! ENDOF ENDCASE REPEAT 2drop phb-debug? IF ." pci-next-io = " pci-next-io @ . cr ." pci-max-io = " pci-max-io @ . cr ." pci-next-mem = " pci-next-mem @ . cr ." pci-max-mem = " pci-max-mem @ . cr ." pci-next-mmio = " pci-next-mmio @ . cr ." pci-max-mmio = " pci-max-mmio @ . cr ." pci-next-mem64 = " pci-next-mem64 @ . cr ." pci-max-mem64 = " pci-max-mem64 @ . cr THEN ; : phb-pci-walk-bridge ( -- ) phb-debug? IF ." Calling pci-walk-bridge " pwd cr THEN get-node child ?dup 0= IF EXIT THEN \ get and check if we have children 0 to pci-device-slots \ reset slot array to unpoppulated BEGIN dup \ Continue as long as there are children WHILE dup set-node \ Set child node as current node my-space pci-set-slot \ set the slot bit my-space pci-htype@ \ read HEADER-Type 7f and \ Mask bit 7 - multifunction device CASE 0 OF my-space pci-device-setup ENDOF \ | set up the device 1 OF my-space pci-bridge-setup ENDOF \ | set up the bridge dup OF my-space pci-htype@ pci-out ENDOF ENDCASE peer REPEAT drop get-parent set-node ; : phb-pci-probe-bus ( busnr -- ) drop phb-pci-walk-bridge ; : phb-pci-device-props ( addr -- ) dup pci-class-name device-name dup pci-device-assigned-addresses-prop drop ; : phb-setup-children puid >r \ Save old value of puid my-puid TO puid \ Set current puid phb-parse-ranges 1 TO pci-hotplug-enabled s" qemu,phb-enumerated" get-node get-property 0<> IF 1 0 (probe-pci-host-bridge) ELSE 2drop ['] phb-pci-probe-bus TO func-pci-probe-bus ['] phb-pci-device-props TO func-pci-device-props phb-pci-walk-bridge \ PHB device tree is already populated. THEN r> TO puid \ Restore previous puid ; phb-setup-children  (rtas.fs371 cp STRUCT /l field rtas>token /l field rtas>nargs /l field rtas>nret /l field rtas>args0 /l field rtas>args1 /l field rtas>args2 /l field rtas>args3 /l field rtas>args4 /l field rtas>args5 /l field rtas>args6 /l field rtas>args7 /l C * field rtas>args /l field rtas>bla CONSTANT /rtas-control-block CREATE rtas-cb /rtas-control-block allot rtas-cb /rtas-control-block erase 0 VALUE rtas-base 0 VALUE rtas-size 0 VALUE rtas-entry 0 VALUE rtas-node 372 cp : find-qemu-rtas ( -- ) " /rtas" find-device get-node to rtas-node " linux,rtas-base" rtas-node get-package-property IF device-end EXIT THEN drop l@ to rtas-base " linux,rtas-base" delete-property " rtas-size" rtas-node get-package-property IF device-end EXIT THEN drop l@ to rtas-size " linux,rtas-entry" rtas-node get-package-property IF rtas-base to rtas-entry ELSE drop l@ to rtas-entry " linux,rtas-entry" delete-property THEN 0 rtas-base dup rtas-size + check-and-patch-sc1 device-end ; find-qemu-rtas 373 cp : enter-rtas ( -- ) rtas-cb rtas-base 0 rtas-entry call-c drop ; : rtas-get-token ( str len -- token | 0 ) rtas-node get-package-property IF 0 ELSE drop l@ THEN ; : rtas-power-off ( x y -- status ) [ s" power-off" rtas-get-token ] LITERAL rtas-cb rtas>token l! 2 rtas-cb rtas>nargs l! 1 rtas-cb rtas>nret l! rtas-cb rtas>args0 l! rtas-cb rtas>args1 l! enter-rtas rtas-cb rtas>args2 l@ ; : power-off ( -- ) 0 0 rtas-power-off ; : rtas-system-reboot ( -- status ) [ s" system-reboot" rtas-get-token ] LITERAL rtas-cb rtas>token l! 0 rtas-cb rtas>nargs l! 1 rtas-cb rtas>nret l! rtas-cb rtas>args0 l! enter-rtas rtas-cb rtas>args1 l@ ; : rtas-start-cpu ( pid loc r3 -- status ) [ s" start-cpu" rtas-get-token ] LITERAL rtas-cb rtas>token l! 3 rtas-cb rtas>nargs l! 1 rtas-cb rtas>nret l! rtas-cb rtas>args2 l! rtas-cb rtas>args1 l! rtas-cb rtas>args0 l! 0 rtas-cb rtas>args3 l! enter-rtas rtas-cb rtas>args3 l@ ; : rtas-set-tce-bypass ( unit enable -- ) " ibm,set-tce-bypass" rtas-get-token rtas-cb rtas>token l! 2 rtas-cb rtas>nargs l! 0 rtas-cb rtas>nret l! rtas-cb rtas>args1 l! rtas-cb rtas>args0 l! enter-rtas ; : rtas-quiesce ( -- ) " quiesce" rtas-get-token rtas-cb rtas>token l! 0 rtas-cb rtas>nargs l! 0 rtas-cb rtas>nret l! enter-rtas ; 0 value puid : rtas-do-config-@ ( config-addr size -- value) " ibm,read-pci-config" rtas-get-token rtas-cb rtas>token l! 4 rtas-cb rtas>nargs l! 2 rtas-cb rtas>nret l! ( addr size ) rtas-cb rtas>args3 l! puid ffffffff and rtas-cb rtas>args2 l! puid 20 rshift rtas-cb rtas>args1 l! ( addr ) rtas-cb rtas>args0 l! enter-rtas rtas-cb rtas>args4 l@ dup IF drop ffffffff ELSE drop rtas-cb rtas>args5 l@ THEN ; : rtas-do-config-! ( value config-addr size ) " ibm,write-pci-config" rtas-get-token rtas-cb rtas>token l! 5 rtas-cb rtas>nargs l! 1 rtas-cb rtas>nret l! ( value addr size ) rtas-cb rtas>args3 l! puid ffffffff and rtas-cb rtas>args2 l! puid 20 rshift rtas-cb rtas>args1 l! ( value addr ) rtas-cb rtas>args0 l! ( value ) rtas-cb rtas>args4 l! enter-rtas rtas-cb rtas>args5 l@ dup IF ." RTAS write config err " . cr ELSE drop THEN ; : rtas-config-b@ ( config-addr -- value ) 1 rtas-do-config-@ ff and ; : rtas-config-b! ( value config-addr -- ) 1 rtas-do-config-! ; : rtas-config-w@ ( config-addr -- value ) 2 rtas-do-config-@ ffff and ; : rtas-config-w! ( value config-addr -- ) 2 rtas-do-config-! ; : rtas-config-l@ ( config-addr -- value ) 4 rtas-do-config-@ ffffffff and ; : rtas-config-l! ( value config-addr -- ) 4 rtas-do-config-! ; : of-start-cpu rtas-start-cpu ; ' power-off to halt ' rtas-system-reboot to reboot rtas-node set-node : open true ; : close ; : instantiate-rtas ( adr -- entry ) dup rtas-base swap rtas-size move dup rtas-entry rtas-base - + 2dup hv-rtas-update dup 0 <> IF dup -2 <> IF ." HV-RTAS-UPDATE error: " . cr ELSE drop THEN ELSE drop THEN nip ; device-end 374 cp p)8pci-device_1234_1111.fs." qemu vga" cr s" qemu-vga.fs" included 88pci-device_1013_00b8.fsmy-space pci-device-generic-setup d# 800 VALUE disp-width d# 600 VALUE disp-height d# 8 VALUE disp-depth 10 config-l@ translate-my-address f not AND VALUE fb-base -1 VALUE io-base false VALUE is-installed? : vga-io-xlate ( port -- addr ) io-base -1 = IF dup translate-my-address fff not and to io-base THEN io-base + ; : vga-w! ( value port -- ) vga-io-xlate rw!-le ; : vga-w@ ( port -- value ) vga-io-xlate rw@-le ; : vga-b! ( value port -- ) vga-io-xlate rb! ; : vga-b@ ( port -- value ) vga-io-xlate rb@ ; : vga-crt@ ( index -- value ) 3d4 vga-b! 3d5 vga-b@ ; : vga-crt! ( value index -- ) 3d4 vga-b! 3d5 vga-b! ; : vga-seq@ ( index -- value ) 3c4 vga-b! 3c5 vga-b@ ; : vga-seq! ( value index -- ) 3c4 vga-b! 3c5 vga-b! ; : vga-att@ ( index -- value ) 3c0 vga-b! 3c1 vga-b@ ; : vga-att! ( value index -- ) 3c0 vga-b! 3c0 vga-b! ; : vga-gfx@ ( index -- value ) 3ce vga-b! 3cf vga-b@ ; : vga-gfx! ( value index -- ) 3ce vga-b! 3cf vga-b! ; : color! ( r g b number -- ) 3c8 vga-b! rot 2 >> 3c9 vga-b! swap 2 >> 3c9 vga-b! 2 >> 3c9 vga-b! ; : color@ ( number -- r g b ) 3c8 vga-b! 3c9 vga-b@ 2 << 3c9 vga-b@ 2 << 3c9 vga-b@ 2 << ; : set-colors ( adr number #numbers -- ) over 3c8 vga-b! swap DO rb@ 2 >> 3c9 vga-b! rb@ 2 >> 3c9 vga-b! rb@ 2 >> 3c9 vga-b! LOOP 3drop ; : get-colors ( adr number #numbers -- ) 3drop ; include graphics.fs : init-mode 3da vga-b@ drop \ reset flip flop 0f 3c2 vga-b! \ color mode, ram enable, ... 12 06 vga-seq! \ unlock extensions 05 06 vga-gfx! \ graphic mode disp-depth CASE \ set depth 8 OF 01 07 vga-seq! ENDOF f OF 07 07 vga-seq! ENDOF 10 OF 07 07 vga-seq! ENDOF 20 OF 09 07 vga-seq! ENDOF ENDCASE ff 02 vga-seq! \ enable plane write 0a 04 vga-seq! \ memory mode 03 17 vga-crt! \ disable display disp-width disp-depth 7 + 8 / * 3 >> dup ff and 13 vga-crt! \ bottom bits 4 >> 10 and 1b vga-crt! \ top bit disp-width 3 >> 1 - 01 vga-crt! \ H_DISP disp-height 1 - ff and 12 vga-crt! \ V_DISP disp-height 1 - 7 >> 2 and disp-height 1 - 3 >> 40 and or 10 or 07 vga-crt! \ OFLOW ff 18 vga-crt! \ LINE_COMPARE 40 09 vga-crt! \ MAX_SCAN 08 04 vga-crt! \ SYNC_START 0f 02 vga-crt! \ BLANK_START 00 0c vga-crt! 00 0d vga-crt! 40 05 vga-gfx! \ gfx mode 83 17 vga-crt! \ enable display 33 3c0 vga-b! \ gfx in ar index 00 3c0 vga-b! 01 01 vga-seq! \ enable seq ; : clear-screen fb-base disp-width disp-height disp-depth 7 + 8 / * * 0 rfill ; : read-settings s" qemu,graphic-width" get-chosen IF decode-int to disp-width 2drop THEN s" qemu,graphic-height" get-chosen IF decode-int to disp-height 2drop THEN s" qemu,graphic-depth" get-chosen IF decode-int nip nip dup 8 = over f = or over 10 = or over 20 = or IF to disp-depth ELSE ." Unsupported bit depth, using 8bpp " drop cr THEN THEN ; : add-legacy-reg s" reg" get-node get-property IF encode-start ELSE encode-bytes THEN my-space a1000000 or encode-int+ \ non-relocatable, aliased I/O space 1ce encode-64+ 4 encode-64+ \ addr size my-space a1000000 or encode-int+ \ non-relocatable, aliased I/O space 3b0 encode-64+ c encode-64+ \ addr size my-space a1000000 or encode-int+ \ non-relocatable, aliased I/O space 3c0 encode-64+ 20 encode-64+ \ addr size my-space a2000000 or encode-int+ \ non-relocatable, <1MB Memory space a0000 encode-64+ 20000 encode-64+ \ addr size s" reg" property \ store "reg" property ; : setup-properties disp-width encode-int s" width" property disp-height encode-int s" height" property disp-width disp-depth 7 + 8 / * encode-int s" linebytes" property disp-depth encode-int s" depth" property s" ISO8859-1" encode-string s" character-set" property \ i hope this is ok... s" display" device-type ; : display-remove ( -- ) ; : display-install ( -- ) is-installed? NOT IF ." Installing QEMU fb" cr fb-base to frame-buffer-adr default-font set-font disp-width disp-height disp-width char-width / disp-height char-height / disp-depth 7 + 8 / ( width height #lines #cols depth ) fb-install true to is-installed? THEN ; : set-alias s" screen" find-alias 0= IF s" screen" get-node node>path set-alias ELSE drop THEN ; ." cirrus vga" cr pci-master-enable pci-mem-enable pci-io-enable add-legacy-reg read-settings init-mode clear-screen init-default-palette setup-properties ' display-install is-install ' display-remove is-remove set-alias q8pci-device_8086_100e.fss" e1000 [ net ]" type cr my-space pci-device-generic-setup pci-io-enable s" e1k.fs" included pci-device-disable (e1k.fss" network" device-type INSTANCE VARIABLE obp-tftp-package get-node CONSTANT my-phandle 10 config-l@ translate-my-address 3 not AND CONSTANT baseaddr 0 VALUE e1k-priv 0 VALUE open-count : open ( -- okay? ) open-count 0= IF open IF baseaddr e1k-open dup not IF ." e1k-open failed" EXIT THEN drop TO e1k-priv true ELSE false THEN ELSE true THEN my-args s" obp-tftp" $open-package obp-tftp-package ! open-count 1 + to open-count ; : close ( -- ) my-phandle set-node open-count 0> IF open-count 1 - dup to open-count 0= IF e1k-priv e1k-close close THEN THEN s" close" obp-tftp-package @ $call-method ; : read ( buf len -- actual ) dup IF e1k-read ELSE nip THEN ; : write ( buf len -- actual ) dup IF e1k-write ELSE nip THEN ; : load ( addr -- len ) s" load" obp-tftp-package @ $call-method ; : ping ( -- ) s" ping" obp-tftp-package @ $call-method ; 6 BUFFER: local-mac : setup-mac ( -- ) pci-mem-enable " vendor-id" get-node get-property IF EXIT THEN decode-int nip nip " device-id" get-node get-property IF EXIT THEN decode-int nip nip baseaddr local-mac e1k-mac-setup IF encode-bytes " local-mac-address" property THEN ; setup-mac : setup-alias ( -- ) " net" get-next-alias ?dup IF get-node node>path set-alias THEN ; setup-alias u0qemu-vga.fsmy-space pci-device-generic-setup d# 800 VALUE disp-width d# 600 VALUE disp-height d# 8 VALUE disp-depth : map-in " map-in" my-phandle parent $call-static ; : map-out " map-out" my-phandle parent $call-static ; 0 0 my-space h# 02000010 + 1 map-in VALUE fb-base 0 0 my-space h# 02000018 + 1 map-in VALUE reg-base false VALUE is-installed? : vga-w! ( value port -- ) 3c0 - reg-base 400 + + rw!-le ; : vga-w@ ( port -- value ) 3c0 - reg-base 400 + + rw@-le ; : vga-b! ( value port -- ) 3c0 - reg-base 400 + + rb! ; : vga-b@ ( port -- value ) 3c0 - reg-base 400 + + rb@ ; : vbe! ( value index -- ) 1 << reg-base 500 + + rw!-le ; : vbe@ ( index -- value ) 1 << reg-base 500 + + rw@-le ; : color! ( r g b number -- ) 3c8 vga-b! rot 3c9 vga-b! swap 3c9 vga-b! 3c9 vga-b! ; : color@ ( number -- r g b ) 3c8 vga-b! 3c9 vga-b@ 3c9 vga-b@ 3c9 vga-b@ ; : set-colors ( adr number #numbers -- ) over 3c8 vga-b! swap DO rb@ 3c9 vga-b! rb@ 3c9 vga-b! rb@ 3c9 vga-b! LOOP 3drop ; : get-colors ( adr number #numbers -- ) 3drop ; include graphics.fs 0 CONSTANT VBE_DISPI_INDEX_ID 1 CONSTANT VBE_DISPI_INDEX_XRES 2 CONSTANT VBE_DISPI_INDEX_YRES 3 CONSTANT VBE_DISPI_INDEX_BPP 4 CONSTANT VBE_DISPI_INDEX_ENABLE 5 CONSTANT VBE_DISPI_INDEX_BANK 6 CONSTANT VBE_DISPI_INDEX_VIRT_WIDTH 7 CONSTANT VBE_DISPI_INDEX_VIRT_HEIGHT 8 CONSTANT VBE_DISPI_INDEX_X_OFFSET 9 CONSTANT VBE_DISPI_INDEX_Y_OFFSET a CONSTANT VBE_DISPI_INDEX_NB 00 CONSTANT VBE_DISPI_DISABLED 01 CONSTANT VBE_DISPI_ENABLED 02 CONSTANT VBE_DISPI_GETCAPS 20 CONSTANT VBE_DISPI_8BIT_DAC 40 CONSTANT VBE_DISPI_LFB_ENABLED 80 CONSTANT VBE_DISPI_NOCLEARMEM : init-mode 0 3c0 vga-b! VBE_DISPI_DISABLED VBE_DISPI_INDEX_ENABLE vbe! 0 VBE_DISPI_INDEX_X_OFFSET vbe! 0 VBE_DISPI_INDEX_Y_OFFSET vbe! disp-width VBE_DISPI_INDEX_XRES vbe! disp-height VBE_DISPI_INDEX_YRES vbe! disp-depth VBE_DISPI_INDEX_BPP vbe! VBE_DISPI_ENABLED VBE_DISPI_8BIT_DAC or VBE_DISPI_INDEX_ENABLE vbe! 0 3c0 vga-b! 20 3c0 vga-b! ; : clear-screen fb-base disp-width disp-height disp-depth 7 + 8 / * * 0 rfill ; : read-settings s" qemu,graphic-width" get-chosen IF decode-int to disp-width 2drop THEN s" qemu,graphic-height" get-chosen IF decode-int to disp-height 2drop THEN s" qemu,graphic-depth" get-chosen IF decode-int nip nip dup 8 = over f = or over 10 = or over 20 = or IF to disp-depth ELSE ." Unsupported bit depth, using 8bpp " drop cr THEN THEN ; : setup-properties disp-width encode-int s" width" property disp-height encode-int s" height" property disp-width disp-depth 7 + 8 / * encode-int s" linebytes" property disp-depth encode-int s" depth" property s" ISO8859-1" encode-string s" character-set" property \ i hope this is ok... s" display" device-type s" qemu,std-vga" encode-string s" compatible" property ; : display-remove ( -- ) ; : slow-blink-screen ( -- ) invert-screen 20 ms invert-screen ; : display-install ( -- ) is-installed? NOT IF ." Installing QEMU fb" cr fb-base to frame-buffer-adr clear-screen default-font set-font disp-width disp-height disp-width char-width / disp-height char-height / disp-depth 7 + 8 / ( width height #lines #cols depth ) fb-install ['] slow-blink-screen to blink-screen true to is-installed? THEN ; : set-alias s" screen" find-alias 0= IF s" screen" get-node node>path set-alias ELSE drop THEN ; pci-master-enable pci-mem-enable read-settings init-mode init-default-palette setup-properties ' display-install is-install ' display-remove is-remove set-alias E0pci-class_02.fss" network [ " type my-space pci-class-name type s" ]" type my-space pci-device-generic-setup my-space pci-alias-net s" network" device-type cr INSTANCE VARIABLE obp-tftp-package : open ( -- okay? ) open IF \ enables PCI mem, io and Bus master and returns TRUE my-args s" obp-tftp" $open-package obp-tftp-package ! true ELSE false THEN ; : close ( -- ) obp-tftp-package @ close-package close ; \ disables PCI mem, io and Bus master : load ( addr -- len ) s" load" obp-tftp-package @ $call-method ; : ping ( -- ) s" ping" obp-tftp-package @ $call-method ; @0pci-class_0c.fss" serial bus [ " type my-space pci-class-name type s" ]" type cr my-space pci-device-generic-setup STRUCT /n FIELD hcd>base /n FIELD hcd>type /n FIELD hcd>num /n FIELD hcd>ops /n FIELD hcd>priv /n FIELD hcd>nextaddr CONSTANT /hci-dev : usb-setup-hcidev ( num hci-dev -- ) >r 10 config-l@ F AND case 0 OF 10 config-l@ translate-my-address ENDOF \ 32-bit memory space 4 OF \ 64-bit memory space 14 config-l@ 20 lshift \ Read two bars 10 config-l@ OR translate-my-address ENDOF ENDCASE F not AND ( io-base ) r@ hcd>base ! 08 config-l@ 8 rshift 0000000F0 AND 4 rshift ( usb-type ) r@ hcd>type ! ( usb-num ) r@ hcd>num ! r> drop ; : handle-usb-class ( -- ) 4 config-w@ 110 or 4 config-w! pci-master-enable \ set PCI Bus master bit and pci-mem-enable \ memory space enable for USB scan ; : handle-sbc-subclass ( -- ) my-space pci-class@ ffff and CASE \ get PCI sub-class and interface 0310 OF \ OHCI controller handle-usb-class set-ohci-alias ENDOF 0320 OF \ EHCI controller handle-usb-class set-ehci-alias ENDOF 0330 OF \ XHCI controller handle-usb-class set-xhci-alias ENDOF ENDCASE ; handle-sbc-subclass [0dev-hci.fsVALUE usb_type \ USB type device-type " usb" 2dup device-name rot VALUE usb_num \ controller number usb_num $cathex strdup \ create alias name 2dup find-alias 0= IF get-node node>path set-alias ELSE 3drop THEN /hci-dev BUFFER: hcidev usb_num hcidev usb-setup-hcidev TRUE VALUE first-time-init? 0 VALUE open-count false VALUE dev-hci-debug? 1 encode-int s" #address-cells" property 0 encode-int s" #size-cells" property : encode-unit ( port -- unit-str unit-len ) 1 hex-encode-unit ; : decode-unit ( addr len -- port ) 1 hex-decode-unit ; : get-hci-dev ( -- hcidev ) hcidev ; : hc-cleanup ( -- ) my-phandle set-node dev-hci-debug? IF ." USB-HCI: Cleaning up " pwd cr THEN hcidev USB-HCD-EXIT 0 set-node ; : open ( -- true | false ) true ; : close ; first-time-init? IF ['] hc-cleanup add-quiesce-xt false to first-time-init? THEN 0slofdev.fsSTRUCT /n FIELD slof-dev>udev /l FIELD slof-dev>port /l FIELD slof-dev>devaddr /l FIELD slof-dev>hcitype /l FIELD slof-dev>num /l FIELD slof-dev>devtype CONSTANT slof-usb-dev :8dev-parent-calls.fsget-node CONSTANT my-phandle s" dma-function.fs" included p10dev-keyb.fsnew-device VALUE sudev false VALUE usb-keyb-debug? s" slofdev.fs" included sudev slof-dev>port l@ dup set-unit encode-phys " reg" property sudev slof-dev>udev @ VALUE udev s" usb-keyboard" device-name s" keyboard" device-type s" EN" encode-string s" language" property s" keyboard" get-node node>path set-alias s" dev-parent-calls.fs" included 0 VALUE open-count : open ( -- true | false ) usb-keyb-debug? IF ." USB-KEYB: Opening (count is " open-count . ." )" cr THEN open-count 0= IF udev USB-HID-INIT 0= IF ." USB keyboard setup failed " pwd cr false EXIT THEN THEN open-count 1 + to open-count true ; : close usb-keyb-debug? IF ." USB-KEYB: Closing (count is " open-count . ." )" cr THEN open-count 0> IF open-count 1 - dup to open-count 0= IF my-phandle set-node udev USB-HID-EXIT drop 0 set-node THEN THEN ; : key-available? ( -- true|false ) udev USB-KEY-AVAILABLE IF TRUE ELSE FALSE THEN ; : read ( addr len -- actual ) 0= IF drop 0 EXIT THEN udev USB-READ-KEYB ?dup IF swap c! 1 ELSE 0 swap c! 0 then ; ." USB Keyboard " cr finish-device 0dev-mouse.fsnew-device VALUE sudev s" slofdev.fs" included sudev slof-dev>port l@ dup set-unit encode-phys " reg" property sudev slof-dev>udev @ VALUE udev s" usb-mouse" device-name ." USB mouse " cr finish-device 0dev-storage.fsnew-device VALUE usbdev s" slofdev.fs" included false VALUE usb-disk-debug? usbdev slof-dev>port l@ dup set-unit encode-phys " reg" property s" storage" device-name s" dev-parent-calls.fs" included 2 encode-int s" #address-cells" property 0 encode-int s" #size-cells" property : decode-unit 2 hex64-decode-unit ; : encode-unit 2 hex64-encode-unit ; 0 CONSTANT USB_PIPE_OUT 1 CONSTANT USB_PIPE_IN usbdev slof-dev>udev @ VALUE udev usbdev slof-dev>port l@ VALUE port usbdev slof-dev>hcitype l@ VALUE hcitype 0 INSTANCE VALUE lun 10000 VALUE dev-max-transfer 0 VALUE resp-buffer 0 VALUE resp-size 0f CONSTANT SCSI-COMMAND-OFFSET STRUCT dev-max-transfer FIELD usb>data 40 FIELD usb>cmd 20 FIELD usb>csw CONSTANT /dma-buf 0 VALUE dma-buf 0 VALUE dma-buf-phys 0 VALUE td-buf 0 VALUE td-buf-phys 1000 CONSTANT /td-buf : (dma-buf-init) ( -- ) /dma-buf dma-alloc TO dma-buf dma-buf /dma-buf 0 dma-map-in TO dma-buf-phys /td-buf dma-alloc TO td-buf td-buf /td-buf 0 dma-map-in TO td-buf-phys ; : (dma-buf-free) ( -- ) td-buf td-buf-phys /td-buf dma-map-out td-buf /td-buf dma-free 0 TO td-buf 0 TO td-buf-phys dma-buf dma-buf-phys /dma-buf dma-map-out dma-buf /dma-buf dma-free 0 TO dma-buf 0 TO dma-buf-phys ; scsi-open 0 INSTANCE VALUE current-target : do-bulk-command ( resp-buffer resp-size -- TRUE | FALSE ) TO resp-size TO resp-buffer udev USB_PIPE_OUT td-buf td-buf-phys dma-buf-phys usb>cmd 1F usb-transfer-bulk IF \ transfer CBW resp-size IF d# 125 us udev USB_PIPE_IN td-buf td-buf-phys resp-buffer resp-size usb-transfer-bulk 1 = not IF \ transfer data usb-disk-debug? IF ." Data phase failed " cr THEN THEN THEN d# 125 us udev USB_PIPE_IN td-buf td-buf-phys dma-buf-phys usb>csw 0D usb-transfer-bulk \ transfer CSW ELSE FALSE EXIT THEN ; STRUCT \ cbw /l FIELD cbw>sig /l FIELD cbw>tag /l FIELD cbw>len /c FIELD cbw>flags /c FIELD cbw>lun \ 0:3 bits /c FIELD cbw>cblen \ 0:4 bits CONSTANT cbw-length STRUCT \ csw /l FIELD csw>sig /l FIELD csw>tag /l FIELD csw>data-residue /c FIELD csw>status CONSTANT cbw-length 0 VALUE cbw-addr 0 VALUE csw-addr : build-cbw ( tag xfer-len dir lun cmd-len addr -- ) TO cbw-addr ( tag xfer-len dir lun cmd-len ) cbw-addr cbw-length erase ( tag xfer-len dir lun cmd-len ) cbw-addr cbw>cblen c! ( tag xfer-len dir lun ) cbw-addr cbw>lun c! ( tag xfer-len dir ) IF 80 ELSE 0 THEN cbw-addr cbw>flags c! ( tag xfer-len ) cbw-addr cbw>len l!-le ( tag ) cbw-addr cbw>tag l!-le ( ) 43425355 cbw-addr cbw>sig l!-le ; 0 INSTANCE VALUE usb-buf-addr 0 INSTANCE VALUE usb-buf-len 0 INSTANCE VALUE usb-dir 0 INSTANCE VALUE usb-cmd-addr 0 INSTANCE VALUE usb-cmd-len 1 VALUE tag : execute-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len -- ... ) to usb-cmd-len to usb-cmd-addr to usb-dir to usb-buf-len to usb-buf-addr dma-buf usb>cmd 40 0 fill dma-buf usb>csw 20 0 fill tag usb-buf-len usb-dir lun usb-cmd-len dma-buf usb>cmd build-cbw 1 tag + to tag usb-cmd-addr dma-buf usb>cmd SCSI-COMMAND-OFFSET + usb-cmd-len move dma-buf-phys usb>data usb-buf-len do-bulk-command IF dma-buf usb>data usb-buf-addr usb-buf-len move ELSE ." USB-DISK: Bulk commad failed!" cr 0 0 -1 EXIT THEN dma-buf usb>csw to csw-addr csw-addr csw>sig l@ 55534253 <> IF ." USB-DISK: CSW signature invalid " cr 0 0 -1 EXIT THEN csw-addr csw>status c@ CASE 0 OF ENDOF \ Good 1 OF usb-disk-debug? IF ." USB-DISK: CSW Data residue: " csw-addr csw>data-residue l@-le . cr THEN 0 0 8 EXIT ENDOF \ Command failed, Retry dup OF 0 0 -1 EXIT ENDOF \ Anything else -> HW error ENDCASE csw-addr csw>status c@ dup 0<> IF usb-disk-debug? IF over scsi-get-sense-data ." USB-DISK: Sense key [ " dup . ." ] " .sense-text ." ASC,ASCQ: " . . cr THEN rot THEN ; " scsi-host-helpers.fs" included 0 VALUE open-count : usb-storage-init ( -- TRUE ) td-buf 0= IF usb-disk-debug? IF ." USB-DISK: Allocating buffer " cr THEN (dma-buf-init) udev USB-MSC-INIT 0= IF ." USB-DISK: Unable to initialize MSC " cr FALSE ELSE TRUE THEN THEN ; : usb-storage-cleanup td-buf 0<> IF usb-disk-debug? IF ." USB-DISK: Freeing buffer " cr THEN (dma-buf-free) udev USB-MSC-EXIT 0= IF ." USB-DISK: Unable to exit MSC " cr THEN THEN ; : open usb-disk-debug? IF ." USB-DISK: Opening (count is " open-count . ." )" cr THEN open-count 0= IF usb-storage-init IF 1 to open-count true ELSE ." USB-DISK initialization failed !" cr false THEN ELSE open-count 1 + to open-count true THEN ; : close usb-disk-debug? IF ." USB-DISK: Closing (count is " open-count . ." )" cr THEN open-count 0> IF open-count 1 - dup to open-count 0= IF usb-storage-cleanup THEN THEN ; : (set-target) dup 20 >> FFFF and to lun dup 30 >> FF and to port to current-target usb-disk-debug? IF ." USB-DISK: udev " udev . ." lun:" lun . ." port:" port . cr THEN ; : dev-generate-srplun ( target lun-id -- srplun ) swap drop port 0100 or 10 << or 20 << ; : max-transfer ( -- n ) dev-max-transfer ; : set-address ( srplun.lo srplun.hi -- ) lxjoin (set-target) usb-disk-debug? IF ." USB-DISK: udev " udev . ." lun:" lun . ." port:" port . cr THEN ; 1 CONSTANT #target : dev-max-target ( -- #target ) #target ; " scsi-probe-helpers.fs" included scsi-close \ no further scsi words required : setup-alias s" scsi" find-alias 0= IF s" scsi" get-node node>path set-alias ELSE drop THEN ; : usb-storage-init-and-scan ( -- ) usb-disk-debug? IF ." Initializing usb-disk: udev " udev . cr THEN 0 0 get-node open-node ?dup 0= IF EXIT THEN my-self >r dup to my-self hcitype CASE 1 OF 4000 TO dev-max-transfer ENDOF \ OHCI 2 OF 10000 TO dev-max-transfer ENDOF \ EHCI 3 OF F000 TO dev-max-transfer ENDOF \ XHCI ENDCASE usb-storage-init scsi-find-disks setup-alias usb-storage-cleanup close-node r> to my-self ; ." USB Storage " cr : usb-scsi-add-disk " scsi-disk.fs" included ; usb-scsi-add-disk usb-storage-init-and-scan finish-device 80dev-hub.fsnew-device VALUE sudev s" slofdev.fs" included sudev slof-dev>port l@ dup set-unit encode-phys " reg" property sudev slof-dev>udev @ VALUE udev s" hub" device-name s" dev-parent-calls.fs" included 1 encode-int s" #address-cells" property 0 encode-int s" #size-cells" property : decode-unit 1 hex-decode-unit ; : encode-unit 1 hex-encode-unit ; : usb-hub-init ( usbdev -- true | false ) udev USB-HUB-INIT ; : open ( -- true | false ) TRUE ; : close ; ." USB HUB " cr usb-hub-init drop finish-device y8pci-device_1af4_1000.fss" virtio [ net ]" type cr my-space pci-device-generic-setup pci-io-enable s" virtio-net.fs" included pci-device-disable `8pci-device_1af4_1001.fss" virtio [ block ]" type cr my-space pci-device-generic-setup pci-master-enable pci-mem-enable pci-io-enable s" virtio-block.fs" included virtiodev 0 virtio-get-qsize virtio-vring-size 1000 CLAIM VALUE queue-addr queue-addr c rshift virtiodev vd>base @ 8 + rl!-le pci-device-disable 8pci-device_1af4_1004.fss" virtio [ scsi ]" type cr my-space pci-device-generic-setup pci-master-enable pci-mem-enable pci-io-enable s" virtio-scsi.fs" included pci-device-disable `8pci-device_1af4_1009.fss" virtio [ network ]" type cr my-space pci-device-generic-setup pci-master-enable pci-mem-enable pci-io-enable s" virtio-fs.fs" included virtiodev 0 virtio-get-qsize virtio-vring-size 1000 CLAIM VALUE queue-addr queue-addr c rshift virtiodev vd>base @ 8 + rl!-le pci-device-disable x48pci-device_1af4_1050.fss" virtio [ vga ]" type cr s" qemu-vga.fs" included x0vio-hvterm.fs." Populating " pwd cr : open true ; : close ; : write ( adr len -- actual ) tuck 0 ?DO dup c@ my-unit SWAP hv-putchar 1 + LOOP drop ; : read ( adr len -- actual ) 0= IF drop 0 EXIT THEN my-unit hv-haschar 0= IF 0 swap c! -2 EXIT THEN my-unit hv-getchar swap c! 1 ; : setup-alias " hvterm" find-alias 0= IF " hvterm" get-node node>path set-alias ELSE drop THEN ; setup-alias 0vio-vscsi.fs." Populating " pwd false VALUE vscsi-debug? 0 VALUE vscsi-unit : l2dma ( laddr - dma_addr) ; 0 VALUE crq-real-base 0 VALUE crq-base 0 VALUE crq-dma 0 VALUE crq-offset 1000 CONSTANT CRQ-SIZE CREATE crq 10 allot : crq-alloc ( -- ) CRQ-SIZE fff + alloc-mem to crq-real-base crq-real-base fff + fffff000 AND to crq-base 0 to crq-offset crq-base l2dma to crq-dma ; : crq-free ( -- ) vscsi-unit hv-free-crq crq-real-base CRQ-SIZE fff + free-mem 0 to crq-base 0 to crq-real-base ; : crq-init ( -- res ) crq-alloc vscsi-debug? IF ." VSCSI: allocated crq at " crq-base . cr THEN crq-base CRQ-SIZE erase vscsi-unit crq-dma CRQ-SIZE hv-reg-crq dup 0 <> IF ." VSCSI: Error " . ." registering CRQ !" cr crq-free THEN ; : crq-cleanup ( -- ) crq-base 0 = IF EXIT THEN vscsi-debug? IF ." VSCSI: freeing crq at " crq-base . cr THEN crq-free ; : crq-send ( msgaddr -- true | false ) vscsi-unit swap hv-send-crq 0 = ; : crq-poll ( -- true | false) crq-offset crq-base + dup vscsi-debug? IF ." VSCSI: crq poll " dup . THEN c@ vscsi-debug? IF ." value=" dup . cr THEN 80 and 0 <> IF dup crq 10 move 0 swap c! crq-offset 10 + dup CRQ-SIZE >= IF drop 0 THEN to crq-offset true ELSE drop false THEN ; : crq-wait ( -- true | false) 0 BEGIN drop crq-poll dup not WHILE d# 1 ms REPEAT dup not IF ." VSCSI: Timeout waiting response !" cr EXIT ELSE vscsi-debug? IF ." VSCSI: got crq: " crq dup l@ . ." " 4 + dup l@ . ." " 4 + dup l@ . ." " 4 + l@ . cr THEN THEN ; 01 CONSTANT VIOSRP_SRP_FORMAT 02 CONSTANT VIOSRP_MAD_FORMAT 03 CONSTANT VIOSRP_OS400_FORMAT 04 CONSTANT VIOSRP_AIX_FORMAT 06 CONSTANT VIOSRP_LINUX_FORMAT 07 CONSTANT VIOSRP_INLINE_FORMAT struct 1 field >crq-valid 1 field >crq-format 1 field >crq-reserved 1 field >crq-status 2 field >crq-timeout 2 field >crq-iu-len 8 field >crq-iu-data-ptr constant /crq : srp-send-crq ( addr len -- ) 80 crq >crq-valid c! VIOSRP_SRP_FORMAT crq >crq-format c! 0 crq >crq-reserved c! 0 crq >crq-status c! 0 crq >crq-timeout w! ( len ) crq >crq-iu-len w! ( addr ) l2dma crq >crq-iu-data-ptr x! crq crq-send not IF ." VSCSI: Error sending CRQ !" cr THEN ; : srp-wait-crq ( -- [tag true] | false ) crq-wait not IF false EXIT THEN crq >crq-format c@ VIOSRP_SRP_FORMAT <> IF ." VSCSI: Unsupported SRP response: " crq >crq-format c@ . cr false EXIT THEN crq >crq-iu-data-ptr x@ true ; scsi-open 0 VALUE >srp_opcode 00 CONSTANT SRP_LOGIN_REQ 01 CONSTANT SRP_TSK_MGMT 02 CONSTANT SRP_CMD 03 CONSTANT SRP_I_LOGOUT c0 CONSTANT SRP_LOGIN_RSP c1 CONSTANT SRP_RSP c2 CONSTANT SRP_LOGIN_REJ 80 CONSTANT SRP_T_LOGOUT 81 CONSTANT SRP_CRED_REQ 82 CONSTANT SRP_AER_REQ 41 CONSTANT SRP_CRED_RSP 42 CONSTANT SRP_AER_RSP 02 CONSTANT SRP_BUF_FORMAT_DIRECT 04 CONSTANT SRP_BUF_FORMAT_INDIRECT struct 1 field >srp-login-opcode 3 + 8 field >srp-login-tag 4 field >srp-login-req-it-iu-len 4 + 2 field >srp-login-req-buf-fmt 1 field >srp-login-req-flags 5 + 10 field >srp-login-init-port-ids 10 field >srp-login-trgt-port-ids constant /srp-login struct 1 field >srp-lresp-opcode 3 + 4 field >srp-lresp-req-lim-delta 8 field >srp-lresp-tag 4 field >srp-lresp-max-it-iu-len 4 field >srp-lresp-max-ti-iu-len 2 field >srp-lresp-buf-fmt 1 field >srp-lresp-flags constant /srp-login-resp struct 1 field >srp-lrej-opcode 3 + 4 field >srp-lrej-reason 8 field >srp-lrej-tag 8 + 2 field >srp-lrej-buf-fmt constant /srp-login-rej 00 CONSTANT SRP_NO_DATA_DESC 01 CONSTANT SRP_DATA_DESC_DIRECT 02 CONSTANT SRP_DATA_DESC_INDIRECT struct 1 field >srp-cmd-opcode 1 field >srp-cmd-sol-not 3 + 1 field >srp-cmd-buf-fmt 1 field >srp-cmd-dout-desc-cnt 1 field >srp-cmd-din-desc-cnt 8 field >srp-cmd-tag 4 + 8 field >srp-cmd-lun 1 + 1 field >srp-cmd-task-attr 1 + 1 field >srp-cmd-add-cdb-len 10 field >srp-cmd-cdb 0 field >srp-cmd-cdb-add constant /srp-cmd struct 1 field >srp-rsp-opcode 1 field >srp-rsp-sol-not 2 + 4 field >srp-rsp-req-lim-delta 8 field >srp-rsp-tag 2 + 1 field >srp-rsp-flags 1 field >srp-rsp-status 4 field >srp-rsp-dout-res-cnt 4 field >srp-rsp-din-res-cnt 4 field >srp-rsp-sense-len 4 field >srp-rsp-resp-len 0 field >srp-rsp-data constant /srp-rsp 01 CONSTANT SRP_RSP_FLAG_RSPVALID 02 CONSTANT SRP_RSP_FLAG_SNSVALID 04 CONSTANT SRP_RSP_FLAG_DOOVER 05 CONSTANT SRP_RSP_FLAG_DOUNDER 06 CONSTANT SRP_RSP_FLAG_DIOVER 07 CONSTANT SRP_RSP_FLAG_DIUNDER CREATE srp 100 allot 0 VALUE srp-len : srp-prep-cmd-nodata ( srplun -- ) srp /srp-cmd erase SRP_CMD srp >srp-cmd-opcode c! 1 srp >srp-cmd-tag x! srp >srp-cmd-lun x! \ 8 bytes lun /srp-cmd to srp-len ; : srp-prep-cmd-io ( addr len srplun -- ) srp-prep-cmd-nodata ( addr len ) swap l2dma ( len dmaaddr ) srp srp-len + ( len dmaaddr descaddr ) dup >r x! r> 8 + ( len descaddr+8 ) dup 0 swap l! 4 + ( len descaddr+c ) l! srp-len 10 + to srp-len ; : srp-prep-cmd-read ( addr len srplun -- ) srp-prep-cmd-io 01 srp >srp-cmd-buf-fmt c! \ in direct buffer 1 srp >srp-cmd-din-desc-cnt c! ; : srp-prep-cmd-write ( addr len srplun -- ) srp-prep-cmd-io 10 srp >srp-cmd-buf-fmt c! \ out direct buffer 1 srp >srp-cmd-dout-desc-cnt c! ; : srp-send-cmd ( -- ) vscsi-debug? IF ." VSCSI: Sending SCSI cmd " srp >srp-cmd-cdb c@ . cr THEN srp srp-len srp-send-crq ; : srp-rsp-find-sense ( -- addr len true | false ) srp >srp-rsp-flags c@ SRP_RSP_FLAG_SNSVALID and 0= IF false EXIT THEN srp >srp-rsp-data srp >srp-rsp-sense-len l@ true ; : srp-wait-rsp ( -- stat ) srp-wait-crq not IF false EXIT THEN dup 1 <> IF ." VSCSI: Invalid CRQ response tag, want 1 got " . cr -1 EXIT THEN drop srp >srp-rsp-tag x@ dup 1 <> IF ." VSCSI: Invalid SRP response tag, want 1 got " . cr -1 EXIT THEN drop srp >srp-rsp-status c@ vscsi-debug? IF ." VSCSI: Got response status: " dup .status-text cr THEN ; 8000000000000000 INSTANCE VALUE current-target : execute-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len -- ... ) >r >r ( buf-addr buf-len dir ) over 0= IF 3drop current-target srp-prep-cmd-nodata ELSE current-target swap IF srp-prep-cmd-read ELSE srp-prep-cmd-write THEN THEN r> r> srp >srp-cmd-cdb swap move srp-send-cmd srp-wait-rsp dup -1 = IF 0 0 rot EXIT THEN dup 0<> IF srp-rsp-find-sense IF vscsi-debug? IF over scsi-get-sense-data ." VSCSI: Sense key [ " dup . ." ] " .sense-text ." ASC,ASCQ: " . . cr THEN ELSE 0 0 ." VSCSI: No sense data" cr THEN rot THEN ; " scsi-host-helpers.fs" included TRUE VALUE first-time-init? 0 VALUE open-count : vscsi-cleanup vscsi-debug? IF ." VSCSI: Cleaning up" cr THEN crq-cleanup vscsi-unit 0 rtas-set-tce-bypass ; : vscsi-init ( -- true | false ) vscsi-debug? IF ." VSCSI: Initializing" cr THEN my-unit to vscsi-unit vscsi-unit 1 rtas-set-tce-bypass crq-init 0 <> IF false EXIT THEN " "(C0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00)" drop crq-send not IF ." VSCSI: Error sending init command" crq-cleanup false EXIT THEN crq-wait not IF crq-cleanup false EXIT THEN crq c@ c0 <> crq 1 + c@ 02 <> or IF ." VSCSI: Initial handshake failed" crq-cleanup false EXIT THEN first-time-init? IF ['] vscsi-cleanup add-quiesce-xt false to first-time-init? THEN true ; : open vscsi-debug? IF ." VSCSI: Opening (count is " open-count . ." )" cr THEN open-count 0= IF vscsi-init IF 1 to open-count true ELSE ." VSCSI initialization failed !" cr false THEN ELSE open-count 1 + to open-count true THEN ; : close vscsi-debug? IF ." VSCSI: Closing (count is " open-count . ." )" cr THEN open-count 0> IF open-count 1 - dup to open-count 0= IF vscsi-cleanup THEN THEN ; : (set-target) to current-target ; : dev-generate-srplun ( target lun -- ) swap 8 << 8000 or or 30 << ; : set-address ( srplun.lo srplun.hi -- ) lxjoin (set-target) ; : max-transfer ( -- n ) 10000 \ Larger value seem to have problems with some CDROMs ; 8 CONSTANT #dev : dev-max-target ( -- #max-target ) #dev ; " scsi-probe-helpers.fs" included scsi-close : setup-alias " scsi" find-alias 0= IF " scsi" get-node node>path set-alias ELSE drop THEN ; : vscsi-init-and-scan ( -- ) 0 0 get-node open-node ?dup 0= IF EXIT THEN my-self >r dup to my-self scsi-find-disks setup-alias close-node r> to my-self ; : vscsi-add-disk " scsi-disk.fs" included ; vscsi-add-disk vscsi-init-and-scan 80vio-veth.fs." Populating " pwd cr " network" device-type INSTANCE VARIABLE obp-tftp-package 0 VALUE veth-priv 0 VALUE open-count : open ( -- okay? ) open-count 0= IF my-unit 1 rtas-set-tce-bypass s" local-mac-address" get-node get-property not s" reg" get-node get-property not 3 pick and IF >r nip r> libveth-open dup not IF ." libveth-open failed" EXIT THEN drop TO veth-priv THEN THEN my-args s" obp-tftp" $open-package obp-tftp-package ! open-count 1 + to open-count true ; : close ( -- ) open-count 0> IF open-count 1 - dup to open-count 0= IF veth-priv libveth-close my-unit 0 rtas-set-tce-bypass THEN THEN s" close" obp-tftp-package @ $call-method ; : read ( buf len -- actual ) dup IF veth-priv libveth-read ELSE nip THEN ; : write ( buf len -- actual ) dup IF veth-priv libveth-write ELSE nip THEN ; : load ( addr -- len ) s" load" obp-tftp-package @ $call-method ; : ping ( -- ) s" ping" obp-tftp-package @ $call-method ; : setup-alias " net" get-next-alias ?dup IF get-node node>path set-alias THEN ; setup-alias u0rtas-nvram.fs." Populating " pwd cr 0 VALUE my-nvram-fetch 0 VALUE my-nvram-store 0 VALUE my-nvram-size 0 VALUE nvram-addr : open true ; : close ; : write ( adr len -- actual ) nip ; : read ( adr len -- actual ) nip ; : setup-alias " nvram" find-alias 0= IF " nvram" get-node node>path set-alias ELSE drop THEN ; " #bytes" get-node get-package-property 0= IF decode-int to my-nvram-size 2drop " nvram-fetch" rtas-get-token to my-nvram-fetch " nvram-store" rtas-get-token to my-nvram-store my-nvram-size to nvram-size nvram-size alloc-mem to nvram-addr my-nvram-fetch my-nvram-store nvram-size nvram-addr internal-nvram-init THEN setup-alias 0virtio-net.fss" network" device-type INSTANCE VARIABLE obp-tftp-package /vd-len BUFFER: virtiodev virtiodev virtio-setup-vd 0 VALUE virtio-net-priv 0 VALUE open-count : open ( -- okay? ) open-count 0= IF open IF s" local-mac-address" get-node get-property not IF virtiodev virtio-net-open dup not IF ." virtio-net-open failed" EXIT THEN drop TO virtio-net-priv THEN true ELSE false THEN ELSE true THEN my-args s" obp-tftp" $open-package obp-tftp-package ! open-count 1 + to open-count ; : close ( -- ) open-count 0> IF open-count 1 - dup to open-count 0= IF virtio-net-priv virtio-net-close close THEN THEN s" close" obp-tftp-package @ $call-method ; : read ( buf len -- actual ) dup IF virtio-net-read ELSE nip THEN ; : write ( buf len -- actual ) dup IF virtio-net-write ELSE nip THEN ; : load ( addr -- len ) s" load" obp-tftp-package @ $call-method ; : ping ( -- ) s" ping" obp-tftp-package @ $call-method ; 6 BUFFER: local-mac : setup-mac ( -- ) 6 0 DO virtiodev i 1 virtio-get-config local-mac i + c! LOOP local-mac 6 encode-bytes s" local-mac-address" property ; setup-mac : setup-alias ( -- ) " net" get-next-alias ?dup IF get-node node>path set-alias THEN ; setup-alias  0virtio-block.fss" block" device-type FALSE VALUE initialized? 200 VALUE block-size 8000 CONSTANT max-transfer INSTANCE VARIABLE deblocker /vd-len BUFFER: virtiodev virtiodev virtio-setup-vd : shutdown ( -- ) initialized? IF my-phandle node>path open-dev ?dup IF virtiodev virtio-blk-shutdown close-dev THEN FALSE to initialized? THEN ; : init ( -- ) virtiodev virtio-blk-init to block-size TRUE to initialized? ['] shutdown add-quiesce-xt ; : read-blocks ( addr block# #blocks -- #read ) virtiodev virtio-blk-read ; : open ( -- okay? ) open 0= IF false EXIT THEN dup initialized? 0= AND IF init THEN 0 0 s" deblocker" $open-package dup deblocker ! dup IF s" disk-label" find-package IF my-args rot interpose THEN THEN 0<> ; : close ( -- ) deblocker @ close-package close ; : seek ( pos.lo pos.hi -- status ) s" seek" deblocker @ $call-method ; : read ( addr len -- actual ) s" read" deblocker @ $call-method ; : (set-alias) s" disk" get-next-alias ?dup IF get-node node>path set-alias THEN ; (set-alias) H0virtio-fs.fs." Populating " pwd cr s" network" device-type 0 VALUE virtfs-rx-buffer 0 VALUE virtfs-tx-buffer FALSE VALUE initialized? 2000 CONSTANT VIRTFS-BUF-SIZE \ 8k /vd-len BUFFER: virtiodev virtiodev virtio-setup-vd : shutdown ( -- ) initialized? 0= IF EXIT THEN virtiodev virtio-fs-shutdown virtfs-rx-buffer VIRTFS-BUF-SIZE free-mem virtfs-tx-buffer VIRTFS-BUF-SIZE free-mem FALSE to initialized? ; : init ( -- success ) VIRTFS-BUF-SIZE alloc-mem to virtfs-rx-buffer VIRTFS-BUF-SIZE alloc-mem to virtfs-tx-buffer virtiodev ( dev ) virtfs-tx-buffer ( dev tx ) virtfs-rx-buffer ( reg tx rx ) VIRTFS-BUF-SIZE ( reg tx rx size ) virtio-fs-init ( success ) dup IF TRUE to initialized? ['] shutdown add-quiesce-xt THEN ; : open ( -- okay? ) open 0= IF false EXIT THEN initialized? 0= IF init 0= IF false EXIT THEN THEN true ; : load ( addr -- len ) virtiodev swap ( dev addr ) my-args ( dev addr str strlen ) 1 + \ hack to make the following allocate 1 more byte \-to-/ \ convert path elements 1 - 2dup + 0 swap c! drop virtio-fs-load ( length ) ; : close ( -- ) initialized? IF shutdown THEN close ; : ping ( -- ) cr s" ping not supported for this device" type cr cr ; : (set-alias) " virtfs" find-alias 0= IF " virtfs" get-node node>path set-alias ELSE drop THEN ; (set-alias) 0dev-null.fsnew-device " devnull-console" device-name : open true ; : close ; : write ( adr len -- actual ) nip ; : read ( adr len -- actual ) nip ; : setup-alias " devnull-console" find-alias 0= IF " devnull-console" get-node node>path set-alias ELSE drop THEN ; : dummy-term-emit drop ; : dummy-term-key 0 ; : dummy-term-key? FALSE ; ' dummy-term-emit to emit ' dummy-term-key to key ' dummy-term-key? to key? setup-alias finish-device P 0virtio-scsi.fs." Populating " pwd cr FALSE CONSTANT virtio-scsi-debug 2 encode-int s" #address-cells" property 0 encode-int s" #size-cells" property : decode-unit 2 hex64-decode-unit ; : encode-unit 2 hex64-encode-unit ; FALSE VALUE initialized? /vd-len BUFFER: virtiodev virtiodev virtio-setup-vd STRUCT \ virtio-scsi-config /l FIELD vs-cfg>num-queues /l FIELD vs-cfg>seg-max /l FIELD vs-cfg>max-sectors /l FIELD vs-cfg>cmd-per-lun /l FIELD vs-cfg>event-info-size /l FIELD vs-cfg>sense_size /l FIELD vs-cfg>cdb-size /w FIELD vs-cfg>max-channel /w FIELD vs-cfg>max-target /l FIELD vs-cfg>max-lun CONSTANT vs-cfg-length STRUCT \ virtio-scsi-req 8 FIELD vs-req>lun 8 FIELD vs-req>tag /c FIELD vs-req>task-attr /c FIELD vs-req>prio /c FIELD vs-req>crn 20 FIELD vs-req>cdb CONSTANT vs-req-length STRUCT \ virtio-scsi-resp /l FIELD vs-rsp>sense-len /l FIELD vs-rsp>residual /w FIELD vs-rsp>status-qualifier /c FIELD vs-rsp>status /c FIELD vs-rsp>response 60 FIELD vs-rsp>sense CONSTANT vs-rsp-length CREATE vs-req vs-req-length allot CREATE vs-rsp vs-rsp-length allot scsi-open 0 INSTANCE VALUE current-target : execute-scsi-command ( buf-addr buf-len dir cmd-addr cmd-len -- ... ) vs-req vs-req-length erase vs-rsp vs-rsp-length erase current-target vs-req vs-req>lun x! vs-req vs-req>cdb swap move vs-req vs-rsp virtiodev virtio-scsi-send 0 <> IF ." VIRTIO-SCSI: Queuing failure !" cr 0 0 -1 EXIT THEN vs-rsp vs-rsp>response c@ CASE 0 OF ENDOF \ Good 5 OF drop 0 0 8 EXIT ENDOF \ Busy dup OF 0 0 -1 EXIT ENDOF \ Anything else -> HW error ENDCASE vs-rsp vs-rsp>status c@ dup 0<> IF vs-rsp vs-rsp>sense-len l@ dup 0= IF ." VIRTIO-SCSI: No sense data" cr 0 EXIT THEN vs-rsp vs-rsp>sense swap virtio-scsi-debug IF over scsi-get-sense-data ." VIRTIO-SCSI: Sense key [ " dup . ." ] " .sense-text ." ASC,ASCQ: " . . cr THEN rot THEN ; " scsi-host-helpers.fs" included : max-transfer ( -- n ) 10000 \ Larger value seem to have problems with some CDROMs ; : (set-target) to current-target ; : dev-generate-srplun ( target lun-id -- srplun ) swap 0100 or 10 << or 20 << ; : set-address ( srplun.lo srplun.hi -- ) lxjoin (set-target) ; 100 CONSTANT #target : dev-max-target ( -- #target ) #target ; " scsi-probe-helpers.fs" included scsi-close \ no further scsi words required 0 VALUE queue-control-addr 0 VALUE queue-event-addr 0 VALUE queue-cmd-addr : setup-virt-queues virtiodev 0 virtio-get-qsize virtio-vring-size alloc-mem to queue-control-addr virtiodev 0 queue-control-addr virtio-set-qaddr virtiodev 1 virtio-get-qsize virtio-vring-size alloc-mem to queue-event-addr virtiodev 1 queue-event-addr virtio-set-qaddr virtiodev 2 virtio-get-qsize virtio-vring-size alloc-mem to queue-cmd-addr virtiodev 2 queue-cmd-addr virtio-set-qaddr ; : setup-alias s" scsi" find-alias 0= IF s" scsi" get-node node>path set-alias ELSE drop THEN ; : shutdown ( -- ) initialized? IF my-phandle node>path open-dev ?dup IF virtiodev virtio-scsi-shutdown close-dev THEN FALSE to initialized? THEN ; : virtio-scsi-init-and-scan ( -- ) 0 0 get-node open-node ?dup 0= IF ." exiting " cr EXIT THEN my-self >r dup to my-self virtiodev virtio-scsi-init 0= IF setup-virt-queues scsi-find-disks setup-alias TRUE to initialized? ['] shutdown add-quiesce-xt THEN close-node r> to my-self ; : virtio-scsi-add-disk " scsi-disk.fs" included ; virtio-scsi-add-disk virtio-scsi-init-and-scan +0build_info.imgprintf t[CC]t%sn build_info.img; gcc -m64 Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/ppc64-redhat-linux/4.8.3/lto-wrapper Target: ppc64-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-isl=/builddir/build/BUILD/gcc-4.8.3-20140911/obj-ppc64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.3-20140911/obj-ppc64-redhat-linux/cloog-install --enable-secureplt --with-long-double-128 --build=ppc64-redhat-linux Thread model: posix gcc version 4.8.3 20140911 (Red Hat 4.8.3-7) (GCC) GNU ld version 2.23.2 Supported emulations: elf64ppc elf32ppclinux elf32ppc elf32ppcsim elf32_spu 矐