author | Xindong Xu <xindong.xu@amlogic.com> | 2018-01-12 08:30:31 (GMT) |
---|---|---|
committer | Xindong Xu <xindong.xu@amlogic.com> | 2018-01-12 08:30:31 (GMT) |
commit | e01226016beccd02aeabd8f5e0c95804ac5b300d (patch) | |
tree | 0f8073766f528fa1f1a6aaeced2bd6b50087295f | |
parent | 143af7bf8724c568fbf4b0b1da57aff1932b80a6 (diff) | |
download | common-e01226016beccd02aeabd8f5e0c95804ac5b300d.zip common-e01226016beccd02aeabd8f5e0c95804ac5b300d.tar.gz common-e01226016beccd02aeabd8f5e0c95804ac5b300d.tar.bz2 |
ref_device_common: sync to 8.1 trunk 2c9d1cfd8f [2/10]
PD# 158649
1. bug 157786 add tv related code
2. bug 158467 move recovery code to vendor
Change-Id: Ied3a58eab6362981d903f068fa8462801a9a9e03
43 files changed, 4922 insertions, 12076 deletions
@@ -21,20 +21,7 @@ PRODUCT_PACKAGES += \ audio.r_submix.default \ acoustics.default \ audio_firmware \ - libparameter \ - libamadec_omx_api \ - libfaad \ - libape \ - libmad \ - libflac \ - libcook \ - libraac \ - libamr \ - libpcm \ - libadpcm \ - libpcm_wfd \ - libaac_helix \ - libamadec_wfd_out + libparameter #PRODUCT_COPY_FILES += \ # $(TARGET_PRODUCT_DIR)/audio_policy.conf:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy.conf \ diff --git a/hdcp_rx22/arm_tools/aictool b/hdcp_rx22/arm_tools/aictool index b9e2f51..4ad79a4 100644 --- a/hdcp_rx22/arm_tools/aictool +++ b/hdcp_rx22/arm_tools/aictool @@ -1,162 +1,177 @@ -ELF -&x0;hQ`Rx0: * +ELF +&x0;hQ`Rx0: * -
hFF Z)FF +
hFF )FF -L1FF -'R;0;h09 ) - -FD,< +L1FF +'R;0;h09 ) +FD,< -GHD@WO - +GXDXWO
O3 -hO`O -hбOPShOh +hO`O +*hбOPShOh - - -Cy D@XGh{G\wGLrT,*KFCF*SFT9)*FF8F)FFFXFTFT<T<o+f+Gpp - h - hi64FV\ -x -Fc -XF9h -gpT354B -"`,!BFKFE -Q1 -u#o0SFSYhhhBP -S[i+H@ -Sh;O -Sh ->F,F4Fgh8FQF``a^a`(a ,OPShOhdh -F<&Fci +( + +Cy DXXH0H$HT,*KFCF*SFT9)*FF8F)FFFXFTFT<T<o+f+H8 + hq + h64FV\ +x +F +XF9h) +gpT354B +"`,!BFKFnE +Q1 +#o0SFSYhhhB0P +S[i+HP +Sh;O +Sh +>F,F4Fgh8FQF``a^a`(a ,OPShOhdh +F<ci CE8CF -740B< -D -j0k@ -ZT3+Sh++ -ѩ!FOr -0@p!)D2FPF " -0 +740B< +D +j0k@ +ѩ!FOrp襨!F"lh+ +0@p!)D2FPF " +0 O -HX,F i - -SiB3 +Hlh,F i7 + +SiQBO0/ F -*FxU4瘱 -F 8 F8-O -;WB+*yY#BPF}iBFF4BF*'"F - !hY@pG8F FH08(FE"F8-O]
U5Ot#
S3`&
^ -OGIFZFI -tPG -
P0
Q1h - BUDAeB -:
^ -Q -BX"` -X, - -X<"Z`X<X,bXl6 - -zX, -F0
P0
X< -0h -D0h -F0
P0
X< -0hl -D0h` -` -<"* +*FxU4瘱 +F 8 F8-OHcD4`O"+ + +F:FF,4BF + +4#x + !h@pG8F FH0T8(FE"F8-O]
R2`&
S`
^ +OGIFZFI +4PM +
P0
Q1h +!B%UDQ-k+mB# +:
^ +R +@BX"` +X, + -X<"Z`X<X,bXl6 + +zX, +F0
P0
X< +0h +D0h +F0
P0
X< +0ht +D0hh +` +p"* - -@,SDATEO8hyhh?;M=F
^ -8F@i y`a0I -GB-B -C=X@l -G@=\0;"+l# -+ -D` 0 R!l D< -+ -D`!,|0Zh`0#pX@\03\03 0Op -+ -D`Op -+ -D`o)j(h1 `ohPoH<(Op -+ -D`Op -+ -D`#b@ -+ -D`Op -+ -D`#,0EF 0 R!l D< -+ -D`o)j(h1 `ohPoH<?Op -+ -D`#bo(h!m `ohSoH<Op -+ -D`oI !Op -+ -D`@ -+ -D`Op -+ -D`|0Zh`00$l -+ -D`ohZ`oIl!Op -+ -D`oh:`Z`noI!xOp -+ -D`F + +A,SDATEO8hyhh?;M=F
^ +F$P0+p,0 R! iDP0T `.FF;#0 @ ++ +D` 0 ++ +|0hZ`|0h +D`", |0Zh`0 ++ +D`OpEF 0 ++ +|0hZ`|0h +D`o)j(h1 `ohPoH<1Op ++ +D`Op ++ +|0hZ`|0h +D`#b@ ++ +D`Op ++ +|0hZ`|0h +D`#,0EF 0 ++ +|0hZ`|0h +D`o)j(h1 `ohPoH<>Op ++ +|0hZ`|0h +D`#bo(h! `ohSoH<Op ++ +|0hZ`|0h +D`oI0!Op ++ +D`@ ++ +D`Op ++ +|0hZ`|0h +D`|0Zh`00$l ++ +|0hZ`|0h +D`ohZ`oI|!Op ++ +|0hZ`|0h +D`oh:`Z`noI!xOp ++ +|0hZ`|0h +D`kF " -0`#h"+@
@̈́oI!nO3MOp -+ -D`o(h)j `ohPoH<Op -+ -D`I@Ch00+j+ nQxX)2f;+bo+j3Y(h11 `ohSoH<Op -$4D q+jOp -+ -D`|0i2`|0ha|0"`Z`FTF 0 R!l D< -+ -D`|0i2`|0ha|0 `X`_'FCFFTF -+ -D`|0i2`|0ha|0!`Y` 0 R!l D< -+ -D` -+ -D`#boiD`ohao`S`@FTF 0 R!l D< -+ -D` -+ -D`<FTF -+ -D`noI1xOpEF 0 R!l D< -+ -D`I(0 -@d5 -B*&B@ - -(`-F -U6 -0ItQiIO0j` -0IaiO0Xj2hB -0I,aiO0XF1 -F(FIDa"FO00F$!FOPROhIlahO4 -O ],P D@ BVaI #k`#+bE@L+ #k`@B -O4O4O4O4@F K F -Ii Ihch+r`h8GO - h?IX"jI` -I,sI4sI<si7xP/sxK+Eѳxf+Bx -0Fp FQ1 -Fi F)F0# -0 -0 -T`!aba -U+`)aja -WN̸aa:b{b -@0C
Pe-&F,F +10`#h"+@
@oI!nO3?Op ++ +|0hZ`|0h +D`o(h)j `ohPoH<Op ++ +|0hZ`|0h +D`IPCh$0&0+j+ nQxX)2f;+bo+j3sY(h1I `ohSoH<Op +b4D q+j ++ +|0hZ`|0h +D`|0i2`|0ha|0nF,F 0 ++ +|0hZ`|0h +D`|0i2`|0ha|08NFF,F03p{$0lpZ zx $0 0 ++ +|0hZ`|0h +D`|0i2`|0ha|0 0 ++ +|0hZ`|0h +D` ++ +|0hZ`|0h +D`#boiD`ohao`S`@F,F 0 ++ +|0hZ`|0h +D` ++ +D`F,F ++ +|0hZ`|0h +D`noI1xkOpEF 0 ++ +|0hZ`|0h +D`I80 + +(@-pF +T +0IQiO0j` +0IaihO0Xj2hB +0I<aiYO0XF1 +O ],P D@ BVaI #k`#+bE@L+ #k`@B +O4O4O4O4@F K F +Ii Ihch+r`h8GO + h?IX"jI` +I<s +FFi F)F0# +0 +WSxhi88`S"`F +0 +T aaaa +U+(aiaa +WNa9bzbb +@0C
Pe-&F,F J{?xEeONxGgyzJjNnxJ zC{NJ*bGkN.G'PkkE%kv _@E@F{_O`_ϲ Y @@ -164,33 +179,33 @@ _@E@F{_O`_ϲ Y [,`T[! 3 S -S\ +S\ +W>DP|Sb@OjOIO( h+c@K@S@ -0@
-MXBOnL`2ŲMXBOlL`2MXBR'L`1MXEN$_MXA -ZFMXN"Eh)MXA E z +0@
+MpBOnLx2ŲMpBOlLx2MpBR'Lx1MpEN$_MpA +ZFMpN"Eh)MpA E z YhfP@VJ hh U@e@On_OiOl_ B/²N%"PZTW@BiE*b B(* ZiJ V -MXHz@ 3U@l@: +MpHz@ 3U@l@: % F0p P @@.c@BK@S@ -0@
-FbAFXbF(RFp -OEEeE +0@
+FbAFXbF(hRFp +OEEeE N -i 2^l +i 2^l %F -L`; +Lx; @@ `@ -s, lj -000{
0c0K03D6B(F
}O0OB +s, lj +000{
0c0K03D6B(F
}O0O B s`o09F pl p#ip}+qkqci @@ -200,7 +215,7 @@ FbAFXbF(RFp t#jt'0+ukucj ucju+0+vckvj vjv/0+wkwj -wjwOpPO2 +wjwOPO2 ^ 0 ADL7DOqH _iOHkID(O O{LJdDLFiNDO~I @@ -399,29 +414,29 @@ pD|ku:6iE pDDX x90Dqn Y8DH -@PDGDD rDD +@PDGDD rDD -"D +"D
( - - + + `_2b"Ol -\^2|,2]"\"aS@`",202S@$"02T2S@X"$2(2S@(2 -DpR-$";$2YF0F +\^2|,2]"\"aS@`",202S@$"02T2S@X"$2(2S@(2 +DpR-$";$2YF0F Y$ )2Z%*2[&"+2\"'],2(-S@^",2 ./2-_ *+." 0a"`12)bS@c23"/ -1223"0 +1223"0 ObOCXO,ZU"X"a2(2WO.TV$"T2`bc,0"`2($S@02 -+]" @N.+^" @G/+_" @:0
+`" @91+a" @,2+b" "ٔ3"c2K@0)F - O\pOHr -+{ٔ."^2S@r3h+vٔ/"_2S@r3h+kٔ0"`2S@+s3h
+nٔ1"a2S@ks3h+cٔ2"b2S@s3h+bٔ3#c"J@s3`HF ++]" @N.+^" @G/+_" @:0
+`" @91+a" @,2+b" "ٔ3"c2K@0)F + OtpO`r ++{ٔ."^2S@r3h+vٔ/"_2S@r3h+kٔ0"`2S@+s3h
+nٔ1"a2S@ks3h+cٔ2"b2S@s3h+bٔ3#c"J@s3`HF ### -"""#
#"
"# +"""#
#"
"# -
B +
B {]{{{z$ )2* @@ -432,131 +447,131 @@ ObOCXO,ZU"X"a2(2WO.TV$" 2
FpXp pp qq -rqrs]sss +rqrs]sss {{) ('%$#" D OT OQ
OROSgLYnEPZ[ \NGF
ED@ -$%l@%'l@'(l@
()l@)l@l@l@l@l@l@!l@!&l@&____X_%z۲Ҳ_ɲ$([,0
-FPBshR$ -F@Oph -+h -At`XD0D@D00DsB -O`F -o - -4X?(F1F:FGLEѽ -1 -KOPSh ->O# -.2.)'% +$%l@%'l@'(l@
()l@)l@l@l@l@l@l@!l@!&l@&____X_%z۲Ҳ_ɲ$([,0
+FBshR$ +FOph +At`XD0D@D0DsB +O`F +o + +4X?(F1F:FGLEѽ + +OPSh +O# +.2.)'% J+FUFSFUSIF= - + E -d Yh i1D - -PF(yhFRF6+FP$/#p -мi@ -}j -DbUF4F<iT "*@ - -`@FhAFD -0FIF -p_0dFeB"_Z -BV# +d Yh i1D + +PFyhFRF+FP$/#p +мi@ +}j +DbUF4F<iT "*@ + +`@FhAFD +0FIF +p_0dFeB"_Z +BV# -SE<lD=k,( +SE<lD=k,( ^yE. -^yA. -F-O# -!8 -! -* +^yA. +F-O# +!8 +! +* SкE
d IF -+hxʱ:*13F+:*F:BFK:, - - -F -@&3"@#۲@0 ++hxʱ:*13F+:*F:BFK:, + +i +F +F +@&3"@#۲@0 -1F" -0 -`4```x""F_+ - F@ -'
z@p4FFFoWF +1F" +0 +`4```x""F_+ + F@ +'
z@4FFFoWF ByOj E - -ZFd 9F"RFGD8FZ + +ZF 9F"RFGD8F DEFk . К !;`\@FA 06) - + P`D6( D$aB\a"Da -#300:0Ҳ *FB;0:0 _ Os$j -7P&F; -" - -B@! -OQ - +#300:0Ҳ *FB;0:0 _ Os$j +7P&F; +" + +B@! +O + - -*\Б -"Bsk$30[k$07;۲BچE<#pELx -"F$1 RkR$ @*E -*VЖ -"B{k$30[k$07;۲BڰB<#ӆBLx61 + +*\Б +"Bsk$30[k$07;۲BچE<#pELx +"F$1 RkR$ @*E +*VЖ +"B{k$30[k$07;۲BڰB<#ӆBLx61 F(DAFEтBћjx8( -"F$6 RkR$ @* +"F$6 RkR$ @* -F7+иEM]D -@ĹXFGF0?zO0 FAF<GF - @|cDX S"0@|fOqq9aCGKE %` "O0{DhI qK"O0{DhI h0L9s@0?$h +F7+иEM]D +@ĹXFGF0?zO0 FAF<GF + @cDX S"0@fOqq9aCGKE %` "O0{DhI qK"O0{DhI h0Ls@0O$Ȋ _oo #
B0 3o 3 - -(FKK"{DhI F`4#PS -_yjѹͱ F !*FC?ǭOssE -$F + +_yjѹͱ F !*FC?ǭOssE +$F ciiBY'"aap3{5Y@=ciiBZY+"aap3{5 ciiBY-"aap51i0) -" -0OssE - -[DGDm@<P +" +0OssE + +[DGDm@<P _ -#
D0x ۲Z+@PK-P5 -|KK"{DhI PX00tK{DhY0hjjP0+x;۲+P+xP -0x$*? ۲Z+?X00KK"{DhI | -" +#
D0x ۲Z+@PK-P5 +|KK"{DhI PX00tK{DhY0hjjP0+x;۲+P+xP +0x$*? ۲Z+?X00KK"{DhI +" -DѹKK"{DhI KK"{DhI F ?0~kX>o - -P5PP.h` +DѹKK"{DhI KK"{DhI F ?0~kX>o + +P5PP.h` %#` 60# <8d9kzkC# B :kB;j3-0#<6 D#8j-:m{l -1F*F FiGB~OssB~KK"{DhI --$h 0FQFRFFm -1F*F FiGB~MOssB +1F*F FiGB~OssB~KK"{DhI +-$h 0FQFRFgFm +1F*F FiGB~MOssB +i [B;c` 6 -<%6 &>dkQF8k*FX>sBsAuF --%h!0FQFRFF&`zi -%m4#` +<%6 &>dkQF8k*FX>sBsAF +-%h!0FQFRFaF&`zi +%m4#` ` C@m 60# @@ -568,207 +583,205 @@ D#m-:;nnCnC2 ) ~@KK"{DhI n 1F*F FiGB}OssB 0}o*D -X --cl +X +-cl 6 -<%4 &f`QFj*FX>sBsAFɹ --"l -` +<%4 &f`QFj*FX>sBsAFɹ +-"l +` # %lͱP` [B`bJ F%!0=~mPV`5P3h -%H%F -~ - F+!`0h9n -O<k - F2F0GBO5#hո +%H%F +~ + F+!`0h9n +O<k + F2F0GBO5#hո -#(hhY`B# -#hF:> FT&P!FSD& +#(hhY`B# +#hF:> FT&P!FcD& 1q `8mF -mZ +mZ v `o+! F3AHBHA -O -` F ! -ݸo -cdFV\Vxo +O +` F ! +ݸo +cdFV\Vxo "ze` Eѹ Л - OI EFghFfh + OI EFghFfh 011`mP;i;;aj@;i O~d{e0)i0) -^ +^ DZ,p+h "ze -HDjBF +HDjBF 3FvEٲ -{ecr0iBf"3{b UxjYF8bpi: "zb;{dFi3bJ.h00 +{ecr0iBf"3{b UxjYF8bpi: "zb;{dFi3bJ.h00 Z -ݻoOS C+BgŻ
& -EKX+B9llkk -`:` -8DIB|xF<cbN& -h -c -F +ݻoOS C+BgŻ
& +EKX+B9llkk +`:` +8DIB|xF<cbN& +h +c ! -#ooxo0yoo+# -hB) o2FRoC& -ORDKFO KFoo`RDBoo -C;Q#08PB& +#ooxo0yoo+# +hB) o2FboC& +ORDKF_ KFoo`RDRoo +C;Q#08PB& B>Scap𱁸 F q{ig+ - }biiB?P !`ap ! FAHBHA + }biiB?P !`ap ! FAHBHA _a / F-!CXBXA i -ǹ) +ǹ) %Fz` zhF F0!0 -YF:k0FBF8ksf)оk:k +iF:k0FF8ksf)оk:k :@ -`7 +`7 FFF^ -`{+!0FAHBHA -B +`{+!0FAHBHA +B ;C# )@Կ `W0F ! -"9F F - - - +"9F F + + + . -C +C - -8` -л08FI -л08FI -Fo#sC(#xhO1!c` + +8` +л08FI +л08FI +Fo#sC#xhO1!c` F#`?%C `USx0; +@&b*F6%C`` F#{PC#soSxh+#{c{ F2CC#scs]#{ FC#sV#{C#sSxl+ FK"{DOrbPDO -Ѓ%!`aoa(Fj -ACa;hB8F;`2ixS!0 -3#
iF+x3 ?2D?B@FzhF7FCpG@F)F/OPS +Ѓ%!`aa(Fj +ACa;hB8F;`2ixS!0 +3#
iF+x3 ?2D?B@FzhF7FCpG@F)F/OPS xr* -B8F!Fn%)'C^OpF -F@s+j*Kp/! -F@ s0 F9F FhF#h0F#S#C%`UBOј -F -00F9F"<iG(D, -%hF+h)ԪlphhCEc!_R -"Aap)+htHo -!0F+hFԫlZh:Z`ҹF`h_S -8F -"KF +B8F!Fn%)'C^OpF +F@s+j*Kp/! +F@8s0 F9F FhF#h0F#S#C%`UBOј +F +00F9F"<iG(D, ++%hF+h)ԪlphhCEc!_R +"Aap)+htHo +!0F+hFԫlZh:Z`ҹF`h_S +"[F 3F1FRF(4pPIFBF Bp<,O? ->F-O<S[`@HP +>F-O<S[`@`P O _O - + X Rh -\E +\E -BC -#'` 0#hF(FC&`#h JpzDhX* -p0FAF"<iG(D, -*F -XD*F1j -F`ba`!`0F`BlChB
#j - +BC +#'` $0#hF(FC&`#h JpzDhX* +p0FAF"<iG(D, +*F +XD*FAj +F`ba`!`0F`BlChB
#j + R`A#h##`0O1iG ,SM -,ЙBD0pG08pG -ED(FFPFZF \F - -"F0+FXF --(Fn +,ЙBD0pG08pG +ED(FFPFZF \F + +"F0+FXF +-(Fn \0ihBRHF- )S )ИEO - -@ -#hk(F0O1hGJC ` !p?O0zDhPF
[v+hFԫlZh:Z`ҹF`h_S -h -0F!FO2O3#2;F@F1FH#3l0? -J@<c@PؿT -F FF'
F<F$ + +@ +#hk(F0O1hGJC ` !p?O0zDhPF
kv+hFԫlZh:Z`ҹF`h_S +h +0F!FO2O3#2;F@F1FH#3l0? +J@Tc@PؿT +F FκF'
F<F$ *;2B -=ГBF3O +=ГBF3O F O0kpFJIh@@ FFgm -FF +FF O -PF -/+ -2k;#0? -HF! -#O3 +PF +/+ +2k;#0? +HF! +#O3 - i F` -B`b` -"FHFpjhDsbb3kHD -"Fhpj3kD, -H!" -F`h_P -%h - -YBF# F -#%baO0O1pG +B`b`4 +"FHFpjhDsbb3kHD +"Fhpj3kD, +H!" +F`h_P +%h + +iBF# F +3%baO0O1pG +1 %x --ЋBF3DppG0p8pG - +-ЋBF3DppG0p8pG + F FjG O3fdk - cZh2Z`iC jii#`bff!flal - -ZF -Vj@s + sZh2Z`iC jii#`bff!flal + +jF +fjA bhLhh`#k+`%c8F#h -DZ`ppGhԜhAvhj]j`b`Xb`h -%Bch:`F0`Zh_Q +DZ`ppGhԜhAvhj]j`b`Xb`h +5Bch:`F0`Zh_Q OJ -E@0PFGF - -# ciKD `HD"jID```caaZbapcih(FB8`O0 +E@0PFGF + +# ciKD `HD"jID```caaZbapcih(FB8`O0 JDY3iTEipi3jrhID - + - -CWLYB9O\TCx|S`E.DBxd|dFF8FA@A4B` + ++CWLYB9O\TCx|S`E.DBxd|dFF8FAXALBx 0O0 -ED -P D -ܽ F!" -, -2B@h*DB@FB0@f`@ihhDXh(@2(FF
Fhch#D6) +ED +P D +ܽ F!" +, +2B@h*DB@FB0@f`@ihhDXh(@2(FF
Fhch#D6) $O\S - - + + . ch@O\W083
[7n3 w7|3ByO @@ -778,7 +791,7 @@ JDY3iTEipi3jrhID vH (-O@[00sErFa?aZh (9O@n0bkBBF -FR~ +FR~ /@ +@D/O~R // @@ -787,49 +800,50 @@ FR~ . )XhdF UE - hhB@𨄏hB@𤄰 + hhB@𨄏hB@𤄰 + F -F.|O~kZhB@ +F.|O~kZhB@ Fh -hB@hhB@dXh`` +hB@hhB@dXh`` D* UE0O "VE - + +PFF FO -O0r` -CQ``tJFGH4GFO -a?A A4B -O\XA1F,A A4B -A -A !QFJ -aJAA4B -KB +O0r` +CQ``tJFGH4GFO +a?A ALB +O\XAAF,A$ ALB +A +A !QFJ +aJAALB +KB - 9O\QBH - Jk`KhCK`IFV<C8FCF,"E!F0F -h`FFR真 -WE= -O\P! -["_(OT + Jk`KhCK`IFV<C8FCF,"E!F0F+ +h`FFR +WE= +O\P! +["_(OT ʿ -F +F O -KdOM3
O\THh_T -a(F*bj -DSh -y -"#Fo -"F -"Fo -"FO0c5 -"Fo -"Fo -"Fo -"Fo +KdOM3
O\THh_T +a(F*bj +DSh +y +"!Fo +"F +"Fo +"FO0c5 +"Fo +"Fo +"Fo +"Fo nO<wٶ.|6~&B `{ -U+2`*`hJ`E+@/FܫkB +U+2`*`hJ`E+@/FܫkB 8 O\* [ @@ -840,23 +854,22 @@ DSh w OL| O~ -VE6H4+3#0B8r -kO\P! +VE6H4+3#0B(r n -5O -L F!" +5O +L F!" P4x -_U -Ba|$0h3hk -Cc
g(F!" - -FF -"B:FF(*F0FAF -"FBF:F0FAF(*F +_U +Ba|$0h3hk +Cc
g(F!" + +FF +"B:FF(*F0FAF +"VBF:F0FAF(*F FB BppG - + #,EFZF#F KEpBD B FBFXFYD @@ -875,7 +888,7 @@ FB Ec -(x\s\1B903E?Ӯ +(x\s\1B903E?Ӯ W ('t&|d%lT$\D#LU ` @@ -883,7 +896,7 @@ W ('x&xh%hX$XH#HU ` 01\# R ('|&tl%d\$TL#DU ` -01\# c +01\# c @@ -922,134 +935,137 @@ W ++KK++K++ [ [""$$&+&+([**,,.+.+ ++{{++{`+ - -F]HD T + +F]HD T -" \BxB -+ +" \BxB ++ E ܻ sFhhBCKSE^DBȿB$ED P -<oa9bchb{b@#h -"qap0F0OPUE+h -!:{j - -' -KABp/O0{DhPKABp/O4{DhP -@! -B##FEC -1 -S#+`8FP FJFoc$<K{Dh[P8F=oc $$$2K{Dh[P -E# +<oa9bchb{b@#h +"qap0F0OPUE+h +!:{j + +' +KABp/O0{DhPKABp/O4{DhP +@! +B##FEC +1 +S#+`8F@ FJFoc$<K{Dh[P8F-oc $$$2K{Dh[P +E# {hKhf -s"{c``B"s`L`ppGhK`Ch``D` +s"{c``B"s`L`ppGhK`Ch``D` qh0K P4 F -^ +^ {o s o {o s o !hF FBFPC3`(hByB F -Bx!FBFHFF*hPF3hOKD+` -!D,` +Bx!FBFHFF*hPF3hOKD+` +!D,` !XF0O - -KdBp/ -"XF;iFE -"XF{`i{hE=ГF:KABp/{DhPB`}aa - B@a"x00; +4 - 1FRF -"P0Bx -i@XD]KpGp?c2Z?(O3B4 -+8 FO3 2h_CR -"+F% -Btg + +KdBp/ +"XF)iFE +"XF{`i{hE=ГF:KABp/{DhPB`}aa +_` + BXa"x00; +4 + 1FRF +">0Bx +i@XD]KpGp?c2Z?(O3B4 ++8 FO3 2h_CR +"+F% +B'Qx )"цB, +Bg O"' T (;(CH|'ND|" ] ("LHLDCH|CD,( "1FTJH|' 9(FO5JFGH<GDHDHH|BTYF
O"f'O OO --OC`#h` +-OCP#h` -C&h +C&h (h -F h +F h `+` ` -P<P,#O2P<P< - F -)@C@s`Fid2C -:2Cl +P<P,#O2P<P< + F +)@C@s`Fid2C +:2C Vyq߉R {)R hIDBhBПh9DBihEREFX23VE`` -D D0@ -x0:Ӳ +"KxM0 ,
1
FB;0:0 ,.+B - - FE\ -oFi +D D0@ +x0:Ӳ +"KxM0 ,
1
FB;0:0 ,.+B +@0/!Cx + + FE\ +oFi {DhEKp_{DhU - YLTh&i + YLTh&i `hX` -F+,* +F+,* aK.F`]$shc`sh&Fuh&F+F-OF0LdЛF+h; - -V$(V<$68Fz@FIFC + +V$(sV<$68Fj@FIFC -;n +;n !F K,<#K4< HF - -,h -0 @F0 - FF:a{` -"{`i{hBE (F!yaZF"za^FMF + +,h +0 @F0 + FF:a{` +"{`i{hBE (F!yaZF"za^FMF F:) -:+ -:+xF1 -(=a[hia3#i
hFCsFi`@\1(`hF`n -"3F:$#!XF +:+ +:+xF1 +(=a[hia3#i
hFCsFi`@t1(`hF`^ +"3F:$#!XF PSD -a -F -+ +a +F ++ KBF4$(F B@ -bBF3#(F +bBF3#(F *ܚEO -C`FC@ C,!Cdc +C`FCX CD!C|c F H k G(\
B@À -BF3#(Ft4F;F +BF3#(Ft4F;F *YܚEO C` -G&h-C@ C,!CDc +G&h-CX CD!C\c -B@ +B@ *ܚEO -C`FC@ C,!C c +C`FCX CD!C8c HO kP3O$h C`@y* G(m
B@ -BF3#(F +BF3#(F *[ܚEO C` -G:h +G:h k FGF -*h +*h
k6m3O$h^@ :F3F BB@h)lSp1FBѓF G([E@#h @@ -1057,12 +1073,12 @@ C` O O 1 - -C` -G7hC C,!C\S + +C` +G7hC( CD!CtS -F2Bq _? -`|C$0C!C@S +F2Bq _? +`|C<0C!CXS $ mk3O$hZ@ @@ -1071,16 +1087,16 @@ CpF 1BDBـB>S
< B - + G3h*&ܜBO -C`C C,!C S +C`C( CD!C8S -CpgFFLF +CpgFFLF 3, EkSF ?3 h2 -` C$0C!CS +` C<0C!CS h! 2 `((eF !D-OFhF $ @@ -1089,11 +1105,11 @@ h! 2 BF=F #E%FFx+o2+`B*` @5B9 G(@E@ - )!)@!PB"FO4 -ٝ@0+
A -ФF<F)!0DBA)`R - -G*Oa"Oa"_C C,!CC + )!)@!PB"FO4 +ٝ@0+
A +ФF<F)!0DBA)`R + +G*Oa"Oa"_C( CD!CC k @ @@ -1102,103 +1118,103 @@ BF=F #E%FFx+o2+`B*` `=$ ##DBB --;F/D\3Bq
C C,!CC +-;F/D\3Bq
C( CD!CC @X`x2qhB0h! -C`{2h +C`{2h
mk3O$hY@ G(KB@5 `P _3F?I -h8!FFC C,!ClC -C`("F -G/hEC C,!ClC -`1C$0C!CPC +h8!FFC( CD!CC +C`("F +G/hEC( CD!CC +`1C<0C!ChC @ F 'G" W ##DBB --;F/D\3Bq
} C C,!C(C +-;F/D\3Bq
} C( CD!C@C @X`x2qhB0h! -C`2h +C`2h
mk3O$hY@ G(EB@ Sp71:FFEgF\FF*-(F -Sp23cE@& +Sp23cE@& C`8 -G/hmC C,!C3 -` BF2h +G/hmC( CD!C3 +` BF2h @36 D R S" sFP" -BuK@{DhX +BuK@{DhX gF @Q ["0FS F -`;`!F!h32:``- -8FXi8j)hJFWF -F - -+@F\D -F +`;`!F!h32:``- +8FXi8j)hJFWF +F + ++@F\D +F }Hibh3C - -Z@"aX@`a#h" + +Z@"aX@`a#h" -,S -pFα@ah FO@@1 FG +pFα@ah F?@@(1 F7 B -lhAD-O=0 +lhADO=0 --,S` -PExe -0FTF +-,S` +PExe +0FTF ii*F - - + + O X 0TQ 3]ID Z0G@0V -PFBziB@P
Ѡm;iB @cB9ieC#h2`yGKp/! +PFBziB@P
Ѡm;iB @cB9ieC#h2`yGKp/! O - B{iHF"F;iD - -h"Oc B@&DwhU$0B -`33#
F;D!"4CqCs -rDn FO - -fhB -SFFFFziFKFFDFFEDD @Fah -O -O93h4`.F#`65.+D0FZh\n - + B{iHF"F;iD + +h"Oc B@&DwhU$0B +`33#
F;D!"4D +rD FO + + +fhB +SFFFFziFKFFDFFEDD @Fah +O +O93h4`.F#`65.+D0FZh\n CQB C ppG -0 -F# +* +F# OJ 9 -JE +JE h -OIFkBAEӿ +OIFkBAEӿ FJ<n8 ?gFW` O1JN X3O 7D - D F9F9FF F -+DSO@@AB ى + D F9F9FF F ++DSO@@AB ى 0{ҌB -u 9FHFz9FFHFCCE ٛ1ҙE< +u 9FHF~9FFHFCCE ٛ1ҙE< B)D=BA, - O ?5D F)Fv FF)FCF + O ?5D F)Fz FF)FGF CBٛ2/ҘB<* -)FPF[PFF)F( +)FPF_PFF)F, ٻi;R0A @DD( @@ -1213,7 +1229,7 @@ F;F2R1B ; V>` A`$! .տ$@ο`C`O3ؿ@sȿD`ؿ`` AA` +@$O
C@s9C[`A` `` -! +! D0F!FBFG 3FxxsEѴB\FУE4FDvF^EBB8FSS<; @@ -1222,11 +1238,11 @@ A`$! EخFFpE1FsF/FxBpFٮB #FxxB!FBFG -#FxxB FIFBFG - -B`! -"
lF*F1F F=%yih -*F0*"*8 F9Fs\ FEF9F9LF +#FxxB FIFBFG + +B`! +"
lF*F1F F=%yih +*F0*"*8 F9Fs\ FEF9F9PF ) ) @@ -1253,7 +1269,7 @@ b B F)FK -BKD(F0 +BKD(F0 J @@ -1275,260 +1291,253 @@ J Fd -XFl - +XFl #~o -D3l ):;m -&`P4!`a -!z`P FV!0 -!,+`@zhF -!z`\P FV!0 -!,+`@"zhF +D3l ):;m +&`P4!`a +!z`P FV!0 +!,+`@zhF +!z``P FV!0 +!,+`@&zhF &g~m4# ` -C@~iBgo.Bc.0# E<xcjjC# +C@~iBgo.Bc.0# E<xcjjC# -#xT - -+~8l - +#xT ++~8l XSBSA*F -+?0F)F*FF`i -. ++?0F)F*FEF`i +. *~;l 0F)F -&*F`2F -.4.#.RFFFFFeF Foz`>k FV!0.FoE9ozhF +&*F`F +.4.#.RFFFFFeF Foz`>k FV!0.FoE9szhF *~9>30F)F -&*FgF)&`yn - -[B`;b F+!L0k -PFeAPF -x[B~eba F%!]0~[>k[jv\30nfF -> -!z`.F` F\!0 -!E9WzhF -7 -~et:i~{)F ;oFr&`[ .Fe츙KK"{DhI ! -!z`.Fx0 F\!0 -!E9@zhF -hF +&*FguF)&`yn +[B`;b F+!<0k +PFeAPF +x[B~eba F%!M0~[>k[jv\30nfF +!z`.F` F\!0 +!E9[zhF +~et:i~{)F ;oFr&`[ .Fe츙KK"{DhI ! +!z`.F|0 F\!0 +!E9DzhF +hF F#`?3C `*F``F#{C#shp#{ -Ѓ%!`a -"b"#C;+#h - - +Ѓ%!`a +"b"#C;+#h + + -#
Dbb3hui+O$h]@(F@O -,30F0 -+BX -F +#
Dbb3hui+O$h]@(F@O +,30F0 ++BX +F 3hB& F FqC(FD#F2F (@ FUF# - -E -DDOIDOOU4L EFgfffHU 93FOd&O{eBBI">.8vFD5%(FE22DFH2H2.[ٺDD<P,BQ2DBFBOBDiiaDaBh + +E, +DDOIDOOU4L EFgfffHU 93FOd&O{eBBI">.8vFD5%(FE22DFH2H2.[ٺDD<P,BQ2DBFBOBDiiaDaBh ,+5+xJ+ -"h]E?ch+ -" -Z(Q#;+?Kc;+?E+?AhDTkx0; +93 - -D +"h]E?ch+ +" +Z(Q#;+?Kc;+?E+?AhDTkx0; +93 + +D ?EjO 3kJF C8chB -Ya`xBРhchB F`-Ahsjj2kCE RDQ`<`<i -B@X -( @FJF!;hE - h +Ya`xBРhchB F`Ahsjj2kCE RDQ`<`<i +B@X +( @FJF!;hE + h FY - - - Kp/!O0{DhPpGKABp/O0{DhPX -F -(F#Dl/)FB - h)ca - -F -G+hmh\a -G+hZi_TQ -KABp/O0{DhPKp/!O0{DhPpG -@ h`(FO|_p@pG1F(FO|_F0F] F -KABp/O0{DhPKABp/O4{DhP -@ hp(FB -KABp/O0{DhPKABp/O4{DhP -KABp/O4{DhPt + + + Kp/!O0{DhPpGKABp/O0{DhP +F +(F#Dl/)FB + h)ca + +F +G+hmh\a +G+hZi_TQ +KABp/O0{DhPKp/!O0{DhPpG +@ h`(FO|_p@pG1F(FO|_F0F] F +KABp/O0{DhPKABp/O4{DhP +@ hp(FB +KABp/O0{DhPKABp/O4{DhP +KABp/O4{DhP FFpGx/) -F -8b +F +8b -aP*NRVC*tFC +aP*NRVCtFBqO"F@# Q3&dFtI(b zd;dcKE - + PD:hADd FT,D:mB0laٸlS,B dT,F9l @8"hF ` - + F
(sxkYF"FB@X1\$Oaq -)@C@s`0F +)@C@s`0F D2BH -D(F~I" -HF"
-hh +D(F~I" +HF"
+hh - -xOpCd,FFDF
FO -FDD -FDlZ: - F/! - F/! -KOО3Fb + +xOpCT,FFDF
FO +FD\ +FDr: + F/! + F/! +KOО3Fb (F *i2 WF(Fe,5F8 -_lQ - -IF" -"hx C;CP*CqO8P -C" -++
-FDD i - hD+hD<3FcD$1zdD"0L O +_lQ + +IF" +"hx C;C@*CqO8P +Ct" +++
+FD\ i + hD+hDT3FcD<1zdD"0L O 4L0c9ddTLED -D!#0
@FTEDX2 -< O 4cc9cEDZD@QD@R D\A#0
HFFE -BO<O -#, aL1p[hhxh^hUB!|QhA!1pk۱[hS+x!1!pGD0D8!D,C +D!#0
@FTEDp2 +< O 4cc9cEDZDXQDXR DtA#0
HFFE +BO<O +#, aL1p[hhxh^hUB!|QhA!1pk۱[hS+x!1!pGD@DP!DDC 'Fh -
F -J -F:fp Rh* +
F +J +F:fp Rh* O,0 D ~e F$ -) +) O-4 D d F$ ) -D"|i -De=lff}g"F#FB_Gp|cdF<F +D"|i +De=lff}g"F#FB_H d F$ -) +) F$ -) -RhhDD -DP0҉ -DPF;`;h< +) +RhhDD +DP0҉ +DPF;`;h< H Ha -;cZc8< +;cZc8< - E: + E: + -6 -ZѾlF;dk +6 +ZѾlF;dk
#HB C P`1dEE -l%C;d5;m/$hhS=mm -F +l%C;d5;m/$hhS=mm +F - + +;Sx2F%+ -+ЈF ++ЈF # - 0O0*+qD + 0O0*+qDDD$ ##0h`2Fh -МEF1F8FE A5 -O +МEF1F8FE A5 +O YF - - + + &a $O @ -Bch +Bch L9iBNҹiBLhZj_D^ FA _DT -BiBiJI$
\j
_&DQ - - -#{;hF3RV,4B
KBЦ -Q2 ?F +BiBiJI$
\j
_&DQ + +#{;hF3BV,4B
KBЦ +Q2 ?F !F#
FbKi1]\B) h -)
h +)
h F `1jOIЈFO a#
3
;b`F -<jO -hFFBIh +<jO +hFFBIh 0
zbF<08}d8l 0 -E -%@.P -8 dDx`D(aEh +E +%@.P +8 dD`D@aE DlB
8lhB`O ?安E
KEّFdO 02O lF8lO -d`DppD(aEh -x0 ,ٓB0x1 +d`DpD@aE +x0 ,ٓB0x1 vvt F'FF
umOEQiB1DHF -8EݽE +8EݽE @CC# U<BBD - -/(- -O + +/- +O ƱnHFbk200BYx20 ԁFEC% -E@ՇBѼg& +E@ՇBѼg& F0 Nk6 -:xzh%=S-πws3xTK@P{DhP<o&O5=g -F1 +:xzh%=S-πws3xTK@P{DhP<o&O5=g +F1 ck30 -Ԑ}o@˅P?%P}o3_n +Ԑ}o@˅P?%P}o3_n Ԑ#0? # -, +, 0"K@P{DhP=o& -?_XF&E? +?_XF&qE? P @@ -1537,92 +1546,89 @@ ck30 @ P -%PD@|gXF9az``?F9izhhl +%PD@|gXF9az``?F9izhhl F<I0sxyD h^ :?\0BK0 +2<n -F0Fc +F0Fc 0cX,F -F0oB(%F?<_XFz`zho9LEF4FXFz`BzhoF3DD -n@ +F0oB(%F?<_XFz`zho9LEF4FXFz`BzhoF3DD +n@ #0@ -%j|ot @!F +%j|ot @!F ck30=|oLV<m`n0 2 <eLXF_ -:z -m(h=m!Bm(`=o +:j +m(h=m!Bm(`=o -: +: Kk308XF_ -:| +:l O4@P9m`vE:m2 -D +D h 0@@xoB - -Y -B*zo4Fl`Rf -m:mh!B#m`8o + +B*zo4Fl`Rf +m:mh!Bm`8o -<B@kx +<B@kx <BApc05 kS"0n+B -@,P&@B@ -kS"0f+BP -:n-n}m{mC3! -:BBcx5 +@,P&@B@ +kS"0f+BP +:n-n}m{mC3! +:BBcx5 *J;nF m3~lEe|d,Fc{bF <HE#F,F5FF -:9MEҠFXFE+3DD +:9MEҠFXFE+3DD *(QѺmTF;j2BekUF|lt| -0E030i2F%FFEv - BȇQ -?FjHSFFF0xD -}o4Fme&+hPB=o:C"@5=gDO5F=g>O4<g9XF?F}`KP{DhX0X|n°OuP;KT"P&{DhPp$&eT -K@{DhX0#PO4 -:< +0E030i2F%FFEv + BȇQ +}o4Fme&+hPB=o:C"@5=gDO5F=g>O4<g9XF|?F}`KP{DhX0X|n°OuP;KT"P&{DhPp$&eT +K@{DhX0#PO4 +z; +4 -k. D"F|d -, -:8l(F>b9lB,FE&XF?FK@{DhX0 -,i~k +k. D"F|d +, +:8l(F>b9lB,FE&XF?FK@{DhX0 +,i~k - -CF$"F0,F xeFD - -- + + +- yn8Oz -#
kFE +#
kFE -kS"0y+K@,0(Ѓ&0.n-n}m{mC3!h@O5 - &&XFFFL&}n +kS"0y+K@,0(Ѓ&0.n-n}m{mC3!h@O5 + &&XFFFL&}n #00$O @>b{d`e<i ZFxlPPAFV B -(`m<&@O5 +(`m<&@O5 xn8Oz -#
kFE -zh8,FFQ,FFMFO5F0`=gOXF?F|K@{DhX0{mp&7n,n|m{mC3!h2FFFk@,n,n|m{mC3!h|nO5=g@&F -<_XFo -4BFF6XFEo3DD -F -xKxS FPF -p yD hX0hwi +#
kFE +<_XFo +4BFF6XFEo3DD +F +xKxS FPF +p yD hX0hwi OyF # 8FlOO - O{ -F!C(2! + O{ +F!C2! ,@msu:D @@ -1630,7 +1636,7 @@ F!C(2! OsDES C{ -O +O E gO@mFBr#7:(%
@@ -1648,43 +1654,43 @@ E # FH #GfB8OFuBOB -# -X:e`CtL `ja|c\1"4O -FTj\EF?OZ1 +# +X:e`CtL `ja|c\1"4O +FTj\EF?OZ1 FD&<SsEfFh -1`1X -S/`1 SE;D -#<b{cdF@{kxl; DDD2\`,;lE+ (Fi^, F99BQ/ - -Fh -PFF +1`1X +S/`1 SE;D +#<b{cdF@{kxl; DDD2\`,;lE+ (Fi^, F99BQ/ + +Fh +PFF Ҳ*JZ{{ bRhpa2 Qh -+AC\#hbQFE$@EDAEhC ++ACL#hbQFE<@E\AEC _Owђ
b 1 -++C\#hQO3HF)F`|(F)FO3`O"_{!hUh -+
DB(ShGFE$@EDAETC +++CL#hQO3HF)F`|(F)FO3`O"_{!hUh ++
DBShGFE<@E\AElC -= += R 0jD2\i!B23нiEhS,3F88BP - -Z=G<kmZh+hDG1E31ii=Laad$7FhF -h`UL<` -#=`ESx`<F`x40)F
(FBTB$PhXFXIDf - + +Z=G<kmZh+hDG1E31ii=Laad$7FhF +h`UL<` +#=`ESx`<F`x40)F
(FvBTpB$PhXFXIDV + %F`1 -E\1@FOS*i -0SD -#=bEDcxb b(!60)F
(F/FEVEe ahxcO8RCshh +E\1@FOS*i +0SD +#=bE\cxb b(!60)F
(FFEVE4e ahxcO8RCshh +( -*БO +*БO !` " @@ -1692,15 +1698,15 @@ Z=G<kmZh+hDG1E31ii=Laad$7FhF F,`E4@! "fE -3 -FrBD0FҲ *,ZE#qFoBBOF7 +3 +FrBD0FҲ *,ZE#qFoBBOF7 "F +( -*sБO +*sБO !` " @@ -1710,20 +1716,20 @@ Z=G<kmZh+hDG1E31ii=Laad$7FhF "E 3 FrBD0FҲ *,ZE"qF - -"F$5 R< R$ @* + +"F$5 R< R$ @* o}O3Bu {DhP6 ,u {DhP -. -F"4F@FAFE + +F"4F@FAFE R1B;O F - -U#0 -R1B;# + +U#0 +R1B;# [h 08Q$Ӳ +_;#aڲ*+@ˀ @@ -1731,7 +1737,7 @@ F 0_ +@FB<0+ SF;,0*FFB -0۲ +@gk$0i+ +0۲ +@ gk$0i+ ( A3xB@$FFCE@? @@ -1743,32 +1749,32 @@ A3xB@$FFCE@? FFE8F# :gBqFF'$O O -8A|kBq"FKABs
+8AkBq"FKABs
F$FMVFFUlHFU<> -0d +d :CU<;DKF 5 - + 2E=@ -1FPF,FPF1FRIIE 3ED@KA +1FPF0FPF1FVIIE 3ED@KA ` sx8Q#0x+ - -: -T0EF -tF;F F" + +: +T0EF +tF;F F" ,` z -U+@1;F0F" +U+@1;F0F" 3DSH@#DSH|) @! E -FeF
{D@&DDLFFHBO6W(FQFPQFF(FxP,CCB -1瀝B>@[QFF.FQFFRBAB +FeF
{D@&DDLFFHBO6W(FQFTQFF(F|P,CCB +1瀝B>@[QFF2FQFFVBAB 2B=@EF#BE8;B[B63FY<B
F Q\ )DD8QMF @@ -1777,22 +1783,22 @@ A3xB@$FFCE@?
RF0F -`f
A|FF +`f
AFF RFMF$F8UlPF :DP[FFFPOD' -[F +[F 1@S<J - -3Y҈B<QDT
1F(F(FF1FF + +3Y҈B<QDT
1F(F(FF1FF 1AҘB:SD<BA 2C36F -FBA +FBA O -O +O -" -Ѻ!FO
~ FQPF
F!C
$ +" +Ѻ!FO
~ FQPF
F!C
$ {DhPz ' 1F1x0:Ҳ * @@ -1800,37 +1806,37 @@ O z -FaF#
dBpFF 0F$Fl3 +FaF#
dBpFF80F<F3 4F 0` -" -OFFF$Fl3 +" +OFF0F<F3 z ' 4FF
dKp/"!{DhP - + {DhP.z ' Z -VF F$Fl3 +VF F<F3 9{ #H|H=%BF5:и F -h%Dh +h%Dh R1B;O F - -U#0 -R1B;# + +U#0 +R1B;# [h 0Q$p_ +-_;#a۲+/x3xB@U_FFCE@M? ?70FҲ *,# 0_ +@PFB<0+ SF;,0*FFBׂ - ` + ` ( 0&$ [ p* @@ -1844,97 +1850,98 @@ F OsO ipEq0 rF -FFKABs A|#FOO +FFKABs A#FOO FFE < F0F$4<0; + -: +: ccsPC K - + <BF ->` - -tF+F F" -,`{ -CFB -CB +>` + +tF+F F" +,`{ +CFB +CB 0X 0Jo @FW+p^,`D @˃L5( " " -E -YFPF FPFYFGAE I0iҊEIcH @#FB +E +YFPF FPFYFGAE I0iҊEIcH @#FB a F! EO5Y -HF8F -HF] X, @AB +HF<F +HFa X, @AB ى0B;@ -HF@F -HF7BAEى2e҉E=`EE #B8;KEX+B 5+F@FX*0B @FAFSF +HF@F +HF;BAEى2e҉E=`EE #B8;KEX+B 5+F@FX*0B @FAFSF 8Ӊ % -O +O !X*L(?Z! Tcs2O -" +" 3x0+?0+?9F$HFRF f$ -" +" 3F (` - - -ԀlpfhB"_P + + + +ԀlpfhB"_P FB? -*D<F,7FOChB7+F -:BAB3ҍBAD -HFGAE 3E= -Z:BAE3EAD@)FF - )FF8GAE - 3E - OCCAB 3𦀌B AD@)FF - +*D<F,7FOChB7+F +:BAB3ҍBAD +HFGAE 3E= +^:BAE3EAD@)FF + )FF<GAE + 3E + OCCAB 3𦀌B AD@)FF + 2ҋB<AD @" , -IF{ -0EҊBAD?IF`F - ";CAB - 2ҎB -@FGAE 3E>@F @ - ;CAB 2ـB @ҀAFXFyFAF -XFGAE 3E=@E @1F @"%&@@HOI8F
CIFGFIF -8F/ -1FIFF -@#E! - FOCCAB 39ҍB 3MAF(FF(F -AFKAB 3ҍB> +IF +0EҊBAD?IF`F + &;CAB + 2ҎB +@FGAE 3E>@F @ + ;CAB 2ـB @ҀAFXF}FAF +XFGAE 3E=@E @1F @"%&@@HOI8F
CIFKFIF +8F/ +1FIFF +@#E! + FOCCAB 39ҍB 3MAF(FF(F +AFKAB 3ҍB> GD?khFhZ -( -O +( +O F h{D DGE X - + -DFB -@+P+0+F@{+
о& +DFB +@+P+0+F@{+
о -Bج -@ - {DhXh@ -,Fh hh F +Bج +@ + {DhXh@ +,Fh hh F @@ -1950,7 +1957,7 @@ DFB - + input. the source ROM image. @@ -1974,13 +1981,13 @@ For more information, see the man page. - -
- -
+ +
+
+
!"#$ - + @@ -1990,7 +1997,7 @@ For more information, see the man page. - + @@ -2063,7 +2070,7 @@ d\h![T6$:. -XXXXEEEE,,,,????kkkk::::AAAAOOOOggggꗗsssstttt""""筭55557777uuuunnnnGGGGqqqq))))ʼnoooobbbbVVVV>>>>KKKKyyyy xxxxZZZZݨ33331111YYYY''''____````QQQQJJJJ
----zzzzɜ;;;;MMMM****뻻<<<<SSSSaaaa++++~~~~wwww&&&&iiiiccccUUUU!!!!}}}} +XXXXEEEE,,,,????kkkk::::AAAAOOOOggggꗗsssstttt""""筭55557777uuuunnnnGGGGqqqq))))ʼnoooobbbbVVVV>>>>KKKKyyyy xxxxZZZZݨ33331111YYYY''''____````QQQQJJJJ
----zzzzɜ;;;;MMMM****뻻<<<<SSSSaaaa++++~~~~wwww&&&&iiiiccccUUUU!!!!}}}} |LuQnZgk>X`3Q}$Jv)Cb4o= x&u/3V8[%L.Aaהlކ{ňv̢UXO᰽B =0'*z<Gt7Nf*Uh!\BcLj^qP
x dory2H+<C".^9 U0 -&;0YҒRۀODɤu~chg @@ -2086,7 +2093,7 @@ dory+2H"<C9.^0 U -IIII$$$$\\\\Ӭbbbbyyyy7777mmmmNNNNllllVVVVeeeezzzzxxxx%%%%....ttttKKKKpppp>>>>ffffHHHHaaaa5555WWWWiiiiَUUUU((((ߌ
BBBBhhhhAAAA----TTTTsrc/cipher/aes/aes.c +IIII$$$$\\\\Ӭbbbbyyyy7777mmmmNNNNllllVVVVeeeezzzzxxxx%%%%....ttttKKKKpppp>>>>ffffHHHHaaaa5555WWWWiiiiَUUUU((((ߌ
BBBBhhhhAAAA----TTTTsrc/cipher/aes/aes.c ^ f(n0v8~8@9;:?H><=6P7541X023$`%'&&#h" !.*p+)(6-x,./>pqBsrwvJtu~R}|yxZz{lmbo$nkjjh,ibcra4`edzf<gHIKDJON LLMFGETDA@B\CTU"WdVSR*PlQZ[2YtX]\:^|_ LЦTء\"d*l2t:|__ehdr_start.e_phentsize == sizeof *_dl_phdr @@ -2100,15 +2107,20 @@ LLMFGETDA@B\CTU"WdVSR*PlQZ[2YtX]\:^|_ - + p= ^B{ I$ B|uPq - - + + + + + + + - + - + <sizes> @@ -2136,7 +2148,7 @@ LLMFGETDA@B\CTU"WdVSR*PlQZ[2YtX]\:^|_ <aspace type="total" size="%zu"/> <aspace type="mprotect" size="%zu"/> </malloc> - + @@ -2149,12 +2161,12 @@ LLMFGETDA@B\CTU"WdVSR*PlQZ[2YtX]\:^|_ WARNING: Unsupported flag value(s) of 0x%x in DT_FLAGS_1. - + - - - + + + @@ -2338,100 +2350,19 @@ $ - - - - - - - + + + + +
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ }L,D4fl}C}Ο+#U>#`e!Q4\Ycɟ+1*ZibBtz["؊4س?ŏmk1Ke6ukG܉ـ( f13j~{j6h߸<bBQuɶluYD?e1Væ5RğIJ@A[ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + entry: 0x%0*lx phdr: 0x%0*lx phnum: %*u @@ -2476,7 +2407,7 @@ calling fini: %s [%lu] file=%s [%lu]; destroying link map - + @@ -2491,274 +2422,288 @@ calling preinit: %s p= ףp= ؉؉ %^B{ $I$I$ =B!B|PuPuPqq - -_ -Z\ -ll - + +_ +Z\ +ll -b` -T` -Z` -? -?
- +b` + + +T` + + +Z` +@ + A -" -v +" +v - - - - - - - - - - - - - + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - -% -Z - - - -v + + + + + + + + + + + + + + + + +% +Z + + +v + + + + + + + + + +( +)Z +*Z ++ +.E +.E +0 +1L + + + + + + + + + + + + + + + + + +< + +'Q< + + + +<'Py + + + +'Q< +'Q< + - - - - - - - - -"~ -* -+Z -,Z -- -0E -0E -2 -3L - - - - - - - - - - - - - - - - - - - -< -'Q$ - - - -<'Py - - - -'Q$ -'Q$ - - - - - - - - - + + + + + + + + - + + - - + + -\ +w - -q -0 - -> +] + +u + + - -4 - - - - -# - - - - -Vs -c: - - - - - - - - - - - - - - - - - -0 - - - - - - - - -v +^ +y +L +S +Z +a +h +\ + + +Rs +a: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +7 + + + + + + + + +v - - - - - - - - - - - - - - - - - - - - - -# - - -# - -E - -v + + +Z +
+ + + + + + + + + + + + + + + + + +Q +R + + + +# + + + +E + +v - - - - -B -V -c - - - - - - - - - - - - - - - -$Qt -8 -8$Q0$Pt - --$Q - - - - - - - - -$Q0$Pu - - - - - - - - -k + + += +R( +a + +
+ + + + + + + + + + + + + + + +$Qt +8 +8$Q0$Pt + +;$Q + + + + + + + +$Q0$Pu + + + + + + + + +k - - - - - - - - + + + + + + + + - - - - - - - - - -3} - - + + + + + + + + +k +3} k -k - +k + @@ -2767,1508 +2712,1492 @@ c - - + + - - + + - + - -.1<u==. + +.1<u==. //g=Zg%)!u@><~t2Z=ggL=. -.!>>l!u<
./K1nty f?@gZ\=[ -mtI-eR-# - / -.*C'K +.!0>l!u<
./K1nty f?@gZ\=[ < -J[s0tL$Y0 0$ -.vJ#./ =>! -h<HZ=~f0?Z3/ +J[t0tL$Y0 0$ +JCgh"YK==3-3Y_A +.vJ#./ =>! +h<HZ=~f0MZ3/ <2214121.!!K<~<"!K2L. /!!!!"!!"!!!'! %!K - /!!!!"!!"!!!'!a *.2Z + /!!!!"!!"!!!'!a *.2Z <B -<}J$K!u?YOY!u=1K!uK=1!#1 -f!;#ugg/k.<Xo<"g>yfe -B -$B - - - - - - - - - +<}J$K!u?YOY!u=1K!uK=1!#1 +f!;#ugg/k.<Xo<"g>yfe +B +$B + + + + + + + + + $A
BR -$B
B - +$B
B + $A
MX $A
Bq -$A
B - A
B -$A
B - +$A
B + A
B +$A
B + $A
Bw $A
BB -$A
B -$B^$ +$A
B +$B^$ $B] -$B -B - +$B +B + - + AP -A, +A, -$B - B -$B +$B + B +$B $A
BI -$A
B -$B +$A
B +$B $BI -$B +$B $BF -$B +$B G ,A
BP$BL -,A
BP$B +,A
BP$B BG -B +B Ai AR AL -A +A ,A
BP$Ba -,B
BP$B -A +,B
BP$B +A ,BP$BX ,BP$BY -,BP$K - - -A +,BP$K + + +A B -B +B BM -B -$A
BA +B +$A
BA Bl -B - -B +B + +B AG -A -B -B - B -A +A +B +B + B +A APAH -0A
BA -AQ +0A
BA +AQ BG -B -$B +B +$B BD -B - -$BB$ - - - - -A +B + +$BB$ + + + + +A $BU $BN $BK -$B +$B $BW $B $Ba -$B, +$B, AB -A - B +A + B - + AM -A +A $BB -$B -A -B +$B +A +B $B $BO $BH -$B -$B -A( -B +$B +$B +A( +B BR -B -A -AE +B +A +AE + $A
BB $A
B $W
By -$A
B +$A
B - - -A -$B -A -A - - + + +A +$B +A +A + + AD -A - - - -$B -$B - - - +A + + + +$B +$B + + + $BN $Bf -$B +$B BU Bi BE -B -A -$B +B +A +$B Aj -AL -$B^ - +AL +$B^ + $BZ -$B +$B $B $BJ -$B$ - +$B$ + - + - -$B - + +$B + - + - + - - - -B -B - - - -$B -B -$B + + + +B +B + + + +$B +B +$B Az -A +A - - - + + + B} -B -P +B +P - + - + $BC -$B +$B $Bv $BB -$B -[ +$B +[ BB - B -VJPf ~Z ~Z ~ - + B +VJPf ~Z ~Z ~ + T | PDDHDDH -rFF`DDF +rFF`DDF ^ -D +D ^ -rFFZDDF +rFFZDDF B^ -B -$B - +B +$B + AC -AB -
B +AB +
B AT Ai -B +B $A
BZ $A
BG $B
B -$B
B -B -C -C -C -BA -BA -C +$B
B +B +C +C +C +BA +BA +C $BY $BI -$B -GCAA -LCC - +$B +GCAA +LCC + - + $BB -$BB$ +$BB$ $A
B -$A
B - -A -$A
B -A -AK -B +$A
B + +A +$A
B +A +AK +B BU -B +B A
AD -A
ABA
-$B -$B +A
ABA
+$B +$B Bf -B -$B - - +B +$B + + AG -A - -$C
B +A + +$C
B $BB $Bk -$B - - - - +$B + + + + $A
B/ -$A
B( +$A
B( AQ -A -$B - -$A
B( - -$A
B< +A +$B + +$A
B( + +$A
B< $D
B -$B
B -$B +$B
B +$B $BH $B $B\ -$B -$B +$B +$B $BK $B $BS -$B +$B $BE $Bd $BQ $B^ $BV -$B +$B $BD $B $BA $BL $Bo $B -$BP +$BP $BL $B $BS $BQ $B -$B +$B $BJ $B $B $Bx $BU $B| -$BH +$BH $BP $Bt $BE $B -$B$T +$B$T $BL $B $B $BK $B $B{ -$BH +$BH $BO $Bn $BE $B -$B~$T +$B~$T $B $Bj $B $Bo $BD $Bu -$B +$B $B $BQ -$B( - B -$BF$ -
BB
+$B( + B +$BF$ +
BB
BC -B, -AMA -$B +B, +AMA +$B Bg -B +B $BE $BI -$B +$B $A
B $A
Bf -$C
B -$A
B -$A
B - +$C
B +$A
B +$A
B + $A
BH -$A
B - - -A +$A
B + + +A A -srq
pon -nml
kji -LKJ
IHG -NML
KJI - +srq
pon +nml
kji +LKJ
IHG +NML
KJI + $BE $B $B -$B +$B $A
BB $A
B` -$F
B - +$F
B + $B -$B - +$B + $B -$B +$B A
AC -A
A -$B +A
A +$B $A
Bf -$A
B - +$A
B + $B -$B +$B $B -$B - -,A
BP$B -B +$B + +,A
BP$B +B BM -B -A -$B +B +A +$B $Bd -$B +$B BB -BB +BB AB -AB +AB BB -BB -$B -A - +BB +$B +A + - + Af -A +A $BZ -$B -A -$B -$A
B +$B +A +$B +$A
B - -A - -$A
B -$B -$B - -A + +A + +$A
B +$B +$B + +A C
-
B -BA -BA -B -
AW
- -$B +
B +BA +BA +B +
AW
+ +$B $A
B -$A
B +$A
B $A
B] -$D
B +$D
B $A
BA -$A
B, -$B +$A
B, +$B - + BZ BG -B +B
BD -
B4 +
B4 $BJ -$B -A +$B +A $BS -$B -$A
B - -$B - B - -$A
B +$B +$A
B + +$B + B + +$A
B $B
Bq -$H
B -B -A - -$A
B$ -A -$A
BL -$B - - +$H
B +B +A + +$A
B$ +A +$A
BL +$B + + AE AP -A -A
B -$A
B +A +A
B +$A
B $A
B -$A
B - -DB +$A
B + +DB - + $B# -$B -AJ -BB - -BB -BB +$B +AJ +BB + +BB +BB A[ -A - +A + $A
B! -$A
B -A +$A
B +A AO -A +A Aw Ae -A - -A +A + +A - -A -BB + +A +BB BC BL -B +B $BD -$B +$B B] -B -$A
E - B -$B -$A
B -$A
B -$A
B +B +$A
E + B +$B +$A
B +$A
B +$A
B $A
B^ -$A
B +$A
B $BJ -$B +$B $BJ -$B +$B BT BQ -B - -$B +B + +$B BW Bd - B$ - + B$ + $B] $B -$B - -B -A -BB -A -A - -$A
B -$B +$B + +B +A +BB +A +A + +$A
B +$B $Ba $B_ -$B +$B $BH -$B +$B AE AD AD -A +A $Bp -$B -B +$B +B - + - -$B -B -B - + +$B +B +B + - -Ai + +Ai BB - B - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + B + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -$ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + +2 + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -X - - -[ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + +6 + + +7 + + +; + + + + + +A + + + + + + + +L + + + + + + + +O + + + + + + + + + + + +Z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +x + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/hdcp_rx22/arm_tools/hdcprxkeys b/hdcp_rx22/arm_tools/hdcprxkeys index 68cec2b..36ebe0b 100644 --- a/hdcp_rx22/arm_tools/hdcprxkeys +++ b/hdcp_rx22/arm_tools/hdcprxkeys @@ -1,371 +1,325 @@ -ELF -h+Ѩg# +Yп_T -F -h FBF -FO -o -h" -&x0;hQ`Rx0: * +ELF +h+Ѩg# +Yп_T +F +h FBF +FO +o +h" +&x0;hQ`Rx0: * -
hFF/)FF +
hFF-)FF -L1FF -1FF, 3vIFFO -'R;0;h09 ) -FD,< +L1FF +1FF, 1vIFFO +'R;0;h09 ) +FD,< ? -9 0@ - - - oo - io +60@ + + oh + ih pt - Xo - 0@"i + Xh - -@"4 -,^3 - -8ׯ( - -@` + +,^3 + +8ׯ( +$ + +@` 0 -ȍ +Ȇ 00 - - ᄈ -@ -6 -R -( 2 - - -@@ M< -8P - - -< - - -8 - + + + + ᄁ + +@ +/ +6 + + R +H +( 2 +H + + + + + +, + + +( (@0@ -)* -W@ P@ -( - -&( -<0@( - -㸧㌹ +)* + +&! +?0@( + 0 -" -@@@ - -| @@ - - - - - - - - - -\' - - +" + + + + + + + + + +* + + - - - - - - - - - - - - -N - - - -p - - - p + + + + + + + + + + + + +N + + + +p + + +p - - B0 -p - -90@ -8P0@$(9 @ - - - - - - - - - - -"n( - -0 - - - - -" - -0P8P@< 90p - -$0 - - 0</00 -v - -X - - - - -pP - 0@"" -0 -@ - -@- -` - -pk - -@ - -/ -p` -1 -` - - -/: -p` + + B0 +p + +<0@, @ + + +$0@`Lp +90 +$ +>0@, @ + + 0</ +` + + + + + +?0@,(`8 @ + 4 + + +" + +0( + 0@ P +0! 4 0/ +0 +@ + +@- +` + +p} + +@ +( +p` + + +1 +` + +( 9 +p` + + - + @- - - - -0 -p -< 0@ - 0 - - -0 - - -/ - - -0 - -w -s - = + + + +0 + +p +?0@ + + + + + + +< + +0 + + + + +0 + +^ +Z + = - -p + +p - - + + 0c?o20 -0c?o2 0J?o20J?o20J?o20J?o2d +0c?o2 0J?o20J?o20J?o20J?o2 P -` +` - -p - - - - -P ` -p - - - - -d1-0@ @ - - -0 -800H?o20H?o20H?o2:0 - - -10@- - + +p + + + + +P ` + + + + +0 +800H?o2 + + +30@! r - - - - - - - - - - -, - c\F - -刲@(&΅ @ - 00 - -(4 -0 -0 - - - - -Dz@ - -0cS - - -@ - - -QP - -0cS -l3(0@ @ -P - - -QaP - -@ - -x SӁِ - 0 - - - -! -5(0@ @ - - -! -0 0 </ - - - - - @ -p0 - -`Pp -` - - -& -`0- - -p8f/`0@` + + + + + + +90 +$ 0B +" + + + @ + +O + + P +`Pp +` + + + +->&OT" + +&V + +" + + +5 + + + + PP - -& + +& -P +P 1 -p - +p + -O - - - -, - -< -@@0P - - -0=0 +O + + + +, + +? +@a +0P + +30#:4 + +0=0 2 2 -3/ +3/ 2 -90@) +60@& 2 -,:0@) +70@& -p <0@</ +p <0@</ - + 2 - - - -
0 --: - - - - + +
0 +: + + + + 010##(#4
0 " -&. +&. M - ČĎĂ + ČĎĂ " -&.B +&.B p -ݍ<0@4 -0 +ݍ?0@4 +0 0 -ݍ
+ݍ + 0P p 0 a - + 0 P` @@ -374,14 +328,14 @@ a P - - + + - - + + 03/p p0 @@ -390,20 +344,20 @@ a 3/0 -=L-0@ @ +:<*0@ @ 3/ - >L-0@ @ -4 0@- +;<*0@ @ +$0@- - + ЍD
d 0</ - + 0 -$ЍD@ +$ЍD@ HЍxp 0 @@ -414,14 +368,14 @@ X - + X X 0A - + P|0 @@ -432,28 +386,28 @@ S S S - + - - -P:kw0EoO0O -7+?O + + +P:kw0EoO0O +7+?O [ J ] - +" - + @0k - + 0 @@ -464,7 +418,8 @@ S - + + v 0 @@ -492,7 +447,7 @@ S @ p@-` -/ +0 @@ -505,78 +460,71 @@ p@-` 0 !0 0" 0 #0
0$ 0 %0 0& '00| `0G| P - - -P - -@-@@ + +P + !s - B0p@- -r`@ + B0p@-r`@ !s@ - B0p@- -r`@ -!s@ + B0p@-r`@ +!s@ P - -@D - + +@D + - -, -X[ + + + +[ - - -@-@ -04 0 -8 - 0@ + + +0$0 +( 0@ p -80 - -@ +(= - - - -0$0 -0$0 + + + +0$0 +0$0 T0 -p -`P@ - +p - + + $ - -@p` -p + +p +A$ + -p@0a0P4@8 +p@0a0P4@8 `.,@#!+(sP| { -0h+dH)nD$)P%k) l(i\%a(`%4@b |*<$|z`0 1qa +0h+dH)nD$)P%k) l(i\%a(`%$@b |*<$|z`0 1qa "\"Ġ"H -jO-<Mp404x 8
P +jO-<Mp$04x 8
P Pa04@ PpP`&Q - + & -5 -4/ @0 +5 +$, @0 ` - -0 + +0 ,00/ -$0 +$0 $ 1 @@ -585,22 +533,22 @@ $ /o" -0C +0C 1 ` A - + + $! -e - +e + A-
g~ rc:UB- -rrhY
M FgKnCqEkI_A:% -00? +rrhY
M FgKnCqEkI_A:% +00? 000001
00#4000#0020 0#40 00'0020$0#40$00+0020(0#40(00/0020,0#40,004`O- 䨠y'e+4*&u'ॱ+$*D`` `x ``)8y'H@堑) @@ -682,26 +630,26 @@ p ,)v'K ` - + 0 - - + + 6 " 0 - + - + - - + + - - + + - + D03/ P` @@ -709,112 +657,94 @@ P` @0 -lN +TK 03/ - + 03/ -l^P@@03/ +T[P@@03/ 0 -0 +0 K -@-W +@-W - -0@1 + - -0@ + -P -0@1P +P - -0@ + - -0@1 + - -0@ + - -0@ + - -0@ + - -0@ + - -0@ + - -0@ + - -0@ + - -0@ + O - -0@ + - -0@ + @-V - -0@ -P + +P - -0@Q + -P +P - -p@a0 - + + @@ -829,12 +759,10 @@ w - - @1 - + + B - -0@Q + @@ -869,14 +797,14 @@ w ∠娐p xP - + p - + x00 @@ -888,9 +816,9 @@ xP 0 Ѝp - - -⪠$@? + + +⪠$@? !C! @@ -898,11 +826,11 @@ xP - + @ - 0 + 0 ( A0L @@ -910,18 +838,18 @@ xP ( 0O-`0 -@T@ +@T@ \ - + 00(, - 0 + 0 1J1 - + < @@ -950,78 +878,73 @@ P0 o0 bP@ -UpS +UpS + -0 +0 0 - + 0! - - - - - - - - - - - - - 0 - + + + + + + + + + + 0 + 4 - + 0 p - + 00 -40 +40 `0 -\0 +\0 T0 d -\ +\ d(0 # - - + + X H -0A +0A X 0 `# - - - + + + H0 -10C +10C 0 - -H0`@ - - -0@ + + + 0@ 0Ϡ -0 +0 !C! l 0 p -!L! +!L! @@ -1030,17 +953,17 @@ p p0 ` p( - + O-p0M 0 `pp 0 - 0 + 0 Ѝ - + P`- @@ -1052,55 +975,55 @@ P`- - + B ` -` +` p@-M - + D -@P D - +@P D + - - + + - - + + 0 N 0 (A " 0 0 - + P @} " 0 - + H -@ +@ - - - - + + + + - - + + 0PD L 0 - " T -0t - - + " T +0t + + @@ -1108,7 +1031,7 @@ H @D ((((4 - + p:BAB3ҍBAD HFQGAE 3E= :BAE3EAD@)FF @@ -1133,64 +1056,64 @@ H @#E! FOCCAB 39ҍB 3MAF(FuF(F AFKAB 3ҍB> -GD?khFJ#pF - pGO2 -h -BOSؿ -3`)h -FMsh
R$ -FI#h -Mxt`XD0D@D0DsB -O`F -o - -4X?(F1F:FGLEѽ - -9Ih -vIc +GD?khFGspF + pGO2 +h +BOSؿ +3`)h +FKpCh
R$ +FFsh +K`D`XD0D@D0DsB +O`F +o + +4X?(F1F:FGLEѽ + +9Gch +vGx3 .2.)'% J+FUFSFUSIF= > E -d Yh i1D +d Yh i1D -PFfyhFRF+FP$/#p -мi@ -}j +PFfyhFRF+FP$/#p +мi@ +}j #DbUF4F<iT "*@ - -`@FhAFD -0FIF -p_0dFeB"_Z + +`@FhAFD +0FIF +p_0dFeB"_Z BV# -SE<lD=k,( +SE<lD=k,( ^yE. -^yA. -F-O# -!8 +^yA. +F-O# +!8 ! -* +* SкE
-d IF -+hxʱ:*13F+:*F:BFK:, +d IF ++hxʱ:*13F+:*F:BFK:, - + F @&3"@#۲@0 1F"O -0 +0 `4```x""F_+ F@ -'
zJdFFFoWF +'
zH4FFFoWF ByOj E -ZF 9F"RFGD8F +ZF 9F"RFGD8F DEFk . К !;`\@FA @@ -1200,46 +1123,47 @@ ZF 9F"RFGD8F P`D6( D$aB\a"Da -#300:0Ҳ *FB;0:0 _ Os$j -7P&F; +#300:0Ҳ *FB;0:0 _ Os$j +7P&F; " - -Mx@! -O - - -*\Б + +K`! +O + + +*\Б "Bsk$30[k$07;۲BچE<#pELx -"F$1 RkR$ @*E -*VЖ +"F$1 RkR$ @*E +*VЖ "B{k$30[k$07;۲BڰB<#ӆBLx61 F(DAFEтBћjx8( -"F$6 RkR$ @* +"F$6 RkR$ @* F7+иEM]D -K-Op-]F{DhnY0F 0 -@ĹXFGF0?zO0 FAF<GF - JDX S"0JOqq9aCGKE %` "O0{DhI qK"O0{DhI h0K@0y$X; +K-Op-]F{DhnY0F 0 +@ĹXFGF0?zO0 FAF<GF + HcDX S"0HfOqq9aCGKE %` "O0{DhI qK"O0{DhI h0IC@0y$H4 +2 _oo #
B0 3o 3 - - -_yjѹͱ F !*FsC?ǭOssE -$Fy + + +_yjѹͱ F !*FsC?ǭOssE +$Fy ciiBY'"aap3{5Y@=ciiBZY+"aap3{5 ciiBY-"aap51i0) -" +" "0OssE - -[DGDm@<P + +[DGDm@<P _ -#
D0x ۲Z+@PK-P5 -|KK"{DhI PX00tK{DhY0hjjP0+x;۲+P+xP -0x$*? ۲Z+?X00KK"{DhI t +#
D0x ۲Z+@PK-P5 +|KK"{DhI PX00tK{DhY0hjjP0+x;۲+P+xP +0x$*? ۲Z+?X00KK"{DhI X " -DѹKK"{DhI KK"{DhI F 0~kX>o - -P5PP.h` +DѹKK"{DhI KK"{DhI F 0~kX>o + +P5PP.h` %#` 60# <8d9kzkC# @@ -1247,13 +1171,13 @@ $Fy :kB;j3-0#<6 D#8j-:m{l 1F*F FiGB~OssB~KK"{DhI --$h 0FQFRFFm -1F*F FiGB~MOssB +-$h 0FQFRFFm +1F*F FiGB~MOssB [B;c` 6 <%6 &>dkQF8k*FX>sBsAYF --%h!0FQFRFF&`zi -%m4#` +-%h!0FQFRFF&`zi +%m4#` ` C@m 60# @@ -1266,36 +1190,35 @@ D#m-:;nnCnC2 ) 1F*F FiGB}OssB 0}o*D X --cl +-cl 6 <%4 &f`QFj*FX>sBsAlFɹ --"l -` +-"l +` # %lͱP` [B`bJ F%!j0=~mPV`5P3h -%H%F -~ - - F+!`.0h9n -O<k - F2F0GBO5#hո +%H%F +~ + F+!`.0h9n +O<k + F2F0GBO5#hո #(hhY`B# -#hF:> FT&P!FD& +#hF:> FT&P!FD& 1q `8mF -mZ +mZ v `o+! FAHBHA -O +O ` F ! -ݸo -cdFV\Vxo +ݸo +cdFV\Vxo "ze` Eѹ Л - OI EFghFfh + OI EFghFfh 011`mP;i;;aj@;i O~d{e0)i0) @@ -1308,10 +1231,10 @@ D#m-:;nnCnC2 ) Z ݻoOS C+BgŻ
& EKX+B9ll}kkx -`:` +`:` 8DIB|xF<cbN& h -c +c ! #ooxoU0yoo+# hB) o2FoC& @@ -1325,143 +1248,143 @@ ORDKF KFoo`RDoo a i/ F-!)CXBXA Qi -Nǹ) +Nǹ) %Fz` fzhF F0!0 -F:k0FF8ksf)оk:k -O#` +F:k0FF8ksf)оk:k +Ls` :@ -`7 +`7 FFF^ -`{+!0FAHBHA +`{+!0FAHBHA B ;C# )@Կ `W0F ! -"9F F +"9F F -C +C -8` -л08FI -л08FI -Fo#sOxhO1!c` +8` +л08FI +л08FI +Fo#sLxcxhO1!c` F#`?%C `USx0; +@&b*F6%C`` F#{PC#soSxh+#{c{ F2CC#scs]#{ FC#sV#{C#sSxl+ FK"{DOrbPDO -Ѓ%!`aa(Fj +Ѓ%!`aa(Fj ACa;hB8F;`2ixS!0 0 -3#
iF+x3 ?2D?B@Fzh!F7FCpG@F)FI -# -F -F9F@F"F۹khDDl` - +3#
iF+x3 ?2D?B@Fzh!F7FCpG@F)FGc +# +F +F9F@F"F۹khDDl` + -00F9F"<iG(D, +00F9F"<iG(D, %hF+h)ԪlphhCEc!_R "Aap)+htHo -!0F+hFԫlZh:Z`ҹF`h_S +!0F+hFԫlZh:Z`ҹF`h_S O _O - + X Rh \E -MC -#'` l0#hF(FC&`#h JpzDhX* -p0FAF"<iG(D, +Kp +#'` l0#hF(FC&`#h JpzDhX* +p0FAF"<iG(D, *F XD*Fj F`ba`!`0F`BlChB
#j R`A#h##`0O1iG ,SM -,ЙBD0pG08pG +,ЙBD0pG08pG ED(FFPFZF \F - -"F0+FXF --(Fn + +"F0+FXF +-(Fn \0ihBRHF- )S )ИEO -* -@ -#hk(F0O1hGJC ` !p?O0zDhPF)v+hFԫlZh:Z`ҹF`h_S -h -0F!FOO2O3#2;F@F1FH#3l0? -JK<@PؿT -F FF'
F<F$ +* +@ +#hk(F0O1hGJC ` !p?O0zDhPF)v+hFԫlZh:Z`ҹF`h_S +h +0F!FOO2O3#2;F@F1FH#3l0? +JH,c@PؿT +F FF'
F<F$ *;2B -=ГBF3O +=ГBF3O F O0kpFJIh@@ FFgm -FF +FF O -PF -/+ -2k;#0? +PF +/+ +2k;#0? xHF! -s#O3 +s#O3 - i F` -B`b` -"FHFppjhDsbb3kHD -"F\hpj3kD, -H!" -F`h_P +B`b`܋ +"FHFppjhDsbb3kHD +"F\hpj3kD, +H!" +F`h_P %h BF# F g%baO0O1pG +1 %x --ЋBF3DppG0p8pG - +-ЋBF3DppG0p8pG + F FjG O3fdk - Zh2Z`iC jii#`bff!flal - + Zh2Z`iC jii#`bff!flal + bhLhh`#k+`%c8F#h -DZ`ppGhԜhAvhj]j`b`Xb`h +DZ`ppGhԜhAvhj]j`b`Xb`h OJ -E@0PFGF +E@0PFGF -# ciKD `HD"jID```caaZbapcih(FB8`O0 +# ciKD `HD"jID```caaZbapcih(FB8`O0 JDY3iTEipi3jrhID - -_CWLYB9ICx|S`E.DBxd|dFF8FK@@K4AL`3 + +_CWLYB9GdCx|S`E.DBxd|dFF8FI0I$JP 0O0 -ED -P D -ܽ F!" -, +ED +P D +ܽ F!" +, 2B@h*DB@FB0@f`@ihhDXh(@2(FF
Fhch#D6) -$I - - +$Gc + + . -ch@I083
[7n3 +ch@Gg083
[7n3 w7|3ByO ("DA @@ -1469,59 +1392,59 @@ JDY3iTEipi3jrhID vH (-O@[00sErFa?aZh (9O@n0bkBBF -FR~ +FR~ /@ -+@D/O~R ++@D/O~R // hثw:8Tn 0 k . )XhdF UE - hhB@𨄏hB@𤄰 + hhB@𨄏hB@𤄰 + F -F.|O~kZhB@ +F.|O~kZhB@ Fh -hB@hhB@dXh`` -
K@K4AL3 +hB@hhB@dXh`` +
II$J| D* UE0O "VE FO -O0r` -CQ``tJFGH4GFO -a?KPK4AL3 -IKaF,KPK4AL3 -K1 -A !QFJ -aJK@K4AL3 -KB +O0r` +CQ``tJFGH4GFO +a?I I$Jp +GhI1F,II$Jp +I +A !QFJ +aJII$J| +KB - -9IBH - Jk`KhCK`IFV<C8FCF,"E!F0F -h`FFRP -WE= -I! -["_(OT -ʿ -F +9GaBH + Jk`KhCK`IFV<C8FCF,"E!F0F +h`FFRI +WE= +G`! +["_(OT +ʿ +F O -KdOM3
IHh_T -a(F*bj -DSh -y -"Fo +KdOM3
GdHh_T +a(F*bj +DSh +y +"Fo "F "Fo -"FO0c5 -"jFo +"FO0c5 +"jFo "DFo "9Fo -".Fo +".Fo nO<wٶ.|6~&B `{ -U+2`*`hJ`E+@/FܫkB +U+2`*`hJ`E+@/FܫkB 8 O\* [ @@ -1532,15 +1455,15 @@ DSh w OL| O~ -VE6H4+3#0Mb +VE6H4+3#0K2 n -5O -L F!" -P4x -_U -Cc
g(F!" - -"2B:FF(*F0FAFuBF70-"pB
!FB(:F5D +5O +L F!" +P4x +_U +Cc
g(F!" + +"2B:FF(*F0FAFuBF70-"pB
!FB(:F5D "BF:F0FAF(*F5 FB BppG @@ -1564,7 +1487,7 @@ FB Ec -(x\s\1B903E?Ӯ +(x\s\1B903E?Ӯ W ('t&|d%lT$\D#LU ` @@ -1572,7 +1495,7 @@ W ('x&xh%hX$XH#HU ` 01\# R ('|&tl%d\$TL#DU ` -01\# c +01\# c @@ -1611,33 +1534,33 @@ W ++KK++K++ [ [""$$&+&+([**,,.+.+ ++{{++{`+ - -F=HD T + +F=HD T " \BxB -+ ++ E ܻ sFhhBCKSE^DBȿB$ED P -<oa9bchb{b@#h -"qap0FA0I@!+h -!::{j - -' -KABp/O0{DhPKABp/O4{DhP -@! -B##FEC +<oa9bchb{b@#h +"qap0FA0GeMq+h +!::{j + +' +KABp/O0{DhPKABp/O4{DhP +@! +B##FEC 1 S#+`8F FJFoc$<K{Dh[P8Foc $$$2K{Dh[P -E# +E# {hKhf -s"{c``B"s`L`ppGhK`Ch``D` +s"{c``B"s`L`ppGhK`Ch``D` qh0K P4 F -^ +^ {o s o {o @@ -1646,141 +1569,141 @@ s o Bx!FBFHFV*hPF3hOKD+` !D,` !XF@O - -KdBp/ + +KdBp/ "XFiFE -"XF{`Gi{hE=ГF:KABp/{DhPM - M0"vx00; +4 - 1FRF -Fp -"0Bx +"XF{`Gi{hE=ГF:KABp/{DhPJP}aa + J a"vx00; +4 + 1FRF +Fp +"0Bx i@XD]KpGp?c2Z?(O3B4 -+8 FO3 2h_CR -"+F -Md ++8 FO3 2h_CR +"+F +JTg O"' T (;(CH|'ND|" "1FTJH|' O"f'O OO --OOh` -Oh +-OLch` +Lfh (h -F h +F h `+` ` -P<P,#O2P<P< - F -)@C@s`Fid2M@ -:2M\0Ml1MS +P<P,#O2P<P< + F +)@C@s`Fid2K +:2KL Vyq߉R {)R hIDBhBПh9DBihEREFX23VE`` -D D0@9s+J -x0:Ӳ +"KxM0 ,
1
FB;0:0 ,.+B +D D0N93+GP +x0:Ӳ +"KxM0 ,
1
FB;0:0 ,.+B - FE\ -oFi + FE\ +oFi {DhEKp_{DhU - YLTh&i + YLTh&i `hX` -F+,* -aK.F`]$shc`sh&Fuh&F+F-OF0LdЛF+h; - -V$(gV<$68F^@FIFC -;n +F+,* +aK.F`]$shc`sh&Fuh&F+F-OF0LdЛF+h; + +V$(gV<$68F^@FIFC +;n !F K,<#K4< HF - -,h -0 @F0 - FF:a{` -"{`Mi{hBE (F!yaZF"za^FMF + +,h +0 @F0 + FF:a{` +"{`Mi{hBE (F!yaZF"za^FMF F:) -:+ -:+xF1 -(=a[hia3#i
hFM#Fi`Ja(`hF` +:+ +:+xF1 +(=a[hia3#i
hFKpsFi`H1(`hF` "3F:$#!XFx PSD -a -F -+ +a +F ++ KBF4$(F B@ -bBF3#(F +bBF3#(F *ܚEO -C`FM0PMQNT +C`FK K!KDc F H -k +k G(\
B@À -BF3#(Ft4F;F +BF3#(Ft4F;F *YܚEO C` -G&h-M0PMQN4 +G&h-K K!K$c -B@ +B@ *ܚEO -C`FM0PMQN +C`FK K!K HO -kP3I#h +kP3Fsh C`@y* G(m
B@ -BF3#(F +BF3#(F *[ܚEO C` -G:h -k +G:h +k FGF -*h -
k6m3I#h^@ +*h +
k6m3Fsh^@ :F3F BB@h)lSp1FBѓF G([E@#h O O 1 - -C` -G7hM + +C` +G7hKK!K<S -F2Bq _? -`|M`MQN0 +F2Bq _? +`|K0K!K S $ -mk3I#hZ@ +mk3FshZ@ CpF 1BDBـB>S
< B - + G3h*&ܜBO -C`M +C`KK!K -CpgFFLF +CpgFFLF 3, EkSF ?3 h2 -` M`MQMs +` K0K!KC h! 2 `((eF !D-OFhF $ H -k +k BF=F #E%FFx+o2+`B*` @5B9 G(@E@ - )!)@!PB"FO4 -ٝ@0+
A -ФF<F)!0DBA)`R - -G*Oa"Oa"_M -k + )!)@!PB"FO4 +ٝ@0+
A +ФF<F)!0DBA)`R + +G*Oa"Oa"_KK!KC +k @ F @@ -1788,87 +1711,85 @@ BF=F #E%FFx+o2+`B*` `=$ ##DBB --;F/D\3Bq
M +-;F/D\3Bq
KK!KC @X`x2qhB0h! -C`{2h -
mk3I#hY@ +C`{2h +
mk3FshY@ G(KB@5 `P _3F?I -h8!FFM -C`("F -G/hEM -`1M`MQM@s +h8!FFKK!KLC +C`("F +G/hEKK!KLC +`1K0K!K0C @ F 'G" W ##DBB --;F/D\3Bq
} M +-;F/D\3Bq
} KK!KC @X`x2qhB0h! -C`2h -
mk3I#hY@ +C`2h +
mk3FshY@ G(EB@ Sp71:FFEgF\FF*-(F -Sp23cE@& +Sp23cE@& C`8 -G/hmM -` BF2h +G/hmKK!K3 +` BF2h @36 D R S" sFP" BuK@{DhX gF @Q ["0FS F -`;`!F!h32:``- -8FXi8j)hJFF +`;`!F!h32:``- +8FXi8j)hJFF F .F1FXFF0O -+@F\D -F ++@F\D +F }Hibh3C - -Z@"aX@`a#h" + +Z@"aX@`a#h" -,S -pFαJh F7@Jxa F/ +pFαHQh F7@Hh1 F/ B lhADO=0 --,S` - +-,S` PExe -0FTF +0FTF ii*F - -DD - + + O X 0TQ 3]ID Z0G@0V -PFBziB@P
Ѡm;iB JB9ieOh2`yGKp/! +PFBziB@P
Ѡm;iB HSB9ieLlch2`yGKp/! O - B{iHF"F;iD+ - -h"Oc B@&NEwhU$0B -`33#
FsNQ"lN!N# -rD FO -fhB -SFFFFziFKFFDFFEDD @Fah -O + B{iHF"F;iD+ + +h"Oc B@&LwhU$0B +`33#
FsL!"lKqKs +rD FO +fhB +SFFFFziFKFFDFFEDD @Fah +O gi -O93h4`.F#`65.+D0FZh\n +O93h4`.F#`65.+D0FZh\n CQB C ppG -~ -F# +l +F# OJ 9 JE @@ -1910,11 +1831,11 @@ A`$! EخFFpE1FsF/FxBpFٮB #FxxB!FBFG -#FxxB FIFBFG - -NP! -"
lF*F1F F=%yih -*F0*"*8 F9Fs\ FEF9F9F +#FxxB FIFBFG + +L ! +"
lF*F1F F=%yih +*F0*"*8 F9Fs\ FEF9F9F ) ) @@ -1941,7 +1862,7 @@ b B F)FK -BKD(F0 +BKD(F0 J @@ -1963,17 +1884,19 @@ J Fd -XFl-OpO +XFl-OpO ƱnHFbk200BYx20 ԁFEC% -E@ՇBѼg& +E@ՇBѼg& F0 Nk6 -:xzh%=S-πws3xTK@P{DhP<o&O5=g +:xzh%=S-πws3xTK@P{DhP<o&O5=g + + F1 ck30 @@ -2000,13 +1923,13 @@ ck30 F<I0sxyD h^ :?\0BK0 +2<n -F0FJ +F0F: 0cX,F F0oB(%F?<_XFz`zho9LEF4FXFz`BzhoF3DD n@ #0@ -%j|ot @!F +%j|ot @!F ck30=|oLV<m`n0 @@ -2021,45 +1944,45 @@ Kk308XF_ O4@P9m`vE:m2 D h 0@@xoB - + B*zo4Fl`Rf -m:mh!BMm`8o +m:mh!BMm`8o -<B@kx +<B@kx <BApc05 kS"0n+B -@,P&@B@ -kS"0f+BP -:n-n}m{mC3! -:BBcx5 +@,P&@B@ +kS"0f+BP +:n-n}m{mC3! +:BBcx5 *J;nF m3~lEe|d,Fc{bF <HE#F,F5FF :9MEҠFXF E+3DD *(QѺmTF;j2BekUF|lt| -0E030i2F%FFEv +0E030i2F%FFEv BȇQ -}o4Fme&+hPB=o:C"@5=gDO5F=g>O4<g9XF?F}`KP{DhX0X|n°OuP;KT"P&{DhPp$&eT +}o4Fme&+hPB=o:C"@5=gDO5F=g>O4<g9XF?F}`KP{DhX0X|n°OuP;KT"P&{DhPp$&eT K@{DhX0#PO4 - + k. "F|d , -:8l(F>b9lB,FEv&XF?FK@{DhX0 -,i~k +:8l(F>b9lB,FEv&XF?FK@{DhX0 +,i~k - + - yn8Oz -#
kFE +#
kFE kS"0y+K@,0(Ѓ&0.n-n}m{mC3!h@O5 - &&XFFFL&}n + &&XFFFL&}n #00$O @>b{d`e<i FxlPPAFV @@ -2067,242 +1990,245 @@ yn8Oz (`m<&@O5 xn8Oz -#
kFE +#
kFE <_XF9o -4BFF6XF(Eo3DD +4BFF6XF(Eo3DD #~o -D3l ):;m -&`P4!`a +D3l ):;m +&`P4!`a !z`P FV!0 -!,+`@zhF +!,+`@zhF !z`lP FV!0 !,+`@2zhF &g~m4# ` C@~iBgo.Bc.0# E<xcjjC# -#x -+~8l +#x ++~8l XSBSA*F -+?0F)F*FF`i ++?0F)F*FF`i . *~;l 0F)F -&*F`0F +&*F`0F .4.#.RFFFFFeF Foz`>k FV!0.FoE9zhF *~9>30F)F -&*FgF)&`yn -[B`;b F+!h0k -PFAPF -x[B~eba F%!y0~[>k[jv\30nfF +&*FgF)&`yn +[B`;b F+!h0k +PFAPF +x[B~eba F%!y0~[>k[jv\30nfF !z`.F` F\!0 -!E9gzhF -~et:i~{)F ;oFr&`[ .Fe츙KK"{DhI ! +!E9gzhF +~et:i~{)F ;oFr&`[ .Fe츙KK"{DhI ! !z`.F0 F\!0 -!E9PzhF -hF +!E9PzhF +hF F#`?3C `*F``F#{C#shp#{ -Ѓ%!`aa(Fj -"b"#C;+#h -ԀlpfhB"_P +Ѓ%!`aa(Fj +"b"#C;+#h +ԀlpfhB"_P - -#
Dbb3hui+I!h]@(F$O -,30F0 + +#
Dbb3hui+Fqh]@(F$O +,30F0 +BX -F -p yD hX0hwi +F +p yD hX0hwi 3hB& F FQC(FD#F2F (@ FUF# - -@L< -DDOIDOOU4L EFgfffHU 93FOd&O{eBBI">.8vFD5%(FE22DFH2H2.[ٺDD<P,BQ2DBFBOBDiiaDaBh + +N< +DDOIDOOU4L EFgfffHU 93FOd&O{eBBI">.8vFD5%(FE22DFH2H2.[ٺDD<P,BQ2DBFBOBDiiaDaBh ,+5+xJ+ -"Th]E?ch+ -" -^(Q#;+?Kc;+?E+?AhDTkx0; +93 -D +"Th]E?ch+ +" +^(Q#;+?Kc;+?E+?AhDTkx0; +93 +D ?EjO 3kJF C8chB -Ya`xBРhchB F`KAhsjj2kCE RDQ`<`<i -B@X -( @FJF!;hE - h -FY - - - Kp/!O0{DhPpGKABp/O0{DhPT +Ya`xBРhchB F`KAhsjj2kCE RDQ`<`<i +B@X +( @FJF!;hE + h +FY + + + Kp/!O0{DhPpGKABp/O0{DhPM F -(F#Dl!)FB - h)ca - -F -l F -G+hmh\a -G+hZi_TQ -KABp/O0{DhPKp/!O0{DhPpG +(F#Dl!)FB + h)ca + +F +l F +G+hmh\a +G+hZi_TQ +KABp/O0{DhPKp/!O0{DhPpG @ h`(FO|p_p@pGYF(FO|Z_F0F F -KABp/O0{DhPKABp/O4{DhP +KABp/O0{DhPKABp/O4{DhP @ hp(FB -KABp/O0{DhPKABp/O4{DhP -KABp/O4{DhP$K +KABp/O0{DhPKABp/O4{DhP +KABp/O4{DhPD FFpGx/) -F -8b +F + + +8b -aP*NRVOptFNlqIbF@# -Q3&dFtI(b zd;dcKE - +aP*NRVLXjtFLTAGx2F@# +Q3&dFtI(b zd;dcKE + PD:hADd FT,D:mB0laٸlS,B dT,F9l @8"hF ` - + F
(3xkYF"FB@X1\$Oaq -)@C@s`0F +)@C@s`0F D2BH -D(F~I"2 -HF"
-hh -6 +D(F~I"2 +HF"
+hh - -xI+OFFDF
FO -FN -FN(C - F/! - F/! -KOО3Fb + +xF{LlFFDF
FO +FL +FL + + F/! + F/! +KOО3Fb (F *i2 WF(Fe,5F8 -_lQ - -IF" -"hx C;ONd1J -O -++
-FN - hN@khNcFcNazdNHb0L O +_lQ + +IF" + +"hx C;LjLTG` +Lb +++
+FL i + hL0;hL3FcL1zdL820L O 4L0c9ddTSLED -N@a#0
@FTENr -< O 4cc9cEDZJO -BO<O -#, aL1p[hhxh^hUB!|QhA!1pk۱[hS+x!1!pGNpNQNs -'Fh -
F -J - -F:fp Rh* +L01#0
@FTELB +< O 4cc9cEDZJLQLR LQ#0
HFtFE +BO<O +#, aL1p[hhxh^hUB!|QhA!1pk۱[hS+x!1!pGL@L!LC +'Fh +
F +J + +F:fp Rh* O,0 D ~e F$ -) +) O-4 D d F$ ) -D"|i -De=lff}g"F#FB_L0|cdF<F +D"|i +De=lff}g"F#FB_Jp|cdF<F d F$ -) +) F$ -) -RhhDD -DP0҉ -DPF;`;h< +) +RhhDD +DP0҉ +DPF;`;h< H Ha -;cZc8< +;cZc8< - E: + E: + -6 -ZѾlF;dk +6 +ZѾlF;dk
#HB C P`1dEE -l%C;d5;m/$hhs=mm -F +l%C;d5;m/$hhs=mm +F - + +;Sx2F%+ +ЈF # - 0O0*+qN@NANC + 0O0*+qLLL ##0h`2Fh -МEF1F8FE A5 -O +МEF1F8FE A5 +O YF - - -##`p/i+O!AFHFO FOpFr + + +##`p/i+O!AFHFO FOpFb &a $O @ -Nch +L3h L9iBNҹiBLhZj_D^ FA _DT -BiBiJI$
\j
_&DQ +BiBiJI$
\j
_&DQ -02 -#{;hF3V,4B
KBЦ -Q2 ?F +02 +#{;hF3V,4B
KBЦ +Q2 ?F !F#
FbKi1]\B) h -)
h +)
h F`1jOIЈFO a#
3
;b`F -\jO -hFFBIh +\jO +hFFBIh 0
zbF<08}d8l 0 -E -%@.P -8 dO8 OO(C +E +%@.P +8 dL(pLaM DlB
8lhB`O ?安E
KEّFdO 02O lF8lO -d`O00OO(C -x0 ,ٓB0x1 +d`M +x0 ,ٓB0x1 vvt F'FF
umOEQiB1DHF -8EݽOP@) - +8EݽM@) + @CC# U<BBD - -/ -O + +/ +O +( -*БO +*БO !` " @@ -2310,7 +2236,7 @@ x0 ,ٓB0x1 F,`E4@! "fE -3 +3 FrBD0FҲ *,ZE#qFoBBOF7 "F @@ -2318,7 +2244,7 @@ x0 ,ٓB0x1 +( -*sБO +*sБO !` " @@ -2328,20 +2254,20 @@ x0 ,ٓB0x1 "E 3 FrBD0FҲ *,ZE"qF - -"F$5 R< R$ @* + +"F$5 R< R$ @* o}O3Bu {DhP6 ,u {DhP -F"4F@FAFE +F"4F@FAFE R1B;O F - -U#0 -R1B;# + +U#0 +R1B;# [h 08Q$Ӳ +_;#aڲ*+@ˀ @@ -2349,7 +2275,7 @@ F 0_ +@FB<0+ SF;,0*FFB -0۲ +Jk$0i+ +0۲ +HWk$0i+ ( A3xB@$FFCE@? @@ -2361,9 +2287,9 @@ A3xB@$FFCE@? FFE8F# :gBqFF'$O O -8KLkBq"FKABs
+8IkBq"FKABs
F$FMVFFUlHFU<> -d +d :uU<;DKF 5 @@ -2374,13 +2300,13 @@ A3xB@$FFCE@? sx8Q#0x+ - + : -T0EF -tOa;F F" +T0EF +tM1;F F" ,` z -U+Ja;F0F"v +U+H1;F0F"v 3DSH@#DSH|[ @@ -2395,22 +2321,22 @@ A3xB@$FFCE@?
RF0F -`f
KDFF +`f
IFF RFMF$F8UlPF %:DP[FFFPOD' -[F +[F 1@S<J 3Y҈B<QDT
1F(F(FF1FF 1AҘB:SD<BA 2C36F -FBA +FBA O -O +O -" -Ѻ!FOb
~ FQPF
F!C
$ +" +Ѻ!FOb
~ FQPF
F!C
$ {DhPz ' 1F1x0:Ҳ * @@ -2418,37 +2344,37 @@ O z -FaF#
dBpF@POTa@ +FaF#
dBpFM@`MD1Mc 4F 0` -" -OFOHpOTa@ +" +OFM8@MD1Mc z ' 4FF
dKp/"!{DhP - + {DhP.z ' Z -V@ +VMPMD1Mc 9{ #H|H=%BF5:и F -kh%Dh +kh%Dh R1B;O F - -U#0 -R1B;# + +U#0 +R1B;# [h 0Q$p_ +-_;#a۲+/x3xB@U_FFCE@M? ?70FҲ *,# 0_ +@PFB<0+ SF;,0*FFBׂ - ` + ` ( 0&$ [ p* @@ -2462,21 +2388,21 @@ F OsO ipEq0 rF -FFKABs KA#FOO +FFKABs I#FOO FFE < F0F$4<0; + -: +: ccsPC K <BF ->` - -tOa+F F"o +>` + +tM1+F F"o ,`{ CFB -CB +CB 0X 0Jo @FW+p^,`t @˃L5( @@ -2497,25 +2423,25 @@ YFPF FPFYFGAE I0iҊEIcH @#FB % -O +O !X*L(?Z! Tcs2O -" +" 3x0+?0+?9F$HFRF f$ -" +" 3F (` - - -F -FF\ + + +F +FF\ xKxS FqPF OyF # 8FlOO - O{ -F!ʼO"!ü + O{ +F!ʼLlr!ü ,@msu:D @@ -2523,7 +2449,7 @@ F!ʼO"!ü OsDES C{ -O +O E gO@mFBr#7:(%
@@ -2541,55 +2467,56 @@ E # FH #GfB8OFuBOB -# -X:e`Nd4L `ja|c\1"4O -FTj\EF?OZ1 +# +X:e`LTL `ja|c\1"4O +FTj\EF?OZ1 FD&<SsEfFh -1`1X -S/`1 SE;D -#<b{cdF@{kxl; DDD2\`,;lE+ (Fi^, F99BQ/ - -Fh -PF-F +1`1X +S/`1 SE;D +#<b{cdF@{kxl; DDD2\`,;lE+ (Fi^, F99BQ/ + +Fh +PF-F Ҳ*JZ{{ bRhpa2 Qh -+AOhbQF@pP@Q@S ++ALchbQFN` N!N# _Owђ
b 1 -++OhQO3HF)F`(F)FO3`O"_{!hUh -+
DNChGF@pP@Q@S +++LchQO3HF)F`(F)FO3`O"_{!hUh ++
DLhGFN` N!N# -= += R 0jD2\i!B23нiEhS,3F88BP - -Z=G<kmZh+hDG1E31ii=Laad$7FhF -h`UL<` -#=`@sx`<F`40)F
(FBTB$PhXFXID - + +Z=G<kmZh+hDG1E31ii=Laad$7FhF +h`UL<` +#=`NCx`<F`40)F
(FBTB$PhXFXID + %F`1 -E\1@FOS* -0SD -#=b@sxb b(a60)F
(FFEV@hu ahxcJNd3hh +E\1@FOS* +0SD +#=bNCxb b(a60)F
(FFEVNXE ahxcGbLThh FB? -*D<F,7FJHhB7+F -( -O +*D<F,7FG8chB7+F +( +O F h{D DGE X - + DFB @+P+0+F@{+
о6 -Bج -@ - {DhXh@ -,Fh hh F +Bج +0FAK K!K# +@ + {DhXh@ +,Fh hh F %s Usage: %s [-qh?] --in ... --out ... --type ... or @@ -2634,14 +2561,13 @@ or - - + - + @@ -2660,8 +2586,8 @@ IIII$$$$\\\\Ӭbbbbyyyy7777mmmmNNNN -XXXXEEEE,,,,????kkkk::::AAAAOOOOggggꗗsssstttt""""筭55557777uuuunnnnGGGGqqqq))))ʼnoooobbbbVVVV>>>>KKKKyyyy xxxxZZZZݨ33331111YYYY''''____````QQQQJJJJ
----zzzzɜ;;;;MMMM****뻻<<<<SSSSaaaa++++~~~~wwww&&&&iiiiccccUUUU!!!!}}}} -
+XXXXEEEE,,,,????kkkk::::AAAAOOOOggggꗗsssstttt""""筭55557777uuuunnnnGGGGqqqq))))ʼnoooobbbbVVVV>>>>KKKKyyyy xxxxZZZZݨ33331111YYYY''''____````QQQQJJJJ
----zzzzɜ;;;;MMMM****뻻<<<<SSSSaaaa++++~~~~wwww&&&&iiiiccccUUUU!!!!}}}} +
%n @@ -2672,27 +2598,15 @@ IIII$$$$\\\\Ӭbbbbyyyy7777mmmmNNNN - + p= ^B{ I$ B|uPq - - - - - + + - - - - - - - - - - + <sizes> @@ -2720,7 +2634,7 @@ IIII$$$$\\\\Ӭbbbbyyyy7777mmmmNNNN <aspace type="total" size="%zu"/> <aspace type="mprotect" size="%zu"/> </malloc> - + @@ -2733,11 +2647,11 @@ IIII$$$$\\\\Ӭbbbbyyyy7777mmmmNNNN WARNING: Unsupported flag value(s) of 0x%x in DT_FLAGS_1. - + - - + + @@ -2921,20 +2835,15 @@ $ - +
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ }L,D4fl}C}Ο+#U>#`e!Q4\Ycɟ+1*ZibBtz["؊4س?ŏmk1Ke6ukG܉ـ( f13j~{j6h߸<bBQuɶluYD?e1Væ5RğIJ@A[ - - - - - - - + + entry: 0x%0*lx phdr: 0x%0*lx phnum: %*u @@ -2979,7 +2888,7 @@ calling fini: %s [%lu] file=%s [%lu]; destroying link map - + p= ףp= ؉؉ %^B{ $I$I$ =B!B|PuPuPqq @@ -2994,1190 +2903,1162 @@ calling preinit: %s - -_ -\d -rt -Z\ -ll -T` -b` -Z` -Ԏ - - + +_ +\d +rt +Z\ +ll +T` +b` +Z` + + + A -" -$B +" +$B $Ba $B_ -$B +$B - - + + BR -BB, +BB, Au -AB - - - - B +AB + B AC -A -B -$B +A +B +$B $A
BR -$B
B +$B
B $A
MX $A
Bq -$A
B - A
B -$A
B - +$A
B + A
B + +$A
B + $A
Bw $A
BB -$A
B -$B^$ +$A
B +$B^$ $B] -$B -B - +$B +B + - + AP -A, +A, -$B - B - - +$B + B + + $B - + $A
BI $A
B - - -$B + + +$B $BI -$B +$B $BF -$B +$B G ,A
BP$BL -,A
BP$B +,A
BP$B BG -B +B Ai AR AL -A +A ,A
BP$Ba -,B
BP$B -A +,B
BP$B +A ,BP$BX ,BP$BY -,BP$K - - - BA +,BP$K + + + BA BM -B -$A
BA - -B -B +B +$A
BA + +B +B $Bd -$B +$B AG -A -A -A -B -A +A +A +A +B +A APAH -0A
BA -AQ +0A
BA +AQ BG -B -$B +B +$B BD -B - -$BB$ - - - - -A +B + +$BB$ + + + + +A $BU $BN $BK -$B +$B $BW $B $Ba -$B, +$B, AB -A - B +A + B - + AM -A +A $BB -$B -A -B +$B +A +B $B $BO $BH -$B -$B -A( -B +$B +$B +A( +B BR -B -A -AE +B +A +AE $A
BB $A
B $W
By -$A
B +$A
B - - -A -$B -A -A - - + + +A +$B +A +A + + AD -A - - - - - - - - -$B -$B - - - +A + + + +$B +$B + + + $BN $Bf -$B +$B BU Bi BE -B -A -$B +B +A +$B Aj -AL -$B^ - +AL +$B^ + + + $BZ -$B +$B $B $BJ -$B$ - +$B$ + - + - -$B - + +$B + - + - + - - - -B -B - - - -$B -B -$B + + + +B +B + + + +$B +B +$B Az -A +A - - + + B} -B -P +B +P - - + + - + - + $BC -$B +$B $Bv $BB -$B -[ +$B +[ BB - B -VJPf ~Z ~Z ~ - + B +VJPf ~Z ~Z ~ + T | PDDHDDH -rFF`DDF +rFF`DDF ^ -D +D ^ -rFFZDDF +rFFZDDF B^ -B -$B - +B +$B + AC -AB -
B +AB +
B AT Ai -B +B $A
BZ $A
BG $B
B -$B
B -B -C -C -C -BA -BA +$B
B +B +C +C +C +BA +BA $BY $BI -$B -GCAA -LCC - +$B +GCAA +LCC + - + $BB -$BB$ +$BB$ $A
B -$A
B - -A -$A
B -A -AK -B +$A
B + +A +$A
B +A +AK +B BU -B +B A
AD -A
ABA
-$B -$B +A
ABA
+$B +$B Bf -B -$B - - +B +$B + + AG -A - -$C
B +A + +$C
B $BB $Bk -$B - - - - +$B + + + + $A
B/ -$A
B( +$A
B( AQ -A -$B - -$A
B( - -$A
B< +A +$B + +$A
B( + +$A
B< $D
B -$B
B -$B +$B
B +$B $BH $B $B\ -$B -$B +$B +$B $BK $B $BS -$B +$B $BE $Bd $BQ $B^ $BV -$B +$B $BD $B $BA $BL $Bo $B -$BP +$BP $BL $B $BS $BQ $B -$B +$B $BJ $B $B $Bx $BU $B| -$BH +$BH $BP $Bt $BE $B -$B$T +$B$T $BL $B $B $BK $B $B{ -$BH +$BH $BO $Bn $BE $B -$B~$T +$B~$T $B $Bj $B $Bo $BD $Bu -$B +$B $B $BQ -$B( - B -$BF$ -
BB
+$B( + B +$BF$ +
BB
BC -B, -AMA -$B +B, +AMA +$B Bg -B +B $BE $BI -$B +$B $A
B $A
Bf -$C
B -$A
B -$A
B - +$C
B +$A
B +$A
B + $A
BH -$A
B - - -A +$A
B + + +A A -srq
pon -nml
kji -LKJ
IHG -NML
KJI - +srq
pon +nml
kji +LKJ
IHG +NML
KJI + $BE $B $B -$B +$B $A
BB $A
B` -$F
B - +$F
B + $B -$B - +$B + $B -$B +$B A
AC -A
A -$B +A
A +$B $A
Bf -$A
B - -A -A - -B +$A
B + +A +A + +B $B -$B +$B $B -$B +$B $A
B! -$A
B - -,A
BP$B - -B +$A
B + +,A
BP$B +B BM -B -A -$B - -B +B +A +$B + +B BB -BB +BB AB -AB +AB BB -BB -$B -A - +BB +$B +A + - + Af -A +A BC BL -B +B $BZ -$B -A -$B -$A
B +$B +A +$B + +$A
B - -A - -$A
B -$B -$B - -A + +A + +$A
B +$B +$B + +A C
-
B -BA -BA -C -B -
AW
- -$B +
B +BA +BA +C +B +
AW
+ +$B $A
B -$A
B +$A
B $A
B] -$D
B +$D
B $A
BA -$A
B, -$B +$A
B, +$B - + BZ BG -B +B
BD -
B4 +
B4 $BJ -$B -A +$B +A $BS -$B -$A
B - -$B - B - -$A
B +$B +$A
B + +$B + B + +$A
B $B
Bq -$H
B -B -A - -$A
B$ -A -$A
BL -$B - - +$H
B +B +A + +$A
B$ +A +$A
BL +$B + + AE AP -A -A
B -$A
B +A +A
B +$A
B $A
B -$A
B - -DB +$A
B + +DB - + $B# -$B -AJ -BB - -BB -BB +$B +AJ +BB + +BB +BB A[ -A - +A + $BJ -$B +$B $BJ -$B +$B BT BQ -B - -$B +B + +$B BW Bd - B$ - + B$ + $B] $B -$B +$B AO -A +A Aw Ae -A - -A +A + +A - -A -BB - - + +A +BB + + $BD -$B +$B B] -B -$A
E - B -$B -$A
B -$A
B -$A
B +B +$A
E + B +$B +$A
B +$A
B +$A
B $A
B^ -$A
B -A -BB -A -A -$A
B +$A
B +A +BB +A +A +$A
B $BH -$B +$B AE AD AD -A +A $Bp -$B -B +$B +B - + - -$B -B -B - + +$B +B +B + - -Ai + +Ai BB - B - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + B + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -7 - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +7 + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - -D - - -F - - - - - - - - - - -W - - - - - - - - - - - - - - - - - - -l - - - - - - - - - - - - - -x - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + +F + + + + + +N + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +v + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hdcp_rx22/firmware/esm_config.i b/hdcp_rx22/firmware/esm_config.i index 466cc5b..fcfe773 100644 --- a/hdcp_rx22/firmware/esm_config.i +++ b/hdcp_rx22/firmware/esm_config.i @@ -1 +1 @@ -CWɮ
+CWɮ diff --git a/hdcp_rx22/firmware/firmware.le b/hdcp_rx22/firmware/firmware.le index cd007ef..6875f5a 100644 --- a/hdcp_rx22/firmware/firmware.le +++ b/hdcp_rx22/firmware/firmware.le @@ -1,17 +1,21 @@ -ND QXLnX|?[Ic99k:oׅ[Pb^ -ZHٓ?-]vBtS##P5: Zo<EH;"QZi%<eLOF8rwDu$ίjr.U_Qϱu> -.x,A8M&V-#2am%ʖɳ+v,VL0aCWao/}6蘾͑ʛw2W_!2mn}6 U`'_tأir&<1ahA`.WQIb6 81 +ND QXLnQm|?[Kc99k:oׅ[Pb^ +ZHٓ?-]v~k!0* +0Zo<EH;"QZi%<eLOF8rwDu$ίjr.U_Qϱu> +.x,A8M&V7Vˑ@Q%ʖɳ+v,VL0aCWao/}6蘾͑ʛw2W_!2mn}6 U`'_tأir&<1ahA`.WQIb6 81 ،.\mG -`ƋC.)̗h'f
9!b
_{y<
Vn=L-W}Z$-8VĦ4<C)G5[s$.m=CQfk`lbE!JNUL4Oe!8exJ`Cs(b)ubWH&0dLߺ52ƯIS!ߔ|+̯|MwvPjG)"ugW.4|eԞ]1e̡
=;{9TtN`~DhPt/҆z3#}t4KFWkcko` -$ȿf?G.|Z40 -̀n'WFZ,f:`W)`68zj&2{q -h>OƦ_0Tҏ' -C"YJy:h;Ŗ*H p@'Ȑk\_a.:RVRەLF=r yf%&b>$E{3\ 0~{鑠#ۑeЃ'S[ZAO"wtT݀sA=`*j^ŕҫ[|YݻrjD)4E[M8U?eIXhcgԮ'I4ϭ1/IQ5;} +`ƋC.)̗h'f
9!b
_{y<
Vn=L-W}Z$-8VĦ4<C)G5[s$.m=CQfk`lbE!JNUL4Oe!8exJ`Cs(b)ubWH52ƯIS!ߔ|+̯|!!k.~*ypgW.4|eԞ]1e̡
=;{9TtN`~DhPt/҆z3#}t4KFWkcio` +B(%$ȿf?G.|Z40 +̀n'WFZ-f:`WEg68zI̮yc@ +h>OƦ_0Tҏ' +CYJx:h;Ŗ*ZK uə@\_a.:RVRەLF=r yf%&b>$E{3\ 0~{鑠#ۑeЃ'S[ZAO"wtT݀sA=`*j^ŕҫ[|YݻrjD)4E[M8U?eIXhcgԮ'I4ϭ1/IQ5;} KSa+was2IYY/Twfo' qJ+6"ynh@5]
e+
Ήik5-`$iRU7M/3 Np=7$ׂk{Ⱦ /NZ;P~3q|So8ixRjg+ -:oeQ4+ dAY.ۅ.6uVy) -9Wn&#T3sD(}%5'k^yRȘ*[#2= -e'i@&lo\;㣴;S."t&${s42i TZZX۶ "lrޚC~Ad&ؾ̢$DU%@Q幞(/Z#4>^s3᳇؝JeMͼ}̌!F*6Hl\"uI5e8|Vh&*~|;bp8c㌊x]^Y:#UrZ#x/cMŋe/&yMKǂ+znrʍ2>s'eK +:oeQ4+ dAY.ۅ.6ILaӢm+M8vI31rMH}{\*{a}|W[`=Y .M.4 +2^nOsع(.9h"抄2͚ +FGHCd1e`+eo<lʺň:<ڿphG90<Ȕ#ƙDxr
4DrۀjfUEdT%(?*B9W{ƍg@PoKο|k;.FXH+'/r?0Q&ϋ01|0p@܁Y[u@tĆ0hN:,9O/D֔B Hx;4$]k_` +8Wn&"U}3s@ )}&4&n}_/ꭎ:.Bzth@#nn]?⢴;X+!v%%{u70h
W[[Xְ!+iqM(j!+~]`vٿ˦&E +U$NT溜),Y#4.OU >k[2$K&@QSۺ710zL͵8/+yci92 6B3%4:2~]r3D[*L&qt2k+*[:ʘ\$Z5+Ci#=kzIh-}<PZ&e` +nY#_0l 44Y*+}sș]Z[?44Jd\tEq K?k 4|\/܇F,:V$f).jp`u^NdKE_a#i3bR@˩N'*iyF ?Cҝ0P"-կ& ~3 BD9DS!9 4Cvjv;?eGuڨ}{ɠ?8㈮tdFqGο/J (D\FK@}RHأ_?B/[#K9'oy;"c@?C?YB0 ~݊>Y࠾NoQ)US<%nPYb&Ľ|qy5a/H#EFVyT43cd[%Mκ4ؿ~s$_ʙ[;ujX5V$wW\`%2#zQ:-9fhHO @@ -33,7 +37,22 @@ T{A(1C?dOfObvTp~%®a|ܙ!;KGmh{ ]B6PQ ,iU ѤףD(&kkA1F'4`82y:s Xt#X;p:D-^^LPJ,UFm!N92vɅºb\0ǖ $gPBug@R``d*8t?kͥr_kNR=~ߡ0+un@PM8`>sn0&^t'@ϲ}q(+~*3ӄ Bi\ZP"-9wy6FطeZ)#jܑd9v'i3oa&\Nu_i2u FIw~(4}Xq=wGYw!ҴGj#Hm6,b -^[w)!z3şsk+Db| +^[w)!z3şsk+Db|P5b +pm%V>%#DͫRNj59vieSO;t?gDUi$]!W3X] K)>L[Nr'4k3!GJ+Gn/&8 +6G`/ Q7dz̳J|Nv!gfݙ +:H?> ZYmPcu\b4fkb܄$;y*pyO=-pkDhgfJH'#w蔅5Jp2N} +զK{D'y|$#fH*=L_<aE'r; XüpX#9
@Ա9bZ8(
f`%Rc?fh<Ei;]7O\Y7Zh1YICvy`:?l]m^9VW' +\ڥ8r4;mGa]$;Fpμ{h̑!-Hm?0T< "_Un/Uvd0e?Ө$|fgUnșT{£IfG\U07 +W6>dJzɗWxN|?
|3`nd >TԷOua]Ҟ<KA)C!UUv~:
}`eB2\JN%)V?m>`XmKQ{0 +wųDj,Gzm4We؎)w B| +3-CJ0!~,}l +,va&HAM*jl aؒ
G0Uwp +` zYr8a2y=6Gw ~v +ˀO@V"^GX%ڇKvyE= +b6$t1J=Ag + Gi\+ t/'*ܻO[6禜Gl|WFw<?FetN4+.~(Zӗo{I9Ս1?Y44.*7!>M!/8
E/w$smͨ6AS&xZvAGd'
MK`;Aq7bM//a:8u~rAVV
2hm6
.gsm't^<Ev9[:RVsI*%"\:!AD(t&z:qѻАBξ +I4;g;9SқҫM片Saܙk3 +G^T`U|"?섓!m76!B8rUr-|)ϓU2P(@>|7fyXgۺجOCΦx(.bt.wEzF^iX뮣^4h6=uSջ:Z*>XQ2ZؓR-0gV'\e0{b(F/ UoوBMļ!#?k(@C vS7da3H-Q]ƉkOVYa5.CSv'O=R!c
i n
975biDZ\Q]̔VlvdzufX):\p<RAxgq˫wgm^iLks;zIE3Sk:р3pb4eL `kOڰΧgVy=f[,#mT73nv
Vá=^V;mV)
yWqr;' 2eL"I7doބ3Ԛdwmh*qt?'Nb oVD3 th>X`e8Kwok8qD,+Φ.MaXN6qL/%A4$~&IG0O}Ns
U?OŎO\dv.z˵։3XIXa<Q8oGM#&%؇ʙ5p lB\O,=3<UNgw|/Zሀ0D)rI"(DߟlJ0yu)x88UW͞9 يӈb6_[ܘ$4:*HDf0J/ jEs'\OpȜҥcqڎ=J:;=r7RzIʝ,0sNaaW[_Id N{z9p79
/_MYzyõncRh&<f
uD,oD
%Zwܵq瞀n1d*2%9KYocI6$թfx7n;Wbh16;b9Z0쪀~@#q}*_~g`b uݘרIĝSJt}xn}-ab s!Ǧ,'2rś@"̰sӒW ðO_䙙}{h9;%H:ſrdIgH"=ۄxحRLq#X@.M
+_g8}_6z{-yԎ @@ -66,399 +85,426 @@ eVu@AoOt7z5"\ԙDȱyL+C{YR& !.)4y =/SU䈌EV{z:XvkVҊI p Q&v" A
B)䶊g̅:G=p&D,I@.!G9Tr8c]-ƿQ,Y\'ZBOݭf} -M-BI.Ncd!*F*x -nb^QM4G:̏ -=|U8pkCC
-JѨ@#ڒ4%ǓI` +:Xl9Q-O.]aUbF?<=Flb7,lZmm=QU@[;!BV -=DXC8
OJ`eۋW~'\{+9mg1jvCEZn -;mHFQJbIΆep{@S"PPW;y/m'+r)Q;kSX5)Dن*5?ZPLR1i]ZmE>kCaA#cśt@xQD5ŞB,bmXҸgR kHb4b -ܫbլtbU$~ -'&wp`f[?
:#zOi8-4V -wov;B6ٝ$ps/jwGPބgL𱫦I:n!3C)d0o#pϢV
V="I4)ZZ -^nS~9zM}Mh`ZgZ`>#w_Xcto\-3G5'QRHd
4
O#ZAKrmEF0gR<\jӉ -?Ob)RV?Sk.9NlC.`\q[LUY=&S: -ߐu_z'.Q1h=4^XQ&yzF&hL)t{8:'RCv2GsjP!\P-"ƅA =>߃w|e/v"ŪL|n4"aLfMrf9ȿ9P>w2mPQuKv#%ܗߺ3re29nrPz{|l)\EK`Ya5=~dmDSWEe&}~fC¢ey -twBĻ -Jʛ iU^Քw5 -F'0
Wg¼]Pyrncm<Rވ*!dFp%
pC40j;'P>}j-~TG*wfˤÖ>HcQ$sU`Ȇh}I -zdhX>62bg8^͊A,8IӼ!vL-L!1=46۸꺗BUVͶؗi<[_q/MϷ"iUf_7!"wHS6μ^"nU*&v7qg|4Yp$HåȖ "Zyi²gr~t$S,diJUJDknN(킙B$iCpv^_/D~M3 -˷% -^_O>:7X2vAA -~,DJc_q*f -ymN,a>FChǤA</G%XpٟY=:25$Tܳ3')28DpsiX -3Xy9cޔמ% -)ABьjnڧ+f;_Oշ__[,Oaqք>arnЋ}"emxDa!
v;(5GCPⶨ\KU;Y -![n@WM-kɱ%=,54;e3x6(|W:$p3
hrb|PI؋M4*#cU6^M^j9u|:B=L2ҷlI!/0ȳ- %Br<^(#.#v7w69«\-ȓl w% /@K]t9)>\G -Ѵ9Ae@xZhH -ȸЛ2 p -. v8*PVdB|N`Jæ`>}Ȗ
`M$\v>OYfpU$ҏ
YI1=(j".( -- ׇH`"G45:CuzdUH~$@-H~cu`yPGҜ~Tϔ_ɮvD1ȝx6{2++%^&Ӵ<N -EL,2+6HGk$GC9lٝɅ=$:*H|:'D*.l^h=W,@R9 -ľa6jݑms笗EKgV5rMLPkQx;o!)54AߓvkHzmqN>̩~eߞ -U͠}*
gP}Vh՟v~]bA7?m;^4Q&CHZ,/$D -WG[ -g"Er]4Mtq~*˟ԙų#=f;だ\QynX|R}z&63sLn/Is(ji2wzkkI3S$4!VUzj^C]2@$H0!?>4Wyj!m<^Ac|F0|n@H^k~b<$0qBP*z0³vY<o梧0@3`C+5xAԢxdTQ3MFKZ"C -OYe~cAIXeb7}#u>p@x -<Q O{^wU $L莏O jQ9o1.ɽ+ 9q+fLj8 )S -\hJEȳ|*JO(}4Z&E1$Oo:NVITsX -oA7A<iNS[+ưfm"L5>p -"GqoMoch#{Gؑ5UUԎ?)!EȜQzCՍ>T,ᚳcb' ܣ-!BC@T7,~
ap9smYIw8й -j첳}#*Ҫ=I1PlfRvNY (܇}혽Xv%ڕb{2ve1xK3Yw}op_:=R+uB -?V06Sqa[܂ FQ3KH%њ$c+QZ24#/)Ej]k)VdG|.ɶ:iL<MyOȌ} ;<&F:Er!T Sc;X"( u-T8ڣp<ZƟn!\yÎ61N"~FSRHY$)l]csiwB.mKbn@+Ku+uw82FʊRJuk/UۿUtҵHEx̴cX/g${0D{NIv'8M-$tN?O8>tbh>*O'WMmbXN{7ZRE\onGB^bĜ^[%UfYL3HX[pMd
8:_2R5VUY2+e
8!}1hphIezS-XtieOwK?>H6.索$C|V@Z9ґX1r3 jɥd{3x^ -R+rp -kw&WYU;fLoNFPl0v1T*J$
Șa31@1:? -ž}K*M-T\KgL{NˇCe|g3cLWӂ#<8[* -vSF/#שQETn?}ڐ -/Kf0jmCF72EȨän?mCSXu9coHP^Z$17 ~{5<bsbocFڼVtuCP64=bȻX4^S>c.[} -!y^[P&5vG^G섔yݾm+k<C|{9
\#P#bC:u~M]+-\(VhO[,*R)5e -HM/bZתHҭyF>~݅B٨oD+Up٫IƱMhR댱`6{J|RҎAEiV6xH5E45t(~*jAQAWԟkCNi~ɇ!LɑbXûGSKtmr -(iVxAcxlg`}{1/h#0tJ9n{
|G"͇﵉
~X
[['6 -[_(៑VGCM^ꞬpyFc7?$&H-#Z[Wc&+8*bDZ8ndLW(N !)\`ƅQE94MAMY -'F -e2hkfd!f^T393KW%=+pk(Heuu5Ut|1dF_~wUAW[RP>I\ -iϯ8KoɄUB2WT%N}ꯐp|2!ZlFyqBk
R%'#9 -ɤ(˖`Cs8 -&i6PFeF[}r -yIfཉ -W09K3hYRKbWKwC8.f{R?mJK -#1Y$5䠢Wi:cT@f|@@]|U䞵|I9a<'f7:Y -2sU@):9& R -&x{3>Th0/(hbHfVJ m)Oj9P*]O4K@0:+Vhh6>1
b^ZPkC'SKlm Tz_bp >pޜ*簖sqX,,*
F{Pښoyr4|}mG8H5Iyں ڏ'RGU&ށ$n
0=KxN?Ox˽(sx&l8Ͼ!zxb0Wk#?*ה_5T_fp~3I.vyB*a/^*Wn[j#Dĭ -kQ.E&=,aƥ
.tb`1zA}OLޅLݭ%O1S%-):#给5P`U2(+Qdla7qCv`H4UL0ͣr787h/=.+e
H2D<ϡ\N#ab$Jzd[^'\{sU^'!ԶmBܡ@ HݎIPi(e:i LQJD>_c(yB<jI@ i$>Suh -_@b(6:U_07yu#_fA([Y`dNri~28Y5\of+҈=~Wh[6}`] -io٤k[nTِ=HcuZͅhF D}GlFބo؞+^|{`Xa-2dZ9.{k5Év]M4Y6,-(qwlwtȐ,,-MCͫ0jLmVkF/O4V%؆祙K -z9'2$:u@_Rt)wM'憫AV7
Y'̠rH! N%!\Cm"ÆLh) -GdO+*jA(&LfW7$S^bUG9HQoj\R u=-Z3Sp -8dc#+B:C9{x~5[RHlf"䬁_@sFNv4C-Anwx_:ԃEh}7ry<ƶdf8_G>/S/a?vZ܂");^Mܸ׆C7AVK@ȃ]j
)T?K5^Ȃ(HɓRxR_nXoJ^K&ctbI#PªgBj1EL|4jԓrux
fo*Ǫ6f%ӌ91+rP6ob -ыjUs.2Bnס$kS&g}!gjǸǿ%RJ':];K>8kM3˄F_C@a N,>% L]T{դ:ܪ"Ki`/JPffknxd,(ÊHzZ`b:F
$oYGbH*evecglk -*<NjY`Uw[3 -:OM3f*U7#UvOSګ& -{*Y\W+'Nb4iMJ4?(Ϊ'<\wD$d,ۄ|povՊzS^^Qڪ.d1 fC;,<|3VS3O6rxshQ]I役w'ξ0-@;z+UAԎ -XQ2frdJDK/ ďG~fPY?.eQP :uȒ`eB` -;)l-H -/Ai@RS;5PNrI?09IfiM|a}Ckcެ:J -jbᆬ= -70 -ȡs<r=SEcKU/v -SOcڗ.;IU. -XaHJȚ+bتD<Zl$gn
t<oLTxÂWçN}u/?)J!<P|gPՂ;N_l0k^M;C˸"wbn-r[>i :)'d&bE@8MY:h_TDQ-b3ɖg8ɎDYPAHDD4L,tW#8(|rӭ?+u7P`27h&
-n#)V&ZVk9j7r;0{&[ãݧDS:iw3P79F36߫6ռ -lNװʭ]"U~S: -4ȴlK,Ѳz -`+[3`o"3XWHC=qvVd7Pz`7˱qOGkO0P۬#۵]. %Kri,yE&K -ҵi00f]ف}fsn3<%zjs<8VS V/4!5g"id[UOzTr{j@.d!lWYα̶[?WJ{*ÝN6<@H$r۹<βVk'{|@?7?;w@%T
a/~]gCu72,u[w=G~t̺ѱL'?+|1 -Ra -&*|
,`JO-d"Vu"IR@IR8|BtL&.^gblyqcl\Ubn5!kݗ H`&0PoI.q5M&;~qT5Rp[s<P"6٬VćDҬ&>Pabj*&T$:H'c/_PQLkj3+(Jeg8!~I*f3~4^nc@ʜ8 ~ Rg), C[%}|q^SDϪ+.zE<)8`xki!UZ #wbH b=?AOMQLMzn{mY6$@Q‗i-m@yбdё%y{GuONЕuuu6(c9M3&gS,M4qP3<UNpUe-Pk]EhaӌzJ .>|85-!+,7Od -Pm$G<]t̩Yr -1r<ﵐ47
Ck[&x`+",}Cu -}42&N 1^HGvhdkac˰ÔcS~47.~}SW?#9R&Fс#m`ﮑ"c56m~=0%Oe0^%W~_0HV7m;T1p"$*7ƨэ$Ѡ>**k~#(آWrŰRI]U<\u<r~Pa[9l
Pyf7'-.ό+3ғ`/{)J>4><ِS'u<n-udy}?f3{J.:|;zZ9$4 -&T?
C@A̍6ca~4uBTw' `Vv_JC$"> -:o`ٴ7+y4/y϶1rUXE/n{]̹_gXR7<^)סE,Yh#0&OvAwy2<>p8D -6*lh1]L-5.<at)f=)dZJb!KM0c!}hM|R|ȳn ~
*3 -DHkRj%fB: W8gE}?Srnjt/;gą3nM,K~eƹCp"3숛@$D[eA:I#ú[>8e =Gv YK*M!V\
JK!A4Urk4 (6.ד0x$`S"ڻaoF%fJ>;up$MK~UF?@lۊ"Xarc^qPM_f$L7%M9ZU1UbtT܀fp\(RɂlIb%ܕ3(`.o^7ܔרeVd
$I6vy|۽{L|}rhcܠ,>
_h]kwF{=L$Rio4ޗMh -r*qV60l+Yn79q:ӫ\&xak-}9拾".ܞ"qPME,72?:-o!|+aY;d #W.#H?F.PD6kB qjZ%.G-mDzgEhI,hU"E=VY-ϔ}}nߍ0w -n|E$t^ڴwxCHulj`М_`nRhiI9T̶q/a4)?9no,
Wf0ѿkW+ -/FqQ<uGҒ{C; -!'`lAarz|]D9hi|)B R3#}AL4ˏ*2'x3呖ܴ,۵}I5 -2.Efjpt -aeK<f)\.m4GK\":U1\Ne7dKK\%j]kTAdsZbbj KaF .*<j~RaM0hP7= `OlhR;tYEXB8ȇlC:KOF=0d
\1+UvIQhh6HzVҺ`X9@u^aG|g(Gưa;Tdh&;ӻ{)P[# - -gWW5)$T?ʢwC ked%݉ۗWPѸȰCStK -K7igѱ6EGRX1K0/JXXҚOY-`m}_K*GR|&ԡ38^AـjR'۽yyBiW`[&h,p?<yW"zILa),{;̢]ou孱!TS -Ъ -(rjzH WaummܗX'D6xג\ڹo%2bN~ +f*js00.5*$]</uH9EV
[$qmZnm;vCt\x駒JC -;U4.]PXj+'FWήa%<!ӒATmiR\5@K}aM`:{شGrҦvhK^rt -ߺ%`ڞG: x.~)&-5+`qKRLք
;z[&67G>lyE;-ڈ~Z|(x'zi"
N,ErZw{+l6@>J<I>
[)n*XkWAi#Bi=8 -(/^=EyYC!TejQ{SBȟ+P9 -K*C-9% #VFbJ:+@<9H,ҷMDŽ<(Y?DXU?;UW!hCY8PKQ3g9
(li8bm?B -ygX~3CW|Cl+!此*),"_hم0!qL5e
J?N|%@v(pѠ_Ib[,J8[b|<\Cu9$=OY7ĪW=<HEiDڡgaq MwLW=URV^. -%Xs*SuRv!D%|@`74m:&9h(kJ^c%xqˁJK5=ԺJ mv۱y,[f^^t&射S9¨H^\U.rxxx_bZJA;
[dsC -E -Ci~dfQ3zznB:9YթCdڈR+Z -H!ilvL{-$ӊ`(TwHP (U}[MS.Z8 HLCZ$I0N2ح~'.u?TK.ਪ]l13خ$CW" M_ʕ3FQ驐M!Zw&4$WlWxy
_>Ldk"e -L5lI>X=ga#26uCQV]t${@uh3v;Su -A폘xZ0PO{3B@kqhituhL_\V\ZHuݟPG6X.R9<$B`W:1:`t+'
q"(ȓ>5 -AJ_ǀ$8do?Ü8Ԉ5:=#@2>x_mrFOdkbTO}D_ՂPJo| -1p6 -
-\H/\}trta)/ H*+&Rߝ[VjU|}5)K3ocM=sIU4|gIH0Ϩ -5X.)WRt#d\!!O+1N~s\r6hbe-Cg -*XxZU_B"Nt{NC|Sfw=&!]&vE94C k|^}IiH3@]qcfEVTM(^{ܐK`'GCYo_WMnSY58h,v$uS)gaMn1bQ%oso^&"L\D4o^lX]`$[$H#7L_mK~zZܞLwXw99➱ަ'+$I4*+z,xJ~ҦB n|@ꟊ?Zxo3a,5P.VDX%)ZȪM$9S1ϟ}]//><F7<$ -?5?'\x;
ѡX-J{zʺGL[?eY+rzEuR$j --C>%Hc^T˞oJmv2z[SL׳k~X-e}uZ!,aT$t378$iDI4UR(UOuܨ{7]T"&; U59+"}oEP45m֚bfLQ!N'VVqRq-jσئX˻z!Zq iEK`%ո`f
dçM\f)銌.{(SMDwpݥw:iG^M5n`ġZ]094S&`BFzkT -s/PL~˽-Lz@i嘾m%( m+#z
KLm -wջX".)vt[}~19 A 9bJc@CcSo4 D]rkr -F'Է3-yx5:0JGbpZ?F6v9boq4«֩8
WkfJ.WAN3yBPLn6p |ʯw?(|jxgr0Osa -f&TA9fCe$m-y w%2b,OA4' 06siUc\<܂r
AmkWlɉsbk"ט/|cѕiJN1{hάl/hOM;ir-Uˌ,O!C~{q<0z
[8V*#,7D߯A~*LI;.[Cm
&GKbʋhسC)lzG:tLqU7Ȥዑ)Vs=ǁ0
;3`?7$\Q%˓="̭8{#LU;!evxܸ3'WEwUw"N\b~q5[AN{>_7ޓ|Xl֕vOb$уoR -a@KTM&B8<*=b78"'b6?q9JW.RZfpSۡ$OK\ha&RV<Θg|ݭRDJI[`R'}ڊw1KUЂ<ie
t֝C"JO~Pt?秹^Ni;lAϫS*rY -ywn"t}Aٖ1^x\b0vVc^nB;X"(rh gZǦfEfR"Im'm,R,`y7dI6;fw(?:OBF琊IR> s_"-"䃆.El_䭑FTS%cgSvl%%$ -wbFPP-i3A,``fͫks&ՂCM#|V{Uu>x5yq%k@DQ\##W""oSlz֮<['A)E,dyӞN{2ѝgH{Pp4OzؕajmYS@ TnL1=g60t%06.7F0A?0bdlc!WdX}b(Dx,H0?ۑh`/[42j.3❼Qjb(RY"Yx㣜LW(Eb,ȝP"`vqYYn_5pZl_;xF DL[Dam۽|3&r A1·j.xĪJ}>z4{2S -g*9'6ʭXob
-'I5,_lX2u=G| pjVMڨ=phj90G˹|ZY
:\({_ʫ-vN)?F<ʊnV)@H`FqOnZ]r,S4x>CTwdl?H74[`E%-Dy]4%EjqNo qhu/z|qhw)ȳ^іFL -(WHYU05Sb^KЙ.kw:Sg+:6<0ٗaQ_e]/oSy"ZIax8z)W9nȇ8B>m|i<DТ_ØgXߎ|͡:{ʊ;&*893TJ*ԓzor綇.İK~sY%Y/\1uE5XuOXk7@0GBˍxCZ9O/ -:?8r!o#dlɄ7C5xFs C:!2rx-hN`{J[8ţ<jZwVrW'3mfbMN:!.}Skǝ iШt_,OT+0mKd -2<!@%O=UR3
m̅< K|J`PUNh&\$.*~/uӱC#7jLֺ,"{tuTent~_ZW=ۭ|A=/IoebNKii4m1#clJ0CvwSFlm_)_T$u.Tġ -|Ȼ4;+RJ"g"m0!Q#(6Mq=.:X1g&,)`y3ʥw#eq܉b$R]jnj[S~⻲AvpNky< ZE$y=:K-(8P':6KL%8_?B_e顰ypT#,1=~OԭĔacqF1ڞGyO>@0?" -!1Eq)B}(H~\JǷ){(~D*+^Z`gZxLCVR-K\bԌ}DO/pO[kGĞL.
<4 -WM|<GpF_i<s4)I{^
4"]d2}֞@`IV%/3\IM^4_xOnR?&Hzf\uoCe4Zo -K=GVwY{[@}6zgdHқ
H^ՙ͆vK/t`)FQ{Z$ϗQaF{k -CaL -g>H̡ޓH+Ȉt!B8/})Lg>~#>m -Rpr5vј,>#Q?Oe`3t@u]_* }T-=l.eJ5xکl@jn($J -lK| -${m4U`Jb!v0Wlg!1w:5fa>GZHMc3ǟ&}E;P@;iGƄ -i}I Wm.LHد Vиvs?#OX9CGN' cɞdGr[̤!;7ޓSJ|
y_e@~pM_n7dﶁTEIw*23
qE -^Cu
!lw#ݝz/xиdT$P~ޫT֩Ḯ
jv\)!+{"jj ߆Cu\;?[t('~F_v];F'Šbo:3YԃFȄ - -*)XdaP -'n[[xq -h:=չrޝ@sL cMnnjՐ5 -vy1Hȫ`(f?M߯ӀL_.ABSȼP~q8q2>TWRF}Ky&q@*խU-yQjJdH"LL-"!l%>Q`.P @pի
۶k^E8=Z.Ȋ3QO -!sgT,~4+eBC1ϱ%%Jw\lZgfo]ղ"Àoe)Kg諂͵iק4W]%!,&u()]7']zDƣK{bT.%<Ԫ.$>KAv2Gq٬Nh V@!!a[GJN%oqAA$٩ѻ[²'su[YP0=u#[.]8̫_0y?h_`hG9MeS5ZTr&>.ee`jj9
܀bE5jQ\ߊc^^QUϡ &{g&S['_9_vn6/9V^+)z2X*d5PPIymn
T4^/AwdL[7=6 -JVǯT)}NqW=>RcJy='TiҲ@+~zptJ<`g`D3M!@Bt)C?k`03hWӺ4}}X;U?PUpQ.ߴw8JxDC!v'IʵZTI8$24
vD&u#%nG C/,ulemm[$2IÕ螵 -XA-68 ^JgLSK0ޘSψ&`܂{g)FI7bV=tt @SOA&VQfNj?)t&PJo%͋9m1Kk/n]ob|]%{@LBf5m& Be[M%@Hc~\RPK -xRoI$;m"4ZɮcRD3/#IbQ&(OMk65--jz;n,5U % ]TF}+WA~'o@DeL/ヱpF>C[6< %p{E(𡗀@tqqPlęyՒ8
(wa4!
'7S.&Usk9QrTEٽZp\ˬkޅURT' [}&BJG-%6IG}&UWӃ iP/@}<U s -^#^|hbc#T[##mB+Î-Sk/|J(0l&pu^1,`ONkU'v7:SVwБ7x@sBa!`P:8.B[<@IT(ԥ餥;ڮ*^M5`n]ćK㏳2͋:w: GA -u+4P|^qϤ(?K
W|r5rRC4Y9q;=pc6i|֯SQvʬxl&YF9` -Id)8SȺ]jhܾ
!;#->:]ol\cuHWkE'b%]RG$HN;F4
-xv8irf%i~=7*{-RٝL'B<J:?lan]F%!
:EKK5ninLFKt
aN:F{`]}wfU_G
3X0Ƣ*+-U^1:ٟ}FPd pL*6AjrP]""LY+@{?IYa?YHI9 ]}(,4|znWǓa3!IkcMi82Q+kNg\L~TpC>: -16rd˞|mz7ؓ]pwdi]ïLë3MW,7vm"A,v|+p4C9Dũ9_sW1)5mݷFgUq;&dᲷֈB(BnhMuLJϳKr9 Ǖ2)3u{w6}(\oL6Pl?ª)W4Gm=|ߢ=]4Kb_.d({~!FGьTHJ%4`ZlUĨ6 -VLi`<=;t5ͽ"'3:/^_Q&<?P7 kq$$[Fо55XmӁq%=c:uӽ,=Pgmqry?+RP%DO|G=Ğ-}K_3Þa.C2EE^ -l%g[Ih?8˵]CbL0FcgT`Xp1;pgă@vy4%@0N|-/*:TOé=os&A6+"h -BPga]R';uJ֙o -0t"\/ʴ.[dWe{Ȁ&|5"yx_mIN - -q:@ح;sjFlF bZp7MC*
agn%{P6=5j1 -_k"æV W!8ANmӤDW =]]oTzt{FIG_/24r13/<j殜#-_3vm&V`"7CTTx&OԨ,?"*~cr4b'B[xa|JR
98
jG!lx;$M,7]}롵m`vC?XmזN\VT -~ա%|05C:1գc>ѤfތA"+$:entvt7F2E`r|V,JIƪi>2Vihɼ~-[::F'1z[&Gi}c\I|Qd9)+>6k5(}E=d#}zRX~sMv_j˛2#vL#Eeq9|*ov6.|eǗ
|ݵ)աK;_@0gI!m{߿nEHܩ[@Bn~*sdvQG -@bP3ʌ}kd\`iep\^duj{Jmz+lpRSj{ -~#iʘV&81d|=ӷ>`UĎfuqk8UFp(b/=JSrID+
Pڅx#c@Ȁ|=8tGN[~d8XK`kUKKJ$iC>\u$Q!2dM-E\Mhj+Z[hJ;"ZkUw8Glvy^],|;&6GhlU]ȼ3Jj'&[cywC~aMJpK^]vJMDs -QǺCMꬿ19VRɔ-@mw3<GGp)}2l?/Pō -gD_n+BXAK -#߯oFm֛|oj -<m -{p_\jyRvώ H>x+Yƶt(XdO{ERFuFb@Ym,^JA+8DtԪ> -_:Mr\U;Oӊg"gULȳ @Wc$`AݠJoJ涭 Rة9;?ApH@rÓMqX
W2&֬gāKgkZT<폆M\SSkd* -ļ<#/u=jW#KahCgقS.A9ʃgGokZ_)_6nW@>1^(*7Q@CCA3gܒLx -#+5L}8JC_4HBps;T,w1$Ti^;zi:e5FPV7xHSE8ֻ=c6ZIՉ8y-Qлz TGru'hr
%+fNy2-%B{Y}P|:(:L$,f -p2hy`3}Ed&,hJ%<B!B}آm1Ɩ|Aa=P<U=ԂƔgۜ-W"^mi67SȁO i;7w>J>{\aN"Rp]*j+q7VVm.BQW:{8N8]*n*lU*:;!G0FY-Kиs#%}
&?87.]pjlwaEbKQwHbE1Ĵ-`r8ޢ !C
F6GdzO.je2
cis -ۺ|GdcHH'/Wf[yVϷ.k3%WQf7Q.Ip.hN6,ESوnH(QJ~x|P+n%9+bI
;0RX hBFR܇a+;P (ϊcJo;>̡Y<xj< [9=:Nb -o7nzcReΣLqz}X z
)C6ͦM.!3pGI -Dnp%6j1
CےM-X -8?\GB(*J|x-m);4rze1QTg= ':=(ў55!S"{[〨(f}'b=&lO",Źŋk*h^#/hS+~>=Ld-BVQI:'N2!_@nTM2v/j[h̴ϏD'1 9!n6ò,7";qV+eŲkĺ2MRy_R;YU{<]0l5j@EBep"f04TObPnSf`?Ãigly't!+%fL_&0&w;|E"t2%EVA_OJ4s_{1g%݆%¦
j -B^ߛLb@a މpUܚQQ?jNOBpV(Y?(?r>71rD^6z]'[I!&G&rVPlt| -csvEûQxK)G^/hGZr*V 'luA`7JK -Jl$#
1Gmύ]}7@xRRKu>Vk`8<t -QqOhXtk -K"ՊbR?lMa/ϤyWIӬT7P7Ɲd{l˞ -8c,xu#Sq]~.`{i.#YR7xgTԇN=P"Q(u̍(fį04E͵v~YLO|=]2ag'זYOty6F)lv=ù
Vͷk0IAa]FZBZNgL }db4$OH$#Q"h"??R+*2/Y"F4jt<Řިݐ['oR_kҿO
?rýQoZT$a1UOkZ:UO -:øEcCg5qMkl
ǟH>N1/Wׄo*|Xը
_A2<n}
X^
!yum
3INĮ9>Js+
h!NDj{"OµcZK#\6s,4] OP0:'DT
10k"}S\ޢYn7t_2)-SF]wJE?(TG}J'E4%4<|YF̊v4k.GMkDܿc4tSfYL)e[=,vMQzxCLW]oE)zQ!- -N><,٬q9qC/Vo)(^4`6bQ|*ou{8ڽ@05
n< iLv5&kE*(L3U)T0 U2ev|7F. -bfdT%
3z*xa2laLv8[ǕJӳQ -q-ह ->2oZXQ;sS`WuZw5Ml WsHc
q]m7?W+Ty^lviwۄ,'jqm3fE0J{Jz}ʻl!zZ۾*:
p5uP5#W܋g8֥-{)Zis5e -N -Ⱦf ɻp?P89#W?zÝأ]N=Z7A=^lzd'R?S!ئ<SXߒ!~XC -zbјC_y)B6w]}S_h˘˶1A{L}AdfM@7 -J`d#÷ջm"¨B7ebOA|{7`q -d_B|GYe-!G"Kc\ 9`=njٻ!~^+,l<3NPsuNb1rI:g@4aT6~jWtR\±x7+}Svb88qe_Mn19eQ\h^Ⱥ&-vJ1+ڻsaS2> Ȟif`Wuclmy5SP%aasDI9Pl_9&nT`b
<r!ʺ/'kLpvw=RqawN&=c"kB|BzC0=[c`209\l8y$#=<Wvӓۛޚ ӧ?.KM5ptC_WKb1yV]Åz+)`/w~- -Avt/Ui1G`kIg~L!QϸMréb6=uidk<s[6io-6DAFsHzڳ3SǜQ -C6slńФM*i2V793EYOӕ3^vR~QCF-SYB$k۠u%=3p`Vds (BT>Oė|`|m_=? -UeB;8CbHuK'Җ>g35-W^q^)dl1q0bERGnp>|C~]eeƦ.~#<bmi\ -^,HKfBv|sg e2,)g8ÞU_{ -$JCN(v[)K{` -[;B -%Z$ʔo~"Y"h$\C -\jb<KMnm2_S~E:Tډ]B -m1È/Ni HT(w
^|Ke&.R1D@rR?Ƒ@6-XF>{CRַ+>ѵqc j9 o9oV_t -9|/ePAXroxңl_ Ť fG'ֲĵ[ -2{C!~$6O^)!>q1T]=sQ碔/P)7AX};iߑH_nS5"K)xMzW@JR`h9 -+ޚo6vPxeUI"p긙Yģr"+R0 6&w>ѭg/kAֹN^$ -9DJWG}YY($zï -ϿxHn*acUĚ-G^Ů<pBܛ@MޥՂ88eLp%T|}=HF抂0.E{nX -jf};kVJ5ó@QqƎv{{]]!iwaz&0DABcLZ_˗= -e=
fs_L@ClƺIP`
E5йt{ -E »]1faXS)7^Ṣ%Qs"6b;CUހjb00Rȗ{3w61fn܄d[̄QVS,wb&,RRhx$ɬn?rfkjk=)6){zb9LXS5Hy5/H!]l3ǶJ>p\~B` -<<k[eZYE?x{u AC\ϙɅwa@HAǃV^nS.oP3L9wH&sDe͍0Bޜ^y媮*.EV_3a%TL"UDuQk[.6C";B^7%*èƩly73BӴ..cvtI^>̾)Mos<^b
ڰ$l{\;[0^q0cCǡsZ{v ټ"n't?%~w=w,{ -퀾pR9/W~?hE+^@NjJ[]Huv x1#ܵEp@ZUxߠT=;S(1D<['\Y$FBUɟ.(̙{VCu@M*ܔzt'Oq5/PZtC{w60M$9fz>('o -fr}|i9L]zTjru3*_ڒzbX)=90vI -+nc\ȭ6lD\5AfFdJ߆|j^D,'|k*Wi*8Gӌ=G,WSiO^g}&2YWCNO -uS2<D}
B`SU)sYX,/Z\=2]xIU:8L[g*j;?n
!>k5os0|I$ܱ;9PׯqjIspH͐[74!Oj(h__l^!URZ'<N6 -(FD®?+16HC# %mQ}x<h"Ո -eUeϮ=|biY\i_
n؛v0ij+B\;TsG'saƵ}B7_%wЬ}1<w -q)˝?WURژg"K*$t%["T#nXӏ+q50(Y5dž=hN*44p|PZM=XOuLcq&ܡVnD<,D+_!2*5\̄ιԃ8Vu\*wѫ<\[dUPZ3+tr
<%6R7FYR
}tVF4OXo9Tl4L@B"&\/[?_UZ&8@
sE&Sgzؠ$9Bc+)B=\Z^_ -f -C}aqaL;?nQkHٰ8GM,cڋğ=C Ғ7ʯXCSf[i>k;D(^3e+3$MF?2<%6g^_7[tHM{|<Nl7̂RF1d#/s%a9-Cѡ} -h.q e?Qw,e>b@oҴk1ZI.Ň``i,*TQ2jPtFђ6)_Q΄߱U]imI,^i4T&3O9yw@YH.p.u_dh~03Cdb#UP6k8/o.OD,MAI8Ar\&Qe8 -pTb*V{ ZxG2غKඃ.-hI,e -?hmӭu+s*JNn<
$w0ΊK ->tv -3ΛZ{.џ.|G!6P;͎hx!!{F
B<]Ϳ!E,8?R*Nrf)f頵av*:Vі9n4|*N$")2 -y.;\-ԴԡW,uz?^in/dyq(4v81.[=C8VYlkk߄p?)n#+p<&V&Rf5kF?gE_QAac'yW1(=ޓSw->I7m -4X.2k
-Vv? <jg4N@oyI 9Y^z'GR>y.RLf:f!St(̍]
<KVX -j1~ǻ^3$5"PsӇ!Ã*o* yk+6 '
v}d# -NY$tQqţ//'!â%CQep_0~3Y\;/WR&"Fm/U/im73:,7;
Eeד*Am{NM-JCŸ -vZ[ⱕie}1\1Yi-xu-S㡝J~i}#M'{#cuO;M4J\Hߥ>ObQnL=tlޫu0XGlaxLA>G>S5X!MMAO'~@b0?:'R2[U]U2 -eG8O/6&Ak\CnT[&6At -Mv0ȾRɟTT_>ٛC!K5põgxZ8'Q*3U̒qkBsPA P^.V. -G~`8<LBfRir=1p0+ Jl7GC|PյgSQMޅrAoǃbW@y{:ެ4im:ںԝ-u+O <W#GYn54%_ HS\"94IzFtZI+ 캈g]<BƁ}̯rC8hE)$c;/xreNf1N"<YU?Ej,'J0aq`ʊZ9:xG a%;TUk_M(D<#_·Y}2|]{ѹOj&M\7!DQ䈌5]>;1Y汁>DpkƳGi!׳NN -w>tzRjp~^^RKƃѭHd+.S3p&\x䓁|(EQԚ~Lȴ9
qd]FpU=JFL
-8hLPHf -Ύ,Ht[Pzi%+TؒǡS`x}sSz$aUD5ZGZM;)pZ<t˙Sch{+[pb9\7yapy-LuUr -YU]Z -!AٴOlIi6? -ae>tl 70V9ɻYl='Zh6QJ[ZPUѿB^f}j9-fNO<cu̬ -iy{Gf2(E E,4b -;v -chBi?(_hATWj/F!J_Y<>oe=yJTU`b7XW`9534DOn;kɃd ARw+蒖28;:^͍α$kn0:Ams:fi-@iYLYUpYMbUS$MLTX{fqq6YNPBfK$P`"vNBXpXc֖v8I<~0*ȂB }4PD:C}Su8fPNCO-ZOlnWU!l ->ࠎb~b̯~DTdO P_;ױo~ʫ8h5CU {t1ttvxP_H0N\%<EM.T>=;ԁV2ܱE_9!aP'\%w[<uZ/>L@-QKF:/*lfFmĈ+|1 #qw!C$Dtf+>~?t3` .=hg Wj(vދ0bxaMO+
{RK&|7]+.?Ħ?N%fij09sv' [Ç./600g25~бVjjn6p+K*,'Yy(zgBXNe;FW@GE1|LFJ!z#}b:^~dd&5WG?b`
n1ݔSx1hy!ad%֗X-ֹjve} yS$ZRA{LC>OSr!,~RLZ>"Y$ElH(̡ J4C.fU:baD[8 -s"9h -5rŭGXX.:z3>چPm8Ǹ -JB;ywN{
Ag1'[ےB?XR R$\d3*L&GܸC -+y -n)lJZum5ng6_AB{oPBGRx/4U%f|Yq -vw^L',{tƴe Azr!K#ub8+u܋=t(¶jašpmrLn1:F-/S37eVo
T/mC-U29N&ܖAZ3oe<+$\4Ms3W썯~gCjB(
@ vnwzU{P)xE)VͯinD;.\CY\$:8խ}=S>)6i]:ϣ|&
Dz'`u治Odj-gA<aYl<ٌ -fKD3L-*xf]{I2A+8+d4KY#@.W1S@.WTarLա5F)"PЕo
1Iw(k -{k?E"yŅ@r[64i.44DF9\^KR*kTw,:';k!N>XpLrpI|)0a'8uc9Nu/]%GPA,A1QU]1E[u"8}xӫعf -2PM^3kQk3C,dyTEQW=8oCAn:xn3gōeXesu># vI=MhD0^CAvZ;Uʢ^rCgo*q
(_\KRʅ8;q1PmP4ATcy]ZYp֓=H6j"k4`1خݕU*f h65& - c - ~{T>\sIV1lz|O0k[W~ȂҐ>KŠӖ1@F:vex>6W ڣkaLNtw8y'fn6%v_z
Md^_E2@\pOP<t4ʚ"<厯XC.][}
jn\{0,\*ܿ0pFRB@KvI6[Gߚ05v^wL'iSVN-_L~/G˳MҾfk>C`3y*a^x}/]L^ovH9UKz{}W\)A f#Y2I۠a' E_L`)S-j0r -gYXG?ju}
}&WϖpIC:K;=i]O#4x
c -b~d=Qr{lTȉ*]qeoҹUZC},ۛ5ǭ"qŔI2psO͉YG;(IiZa/+̹# v ķ -JZݓTL
7$O,E?]H.qyM&}+1'\0[<C?d(mf% -:td;-uO{Uz4uވ_eVTlҭd^c06PA>+>?* -=|cv\h.G곬,'a$fLaiD2
u<J^§犜o#k7dv:UW#h'+Lb^βw@ҼNΘY@cw('N'XBĒf)hA`( iBwj*
fg\V+UisdUM -:O;ɧUwQL x4vY}-+ PIwѷ<<.sz|sl:rZ - s
B -
ymB{>(~j!')%'ޮ?!->n璨"r{zG,R7
)nRӧ<~,_3ЊJDK*<[`w@4da!V
.LLH.#a -tEkgV$q*ʰgZVLo
7{C#G)b\#G/6uXE'`AeA$k2w |C7l߸vpD1Ъ96\K.#dW]{趇RBZ/{va C從-&?_8(%e
d+_o&p[zVSBgdy3;#nr,ܔv!c36F@sy773Wɤb4wVβẄg,,}5.u NJxΠo T^ǏJ6ŗ$wN
MͥU %wOnnk\4H\"aGQk
9Wv -秆lMWui14 _؏^ *yRI|׳kn~5X7-XNTGqN/l1|ÄjK}/B@"۪ؤקK/پ2 -rfU:Tm e-xqx"eK=L;htn4 e|zGA7
s7Q=Y̜~o.Kٴ9̻du'fg,Wx@)/,ڇ֡D}/N Ʀ -ؙmi -7
rv|Y"Wʏ*\Xd==&[(x$-_K犔LKɥy-[AI)f%v-OOi=,菭b2.gZԳ 3*,Vs!2 CWrB/6CK'>??icZ,TxSL3 nt66 -H._}eUUo-[+%S$pi k=_瑏RU=پm6c^*MA6)$i!NND$Epݮ^%EЛ95{ =2·HN2( јá*LJ0<"|keؿ }wVLakcui2Tߠ !h[A^F(ݝ˸V=6Αrݜ[y{mILʟf\Lx]ԟWt9DZh.10u:µN`tіU4nQBYVo:du=]q#*MC0[gzFPb0I[+XoWg7rU.1u涻T+lag2RooST?#62Q,'4gF=JaX}?TaZHmT!I(AQuyALPT(O0ris 4
\7H} -,o͎~ˋϧyCV3-|4se~kyOԢ^j:Z).Xb
ژjs(ooy=a1p疐~ -*p"{@doR7U8Rp9aB:<OV*Yh$֑ݏem0%{.<6|u?qTF1ߗ[@ -b%w*15_w² -(ӵOo,: -U`O7W0
L c_e7FxxjkUZ˜>Zr;2#<DvLGp>ӴK}31J=IRD;,F1S@}k9&36Ǟ.]x/u;n -wq"uVNo?"&C)+Vj;>@?D*FdbH`H+7#S/Q\ -!dC2
C'UrU*=xv5A˕AܰSĩ2[Llj7̅XH?FC11IV]p1zLX&J~xu߯es0p0ݙ;Y`ʠ;6La؇@[XY9 -m+L
8uDՅ?>@b3'rތ;'S=r -.[ M1bpQEs"Mkهsz9"<U.K>:R8ՑEԓS'4^UKQZ-_}P5#Z<2vP$Is'ۛ4[2"~9BSZlzHÃ㔜v2'oO- -%%vԌxxǂI{_J)v\EOr}n^o3;s}_Qu(=G}Sx|, -1=ب?rg (.>(6-z WTUCtǦEF -[A~<DG$SPu/gTYh)|DoĮcY}1f*a3:BF[yv!?i٥8fMnsQ,;I | gRx0ۿ0L8fHYPW>-<J쒧L9/ݕN#ଙ>rDg/^xW9BS@JΣlYM%=-#-Q5S%N^y -ɢ|=y$~$-LM;2 -o{A#a=Z^>j*5YJK6'PBES^f;R" -ZlN6 -:mK~
R+wz%pLSr`ɺ=ΆYFh8HA.h+iDvrEќ&y0U^olj:m;B/|?HNT"z7^fȞXWBW`%\r$s -ܢqF^sYwj$y.#[gl,@Pz֎Bxҭo!y,j~bNQmη. <r])zJ=^B\iBi3ͯu
A쿿Mj5pvG%k90 `IM}lԥ
p"><d"L10Vu1lo
-#)e)x~F+3|!&?;(=0&h>T4t>' -|dTD$JpAh?ȶ0RBЖ̀<F 0f\U$[a7q# E"0+Y|}FQǏ!mq9b&!LŖxB6ũs6s9xvjKqg^,z&:Q/:%ؠQ,r&H!e.k;w&\Ht?`2B -B3?^`tLSc]n2ǰ
VB?,]_ -壮g48dk#[0"Ve --l}^B'0e~ys>JfR"fF/j7QOm`6@Ỳ8yV3dy}%6Mtu@З-jP(} -Q D.sYv}/UMb1#kj')zS+7ϋ0$6z^7.g·B櫆Q/p dq߈{:ՙu -gi[2b[=`}v?T3rN؆uz=`r2]>IS3_n[Ed;3qy;BÖ, 3ڐ&f[IJE~g\vI5P
̵?vUc~5[,B -]lƮ,H$WW7īw۰! nGjдlDaE1h`xɺKM$T `CwgMߢ -'qnH<lC!_HҔL5u5!/G<>=a5I{li -QMaI?ϭȎ5v/ -z ̝b֮q{}*3k|a.Q fP344$KeTEfji'YQ} : TDžgEnɌSA;"x1\6B2 -b(S\Z:UQ]?G9r~!F_@C,'̽qmS3CwGFXA*.Ysש$98wyQ5LiڱϢ}eot$xtb6"5)\dp˞t(. -va'H(np>Z9e[0ZQSٍcZwsCA
&'`\<e=qRɇi&DžMr]j@V8Pi#`u_y^A8roxq.ig!Y+R N6oધy+j^ -9FSb+`xǽ -0PS^U' -?L㑍Sڑ`M/ HW#OT15vf7r臣E:(bw K?92ȸRY=}tjo$DMFS/P/ -x5$ doP afC -Ё,eK.{oƳ*9./̧nVbr(uc - c8hXR&ecꮮ\!a5mk.Hz?Q"P!?#BZb?{2m&Qk-2[3 Rb Y_%U:تtu1c߄˼feopEtE&U^w"YDK&ʚ75I-Ws%U -CeU4
*k3h{eZ;MC)6"L?I :P,"~.F:
W)>jRo;D -Uh{bmo|dV:z'3y:Qާ$QF{i=.40n+ezmw=y:o7|
NՌS/V>9ncB] i$@)\AQ<RG}`30%EgFDʀBT`ߜBVSTCnfW}T@4&Sպβ7(M٩N &u_8X_, ,.SصmeG6?SўRyȲ#u=h9V}?'a)"ւu/O&)Z+/9Qڧ!g鼒i}
1bb Ec>__AX ~JdK27^G4!=DvRRw]^Kos*{SEuҹDhWȍ)G8x5N\%oCi:UB.gosH<JR6Ö*fik=O`Y^һ1ssÑi+ -9Qk6C-9 R}bVq仙"=2/^shwǎEc?Ĥ""5"tJ[WɸWqM=Q)F;e ixge·cA+>ISF^5moցgCk
VU%P!B4EfIy?R9j&tYh;o&p=' -k*W&>"x -#|&mVg6``3ǾVF^<(){887N4Nٟ4}{LfvyMm -ǥݠ͆Uf[E&yZfM$nHiU[XQnk}BtԻxd i0Nt -|]ꞠS~4N>m{NЙX^5~NNL gť[T(=1jA\֪Jl`&{*ڎdB7uL/˜v2YszlU<5rH5.G*r8ԯJ~=:XDˊ}&YYlRҬ;ӱ[K7R&xƙW˜YA4F\[/FVG&{զɆT6#q?B5P.Xuc-l2J<~ri|FZrbq<*q4|;;s`5oo8 -C~eZa**uGsF cc7v~i&wE`D%Id'aBЊEQ~;>Kwca|3ux9lk\i`[0q -O!5
PtՕѶW(1
ّ#¥e?<JeK"zh ́YQ_DrϬ6~ʟj]Ywr j(rJ'++L|u3Vn9trv̲֢I+ -B S[b-W}f^AhewXsY=\/`]bƪ2dsC'$I#=)ft_w[嵝j/@]L#"Zui-*&SЎѐ9*pNn6skZ7жAlC1bSXHMm=pHtulUh}',ڛ yճPju\q1)t",|uUN jZpt Jgr˝J噅@V'wx,S"ϟ=2%vjN-NHf/?BlLԚ0p^@>BF*$fy{ -}@؋ԓ7Ê>OR.dѤJ^7롕Ly`1_t$3GzX.So*!X߃~Xv|Y702(|E-BP,1'UV>1ЪuZmv3Cީ'Y%)o'EpqS_u?z_K>PCL&-"x\3CVuq"8Ud2 -_3 2ﱵ(aoMPxso_Z@͔ư͐"&}#Q|QCR>YgluD֣,ʍr<rDVbS<x}ۤ)Ǫqh'NLN@8]#!e[} -0H>K-vyݐf9h#jwzR֖xr'Z(y SͲ>U_FkB(C6d@y@4"..mN֎A_ɦe:p% 'N˿ٷCPIdt>HM-*sCv&ETƽpK^u-q~ě=foyUUkzPt9ME[-?oM
/BiFH(a&k6Ag?VԘw[kOxPv_:I>~yƲlc#jpͷsHM-
$GB3ÝE9wxהۯ_>AM)oef~Q +OTWv[`ppX낂7n!5M ͻ^PIXg9
k - -˫Mgq6SBS^ta~u3-Sh, -Hr1#өJpdY6qUD5Xppw[Vk{14Uj|@>_~5%m( -pJn`3n6|;: ]b@J"xyZ2;s-Re%+Ղ2x>H}
N=} -{bcp5rVoM#'7-_<LV<,yY'tv0.T"<pF$g [^t?Sc ^tOa<́,.Dǵ[ QUiMXH~n^Ky˾,WJܬ7Dm_Fe(f@-vxbW?>O)# -]UKP+>I=zMd\fV'm6KRu]ј *Hwsj$cPz-T)bXyx-uY^tY?FLmK9/OJ6^=`z=GWО/IwbljZeDL7 Y]v=d2?J*η#" ~` -
?8d>y/ە]]} -0(zyzd*Qʍ.X*$tү]#nbNdb2s_\x=+t -e?#±!3,ӬXwN0B1H0yę46*\9\ST t~±
ϐ3}юTRIGEx;tbkE~wh5x2Stp|jK7^䍩z䈴B?3c9k[0 ϶drRU}&
{^+ΫZӪGbz/h^sGIJt -[W4ٸ@aԁ% A k,䷪W~سD_CC}ڛF1A2YNKuW=2Ezg'塴mNQ#M#~Xq6Hzܒ+//Pn-rU0À-mTW}5ʂI81e_-rN~Å1;I9)7\E/rCSj.'G])JkM}=\zC̕$uoG{*I"t`╥4jg2E_LQFI4f"fr.:YQ
6梈L۳Ϳ'~!㇃d#My"xq[Mi~)?DUxлْt -~?T6st}ej`~Vi@D,| - (߾#&ͮ^
*iYW&R7YBZDP$ !4˄ˍG9b qW>> -HղmW -mh6lUsX(}`㏓OM29.2VU?ƫ;ggcrUƺǬ5Mg1~mz?6$<(*x.d_לw<] x#/ÅR{ދ<^\KajQһUq/0.r*t2[%#RhOlޱU2R$ζ#`ↂ"(XT]&sÉCEnSw4
)c)F5ڎ0"7Na7E]^9!0&7wB!~qw}ɇO_^yl̿osKr1Q)0>MtfC5X4Mc8B2 -@-|H m^JTcjD8OXwDm*Eq~T=_8RV⚗<@KIލqnOwD[:jxqK&0ydEXy[XG|"ߏ#c>B??uIav3O;[)^+=F<5wXīٍN}d<X\).h$c3Fc2΅Ņv+U2a -0R-H}4UjB]]+^VR-;fQ v
-h91,e$q1,~xo\SLo -[\cq\ڡzubDGp -GOEa9s֤uwm=Elx7t<ZoސfٽXJ=иn唽5o˝XrJAm6uW!紲x<(>f<C@\q;"V,l6LMujir|?cYBG-}'~X)/**]J9kqhg%68R/m|.$oK -*$r%ֺ?ls" -n)G|8jn߫xv - }k`'^A
.Wځ)l9`2GmQ2}j_Ȏ>5vb[4ۄZWڠ*!T4'`R-y6-EucX(r0hf <[_wkktj.!&5wZ -jsk7I[xҔ{* f6.[Iu+\.q4^*<j˛4]EU 4P'Iu/+*%qy_JvmBr-hgPԾR1jնQܗt"龜5kƷ`YHUﷂE{!>_[+l
|LfMudi ,cCps{`3Ә!a]^IpswdL_8, -ߺ?X@ и:p+dtG!}oѤڀoO{3iǜ +L{n/ۡk-ǢBUq-I(Oa2γYBNTLSdE98dY n74@Eeݷx -TrT<& J=n)ٱ"lLPtI+)ds!1% (B~ -VK4Q1,aqT3Ӣ1_\ћ|GNڐwa#=ls^z4b@ꞙ8*|$ݸheIЃzd]W;5dY2ۃM?` 6Жڂ'yxtHH,U7gbLTpUMlj|l)چr]~*635E\z0W;U),jL:{ / -CTڻo.T)}ܚ[yG!Zo<U`END6[m,ANp -66zV --cйК[V])P/mMFj{i7 5H]6}:fHޯ0 -a%/%(_Qe#Icp
-\oj$G 7G
/rnI;֙$6&#S>dw|.s2y|3rGy+>^iM^m*&΅_*0ؿvG?u'%djuXq1h!?gWpS{<I=8h<q^X%/~Ґ$f2#浻X]4zɇq/ѓ{G-jalL>\-ӊҊ2^fӟ٧b(T?TӮ$q8 Fg{18
3ޕڷØ8g%H+5y8p(QKzX'4G0#e[+AzGF?JB+l]"|"ѧo(3+n6Dfznh0>[r'% $8WKҬ'pQ+˔+nĤð~I(QMeae3(*#;Zn%|$<3ŠITfE_g\J\2˯sZcaY yME!d'[4]w_<":Q[tWϤv&?)lkյMW~FJNᄞݔ$fly`s5>yל1\i+kғ@]LT䡽{^RPJ϶ -|.Kby3M;N -n|Fzϲӄm%I:$!?s#JFR<~(` -$u%r6ȹl5^@ݮjt`P5*-ZPӂ -nNu&5_ 3sNFM٥vIzL؆&0)m6n_5qqSiN7NP_u
3I4\J@PjTV@87/j\X0a,QAVb(L!90;f2C/&7>otMFbC*,|UO$f_=ȸd6S?,B:HiwЬ8ba5yUpվ6p]1B%`wLk? ^S8܆Ksa$ºR̴Hazat"74ժv`a,5uCP|!m5%H6J|$|9\N"=X"%+D\,GUZk$x#@o^bY?/vo,ECQ -wp(ݬ"%ϋ7ʗ7(;r+QTuq"Y7UZپf!fz[!Zt8&@jy(l8O?li?_ey!iGD4dS&$ŲNn~5cR{?fZ5m;MDŽ -DbuL5GP}*EXo -B7Vx3BK%g#5Mq$ޅ=.sƬ̱N%mhL-W肺!ÓE+Fv;Ożi -Y>p@"UOoO?T0iMt I|Sp4eSBu
MEr9@Hd9!ܭFN} -Sn~H=ྫ.nl}\ƚå'|\vW铆V2f -Sws2H]ꀒFγ~!XD&dtLtvdǤ\ -NV -oؖ -F+ - -u~2s3Us: -`(@iVU{ϲgHޤn6sMl|0EԕJ7k>I+[2S+ǽ -iQh݅lFOl#㙇p1ͦb~P<秉b\qz]nLMSkRӾAm]sm؟]>~9ty.|Tɸ -K3VHD"͙}Dr
;eʨh 0>;ZT3~(.q#~
E@狛h7fhQ@#O0B~c0N)d 45XIͧ7ݘZc{CtGHFy, en^rw! n"id#38kaƮO}N+2+ -EK<%a߇ZO@UϑQIz||zZ( ~߭0\qr -E -!A)t|E>jAjD%0:5gV ̮`.}z9ٺ*dED3okEnOF#sw ڰtWv3LB@8`^a`PɂCj{Mh<OOhntY=ku)87綬&j
^H3O3
g}O\J:.VӝiME -b"ғ]ˏFCr,L!#XF@+۫c&Ae_U.0BSW]J8x{ѲIw'Gi -vn3.{T-mlG&8A?HI?`נtmq{k8)N"<pjcc(Q`] Jk2{oyp[hQN$^+2R=](#G -h`|[RFPFo!sd#'"<V17a#j79I ]RI -ˬ4a97xOӒV$eB9{esrvԎ[& -ΝHLA\dT%*O(L}Gh[mTP5g2öL*(9.͎g2=(s@wKgr5ylqwb4'MNQEq4ʴL@.]u[٘q<wʨZc)GR!l)j;(& -: -%KݴJ`&t!* -
ק??e3^) -Az -Y9`?O[ɩ2g=̚#~c$Q?{'lkLSN?CIE +,#q%1zv.z80 Τ6` ̲\Y6*=
P zX/sԋ);MRt`0A~RӲhm6') _R}?ty&fP7pFաۃ,2XUX7":곷Bj|i1ʐ0,'- -Gx)ߩ=L3bҲW:
tVg$/RIW 7o!ʋ/?2 čMn`tOG^x.zcϣ ̃ :_md|Է=k}ߙG M6l^pCGb'{KOIa%V檐~Va+ 1JQ+ԵoRE}%LcѼAm~s7{k$)Az,B'KC -Q$~<ui/( -pM3:tؙԢ2h-MUԈ
5me1O7
RRsv筟踊ʆjuب#'tĀ<N<e5k̙fknL -- -_uUM. h).W -: -< -]hyeo<F+\"-#njġhV* -tj^ҭa6 &;V\зw*Ȋss慁ѝRjU@!GX %r3H&zA5nJ\a=CRV -̓]Ɛbg"HV ʈ(Gl<4Ϛ,=`(̣֨M-Iev4y]67F|Đ0AiQבVe{^XĚ!۳iPo4ês+[\+ z
-j`ʀ#>b[XX.Iol]dJOfj%u~gON+in4¿t2]ǢmTXgB-o68 - ȇl-atgSl
*wannŋ6Pf4cU8k3R -wJDL>Sʟ-KBH3LkJ(NBjyj$C? -zY1BV]r/* 2MPqAF<RhAᩎ{%A*!7ůmy>VN5V5{R5^!AB2iL=i{IFtW^h͏Y"2΅a,
KfI(kp 3(Pja^xX466M{eֶ-p~l]c7ZHgXsK6J%Ho ^"8-Iā|WL -cIS-5w|ϴݚr~&tPkEfW> -*:"Yxm0[7Xdb
-]N4-Y><X."B|Fv2s7Ԅ<^(ӐL̼p%J -gOUc8s2}TݑOh|+ӘiQ>W9CU%U4%¡xOs5TUe\hoI߱Ky5SV-4ΰn`!1X<I<Lj1++r= -m0m5bELqƇiW!s0`V
8Ԥ}78W%4',ڢ#2uz;rɗdr~K-Յ_;ǯU?i~JGKa&)H&=H76|cbSY|AWpHָWnBGDpG|;!+2/Q$sm[pr\q}m(@e7&<yy' -_7,H{<pia}.=ހ3XC&`R>3kϼO.c~$`<ϋ8ώZPvU\ -esQJ>EUB.[XPn|/@ <?l Qү2 8L7:;S\@O9P_Z$X!PzE>x,P!T#-ص2:ieN9"G.# --ju9Ǻf
gwcL-LT|s
VUGxXDK %;a0>:Sl6zLs6\kH^@jk
~;>$l}&e
dM:&Hf%)dt.hS9iruybR6<0J*b@UEJn6u <f¥(vԐ~I6Xk'㩕&?e=Xz7حYJ::'t[[܋Y'eѧر
]8HVO_T9qqA*U&4eseʨ;}*`!O~%~geFȷBgf)%H^L<:&r(3H?0W cu벭@ -*/o/3cxMdYIܲ^-bO~ӑ_,$tQ. +M-BI.Ncd!*F*x +BNvg/5-Щ/>ОΣM}bȧaz& +IoXk{P50X d +tNr;Z%
>; +Ů:<嗂o?dk-\'zmK3^
55@N累QgO7$̦>B}ٖip +DXAQJA.>̓}q`KGHUj2${du}T2b@/8Ҝ*ŊmQ> Vb97g:e/~Ǭ@>.;)Y[9=bR#N%3l4n̦cxi&4ptE&qC@6VEX|ćj
36[[sq:|[93E~ +1nŷ(ml@Ճq{
N(?]m5n.ώ^u0cn$ +1ES6ty|[lӳ:p:Lkn-ĨsXY!p +V2<*¨ʿǶk@{/)Aka73Sr`1/RM'v+c cb>T^.5싻{HUusRޕ4kwZ +'RJ[Rz +7M_Kffχ +R:wH\Qra7J'N{A-Ja-#O{㠶c#(QK`72j:w1E1%P21xv`q93A`'cLeaw@rLm\~}u +((^qԙ= tL&pHv$2RQ'K7GdyUcWLJ@L0};Q<O[lg '/Rzq>X
<}FonswӋƯA%YMh bɔTY04;+W!xҙc CGC,)3%0hgurrk\Ox0nSr43is* +2w/. +RuVk%yB%ݯ.}%T}1t6䆒e/0Y#S( ֤0(-5"jQ'a3/EQpc@fl] Dٵ]2
` +ɟ$v=:Fab4R}JvPP|~>In]X(uDQ]ɬÖa$v
ԗΟD,8s|i4cXAD2չ1b /EaSfaLS4N
_t1"X~]`C {x]?:,U +/W>d
#6^rbрP4ظ_|dCxT~?B?-pLLd^@Τ8Ze321M.e] +]Y\<J,73N;YVq!2Й +yĚ?tJ\Ato7[ +6J{n]z`KW-ĆVߨLQUF$"ṯ +8pCM2c& jŤ1Nf9I ;X02i/ԏr bOfwq, +i7WuH,^GkPPX@FMVKEL,z|xn@4oٓ2]&^q$G˟)k{mS%.:l2hyHIv +We7(M@Cނ&k7jBR-u6RYP\~-!M`D8;-4g}^ԟT.e(*9i- ;{=2;!x+L̶_]CM6j`/pvFQ}̉07W|=*0DjѸy5 @D3xE@DS"J}X^@C#Ta~w/ +<,}`ZߔY};:!8-_H8[h~rgbv25DpV +LuC5+|</oa>;3 +!|kzot[*?C<wnJ:,^(R:۷qغ"k7FkS"2SLN*˰IO'jdM&/"XOa֚(Jaqq8:LAvlF-F)TE BU
'ySs^n-j!Ɇ "-kUBMi|G`2OklLXr2¼m
_JD)8hx2j!6Y`?{+3Q(G
:Y4s`@;"s` M^:@2^fƺ_8YjL"&2xʮ2@?J/l+K9>qr|BD~c˷O܂: w3brߓY7M:Ȯ~ȭ(aJ?.5l2>p+/+nϚPK.[iOF!rei]B +%QEp6RaBU6 +N&~N6U#~}۞]}`VY'v6LQs|I -&7R^a)*>ܫOpDh79h>Nk0mےq]=AO&/ <CN +C&1? x[wD]+.yT&_ouT6bZ +kuʭzf;l_F5 ?gxBa{:ALִwRQ`k@pC1e$~{&@- +F^*C]Gh<,!hb r1 .F^DVí
(Yxi:m<ǮVViZ_`(7s{ c0]yR.j<FQR
~"7ؗ]J}+"+\pJBDIƴ-B\o0=2?Nbsj7(BwP*!S"YW#>ya7r:er9ŏ5b`Rsa>`Oazt +y@rLtPdQGKNOQ(:1L*r֎Qů, +Ԙq+0-y3sEI=fLk>'C,.7YI + )~+#12 ŴB/vh`Ψf6IƉT1[X)I8rN,A<t&_Flhm1E4 9(.H$dtpZoOV?9wqE+Ԃp kQN~';"ԍY;G^݅xcMѠ°]1c\oijON oljftnhL?:2{[`KXbj[Lt$~Ԇ:g̈́curJOt}V<
[1 ^@j4E/
e**&Tt#/2A`ӲI]:5ETvjSUHMmK qgl(*`WV_2w#I#xq%Aqa74|xTVI+{I$}ҜP)(1W $hu+OrUh.yiX|s`=_!.q&I_!O@⒧e_JJ4Tc돚 +W:jՙw,({Z=6Ϧ'Ƚl;Pm@_>D"fbO"HO3_Ep܅{fqbBt5Uά3Z^5ͫ +\SDw-*HVLc-0g!5 V+`w@01ȈoϮ)*2>zKA!>%[K#P\|zG5<`,>GYtt?B(VGWGdGKJS3`/A[b/IabVNz@t96|c柈 ;$*6R_=oΫǧ!`4ngyCM0"Z? +H*{faf o>%6OҢ|*B%: +Զ7\Y +ĤV@+|Uߖtg(I
_̐;wk?+[Ka ~hcy᜕vi͢::6
6Dm\SEyL]8g{fNhmCk*H_ u݀TJȨ_K̿wO}ָhmXP,
/`LnYgVidn
|hUd;N;W 'rP8}QXgڮt&9 RfhbFx!R2TC&.(ZCf4-8ePn4Iގٓ_/;ad_r|`1ۥC ߽3aEɊY3]`#LOI +4vpwZhm1Z;sHC^sf`4D~ӿj+yU,D8=AӶyCV .Y4 @cuxe1"Ɖ˟חNva_V@}d>ϨXu>FJPD]G +kSPzNyP 6FZvAq=E F}Y.i6mp]mP6j"iZ3c{oȦb
#T5mp>(@Sc8Ȣʫ}/E +E8ZdUsqOaQ +9'z$<#1pGo~t]8nF%!ˈJ3Q'VpEZD>gX_JdA +lV۷tE^1k!7S|a{½\YuB$DUyWضlkDUs[?Wo0DFfG|C://8B_E&*{( A+@1F%it`5h
H{˳wi݄j_fr?ڛ0 + +#|`(Pm6͌_ً;1څWN>m]\='Yr9Ll@TkMDxr'QvN;;y5s^#d0zaC~:w6 +IJ ʩ8+/$f3"=76<uO1KJƀ53z67rpMYP~c0r2EҗQAQ9 R|J;n
#.{&%t%{-*W=oKS(n<غ}r
mk +Ŗ +/r<|^X^^NMs o9oTך$ tltPrpV,~YÜ@xgK^~t /I;GDYzHd) Ŷ@eVaHaىulnFg&}=*o*s\b$;a+͏mJA}{UBoDe?.=!7E +[Y
V +$IT``f
1Q<J m_삤p6$t/䞈^|2a4S1Xgۋۂ +fl0AB/pJIdlY7*#~76U"AlGj4L]fl_ 'pV]WTkH< O'XPg5SEƮP0c,Cu8Ȣ4 +Sjшr +;D&܌[_p{8 80EĒH.Fm\4 <{M7vm~Bcjt"λ"E*9rw(+g&8A{'+}wc1mDhwS,.uᓂ|G CGYf0܌ˊ%ciU1w99\@QGVA"ww0ol?R'd죊i{J0M~y8BBTㇰsG^T:!@wg A5K4fB8S#ƈ|YXTn3٨ +\wh~OX8 vF3
6`=s5[ީRnzq:2FUs}\0y-yF?V9%~.}=??Q*.Ď6Oyuj +v{o\cRU>Ww yDmoSncFaMq1R#)a$E
Gx7;,P
4aU*<-Ӏ +9QiY1Fܖkw/Db}/MV?Y[&뒗dzG9r4= +~A5֝]K[{Pvt}Xwl
Z.78(vʞ2h +[RrqH,S2?*=NM2ڬtVu njZP*Nr7Kj]<rÄ?iݗ|m8ꮕ3fu.eᒍnLX]nr'*pi&XDOs?ǣ;n*<jq>D'iS03c}E8P@]^"x.[;u4G4ށ!*0Xsֵwa7\u/0z +9,~?顿dac=F5ҵeՐsw5MM%( h.g/¤<9AI8 'T/r6=_XHOGBߢ]FZ5KR馜`3+q>q,~Op$
hq]C~+!|\G9r݃tpv2J![KD +\De +^J}2* [OGc>J +볟 3`b<r\V2@@үҶ!)AZ}1&<{vrp?u :H@zYªq˫iae>'~Eo-r<zl?05;:h'ϸSt?Ruk~JH +[OVg۸Yvĵ2
}FP
TtWg ++7\sYâ&HGNNHK|Lvz/y˖
x.=/\P'7^="l +] TIE -8`a]qgnR>ت
waK($l?9fmrzxk%GZ;/ +5Qfe./|:6R'"`DƊ9@'7Hk!.pd=6IХ`RCƷF!x*nʫz⭞
!\1E:2%pN|l.~||/O%8yJ +2s} k,L'v WBl=ֽ涕%
m +)ZseC Sx~O
i>imrYGnTfY`M.Bj]*?ͫPEn2>>5:SжVgY*5&zTIPI@.GaieMh,B=w#jCb[|@*d
Ey,Ck}Ɯa@{~7!qqb%q|s3F<8ϸE||#:lԃ=C.b\ښ]uESne,ҁAþ/[dHϋDq㙂'R-p]݁˵Up27wBgJs߽I1諲'<&H_H%qlN_Y.o>8+`iWyIl<qlFH"-F{>3
j!0MŊ^~1Z:Fi/79\z'7-7\&&1'cԭG >܃Q`}V +;}5YIvnZ{8w<p")ױmBb+NjN <Jȑⴗ3$4
N1`N1n<+ ;h]$XnPsHV ;T}Bʮȷ6EdtVt.˧(!"DZ +&GOjN'&пGqco8^*'$@Y\VEBM.YUsO{5zoΛP ?4PkKV7)LY2 gob}{AldC?z7R9 !jSk%w+.?8(5< +.8]Ewճ϶NߛۆVVw$x^)"
*d= 3 El`6xmLe9s!zypރ2yK0>[>^h)M(75ȄsRx.rc\5I-喛KT%A+CI?*Qf7PAq´AJ7H{~ |b07ֳȩ}z^;`l^w˱Q@ xfM mGkIYn +;]DKڕ5gѦx'ac!ej-#S$j@8NT&'ohOPvd ?F/Mm(%B9C#Xnyg&+l$<_ +~hra~=ӝxA9Ed^8) +1mY>Zɿ% +l8ܜ}Jjt7^%#5 lX'*ͺqgfw#{mvB^bv읔WKt`!>c:%5"V+^omt5`@`vyr+YUa6CD7pCM + +e|=h + +r-)`iAb~n=.nMh>QBW1 +hgse(2 F\pHX_ +`>8̸2+NGu20(%ǤEG=|jRz\i\j
J;6|Gjz#}<M;)}څHamv@-7o^^˓ H(4z>k^W诺JtT)\;92Mm<zG7B@`(rDwucb
[<#H֟o-CZO +'s'RM:49Hm@ޛr{sF&r먉?_xko=X?QE%P6 +v7c9:8kܜJJ5 +as&9;/VgՅ:0.5Ӥ5#Y(߸\ywD\vz9%|yuRla̅
qnWU;~0B~p+RBw>_/Wah<dY1}@Tͫ#]dgOA ܲJ0 +Hz}k@R oV5:x Ri_7nrQx*iKd7=xc2bKk 'B!>nۅk`Z4lquqb,tvEwq8dubr".e1qQFۖ\PL zL:I|*E>9M-+?'A& +\CuO2R,$^n;SֽksZESX)"]=xFl2>6 +̷D(S:[yw{oE;?lIKUY%C#UzIu!*nvڔNjѺP\ho4+> +$4wa{%vU!OCqE RbZATCoFme]ttus\8- +Bj5 @.znks-+^v
և{x&ش>6:`o6Hftw'W(ɸdG:QI +II˿Wo훮5}n{cϪ#<]jld +w#E{`WɂK3)d2(6Mo8^K0,ʂ:AP*Vbo9Ԁ Hi~y}_JX|Rl,N)-.Ox`)K$upzx-r(xy'@-?կԀmk驙I3`ĒL zZ~z6XxϞqͅHr%-3Zş ZE=!? +'Sm@)KTd$@[lF\BjOO֓nS}HF߾ +j' }L? .5dlQ@O,p7%> +ZyӜy,#䵽V!5{k}?+$5/^=td΅#:$sXjb1hwF)06\a}=n8a6Scd@A+hܛC݁m0 +^к2|y(HgS=A/01f*JK|OPPG#tkr"א +FOž,} +&YZ:|}V}!]^_&U+L_Wx)'sƷ> +0mT*, 4Q]?J9~xaE#wfY +TeXu?v_s,,;CehHG̮O%KhZ: +o'- +H-nVKfc,K&i|\T@MUWJI7jHFy?TVH:beF6]|֚gёwtvl}xhX\? 7&f͗b(7'wM)z+.Hkڨk +vDQύ^=̖Y:o0&Dkxk*wi=N_ɱa%@M r,HwrKH")0C*=Pv$ښR'vQbq~Iu,{3&|VC.->d
gc>AcQ;ڶPjx^OCXP3٘?^AƁ(C}}Nٮ0x5;F* +?MbdF(T\7XȏQqU{"24N3*Yg2d(N|Ăr*|@sf//5$?7/)8k;C[i' 7%OM8h yk"Q +;ŪIvcUscZ?T4
oIY\YHdH9g%;(PeLk|56.:#HSѠ(W%EL3KnTyۣ +L:PގcNK-{O25Uؚ)S%<"ZpM +6iK!3Wvy_lx9Ѱ'm^Q}Ha)XïQiY1o{_6^Ϭ яLC8#k +Hq) +l
Db|sG(︀+MG(,NFwC! +C +]C
$hC^ЗKmT_0"&vjba\jp:#%uDuuOÛAyT
Ph7G +po3=|; u5`F(HXA +"0Z"Qhv_[S8MgKՒah FgjJP{QL7zv \ːH%7F +ِ>c3XSs㾔`9GHeɑRn>c1kZ҈"y929SnP1daߪ>||B GS(gͻƣ&]5w95aOھ;LQ_2G]<<Y(zW8V P%)a%-zW;T2<Up[(,rk8Kq<}k yUgz}Tec)}0R<jRb1TG +2< e쇕Ч"`i(V>X'-V`bnU[;I" +>Pdx ,z[((GQi
(k7̡sا<lx +{z>Jp[ MĄsC6GVVE*ą];
}M\Fw
+8j, ,hH +Nh$&R%+R&RK1p(7mW?q{/ρuW1TX*O0.Ǵ +{>- b4/\ŵ/U:tq/"B"$f gZV\wk\s'Z8˵Dus>TUkZr8u v0ڹΰbZ
aR)S~GHB.wRQrw[lM@0"1gd{\&@}+(w!+=h@
g>ciU鍬0]SO ١Wu+:[ݣ*mi,VǴWCV2t&G9^$IK Zhp3N<Hw7 +OGmX*awkZR + r85FD,Lg V4XL[%)Ii1[oK
]̀_3=F&kANlEy0
q2ͭg5+);z& +bݝTbX'L4"4L[~pi̻كfK M''.B+\lL t>Ff:t[*UOɇ0L}U@:kcV]F[Ϭ〤th*r_]GҮXiQf{-!fwʏt,:cvK]]~HG9t|f}F!ZC# +NUN </ϱ>aAs6DG}T
zb{or9ɛv+<9{64lźSwn~ sAl7^NR=oԏtmKfJm81
[X,6{,jQ-ZJFZCX<6 As=KY[N:"#~gC̡.ܡ!{'tq +'Qjhj߿=*"7XƟ'Dqȉ^ѻq,9R"zGp[r@NÜtU-HPu0@~TlCTKj~}$Kt͏j$ep])ܻFWR;7i 4ՐT//Z +JBqtqI[<fyJ8"3$B.>0n褉R6H@)n:E
a* +ݩ%8WܿhTAu|| .!=)#+MKwĊ4"W@N?˙K8v +tH0(X9@:S˫f:#Z<J_,TW{[48QILD4-)'>K6#h{ÿsٕ[`hŇ"Ux5Ct~:' ,-qRs]`
ӺFm9BQ-։n(2:xJW +gIbfrr狽tc%zBw>f6$0DiXc2ҳ"^\xV4ZD?x6@u5ev%<ިM:>;46叟UmeRfGN!ec惠8n[$8=;ʙt=)[LbKM,y<5ꟷr]q8>#גpj>q;Um&'>Z2Q4݀'F[#hYh擼`fB,ޗO(DzʃfIҩ?)6"52LM*x +%!@ ?<7o-d]#ƴy\۳[^!>QFX.ڸih0B%`/ +jȐqOX/@8@3B,NtJ:]!q3֤{2 Pg",c_CO&Ŭ)(L5eVBȱc2wM^+57Ա3>_&JۭWD~WͳbT^`59"$n.G#W`"K\ YrBĬkt5ĦNh
7xGϐ#G$ө[Db#>k?Y.%8mC~ln" n07/VjEN1Ub)V(VnEe^@]pgLx,V\KtywqF tz<|ʻhh(JYqԤǩGNAp/-*$2}ٺY38%BrN
uIݭF4_yS/ꇙP=yO q'ʋb,n8^YD$@.x;euݝ,],Nch/~H{ɽXI +z9YgF¨Z$]tH hI'%{0Xp|2OKJbaoSAizP$
QFFa;t⬬/ZyG$ +K2ұrbpq + +ײB+;g"@#
!.G2Nt )gQn=~~<v4FU3
ةh[ؚfC%J;HpO ^,hWð>V|@J`*-go j݉sLH軒 +_?̭hcAY-E$?{Y=S +TSR +O5E"VPS+έ$^lR1D=Z@o +I&:]G |^sf([xX`~
}S@xbZ<\kqzAI +RxƜ|]`9Nޏ +=~)D=3Pm!cL)]P7[|oX;eZ3uH]Wp~A[PU[K);#g`sPq0}vJ0<҈%ȡrײ7De2L<[2h
IAjM%}URT/W8(БN]:C3duT>"WH_7p($%R
t(`6^}O7ѵ{/v蛎f*Ek4:n9RQD!<ٍ^pk%0N/;m R>f:!GZS0bGǫ*xbI/?w{żw_\Q |M*ɖ)4I!kx(gae-8fI9rD]ߔQO:落O}-'DVUpﺣF_pB<gX¨у<4ڝ>kU7BYw__.2vE(kЯ +j,2ʄ>^WKC8[P'Ei{wfX{&#fF&X_T(٦4{mG;2p%dM7} +hnLVfC +*8{ubEAˇr]wN_C`wWrEI>?iWС)T"U@ RAƖF8m=(ԗ^:w;Vs-sQodr+KI{T0:I04ʼn^$s6'7%)ь5^gϘ# ^٩vq-H3b][·.2]C#pib^1<NZ}.fC×v@݇5)lMM!zoC;Eӑ[<XuLw˃y&:(q?c=u:W{d#1i St`:buԱ]h܀>m2MDRW|qv©/;Oh: +ڻe"ӈ)a<9Ѓ&Fl3ӄ=7EyO# Evƫ[ cKxVqB>pahLXbs)Vwv<[7PC}*BX9Xicf۲l5Z0t,X}5v[jG~'DQ}vuQ$p[Ѣ}J!Cv1L~4&<{:ͷi*6pX#>WWa)[ 9B~e +4]
#]'e 2
v
iEuvS cY6n\ Ž]\hL[rMYEpS9V
Ϡ(H1t;x!+{E$!w5}yʶf +[m5n^o_ՌϞ
'*f`erUW<?CIۗlW qyJVEIԂpŦS<n +KMFd%D>UeIz&HM6#~*" ` +<F( @)
F&iv:sB`*C,2)Ү4Qlz,W1_${XO +F^ҝ&9e"̖#-Tql fH5740bi8Hs+mjYcPl/KKDFʒzf^.5ٝ́# { gJHAwh'X_3 bHXS2B5B6Ǻgi.@%sthpV0Rs~}tޔOfeGPUyݜ͚UW/tѺO㈊IXUךpOp0ׁd+v,e&EhCN
%8n+#ZOwﲊ(zi|&,lSQ P I)E#Fb~2`@1·.5ZTl=Ԥ>Q쑚6!eZ4;Jvrm9Xuьc
v\,p.jۦWeERibq3{zY"팗7g]K;(kjp6ٛ&w .#u'DdP"BZ`,P;CLGI9~<S/v| +QѸvS +֊Wf-#x$Pho0~T}K. *x־V4XI #ue#rEs
Y'oTJ2R?vߗ=Ƿ{pKΚr_E?Zcx~WdoGL0$$.G
R2|cOVv8sn8eϗ<66))|pܠC!*JQHyU`U'ϦIfB +1Ɗ'فuv) +@tzX5FڼGba|-djvr72Az7 IJt^4S)Rk JCUnL|]/կoxcMB0k] +%?kR9Ņw +x)9Kdfw։Ob2*G)=~- 8za| =
*Ξr/lS_"s.bXd34AǣgFfI"X +~G>$[K%/HI\Ȟӡòd=%א5;O̿jpi6 +%K8^dam=&%ޔ`n"չIK;g#2)[ݟ'xs'713C0}i6p4<K=(esږ/0dSH'$*䉇K,Bo,z|t-ѶV C
X'yg0^yy@+<J!!q*x^:7T6_Y#{G|*r3D$Ffx(*n,dR +PЅ\L%`Ă~p(%rS}xiS2rwx\ Н>8@Vΰ"Eכ" bnnu}_Jl +}N\*{Au5&NN ;5θ峒/yҪ>~ڲ)_93<P2֍oY#;: +`wjO{bz) -V-rMR/:8ʫ\*yn%H+=N=L}f*o
!cZu|\tLi1%`3#D)RgFoVßt E+9%;Y7BZ~C^d=wF!.:t@6iglmܨC0]C98f1r;nPCvm4`ar [1"Nf:_m&v܆eS|6LA 왑iM>K̉Rl657r +>
ŀ8>"0xtw(B)GdޤS
zMd9.%MfէnjsQ0ԶFωjzT҄
93|IִL(h^+{OmOae
CYd4\6Wp`cԆr$;3/1)GU낖M"<'ogR #
͖H͚d @'Qy{U});g +JY`Mvm:\f=MDۓJb~+͑adc*ELj{xemB_^h#e~sb-I$ZIH`T]0T!檯*%"DJ"*Oxђ:7k;gQ~tתZ9gR7X0o9+Gc̒^qcK'6iG)ϴɽ5~4}B +>{ǟMh?/,GW8βhjE^O.C=[zA$g?{Ʃ|lUMVJP<kD<W~JQc! +rM8cao +r&-kb.bnOp|W~ţ +ĸ6m.Gd@(H̺8?j:Dzw8NKv%j`/ݡԙy +BIUQϬwڦ.'}dxȯYHAν,@͇lF>&G"SI)̊{0 cYGky>uF_{ +M,XLD||&J +%\(E#7vHB̞=,ZH +x8f^݀pEjdթ4
@9+ŔYnlZCv"DXݬ,ЎHK\HbU#]ǯȝнI
ey>RAM=@ Z1~,M-)y=wyT۠LSץƜTZ_3e;hq7)mzWh`!0cY&LcHl}Üiל7m|u|us6ޤWthLt}BH5j3OtR+VLNPr ,9A(_|i +>+XĹZ6>a/?sjHp0p%/(ۄޖ܄mAVȬ]\Ty'jbjFXEp0eD+WNg)v=t@T5fuzm)Ӿޔہ>e'(<ĸIb98wн'Dc<YӌAq؈H.dP3EWӊYM1H`b' +ґNk}57Ʊ3h£>$9ߍ|s2'0ݞH[QǪcR,[x>L +yE!&"W^R^<WD![u^ۃmV:*,k>';
4[!DD!5d +;HWpt]n|[#~fD'3LI,UU/N߅ny$l%-%ի NAs!Bޗp1v9oD4~}PYV2/fT#/crw2#lFw?),ep/uP|rXkx_#*ܱb
b(㋛`HPV)nfYI2.սq +#
~A`lL|+T)
G5 6Ga@ D ;x\XS="\oEoV
& +&n-Fi?ORZ}iPAK|SX??AryN/I)jMjqlpA
{i=8溳 FrhŃ@oFCEۭmf#2EDAF`_2^9 +ًؒг`R7j4j?r2.ћl၌Ḭ3Z70?*yv#juA\Fɂr_+ n%Jf`JgR퇰x9 [U/wnG)lzeV&:nt,s}^+H VuSl$V@#KgEτ>D\o1=wdm`Ƴx7٤aK*/,wbgF}ҡruhQDMc%5Dog~ O&ibOx&̡R:ߞ٘cK8@l*)8ڀ8_X&̹d菊IuMYNJhB +pOhX?"wqƀ2n*naf`k@nLtSDfIuSU٩%Z[uY +Ѳ %WVc
(5i/lB8;I16cM7}6Ug5Ed~)*ҫH +)e>]܋NHz*Mv@_y6<k{<mnFa +LPi|:ŒG5r4UqƂ+WIZ
%EW`H +(ݰ~|0^D!Pg"역0c>SETD;kU4t(@7E/6](RWtx)*'^]W%hM;w<X,-QWpNfnلps_/"/%\,Q3DKzfOy4%FE^*0-KμM])2q*!2~j3HP6)K&i+px/YIeHK:tUP蝇4aYzCO^h<//AнvU?AW&B29Ya<?! +ݩ$rxW +xF 5RSZ6Td`;wv1*Fw6NKTV(MI5*/ +\WFK$FͰ_Ӝ d[E0Rf3Mx29߈}/uJqUE!Ӛ{3Vz~Ec[9&Ux^VqK
|2LLV0a$oP>O`_T,ȿ9:CdJ>,YIP}e05"wXI܍xXslvƔ)U, +1~F>@W +3e:{BM!s(+:g7f)e ++濏vr +4ݠQ<'%&L<doyer@Bqc(FM+TғfZpf.>ƻfqM8.<ӫJ2\_@5@bpnɄB/zY_4ZDD!G5o%t⒴Ls'n܋-o}/VLxuKF/F2(]:Iˀ.$ Ml}\R$rJrF5a(I293DKÆ29I8?=Ds<{\ʺx0+CKʇxi'8uY҇| \}|_5 Tg +gFώ>b؇82-K!"j~<ʅ-XPV_J h@;g3iQ+^lD\2$t5$<չ1Qkh +BB4^EZ/ێsDHCk)/nԆ~OgyF_aEi>s3w~h#n[" 8!Y'C*h~8=Kϸriܻ +f`aF8ݼ͈7ŏC^F:֗af%acP@*BI
?]C,
V6QnaL{et_|$EW{n`T#07>
\s9bEB'gVW\ʀ&"zu{;*ZŗBΓ\k~]5}J6IJT'0Ylpq-x\$`+֎S_m-5x8UnAF D2Sdvw$gz&6BlI2QXEz
ͧ*\%(yQ"mǎ2xdLvyH'[Wv
A/4?KULQiкjNaqz˴ẻ5Ś<am@ҿ5@ODV%[Gwv
vrWߌ +ב薻Ud4[v\ݽ g==xRn.^t%i&P\u -S'~PI71 +`"7p@mA~.oZ?֫BU5hI?0n7y)F.q9~xX`-,ψp%?0WW{DxzJyUua~dH>b6P,!oy( +鶀lAcJUf;>=
$#k5m۽i90oVAdE +t>l +tJكڏCW?Q7/̟tT.{25o5 %*+[-M/ke
<Qt[ꑓn +T$E;v6FDEbzXxǕH~X,V?cEIX`i*7յklCGU+" L&y$ z"2crWImIjN̢]QMy+,*v;J1c8Ē?Uĺi{F4hvvpzh'c,_PrhnILSjoϏM4'N_jddg +2f浂Z1D7q7ꡰMX~d8Kǔ=[J/ѯPUh6LjX}\U~D1><N>&C7utuɯcB9M>m|EzX:vgZE2@;+'$@ꋕCXm4&!kƞy_^{DwWFҼyrBC eO*gh#+W@ۓEqޛ +DK{/xcIm43QWjny +0j24 zqzp+
0?6ftO:Br +s&0=8ƽkOS\s + +8>5skȆ?4ZilgN `jI|~~BӌJz`GE + Szg% ʰDP+봎W{&C4@[`!ʖmW^"02RDy
FM)'ui[7Sým߫S46HZ҉cdW$Vq58ymFc}6+KW'+Qݝȅ;/~guni@v,]Ek(,EyϲCm"̾*Y+U +#Au]t@D |y +sJ
j҅MG=;!]BԫES]^~OȺ*ù'd=ZTwrO]x}D ##)K+ضf:{փC+)ߐqdq~9`INBVbzon +4B*o^! +R0Hem\Ȉm@}è$PT5(tɝCb5JDKIs +چYq=8 +_9ѴHq)p^ȴV)*49S?DQv[ +唇Ҿ2χȔʚ^[JӊqSS<` +ܻ*Y}VH~4'%k$Xx*XgW$8yYziww@o kjcÉ9]9fՉ^i,m0SCٯ
1\·]ʇfY0&F7_os)B>f̥Q蒡3~=(#YK^Ԃi0W*˭SGFSQp^P~]H:f+6b$Jҙ}%ދZ4:W$-§.0@)~^w.GBsl[Z}kwᜍЎm9EǏjr,a֡x}+$#FՔ}Ul_ Z_;/pxRKJK^_KTMS^(,]{wVԈ7qV]&ؙ9:zɻL6@\lj'S3sA2?7%_/nG@#eDX5ӓtٗ/4ּ4GZ}I8u7㆘C>{S +YYhMK$
ۼY!$
6{mufuRB}ϤH/թ@v}F1L3\D>kxS_}<02YƊenlS
BIuC+|I?&Kon)-e4 ;\yjp>tlnwٿDo+e՚{Q[ι(w)2sԌރoR( b1si + +`L!ĚAq#N조U<tRjqFqBnwlO_
_4a09M5YDI*<pW%'6hKB`}4fSsOL̕!apOcFY&uΥ]RoO3`ͱVZǻgD_ވdu2=k?ECOQҘmt
C8ԻHs3Ë6JiPUl'pGm5MI~ +s"F'<4. +br +/0LT*Sf$p.#;X"DP肉MG [GbaU#vYܲ'1XJ]
p#''?'U}./hmooMk5d/0s7xg@ڤRk>!$6aFدxgA)_7{9'|[8-C9a[$lIlʣ~f5GdE0Fe<?U-Q^a,)nCO5AY/p|:R!'<:>l!A<%qbYvMEad8DՀd<FjXxǟy-[0kޑ\.?UuO bgׂ:Ln1mﰭ:NA9tƉu%wKO}?
ew:)I2KIe*s})XW\^i`)xR7 +>tu/;4ۘpk/gJ:%Găԟ" D{x!qCNHLwWscd幦 +ZhnpOj52+3a +C`!Iy=t4 ymaK1KXV,qaʾ՚0#^REFe)ަm6ehW= +Z',;M0;}w1>|MڍQXk%T)BZ#h!kD5 +KvvMkgc8zSsz+^JT28d[acJ$jsmf@Z@k#^EWm`)5C¡z1) +V:Fꩂd:`g*M=]A_x@ 6Gx)0~cofC9NeL($M'0唪J]N-ׂ.Qp >ݢ + +pPtJQ[HhP{_%>G(\99{FXóIڟ1Pf#HAOeyfJy3~\R<C<:G΄m~?LWVC +XW~rZ}`OLqYUa,XMW&2:+aiFMx/ <n綵EKB.;z~&($ȈU&5B91B~me!jL`>IKlu
Һ#̪dX +2nanq@)o0FwBK;p?yӷfv%W)^3N"0D>,GI=!*?%?_.͚Gba$]RĎm$QmZC~(&_2KrHTZn@Bh-X7,>t4bv'D'>εj|z^eA"t!GI@SEegm"f|Xߨ85^!?19mRxȴN +0oiȘ4\>9tKfg{x=*o&;36y40l.dIÒ/8oJ][vOnF%6o;j:M62d[UdJQbdeVQyM;>bVN9:ahzH;Up 5*xVyP ,zEt^VrKm9@
ߜy'/#D{hP.Q!-IR &uyty3;CA^De;|o[e0gP!یI +KL1QZdsb`G=K`ajTl^3-?lg5~Pb <tjPb:ɺ(3j3mj,TyW=0iJNdOF(};V,Gk}#q.-ϼ{csa%i +GaL
5аݚK7E74v?ߑn!0ΑuڧJ뒉R( +G9pxoKoЭ"O'*Wor4y}%&Kq(AO9vŘJZ(%x:JTB4(٠?ݴM::eQT"xr@փagkkN; IR +_p4~2ۣ# Ga^cL8=\6'SM~cQB& +'\nUd9fA-{>SƄiiWg`UF&NDfw&kҬZTwbg_6⮲Y5ta{Al#\k?%Do"M$DIHn^AΝ4ZYTSBVr
b.I1B
"S!:<m]tE;}uNaVz6}tABU
{-VyM;-H0ups>cC:VZ]F7wݩ˖jbYީbFױJKd<R S_m/iIIyW1ù9M)J 9^N{ҁt"^SN4^/fI4WgߨJ[G^wavI KەG6GUnx*+,EpUf9`%ޘ"gWX!bAݟL<~]z殝q>mX`
7ֆs5*7[6!AgCfe̙b'i̴Q67 +u3OR0|!{ZRp($tPQӪ[I'WZ 5FAlkE3UA5(3V(2t\;YRCȏ=jsn +4sF,;&/!y̫9,rr;o#֡S{~s8c ۗM׳Ís`<
n+үK; vZ jl/V{+exQgG,%o
*g"S ~S +hK!U7k̔>W.c_r!}$KpR<s?85%5ăaî_ؑπt =92]L9TA0=[%,Mq*ƄE0A{bټϤ=s\ wJNSLE$cλWzh;78LuΎ&λ͎PE~>\gy$Xͦ=}n)O:yBy8%:n=5-~ecCglW|YSJر9ֵ)@wUI4X UǪj$JKMiA܅"$1л.-p,ZE=WX.Y1i}4Q,D/mOxgCLZ՟ʭPٺ+i3,mN3!)jǾc۠(Қ
AB< +H%¶;A+wĻP;mtru3u0P=s_Ij>X\[IqBH)vX\l+QDR3'tsI.r'B{[DZ?Zg$G皙
}//f&!Q1WS'dH[yЦD˳7ti
r,"h80o'G_5ggJ~ p=ueUku}r%hkڨ&0; +2IM`;L?Wx +Hv(wApع`&+^3V͈ RR8YuZp@Fkds|s]u&a]t +~!L_1^զV ++sM
g}jf6ɭ?>h&8;&ަmHOI,e٠$gk>1 rf[:KMd4 +aB'C01DNEabDPb.:}J.=c0^E#%Ha8{t6R@#*F; +vR r+z7p>?ĆN<mw4 + +}wCN]G>IAO +ڰą`RO/*|8*EĨM2x^hUcd9'o7qf36~q&˯b;9ZB@""փ@ 72L
@95g(2qT*Q/Ya:&BJae
yun(@ٹ +_
YIc!W#.C'F7jΤ֍¸s,\v,Ƥ1Kg^+SRdqOs^qᄗ:A{H6{^K4vZ+rσyTEɏO_[aIJ]Y]LJ>пgDW0\FΩz+,USLKj7$r`P[9ItU:r ̬ԴG}.%@sl.S|\%Jtܝ5>Lʖ01:$nW]/9"KzɷaCXVQ$$$4gNb6AIW]+hIcqbĠ66~ 蓯)qn_<]KpO +0{= bqT;}"TO4Gy-\r hruh*J*\
6є[㍃qԆvnH
rcLg\O^dq)vk/[ZTz1"-n+ęeK3SM'6~=QdlE>T~5x/s[+5wH=@QG=GA|PW !AOwiraN̽{6e&G*c?4]B6aG9K)ف}^OzZ0PwlR5=} +Ga-HXV
Za`6\hik>"+FM,1/"]u6qNDxPȲF#1C4(=z>uG$;'I\Qa2çѐ#oh>NGmvĦ3۔^,UmWd6E7'}}3#5)((WLƟcnEl-תOS@`hFbծZdPPc4NJzFivlub*i{חաjKm+DAYl{4y?HN@?y9PdvyW[Ӈ=bh?LpKgNKqS]d'R&K`5L<DAb͚x`(0Bے>Aƹ2Qo@Bmr&lg u $gGh1^0yj4>)_Me^Dueaeoaҝ36|9V%|'qHwJLr += +|XzKw@pgD/J;@ԙkbSzyħ#4 +;δ?I +2ax=Q$)nIi=(2KE'nE/m"zjBx=0VbNo},hcR)DҖ|bޅɛ^d:an@9<uڈ֤_,YJiV-3h34}6xTQ!]~3l4 +wE8IP\w.,yNn&P*}":hi(Y@EWC +%GĨ?߭J+T:\~*BFlwpeLApT̫/.rC/y $ͥFU=F,R{XGF%3@;:ke%KuRbuX~¼cbm\ `'?`4mG*[O!c%R+֑D5m)@3}{,amJ`Â'FP!6uUz3$HJ n<ڷsP=;%"?ѕgmZ܃I2p$U2-E"+0c̽vc"]`璝vi>ZT s70`M3z;#w:~g pz1+ܳ,=:0/ +/x=vqx0JAI~ +<Fo_[Mx['@N#踝VF k(I1__NIќ'нK6D7ly X$*kJ=a2)\
@|t{COO= +4;ҞE@èjm 6 .(,j;tA('"]PĹfK5.Ώlr|'T~W`54y~_DP0[& +(c6`;C9GQr^صM +T)
_bvejh*qtG;& [>{mKCrKKlq$,N]
5cWBs舞/erͳ`I0 MɈ;ARܪ'[C9rџ|?,r9Fb#ج}s.P&@pcLM5*Ϸ\J%Qz+t/E'#~iHi΄ +!a>%%%BNcl|ֻGѶ=Y@+c;'
ۼk +AT-BYt%UX1O;O1 E/ [tpLc}HŮt[SD)fX>427(jݿ{%Um̳0U¶"uyufɣ43 ̩<h' }P4INog{.z5ie䘷m,0a;I|ȗL!N0-n3HP\W4Q_ʃ~ڠQCfS3. +ݴDh?: ,s
<)O#k搤^XgDY:)0ÛIIBhȌqtuv^bf4=GkYr +| |$K<yzyU+/%c}kTиX'u%; +,fI#xIjICF2)\ٌBz(1_?8DRzJ$PwދDK,YTx',J6Έ'lpW.ͮ5zi1oΙ +.mhzS`&yP ƺu2rو JWQڻmٽ69E,L?<]/d1ǙMULZ]Pԛz[!aumjbO}̏}D??I]RmWG}^ +g-?aLzQttK|E&/MGԫ</tzgIeS{7?_`LluZrKh(;;D*T +1M#nϓ)Y;>'[^` }7tXFYms +k *E/^KbsYg@1agfo^Uؗ +y'V(MJnMjSjyB?VtJuLqaC,VT%Ļ0,І3}/5ۤAe<6v|ɧDbgf'G8i?ls +*#gc7eW5\b~e<(Bl/#td8l5V*tHRUZhzAafNJlw,n0*C{b}<$z,C>RBô#Bq`_|PQJuKVJr9tڹ@oX'skdZEn\e"$ZQ.8ΛQ˔`ˏ1g\Y93A|{#
%8VgqO
@}o9b5 +LDYqу?BC]s
N㼑/ 9 i-u#NQ?#}hcpڳM3z>2X
NDX^R&%g
r}掎7Ky桵$0B{QGsyQ, +g<G{9-:R:?i~BoUEXjPm Lwx+Ȃ`1 C|!YF|!)_WW'{:k͙B~_$kv"~NXXӆ$bnFHqA5=B˵p_HUϙ_$d!n
Jz7Q39$9rYfح;Yﹱit(aϗw!Wm$#A 5n\r K2h6c\*ֆp3یk&2ѧMǮF%3| tɳp̤KAvuENy&'+0c-;vϿp`)A+0Zg*ʺ/{S-gnO]:
7¤҂=xu.cv'PJQ26_q;`NkԔ0]F.{_6`gtԯ)[?`6Ws)~sZ U2|A% +7cK2a wkh ?\jF_"-/$8Ht|P^\@FÄb@3w2a9D6_.=o[<u${yV|̰an},U>!omzY1RwfTg}NqßzIVD25W/oC1cӿ0֍f0dmɇ,
pi{-/vO7p7֫Pgꡠg Rn/ИOS%3|:%7tt%k> +-yW3W21~!RO¸* +|zXyR3:ڗ?7|Y~35($9*=f%Z$_Ōg X%)^(p蛯Qʾ>vm++F.}cFL!.&[ J{u.:=Rb|jwAٙ w}[[겡Ӟ x z>m
9#/ +Qڐ<vK&?)Ji@GWXq.ƙd +[k\iJ,ԧ5=CGnCS+oϷP=v-?!/#;pg0x\]CcC02"<Qf|hv0sB#z7'~U>?f#sW]z{!b*d|QU1.ąɸ"uKn.
O1s9yяKp)\1WT"y-LMf
[]ƨ׀7}?1 +ңdDZNC$3Ab1;`lZk]k`nqmW<'%ɝ +x,]#[ڹ4P .Tx]J.[R/fn[p+~:j)i\y.>qS횋Nh̹IͿިͯ`+'g0"+x!~Ə|$8jJ^x QU]NSE6Yv0CL-聴=1Em|?%$+~9pulne +|6?N,w&f`S2EhPI@'SqE:M!rc";{ +Z%I 6.c+mBlmW)`Ҭvӎ9эsPJY9y]ch3x9o.:XY؈E`"-'(U.J">sXʥyЧ!Sٿ*!4^i >"TAXPjG_w%m2b3D4e[PIڋ.1ЯPj}5 +(p~Qa4Lqж}ŭ@8,69!PN'@SQMfx߈ +qbԱ&o3X`9
QE;=_BV+K#3!l=8|q"PYF#ӻ~bԽEeN3%'Li(N!H2+Dqq[!Ɛ5MEQB,փuE|~1c|
4(u&ZǮ#9О3dgM|}e1ݙBr0*4ljnDjZM`7um|ͧcD0|T"Ӟ:'<*SFY%S&dCV5뢇 +<
;MH+(FF6(0Ϯ'ֶH z78) +i2oq7t=g7?3:EkdFi(| +G7K5RPMCi@0]=3apY>a ݰx;X{yxIsx +02{ҍI]ĔX0z +Փqo +VxQT\+l܊ +G(Z֒
hVrʈ rJ_6a5JVAVj9̞$Nŀ@ix.y5SFt{l1sQo?0 hY4
CU$ߍ4M«>mYjwE Lkv7^Ռ"h +yjyDja`hZ(7bK +ʙVZzm3uf/6HqT22[ȥMj",*]vK3jF3U<[yR^Ӕe ż8OSZ4062<Kӟ +{2E`qȰtv6S6ׯ>PWSh
pmx-)wO7")L@2Y+3{jnRp=6OK@_䌥%@ +RdnC\sC2ϰA^Փ?6- Mt1L*,(ip^!`o?Z*qQ; p +\bc۴\ŭ LBIT/"MK-*彭p̏Dh9rBݶVjFɴP$@M`+a +{!pk!zQby#\4[V _Numt2tpp=70b7+}<ѨLs2WιH#9|sYFdkYu5lH(uU\yf<nKY_*4/ݬٔwM"]t;&tO36c6Mwkwj +Ϧ>p*' +ѧP;:i<=Slg+(H<-OQ8'J=f14u:15J:=\F@4kLsV[.(|&V*&~n"*xY]3t⊤.wl\xo}#]'ۏj<U(fGa1ьj~$ӓX@x^Q`7͠ +A^(fs팊N?EWGt0@{J=9 ^"ىkxCze5Q-;eѡS-Ig6sՕg%v4uy2?m0%iǫ7e0kdyOdrԎ}M%شlXFV4BHWuD.;rJ_yKYCP2٩J< +$[:LhVD]/Y?W7ٮ2iEKbآaR^VO)@;B6^щ97 2BeNV3yL~a4n=[|ŕRot:%V>
rl"duΖ&`{yaPb>X5:ZJ*J,8V[ +FFc|7V|}q2`h<([4݀,)ΨOm!7 a1Sʙ]cMa +[-Zފ9S&7:CҸE]
ԠQt!zYK~v V=|RsMɿm#MpBeScg7}! +RѦ_/:ȉax\Ć* +!?Hf6¡<gKBOq6 +`t`P!5q]_:ӴQK)aKXS'Qnv懺SraL&dY<xOt1I#$0#z9V{b?:f5)%N]CX~dBڅW>ފgWRB
;Id)L3%L0cMK{4#> +VOc$JhBCO=+9+66*/lJ<Q$@,^'gqW>!(ˏ_PJXSweNzf4?LH}{!bE̍
&^fFʶOpېwuȻ
$>7UV3ʗ2v.00w\A"Pb/'\qbo5j~1u%(\.A+X<zl2v˵Ng*4{nثG):ۉqW?snRiNaQ0'^ʨƹY/e%Vn86[z[DYk+ZE +g +Pdӑ90$ {<B @\ +D]BcvUߵ=\Piii3x^EкϾNAk +JJ#M-MQBȱA4J&:#[oSK3?$>{Y>ҭ.8.w2h)l%3{E[lpaǥ[+Mık8ښ'hP~Αtd^ql*|<"tqEN
)5yTIxv^s6S/8'BqkA|x!+8 +vd$_<21;ɻJ=9X`cr߭1[7ARzSϋl)a13FqE*ȟ6b~8@] +3%sA^f4UaU"ʞiPfgVYX|=VK{BKȜ{<=!/~/Dw1GpU"̎vׂG(S=jyTLׂٷױ";n]XkS@ŁE?u^Ubehmyb8DXS536Pi[%٦&EITeG4RF,BNg{E+$|ꃖm+q_]d +X$؏AW9~a$!aߎ
)/0|>eA9$.tH7F͙p +bj{y qTΧ
L#OR
+Գ8]8wDůJϨ_ۄn%kÎDpy3cV7/P9э!)LZTXzޜ$J5Xl
WN"N
/6D'=0?D>'܉r8cm+4ϝ +-CqF|gfH +qQ0Nb93hKm%dL2âd/RQ>L&5}&lF'y$#`Nܰ`|#o +'3ev݃F@گ]9V:U +]ԭӁ@H/-Zn<kPxQ'9gyW#L2n>(-HbIד}i?wNUjD!-Z>Z"CSYMri4sVhP:qgl͒+\Ńsh0gA2GL;2h1SlS\24a$Tbiu%,r{}P}7Lr'T;hQ'ݽ[:y 3U2|qcOP^L(>x*b)GVz0-N ~TE `QؕD k+#LL+aі>șTCX-(&Zy0z|hZn\+QgʽTF]LDۻo#磤J["E :K8~ym͙뢲Bɧl}~G"HUߊk Qd^Fot}ꤥ(K*H` +'~D^LLœzK~\7p4#
_yNISQ +l^VlNf,2Ԩs<meU-!9^LvKgc`f<4ϻ!ؠr K)Y|[y<Ki6}^[ K CoOF"bloGE]8LT 1 +#8[,m2]{NDςp
+b*@¬=Q o4ӜbHfR?vz{uRe +Y +HR,B㜇_oIo!pζH;aZ- ͤ8rQ2[kMf[ڐm\E g +|*骎+knȉVN2䌍X͍CeՔDXS¿ +$o8( +9>nGґqm'U--Ѱ{w7@ +CzdзVu<8PPGx&2^zQsc#Ut9bnU/-c,LkoZ!h3b9k_:B3n}w ¤egkNy1^svIkasj0
?In]c돭wh9Iw=b"t`?/N?hHmH=+,mSA +fT?5H"EXʒUѣK +Sl E:ldn4 ,ˮ;ܬaTfJUm +|)iGhjM:ֿRؚsF"YOU#g%ib>h,)YŞ7N<[so+[No܍Nl9pHJ6ET.&Q30G@ kx4<I5*פؠ4}9"|5Id@X6{ R8e?K`2$Oap&݇oZZEcBܼf;
x +|]`7Rf,(wK9G|]8ې(E\xPGZbDoKDRKVoE&J&6H*-:+n/!k`Ëj@a<wob(6հ e܀,6<a. +XM}t
%TVSԙFa`gb7,!h͖;J8y6;KƘX3<btZxK!u8ޗJ&ŖIQ̞-ą=&Kv_qZ<st'guQ#s:!E<^S +Z +O/ne|{&ꓑDOmmhp +s;//k[N)FR>NxoVҲEs82<GHT}'l%H!l@wbe3]RD9 +LYuHsմp%䷐1RbE|@Q$V$o>EhwG}k3 zxy!@$:WT`2Kרs +18xQAݰ4T}#6LJ<.Y#v=-A7IFW]>gk{@,3NT 9b `Ǔ,oDLo%0|B;XNU98ٯҟ$=:*չ7gٕGM)bv>{EØ"#_nc?JjAB!\w`^pcŭ aL"95kIrДsgwiJ5~6"y;<|A\ds%M)68Q|iI.@g@ҁ&v%QPk\&&%,qGr$MA>8m(?A@V2s9?5Iե(=cd%koLR<tТeKQO*"N9yNfr}k"Tä2s|77`q?;Tw܇o74?>A>T}`QH΅qԥA#MBW/AI3,Ar!DŽTۃk<Ǔ1.@W+%u7F#EivRg0 +ރiY|Qp֘ygӓ4`mlՄ31BtT:ĥE4!6NbnXkL!!A)raf9ws#{hW՞Es +HkTb,o}:6 iaƞKrz.A'{s|*+_/!HR/vT'%jK8rvTֺ)N;9E(6q~iN}`(J߅*<9#udZm<75z%LSC~ES1jCtm{gq$.%e@ق?<47zz`z\#ׇb1ēKv"<m^iw">{mL8>\N +qB*εO +n.\ Ӣŏ➍DCD=s%qt}lm@.'{2?7,ďҊ{OeNWݩZO85唾L:YpD"mK_e'$5IzxgTp!ߣ^iK|(-|EgA}EIW^Z#mZ8 +)4<3: TVku$i0Qٶ{|0H¨0hX2 ]QQEŢDK DЖ@|<3ΠB(`I+ۆ+TdO·T-6m[R_H +v\0 .HԈd1^$T:_8i5nN)U +Է&&6,veǼ֕;.L>!0+I(4hZѼ*,iNg<QQA8hn=)\Յ[& +<fڊ+S_qPE +Ι5ȃl:JJ[FD2 d9.j0]1pX]t&p&Nѿjp;~~qs<,SOB2q) e5DZˆ`m <DpP %vVmЬDۺCPHdexa>O6(PߝP.g$piS/Bw@Ϩ94fOoyD4JBd6q!D:>vme`Pi/U7>9}0?YPMȨ +k2Qxozwj"k{J+LF0M|I^2簶ZHw2'a`VFչ2Gٚ2xz7-,TK►_%E/]::]BTQRx*J%W5q}B9ߩlOfۥ'c)AZ3lc9U҂PA)y +hZ*nuYk3M&_y(*O݆T3Z +sxF<Fz`i jbp>ǟ/;dX&V)QY%uf`7OYQ;M=x,zh.%nTzGGeǝO*/m1Ev$- ;+;UŮyv:Ϊf;3yW +g[>ʼ˼|y: +!JDb}CC+g@/`Ty%=iAl9. +ql]茤7`*׆IxCD%coi]m3rurBT@}43-&̻A:&<?e*k(no^[Ot\KA,uH?Yy% b얈48^˼f9~?;%dޞ4
4![0]-~| +7jԂ3);um27dc{Ji%jpohصe>Xw9mRGPeOA!ԓW&#gjςxɻs~{ַ0o$ ,$av]0Zd1 +pt +,\ƥ\|zJvN5l$4̮7y_-7ȰӱIp\}_1&Sq*lt}>Q6S?ojajDZoY-gv,km.rt^i]3!0Z[/n 5Og>Q&XG%k441+ +hfid +STT\g/x
Tai+l#e[3X:&YӺ7GL2"_m +_azˠɚս+AJØ+L\:&S~r3JS_4_aR>;,mX{ +m +8]I}'LL0E{aW\{uAi"RdIۙzEլ*0TW5>rad?8!;_Hf:^Zs V[d +l|'.v0_²3L2ļ<y\T%jsg%BQ4 NI'p!mn{UqM%{z繻+n,0 tKc҈ijZE2)?=|/ +8nE+зM6.y2^ws6˅.rmm¬a:uy!h;|finڐk婢bkOHfשt'B45fKhYEI@lQ(CoAq(h5:PUcNSKu:ǸߘΟa95CK + +xnF'Ef^ J'`H 4te,Vo
7?k
+dz+('-wg=)M=Ӛ>
ݦK
Vqu<T$E?|ylQ#]ys@ZE
Ҫ$lKyW z }AG7tN4BE'YYMF *phni8frՒBؓ<h'"ω/$ e$T)a[,ܙz>SA6J7&^XKLJkM2 I`W6x<ҋ)zfVh%=ɍޥ/ +3nĈFRPzohkO(Gڼ^jH#i&WmLӦpҔ`n,"ۀ&7,e3%
u]={)ur/ۯ@&iDT{QyN`0ݤmv@clϮ`qju}=_;3
߅CAѭt\DY5!h.߹hOݎN-iqg*`qH/ƪ3yBP&]@m 1LwIhIs!!\`R
r#צ1C)%pڽ Lْˊ-[+ +ex,(remqɱ;MBB?ha>\fĦJ9.9,osZ4WaY +ꡎ|gHωa/31-#qʱhbODRSm8TU (!VmSH9=GtFצ:J2Ў*0IҡZQ'%|пaC+/·npbnXyLA9 EX5T`~Q
Y
^mYM'qe^[!]#U]}W:p쫹=ux +m߀:s[T*Y쇿|6VZ2JڈF+naj-I3$8Y])5aʤBv^u%dZ>cJ滰;G*xyRսЏS0Kˡub'Шj2)Eؕϵ%&G)AqjfddI?&U7Yј~Іڪ,/!{ӳ^t<'sZ]}Eߓzm]Q)h}J=,QIC2V(pRlI^-o?{g"2Z4MH^o7B0{$#]>p@ +sn|TY=hǏ"YNۑx0eV.\";$WD㧥:Fb8SikJvhNh"hc6:jOW'0Ni@↟miNG@5vȋLJK<av}t +kixeX*Whv#`/njip'**?mKHԝT4>(E<j_)*pt*'7AD/?qnuk(j:/uu1TQ7Q/`1>vwmܨ\,s\?\G +i:#<YnqhįLPT>9ߴfeeLTYN/ܙτY$)n`Ji_]D*fyXn7Zm?MΕ&T\P@[Pksm<}ufQȫ`8jy:0^v0@LL +dGE:ɦߡAϿq~ʀt9ظL
.F@ +0aUR'ŁA7IP+@ +^ړ;ftlGvejHJ'˷A#Pb|xe.qH +%ۅ!s3"y.fuHu, +s4U1IJ\Bs +VHN!1UC!eZa%JТ9xi&&NI4elp3z'y=j m5C%}~Q>3:jn6c5E՜t`1aVv3Fv^$<e:b +ldK x +\,RrFj +d +A+SqC\_Qs(|xptp7JR4
z[ֻz=^M.. +9hH4wFV
̎$(&u +iɾyP;cT?%5Mq*ڊkx7 Psou|=ë?r<_'[j
څR[?n"5v U2]I:[hZ#4Bh̸/skl'_/Zeq+`3&h{KƇv<默}+b0m`3|ڒYcԉ8og:噙bx~LX!_'u '8N^a. +:pf +36TGUV@
5?
Rt3q˜x"A<4Ab~ғ* FZXi@Z#H%R#DJn.hs=1<gOz0Xd_&JW-vL(0~8tR~GqS-У:\HسBRUjbnz;JDۓ/vޱtƶ :l]2, +a735J٧!<uo2iFF.ìm`0y枆-L?vݳ1H@F`x/,ny' +b韁O&2Ú#I/jsBƒHRpUp?MOb +lߖ"I]:adMɽē$]ن琍Qu2܇3Jh!DxFGLEAz2p1ݣ,Zdv+`H+ +S%pwmsRzHr`Xc2ɒ$!gfGXl[Ce~UgXފ\3ï.sfj<b'Su,1'y -q}c囌EGҘpy;&-!⡕䑆 /, '!SVIMqc +NIIELw)sD/^#h7zOR+U~H]
@"e6IiF`@}>u&9{VHV +F38✟B3N1It6Y͎Ʉ} +Np# $</TO@W8pTk|U,8HXg=q4]w="Q`蛈u;t +ۋؓ+aS},FJ'}8֊ūH\UiqΧj\PVal,A:zj[:)"E1~X#1ʴ +\um4F| Q0/H
x6L#ɟ">,(3n +^I*FB%}Usz ezp`x&&/ +nԜVFW姨.V):{ 5!>7%Ix, +I/k-6NX}1iWnC?i>b*^UN:Q\JZr=(䈜8OVl/
/bKiYdab
v$T{ +jiZXQa~]ILM~Y_/(^PAWT~h|h~aٲV-aLGa240, +:cv +=#6郷t&rVf|ED<#\0?؆#E]iDpz>+UD{SІ;;oo1==Z.N)I ΟzNzw7}_4XϝY_R&Ndᴢ)1IFOD& ;1i
uF]"Mtle唯QWh':.dHBe;8V'rOhj
11@sY1ƙm!R6_yHge +0ۆihJZaEC#H9g:Y#}Da^I{wgH,"T_#
F%Iyi@!Tv֪P0uù.۴scu +39rׯTq,+ ْz0+n9]^sS%l9_{c}"2"0)<vDZE&D}؝<H1it[ +Df{&=M"nMW(wvMx5<_Z +twbИP!g@4mId$f +%5yʖė[a@DD.:3QA +B;Vӳ6Mpy嫺=FT<whK[,첞
%Y{$_6c8\:OzQ=?T}1TwmElv& {Xc&7Jg: +4b@2yUxR%e<@}?UHMmop+Rn ȕD!}ͿN_NK%- ktG!O;;"9!{8{:뾏5J`Ȗ+WhvC|| +DR4e!,|duP"=dXCN0ݢw +D +q#a.yۭNX,Q?>NPI<u]|XQ.ydNJGX$`E#?ݰ/kV(V&CDdF/A>7lR+(8;?-{:)T~Gf`F0<#Ǿ/ +7.e>GluE"wlZ@1^'pRaH>4ddi'$Y-nɖٕLYE/L3H9k{v98}C2s ZY[3 BV#\hMtC=ˇ1]3}EX& >lÑFٳ#,z u̲ssjև
8d(CgC+xC)DM5P;@-)
*Y569ŇuHM>6y/roHNaQ%`kOL'ۆhg-xxPGa)c%]/<"+oqzz\,>+Ak
${_{.g)6^\ٖKP䳲wR3 L )]`rmkF~%rKIFan7~Q]mm}zauLq,僲gx70DÆB$ +gEf :*P#|F{V +PdL_2t}Oɨ]SB
UǠ`t_z3r:vy>^_p?vߥ!E!Y5G^mL+xpZC+@c03Ϩ hF#Kv.3UV"h"8VftҀ?w]ҥ9lV Y~PNM%|.meo7_T:|FCaYGIkpѪԈ%.l5h0X+)a;c/U*
W~b*4#Tw7"y?ZoAwA͙|mTD(=o2ORWe[yndefl'\:69[eXq^"<'[/.8])ul_u-%Ͽ4sQEh@KS QЖѱo05AHŲ|CmC:EڤY|i"F![ _^Q%4q۰Pv_r,xWYILi oO濍dÒPLH؋&C]l*oO@:)Q
+
W][e;YMW>$ +ךX0u&*yǢYq^m"Ƶ,fQL,C+)tJ;Ү,<{.x٥=1IS:A]j 2
P!~6s>WYt9lb8uakᡡLDUqB]mM-zW+y*xa?P>pn GFmջJ дwoɜ2ҨVBxrpRҵ(f-1?#/|pv[jvK!qd{S!?IjlLQeiz@>yrkA:]|92LštSF?ypOg$AWxľwzE_;S[BhۚH,d4c]ئ? ^u%H-oRr$Dsh8oآ OYR'pƺl]V]V(A#c!L82x$pU#|%T}>"!C=NnvTq~ +~iSdO
_wb`M=t9b)68ҕ=ر(Ѡ#F~KnJ?VQ_Z6+^#c1K%J?4E?3I?f#~Co uj\ g((㨘 +ud$en7 +A) +F'6z*/qɯ-(nY"w-^v _iyJY]V}m
*IڣJ }k'lvI0'̓ H_⹁WxoW7G/)_s<bwv&qH%bnŃN!VGwКdVP
2Xu숮$rbOjԜ+Ewnl٫{MWPf=ìDR* Xێ20BM6QA4@%oldEEe9&HGHp3c +s,M/6V+XpQM{"0<m\֗Y8n¡UC[ hYam +qV6`R
Dmg` +@ˁ֖;qNvZJu0
mٔbb
'=;B9QpNogQ٫%斔IJ5(/Ar"?g1i(~E| dG6FF']Ml{g>b"2Xť~ӽ!Y\a]~9AWbwzlkFd{PЄ7\C,#5U{uΞc)h&VJ$
zYzZ3#uGo6I=zO6BefOOcl{dDz1 7u3G8Prpjմڮp8TέSAw&+7o5_ diff --git a/hdcp_rx22/hdcp_rx22 b/hdcp_rx22/hdcp_rx22 index 5f29150..430c07f 100644 --- a/hdcp_rx22/hdcp_rx22 +++ b/hdcp_rx22/hdcp_rx22 @@ -1,78 +1,123 @@ -ELF - - -K
\ -}DJO -FHrIU0yD -\*I yD} -03/K -!C-*FO6" - -KJ {D -8F -FQF2F8F -0 F -JFGHFu78F1F2F -MBbhDh+FJFG - -) -,@ - -!!7 -DO0 - -SDQFC`"F0 -!hf B -i9DhjF$#G - -% {bh$!Wih2FGh"O#"JD -OsRFi -F!XW#'}D -! -IhRk OBD9((I J - 9FZC - - -3HV`xD8R" -bFK]{DT - 3YTHFD
-F
-FxD F8@ -F#FxDz I yDz F8@ -F#FxDH I yDH F8@ -Fh -F
-F
-F
-FxDr F8@ -F
-FxD F8@ -F
-F
-FxDh F8@ -OpOpOpOp -!`t!t -lh|p - +ELF + +03/K +i +FOy +4 +JC +O0 +O0e +O0 +(B7'{D!h + f +c +L +@W eT +T +iGahhhi@!G8B вJK!hzD{D +I +" +!" +K +VE + + + +8 +bFN + +FE +)BxxxC"`@ F +& +O1
F1FF +i + + +O
0 O +Z +6]DfE +ahhKiX!GOqB'J'K!hzD{D + +?I ?JyDzDbH !@q` +.HxD +I JyD + +IF +J + F@PF? +IF +J + +IF +J +Fd +IF +J +DO + +j F F +H +xD +O +P + +
(H + IF0FDD
H! +HxD HxD + +p!! + )$܀)6А)OР)@ +"1O@ + +6 +A + + + + +xD +!F +(FoBF +HxD + GpGF + h)F2Fi FG? +Nreu h +-
- е?D + +pJ +OT + FoG +p + bh^h +B& +xD +
dxDpGp($ +HxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpG}HxDpG{HxDpGxHxDpGvHxDpGsHxDpGqHxDpGnHxDpGlHxDpGiHxDpGgHxDpGdHxDpGbHxDpG_HxDpG]HxDpGZHxDpGXHxDpGUHxDpGSHxDpGPHxDpGMHxDpGJHxDpGHHxDpGEHxDpGCHxDpG@HxDpG>HxDpG;HxDpG9HxDpG6HxDpG4HxDpG1HxDpG/HxDpG,HxDpG*HxDpG'HxDpG%HxDpG"HxDpG HxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpG HxDpGHxDpGHxDpGHxDpG% +?o/o C02 +@-@ +$hXX&( +D + + + - - + + + + + + - - - - - - - - - + + + + + + - - - @@ -80,15 +125,20 @@ FxDh F8@ + + + + + + - - - + + @@ -96,9 +146,15 @@ FxDh F8@ - - - + + + + + + + + + A -"Dhdcp_rx22 +"&Dhdcp_rx22 diff --git a/hdcp_tx22/hdcp_tx22.contenttype1 b/hdcp_tx22/hdcp_tx22.contenttype1 deleted file mode 100644 index 72b964f..0000000 --- a/hdcp_tx22/hdcp_tx22.contenttype1 +++ b/dev/null @@ -1,165 +0,0 @@ -ELF - -03/K -i -bhhiGOqB@ -O{@nBٴ"R 5C/ɲf Fah$#"nhiRFG $>$Ѹ -yD h h -O0 -JK!hzD{D -O0 - f -c -L -@[ eT -Q -iGahhhi@!G8B вKJ{D!h -JK!hzD{D -" -!" -K -VE - - - -8 -bFN - -FE -)BxxxC"`@ F -& -O1
F1FF -i - - -O
0 O -Z -6]DfE -B -ahhKiX!GOqB%J%K!hzD{D -J -K!hzD{D -.HxD -I JyD - - -8h -GYIFYJ yDzDb -!FzDEJ !FzD2 -7 - -c -/йJzD'vhI(FyDF - - - -(EAF=JChzD <AF1JhzD xO - QFP8F LDI JyDzD4 -HxD -I -JyDzD - - )$܀)6А)OР)@ -"1O@ - -6 -A - - -W - - -xD -!F -(FoBF -HxD -- - GpGF - h)F2Fi FG? -Nreu h --
- е?D - -pJ -OT - FoG -p - bh^h -B& -xD -
dxDpGp($ -HxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpG}HxDpG{HxDpGxHxDpGvHxDpGsHxDpGqHxDpGnHxDpGlHxDpGiHxDpGgHxDpGdHxDpGbHxDpG_HxDpG]HxDpGZHxDpGXHxDpGUHxDpGSHxDpGPHxDpGMHxDpGJHxDpGHHxDpGEHxDpGCHxDpG@HxDpG>HxDpG;HxDpG9HxDpG6HxDpG4HxDpG1HxDpG/HxDpG,HxDpG*HxDpG'HxDpG%HxDpG"HxDpG HxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpGHxDpG HxDpGHxDpGHxDpGHxDpG& -% -?o/o C02 -@-@ -бԱܲT -|@DL8N\vxHT - \ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -A -"&Dhdcp_tx2201 diff --git a/patch/frameworks#base#0001.patch b/patch/frameworks#base#0001.patch deleted file mode 100644 index 5df96a5..0000000 --- a/patch/frameworks#base#0001.patch +++ b/dev/null @@ -1,41 +0,0 @@ -From 787a233d2b30b7aecc795d7a46d20b649cdbd033 Mon Sep 17 00:00:00 2001 -From: Chaomin Zheng <chaomin.zheng@amlogic.com> -Date: Wed, 5 Jul 2017 18:59:38 +0800 -Subject: [PATCH] PD #146924:remove HDMI/SPDIF device from fixed volume - devices - -Change-Id: Ib61a667204ebde2f4daa7f2043ebd6eecd18783c ---- - .../com/android/server/audio/AudioService.java | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java -index e5c3106..f1c9255 100644 ---- a/services/core/java/com/android/server/audio/AudioService.java -+++ b/services/core/java/com/android/server/audio/AudioService.java -@@ -546,11 +546,11 @@ public class AudioService extends IAudioService.Stub - = new RemoteCallbackList<IAudioRoutesObserver>(); - - // Devices for which the volume is fixed and VolumePanel slider should be disabled -- int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI | -+ int mFixedVolumeDevices = //AudioSystem.DEVICE_OUT_HDMI | - AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | - AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | - AudioSystem.DEVICE_OUT_HDMI_ARC | -- AudioSystem.DEVICE_OUT_SPDIF | -+ //AudioSystem.DEVICE_OUT_SPDIF | - AudioSystem.DEVICE_OUT_AUX_LINE; - int mFullVolumeDevices = 0; - -@@ -5402,7 +5402,7 @@ public class AudioService extends IAudioService.Stub - } - // Television devices without CEC service apply software volume on HDMI output - if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) { -- mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI; -+ //mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI; - checkAllFixedVolumeDevices(); - if (mHdmiManager != null) { - synchronized (mHdmiManager) { --- -1.7.9.5 - diff --git a/products/tv/init.amlogic.rc b/products/tv/init.amlogic.rc index ad50075..914b594 100644 --- a/products/tv/init.amlogic.rc +++ b/products/tv/init.amlogic.rc @@ -428,6 +428,13 @@ service hdcp_tx22 /vendor/bin/hdcp_tx22 \ disabled oneshot +service hdcp_rx22 /vendor/bin/hdcp_rx22 \ + -f /vendor/etc/firmware/firmware.le + class main + disabled + oneshot + seclabel u:r:hdcp_rx22:s0 + service ddrtest /vendor/bin/ddrtest.sh class main user root diff --git a/products/tv/product_tv.mk b/products/tv/product_tv.mk index 3b499d1..4174f12 100644 --- a/products/tv/product_tv.mk +++ b/products/tv/product_tv.mk @@ -2,44 +2,47 @@ $(call inherit-product, device/amlogic/common/core_amlogic.mk) #TV input HAL -#PRODUCT_PACKAGES += \ -# android.hardware.tv.input@1.0-impl \ -# android.hardware.tv.input@1.0-service \ -# tv_input.amlogic +PRODUCT_PACKAGES += \ + android.hardware.tv.input@1.0-impl \ + android.hardware.tv.input@1.0-service \ + tv_input.amlogic # TV -#PRODUCT_PACKAGES += \ -# libtv \ -# libtv_linker \ -# libtvbinder \ -# libtv_jni \ -# tvserver \ -# libtvplay \ -# libTVaudio \ -# libntsc_decode \ -# libtinyxml \ -# libzvbi \ -# tv_input.amlogic \ -# droidlogic-tv \ -# TvProvider \ -# DroidLogicTvInput \ -# DroidLogicTvSource \ -# libhpeq.so \ -# libjnidtvsubtitle \ -# libjnidtvepgscanner -# -## DTV -#PRODUCT_PACKAGES += \ -# libam_adp \ -# libam_mw \ -# libam_ver \ -# libam_sysfs +PRODUCT_PACKAGES += \ + libtv \ + libtv_linker \ + libtvbinder \ + libtv_jni \ + tvserver \ + libtvplay \ + libTVaudio \ + libntsc_decode \ + libtinyxml \ + libzvbi \ + droidlogic-tv \ + TvProvider \ + DroidLogicTvInput \ + DroidLogicTvSource \ + DroidLogicFactoryMenu \ + libjnidtvsubtitle \ + libjnidtvepgscanner + +# DTV +PRODUCT_PACKAGES += \ + libam_adp \ + libam_mw \ + libam_ver \ + libam_sysfs PRODUCT_PACKAGES += \ imageserver \ busybox \ utility_busybox +# LiveTv +PRODUCT_PACKAGES += \ + DroidLiveTv + # DLNA ifneq ($(TARGET_BUILD_GOOGLE_ATV), true) PRODUCT_PACKAGES += \ @@ -75,12 +78,6 @@ PRODUCT_PROPERTY_OVERRIDES += ro.hdmi.device_type=0 PRODUCT_PACKAGES += \ TvSettings - -#USB PM -PRODUCT_PACKAGES += \ - usbtestpm \ - usbpower - PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.software.live_tv.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.live_tv.xml \ frameworks/native/data/etc/android.software.app_widgets.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.app_widgets.xml \ @@ -89,6 +86,7 @@ PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.location.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.location.xml \ device/amlogic/common/android.software.leanback.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.leanback.xml \ frameworks/native/data/etc/android.hardware.hdmi.cec.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.hdmi.cec.xml + #copy lowmemorykiller.txt ifeq ($(BUILD_WITH_LOWMEM_COMMON_CONFIG),true) PRODUCT_COPY_FILES += \ @@ -97,10 +95,6 @@ PRODUCT_COPY_FILES += \ device/amlogic/common/config/lowmemorykiller_512M.txt:$(TARGET_COPY_OUT_VENDOR)/etc/lowmemorykiller_512M.txt endif -#DDR LOG -PRODUCT_COPY_FILES += \ - device/amlogic/common/ddrtest.sh:$(TARGET_COPY_OUT_VENDOR)/bin/ddrtest.sh - # USB PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.usb.host.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.usb.host.xml \ @@ -110,9 +104,16 @@ custom_keylayouts := $(wildcard device/amlogic/common/keyboards/*.kl) PRODUCT_COPY_FILES += $(foreach file,$(custom_keylayouts),\ $(file):$(TARGET_COPY_OUT_VENDOR)/usr/keylayout/$(notdir $(file))) -# hdcp_tx22 +# hdcp_rx key tools and firmware PRODUCT_COPY_FILES += \ - $(LOCAL_PATH)/../../hdcp_tx22/hdcp_tx22:$(TARGET_COPY_OUT_VENDOR)/bin/hdcp_tx22 + device/amlogic/common/hdcp_rx22/hdcp_rx22:$(TARGET_COPY_OUT_VENDOR)/bin/hdcp_rx22 \ + device/amlogic/common/hdcp_rx22/arm_tools/aictool:$(TARGET_COPY_OUT_VENDOR)/bin/aictool \ + device/amlogic/common/hdcp_rx22/arm_tools/esm_swap:$(TARGET_COPY_OUT_VENDOR)/bin/esm_swap \ + device/amlogic/common/hdcp_rx22/arm_tools/hdcprxkeys:$(TARGET_COPY_OUT_VENDOR)/bin/hdcprxkeys \ + device/amlogic/common/hdcp_rx22/firmware/esm_config.i:$(TARGET_COPY_OUT_VENDOR)/etc/firmware/hdcp_rx22/esm_config.i \ + device/amlogic/common/hdcp_rx22/firmware/firmware.rom:$(TARGET_COPY_OUT_VENDOR)/etc/firmware/hdcp_rx22/firmware.rom \ + device/amlogic/common/hdcp_rx22/firmware/firmware.aic:$(TARGET_COPY_OUT_VENDOR)/etc/firmware/hdcp_rx22/firmware.aic \ + device/amlogic/common/hdcp_rx22/firmware/firmware.le:$(TARGET_COPY_OUT_VENDOR)/etc/firmware/hdcp_rx22/firmware.le # bootanimation PRODUCT_COPY_FILES += \ @@ -122,10 +123,18 @@ PRODUCT_COPY_FILES += \ PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/tv.mp4:$(TARGET_COPY_OUT_VENDOR)/etc/bootvideo +# TV EQ +PRODUCT_COPY_FILES += \ + $(BOARD_AML_VENDOR_PATH)/external/libaudioeffect/EQ/lib/libhpeq.so:$(TARGET_COPY_OUT_VENDOR)lib/soundfx/libhpeq.so \ + $(BOARD_AML_VENDOR_PATH)/external/libaudioeffect/EQ/lib64/libhpeq.so:$(TARGET_COPY_OUT_VENDOR)/lib64/soundfx/libhpeq.so + # default wallpaper for mbox to fix bug 106225 PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/default_wallpaper.png:$(TARGET_COPY_OUT_VENDOR)/etc/default_wallpaper.png +#ADDITIONAL_BUILD_PROPERTIES += \ +# ro.config.wallpaper=$(TARGET_COPY_OUT_VENDOR)/etc/default_wallpaper.png + # Include BUILD_NUMBER if defined VERSION_ID=$(shell find device/*/$(TARGET_PRODUCT) -name version_id.mk) $(call inherit-product, $(VERSION_ID)) @@ -134,8 +143,4 @@ DISPLAY_BUILD_NUMBER := true # default timezone PRODUCT_PROPERTY_OVERRIDES += \ - persist.sys.timezone=Asia/Shanghai - -#TV project,set omx to video layer,or PQ hasn't effect -PRODUCT_PROPERTY_OVERRIDES += \ - media.omx.display_mode=1
\ No newline at end of file + persist.sys.timezone=Asia/Shanghai
\ No newline at end of file diff --git a/recovery/Android.mk b/recovery/Android.mk deleted file mode 100644 index 3c93256..0000000 --- a/recovery/Android.mk +++ b/dev/null @@ -1,8 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(LOCAL_PATH)/recovery_extra/Android.mk \ - $(LOCAL_PATH)/ubootenv/Android.mk \ - $(LOCAL_PATH)/fdt/Android.mk \ - $(LOCAL_PATH)/check/Android.mk \ - $(LOCAL_PATH)/ui/Android.mk \ - $(LOCAL_PATH)/updater_extra/Android.mk
\ No newline at end of file diff --git a/recovery/check/Android.mk b/recovery/check/Android.mk deleted file mode 100644 index 0f1921f..0000000 --- a/recovery/check/Android.mk +++ b/dev/null @@ -1,27 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := security.cpp dtbcheck.cpp - -LOCAL_MODULE := libsecurity - -LOCAL_C_INCLUDES += bootable/recovery - -LOCAL_C_INCLUDES += \ - system/core/base/include \ - system/core/libziparchive/include - -LOCAL_C_INCLUDES += $(LOCAL_PATH)/../ - -LOCAL_STATIC_LIBRARIES := libcutils libselinux - -LOCAL_CLANG := true - -LOCAL_CFLAGS += -Wall - -ifeq ($(OTA_UP_PART_NUM_CHANGED), true) -LOCAL_CFLAGS += -DSUPPORT_PARTNUM_CHANGE -endif - -include $(BUILD_STATIC_LIBRARY) diff --git a/recovery/check/dtbcheck.cpp b/recovery/check/dtbcheck.cpp deleted file mode 100644 index 9d13bee..0000000 --- a/recovery/check/dtbcheck.cpp +++ b/dev/null @@ -1,860 +0,0 @@ -#include <errno.h> -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <ziparchive/zip_archive.h> -#include "dtbcheck.h" - - -extern "C" { -#include "fdt/libfdt.h" -} - - - -#define MAX_LEVEL 32 /* how deeply nested we will go */ -#define CONFIG_CMD_FDT_MAX_DUMP 64 - -#define DT_HEADER_MAGIC 0xedfe0dd0 /*header of dtb file*/ -#define AML_DT_HEADER_MAGIC 0x5f4c4d41 /*"AML_", multi dtbs supported*/ - -#define AML_DT_ID_VARI_TOTAL 3 //Total 3 strings -/*Latest version: v2*/ -#define AML_DT_VERSION_OFFSET 4 -#define AML_DT_TOTAL_DTB_OFFSET 8 -#define AML_DT_FIRST_DTB_OFFSET 12 - -#define AML_DT_DTB_DT_INFO_OFFSET 0 - -#define ENV_DTB "aml_dt" -#define CMDLINE "/proc/cmdline" -#define STORE_DEVICE "/sys/class/aml_store/store_device" -#define DEVICE_NAND 2 -#define DEVICE_EMMC 1 - -extern int IsPlatformEncrypted(void); - -extern int DtbImgEncrypted( - const char *imageName, - const unsigned char *imageBuffer, - const int imageSize, - const char *flag, - unsigned char *encryptedbuf); - -struct fdt_header *working_fdt; - -static Dtb_Partition_S dtb_zip[24]; -static Dtb_Partition_S dtb_dev[24]; - -unsigned int recovery_size1 = 32*1024*1024; //default value 32M - -static int isEncrypted = 0; - -struct Dtb_header { - unsigned int dt_magic; - unsigned int dt_tool_version; - unsigned int dt_total; - char data[0]; -}; - - -/****************************************************************************/ - - -unsigned int -STRTOU32(unsigned char* p){ - return (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0]; -} - -int GetDeviceType() -{ - FILE *p = NULL; - int len = 0; - char buffer[32] = {0}; - int type = 0; - - p = fopen(STORE_DEVICE, "r"); - if (p == NULL) { - printf("open failed!\n"); - return -1; - } - - len = fread(buffer, 1, 32, p); - if (len <= 0) { - printf("fread failed!\n"); - fclose(p); - return -1; - } - fclose(p); - - printf("buffer:%s\n",buffer); - - type = atoi(buffer); - printf("type=%d\n",type); - return type; -} - -signed int -GetDtbId(char *pdt){ - FILE *p = NULL; - int len = 0; - char buffer[1024] = {0}; - - if (pdt == NULL) { - printf("param error!\n"); - return -1; - } - - p = fopen(CMDLINE, "r"); - if (p == NULL) { - printf("open failed!\n"); - return -1; - } - - len = fread(buffer, 1, 1023, p); - if (len <= 0) { - printf("fread failed!\n"); - fclose(p); - return -1; - } - fclose(p); - - char *paddr=strstr(buffer, ENV_DTB); - if (paddr == NULL) { - printf("not find env:aml_dt !\n"); - return -1; - } - - paddr = strtok(paddr, " "); - - paddr = paddr+strlen(ENV_DTB)+1; - //printf("cmdline, aml_dt=%s\n", paddr); - - strcpy(pdt, paddr); - return 0; -} - - -/* - * Heuristic to guess if this is a string or concatenated strings. - */ - -static int -is_printable_string(const void *data, int len){ - const char *s = (char *)data; - - /* zero length is not */ - if (len == 0) - return 0; - - /* must terminate with zero or '\n' */ - if (s[len - 1] != '\0' && s[len - 1] != '\n') - return 0; - - /* printable or a null byte (concatenated strings) */ - while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) { - /* - * If we see a null, there are three possibilities: - * 1) If len == 1, it is the end of the string, printable - * 2) Next character also a null, not printable. - * 3) Next character not a null, continue to check. - */ - if (s[0] == '\0') { - if (len == 1) - return 1; - if (s[1] == '\0') - return 0; - } - s++; - len--; - } - - /* Not the null termination, or not done yet: not printable */ - if (*s != '\0' || (len != 0)) - return 0; - - return 1; -} - - - -/* - * Print the property in the best format, a heuristic guess. Print as - * a string, concatenated strings, a byte, word, double word, or (if all - * else fails) it is printed as a stream of bytes. - */ -static void print_data(const void *data, int len, int *index, int flag) -{ - int j; - - char *pd = (char *)data; - - /* no data, don't print */ - if (len == 0) - return; - - /* - * It is a string, but it may have multiple strings (embedded '\0's). - */ - if (is_printable_string(pd, len)) { - j = 0; - while (j < len) { - if (flag == 0) { - strcpy(dtb_zip[*index].partition_name, pd); - } else { - strcpy(dtb_dev[*index].partition_name, pd); - } - j += strlen(pd) + 1; - pd += strlen(pd) + 1; - } - return; - } - - if ((len %4) == 0) { - if (len > CONFIG_CMD_FDT_MAX_DUMP) - ; - else if (len == 8){ - const __be32 *p; - p = (__be32 *)pd; - if (flag == 0) - { - dtb_zip[*index].partition_size = fdt32_to_cpu(p[1]) - fdt32_to_cpu(p[0]); - } - else - { - dtb_dev[*index].partition_size = fdt32_to_cpu(p[1]) - fdt32_to_cpu(p[0]); - } - (*index)++; - } - } else { /* anything else... hexdump */ - if (len > CONFIG_CMD_FDT_MAX_DUMP) - ; - else { - const unsigned char *s; - } - } -} - - -int -GetPartitionFromDtb(const char *pathp, int depth, int *partition_num, int flag){ - static char tabs[MAX_LEVEL+1] = - "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" - "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; - const void *nodep; /* property node pointer */ - int nodeoffset; /* node offset from libfdt */ - int index = 0; - int nextoffset; /* next node offset from libfdt */ - uint32_t tag; /* tag */ - int len; /* length of the property */ - int level = 0; /* keep track of nesting level */ - const struct fdt_property *fdt_prop; - - nodeoffset = fdt_path_offset (working_fdt, pathp); - if (nodeoffset < 0) { - /* - * Not found or something else bad happened. - */ - printf ("libfdt fdt_path_offset() returned %s\n", - fdt_strerror(nodeoffset)); - return 1; - } - - - /* - * The user passed in a node path and no property, - * print the node and all subnodes. - */ - while (level >= 0) { - tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset); - switch (tag) { - case FDT_BEGIN_NODE: - pathp = fdt_get_name(working_fdt, nodeoffset, NULL); - if (level <= depth) { - if (pathp == NULL) - pathp = "/* NULL pointer error */"; - if (*pathp == '\0') - pathp = "/"; /* root is nameless */ - } - level++; - if (level >= MAX_LEVEL) { - printf("Nested too deep, aborting.\n"); - return 1; - } - break; - case FDT_END_NODE: - level--; - if (level <= depth) - ; - if (level == 0) { - level = -1; /* exit the loop */ - } - break; - case FDT_PROP: - fdt_prop = (struct fdt_property *)fdt_offset_ptr(working_fdt, nodeoffset, - sizeof(*fdt_prop)); - pathp = fdt_string(working_fdt, - fdt32_to_cpu(fdt_prop->nameoff)); - len = fdt32_to_cpu(fdt_prop->len); - nodep = fdt_prop->data; - if (len < 0) { - printf ("libfdt fdt_getprop(): %s\n", - fdt_strerror(len)); - return 1; - } else if (len == 0) { - /* the property has no value */ - if (level <= depth) - ; - } else { - if (level <= depth) { - print_data (nodep, len, &index, flag); - } - } - break; - case FDT_NOP: - printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]); - break; - case FDT_END: - return 1; - default: - if (level <= depth) - printf("Unknown tag 0x%08X\n", tag); - return 1; - } - nodeoffset = nextoffset; - } - - *partition_num = index; - return 0; -} - -unsigned char * -GetMultiDtbEntry(unsigned char *fdt_addr, int *plen){ - unsigned int dt_magic = STRTOU32(fdt_addr); - signed int dt_total = 0; - unsigned int dt_tool_version = 0; - - //printf(" Amlogic multi-dtb tool\n"); - if (dt_magic == DT_HEADER_MAGIC) {/*normal dtb*/ - printf(" Single dtb detected\n"); - return fdt_addr; - } - else if (dt_magic == AML_DT_HEADER_MAGIC) {/*multi dtb*/ - printf(" Multi dtb detected\n"); - /* check and set aml_dt */ - int i = 0; - char *aml_dt_buf; - aml_dt_buf = (char *)malloc(sizeof(char)*64); - memset(aml_dt_buf, 0, sizeof(aml_dt_buf)); - - GetDtbId(aml_dt_buf); - //printf("aml_dt_buf:%s\n", aml_dt_buf); - - unsigned int aml_dt_len = aml_dt_buf ? strlen(aml_dt_buf) : 0; - if (aml_dt_len <= 0) { - printf("Get env aml_dt failed!Ignore dtb check !\n"); - *plen = 0; - return fdt_addr; - } - - /*version control, compatible with v1*/ - dt_tool_version = STRTOU32(fdt_addr + AML_DT_VERSION_OFFSET); - unsigned int aml_each_id_length=0; - unsigned int aml_dtb_offset_offset; - unsigned int aml_dtb_header_size; - - if (dt_tool_version == 1) - aml_each_id_length = 4; - else if(dt_tool_version == 2) - aml_each_id_length = 16; - - aml_dtb_offset_offset = aml_each_id_length * AML_DT_ID_VARI_TOTAL; - aml_dtb_header_size = 8+(aml_each_id_length * AML_DT_ID_VARI_TOTAL); - //printf(" Multi dtb tool version: v%d .\n", dt_tool_version); - - /*fdt_addr + 0x8: num of dtbs*/ - dt_total = STRTOU32(fdt_addr + AML_DT_TOTAL_DTB_OFFSET); - //printf(" Support %d dtbs.\n", dt_total); - - /* split aml_dt to 3 strings */ - char *tokens[3] = {NULL, NULL, NULL}; - for (i = 0; i < AML_DT_ID_VARI_TOTAL; i++) { - tokens[i] = strsep(&aml_dt_buf, "_"); - } - - if (aml_dt_buf) - free(aml_dt_buf); - //printf(" aml_dt soc: %s platform: %s variant: %s\n", tokens[0], tokens[1], tokens[2]); - - /*match and print result*/ - char **dt_info; - dt_info = (char **)malloc(sizeof(char *)*AML_DT_ID_VARI_TOTAL); - for (i = 0; i < AML_DT_ID_VARI_TOTAL; i++) - dt_info[i] = (char *)malloc(sizeof(char)*aml_each_id_length); - - unsigned int dtb_match_num = 0xffff; - unsigned int x = 0, y = 0, z = 0; //loop counter - unsigned int read_data; - for (i = 0; i < dt_total; i++) { - for (x = 0; x < AML_DT_ID_VARI_TOTAL; x++) { - for (y = 0; y < aml_each_id_length; y+=4) { - read_data = STRTOU32(fdt_addr + AML_DT_FIRST_DTB_OFFSET + \ - i * aml_dtb_header_size + AML_DT_DTB_DT_INFO_OFFSET + \ - (x * aml_each_id_length) + y); - dt_info[x][y+0] = (read_data >> 24) & 0xff; - dt_info[x][y+1] = (read_data >> 16) & 0xff; - dt_info[x][y+2] = (read_data >> 8) & 0xff; - dt_info[x][y+3] = (read_data >> 0) & 0xff; - } - - for (z=0; z<aml_each_id_length; z++) { - /*fix string with \0*/ - if (0x20 == (uint)dt_info[x][z]) { - dt_info[x][z] = '\0'; - } - } - } - - if (dt_tool_version == 1) - printf(" dtb %d soc: %.4s plat: %.4s vari: %.4s\n", i, (char *)(dt_info[0]), (char *)(dt_info[1]), (char *)(dt_info[2])); - else if(dt_tool_version == 2) - printf(" dtb %d soc: %.16s plat: %.16s vari: %.16s\n", i, (char *)(dt_info[0]), (char *)(dt_info[1]), (char *)(dt_info[2])); - uint match_str_counter = 0; - - for (z=0; z<AML_DT_ID_VARI_TOTAL; z++) { - /*must match 3 strings*/ - if (!strncmp(tokens[z], (char *)(dt_info[z]), strlen(tokens[z])) && \ - (strlen(tokens[z]) == strlen(dt_info[z]))) - match_str_counter++; - } - - if (match_str_counter == AML_DT_ID_VARI_TOTAL) { - //printf("Find match dtb\n"); - dtb_match_num = i; - } - - for (z=0; z<AML_DT_ID_VARI_TOTAL; z++) { - /*clear data for next loop*/ - memset(dt_info[z], 0, sizeof(aml_each_id_length)); - } - } - - /*clean malloc memory*/ - for (i = 0; i < AML_DT_ID_VARI_TOTAL; i++) { - if (dt_info[i]) - free(dt_info[i]); - } - - if (dt_info) - free(dt_info); - - /*if find match dtb, return address, or else return main entrance address*/ - if (0xffff != dtb_match_num) { - printf(" Find match dtb: %d\n", dtb_match_num); - /*this offset is based on dtb image package, so should add on base address*/ - *plen = STRTOU32(fdt_addr + AML_DT_FIRST_DTB_OFFSET + \ - dtb_match_num * aml_dtb_header_size + aml_dtb_offset_offset+4); - return fdt_addr + STRTOU32(fdt_addr + AML_DT_FIRST_DTB_OFFSET + \ - dtb_match_num * aml_dtb_header_size + aml_dtb_offset_offset); - } else { - printf(" Not match any dtb.\n"); - return NULL; - } - } else { - printf(" Cannot find legal dtb!\n"); - return NULL; - } - - return NULL; -} - - -/** - * --- get upgrade package image data - * - * @zipArchive: zip archive object - * @imageName: upgrade package image's name - * @imageSize: upgrade package image's size - * - * return value: - * <0: failed - * =0: can't find image - * >0: get image data successful - */ -static unsigned char *s_pDtbBuffer = NULL; -static int -GetZipDtbImage(const ZipArchiveHandle za, const char *imageName, int *imageSize){ - int len = 0; - int ret = 0; - unsigned char *paddr = NULL; - - ZipString zip_path(imageName); - ZipEntry entry; - if (FindEntry(za, zip_path, &entry) != 0) { - printf("no %s in package!\n", imageName); - return 0; - } - - *imageSize = entry.uncompressed_length; - if (*imageSize <= 0) { - printf("can't get package entry uncomp len(%d) (%s)\n",*imageSize, strerror(errno)); - return -1; - } - - len = *imageSize; - - unsigned char* buffer = (unsigned char *)calloc(len, sizeof(unsigned char)); - if (!buffer) { - printf("can't malloc %d size space (%s)\n",len, strerror(errno)); - return -1; - } - - ret = ExtractToMemory(za, &entry, buffer, entry.uncompressed_length); - if (ret != 0) { - printf("can't extract package entry to image buffer\n"); - free(buffer); - return -1; - } - - - if (isEncrypted == 1) { - ret = DtbImgEncrypted(DTB_IMG, buffer, len, "1", buffer); - if (ret == 2) { - printf("no decrypt_dtb and no support!"); - free(buffer); - return 2; - }else if (ret <= 0) { - printf("dtb.img encrypt from zip failed!\n"); - free(buffer); - return -1; - } - } - - paddr = GetMultiDtbEntry(buffer, &len); - if (paddr == NULL) - { - printf("Cannot find legal dtb from zip \n"); - free(buffer); - return -1; - } else if (len == 0) { - printf("No need to check dtb \n"); - free(buffer); - return 2; - } - - if (s_pDtbBuffer != NULL) { - free(s_pDtbBuffer); - s_pDtbBuffer = NULL; - } - - s_pDtbBuffer = (unsigned char *)calloc(len, sizeof(unsigned char)); - if (!s_pDtbBuffer) { - printf("can't malloc %d size space (%s)\n",len, strerror(errno)); - free(buffer); - return -1; - } - - memcpy(s_pDtbBuffer, paddr, len); - free(buffer); - - return 1; -} - -static int -GetDevDtbImage(){ - int fd = 0; - int len = 0; - int ret = 0; - unsigned char *paddr = NULL; - const char *DTB_DEV= "/dev/dtb"; - const int DTB_DATA_MAX = 256*1024; - - unsigned char* buffer = (unsigned char *)calloc(DTB_DATA_MAX+256, sizeof(unsigned char)); - if (buffer == NULL) { - printf("malloc %d failed!\n", DTB_DATA_MAX+256); - return -1; - } - - fd = open(DTB_DEV, O_RDONLY); - if (fd < 0) { - printf("open %s failed!\n", DTB_DEV); - free(buffer); - return -1; - } - - len = read(fd, buffer, DTB_DATA_MAX); - if (len < 0) { - printf("read failed len = %d\n", len); - close(fd); - free(buffer); - return -1; - } - - close(fd); - - if (isEncrypted == 1) { - ret = DtbImgEncrypted(DTB_IMG, buffer, len, "1", buffer); - if (ret <= 0) { - printf("dtb.img encrypt from dev failed!\n"); - free(buffer); - return -1; - } - } - paddr = GetMultiDtbEntry(buffer, &len); - if (paddr == NULL) { - printf("Cannot find legal dtb from dev block \n"); - free(buffer); - return -1; - } - - if (s_pDtbBuffer != NULL) { - free(s_pDtbBuffer); - s_pDtbBuffer = NULL; - } - - s_pDtbBuffer = (unsigned char *)calloc(len, sizeof(unsigned char)); - if (s_pDtbBuffer == NULL) { - printf("malloc %d failed!\n", len); - free(buffer); - return -1; - } - - memcpy(s_pDtbBuffer, paddr, len); - free(buffer); - - return 0; -} - -int -GetEnvPartitionOffset(const ZipArchiveHandle za) { - int i = 0; - int find = 0; - int ret = -1; - int offset = 116*1024*1024; //bootloader(4M) GAP(32M) reserved(64M) GAP(8M) cache(--) GAP(8M) - int imageSize = 0; - int partition_num_zip = 0; - - ret = GetZipDtbImage(za, DTB_IMG, &imageSize); - if ((ret == 0) || (ret == 2)) { - printf("no dtb.img in the update or no need check dtb, check dtb over!\n"); - return 0; - } else if (ret < 0) { - printf("get dtb.img from update.zip failed!\n"); - ret = -1; - goto END; - } - - working_fdt = (struct fdt_header *)s_pDtbBuffer; - - ret = GetPartitionFromDtb("/partitions", MAX_LEVEL, &partition_num_zip, 0); - if (ret != 0) { - printf("get partition map from dtb.img failed!\n"); - ret = -1; - goto END; - } - - for (i=0; i<partition_num_zip;i++) { - printf("%s:0x%08x\n", dtb_zip[i].partition_name, dtb_zip[i].partition_size); - if (!strcmp("cache", dtb_zip[i].partition_name)) { - offset += dtb_zip[i].partition_size; - find = 1; - } - } - - if (find == 0) { - printf("get cache partition size from dtb.img failed!\n"); - ret = -1; - goto END; - } - printf("env partition offset:0x%08x\n", offset); - - ret = offset; - -END: - if (s_pDtbBuffer != NULL) - { - free(s_pDtbBuffer); - s_pDtbBuffer = NULL; - } - - return ret; -} - -int -RecoveryDtbCheck(const ZipArchiveHandle za){ - int i = 0, ret = -1, err = -1; - int fd = -1; - int partition_num_zip = 0; - int partition_num_dev = 0; - int imageSize = 0; - int recovery_dev = 0, recovery_zip = 0; - int data_dev = 0, data_zip = 0; - int recovery_offset_dev = 0, recovery_offset_zip = 0; - int data_offset_dev = 0, data_offset_zip = 0; - int device_type = 0; - int partition_num; - int cache_offset_dev = 0, cache_offset_zip = 0; - int recovery_size_dev = 0, recovery_size_zip = 0; - int cache_size_dev = 0, cache_size_zip = 0; - - isEncrypted = IsPlatformEncrypted(); - if (isEncrypted == 2) { - printf("kernel doesn't support!\n"); - return 0; - } else if (isEncrypted < 0) { - return -1; - } - - ret = GetZipDtbImage(za, DTB_IMG, &imageSize); - if ((ret == 0) || (ret == 2)) { - printf("no dtb.img in the update or no need check dtb, check dtb over!\n"); - return 0; - } else if (ret < 0) { - printf("get dtb.img from update.zip failed!\n"); - ret = -1; - goto END; - } - - working_fdt = (struct fdt_header *)s_pDtbBuffer; - - ret = GetPartitionFromDtb("/partitions", MAX_LEVEL, &partition_num_zip, 0); - if (ret != 0) { - printf("get partition map from dtb.img failed!\n"); - ret = -1; - goto END; - } - - ret = GetDevDtbImage(); - if (ret != 0) { - printf("read dtb from /dev/dtb failed!\n"); - ret = -1; - goto END; - } - - working_fdt = (struct fdt_header *)s_pDtbBuffer; - ret = GetPartitionFromDtb("/partitions", MAX_LEVEL, &partition_num_dev, 1); - if (ret != 0) { - printf("get partition map from /dev/dtb failed!\n"); - ret = -1; - goto END; - } - - partition_num = partition_num_dev; - device_type = GetDeviceType(); - printf("device_type = %d \n",device_type); - - if (partition_num_zip != partition_num_dev) { - printf("partition num don't match zip:%d, dev:%d\n",partition_num_zip, partition_num_dev); - if (device_type == DEVICE_NAND) { - printf("the partitions changed & device is nand! can not upgrade!\n "); - ret = -1; - goto END; - } - #ifdef SUPPORT_PARTNUM_CHANGE - ret = 2; - partition_num = partition_num_zip > partition_num_dev ? partition_num_zip : partition_num_dev; - #else - printf("partition num don't match zip:%d, dev:%d, can not upgrade!\n",partition_num_zip, partition_num_dev); - ret = -1; - goto END; - #endif - } - printf("partition_num = %d \n",partition_num); - - for (i=0; i<partition_num;i++) { - printf("%s:0x%08x\n", dtb_zip[i].partition_name, dtb_zip[i].partition_size); - printf("%s:0x%08x\n", dtb_dev[i].partition_name, dtb_dev[i].partition_size); - - if (!strcmp("recovery", dtb_dev[i].partition_name)) { - recovery_size1 = dtb_zip[i].partition_size; - recovery_dev = i; - recovery_size_dev = dtb_dev[i].partition_size; - } - if (!strcmp("recovery", dtb_zip[i].partition_name)) { - recovery_zip = i; - recovery_size_zip = dtb_zip[i].partition_size; - } - - if (!strcmp("data", dtb_dev[i].partition_name)) { - data_dev = i; - } - if (!strcmp("data", dtb_zip[i].partition_name)) { - data_zip = i; - } - - if (!strcmp("cache", dtb_dev[i].partition_name)) { - cache_size_dev = dtb_dev[i].partition_size; - } - if (!strcmp("cache", dtb_zip[i].partition_name)) { - cache_size_zip = dtb_zip[i].partition_size; - } - - if ((strcmp(dtb_zip[i].partition_name, dtb_dev[i].partition_name) != 0)|| - (dtb_zip[i].partition_size != dtb_dev[i].partition_size)) { - ret = 2; - /*just emmc support partition changes*/ - if (device_type == DEVICE_NAND) { - printf("the partitions changed & device is nand! can not upgrade!\n "); - ret = -1; - goto END; - } - } - } - - /*the offset of recovery/data cannot be changed*/ - for (i=0;i<recovery_dev;i++) { - recovery_offset_dev += dtb_dev[i].partition_size; - } - for (i=0;i<recovery_zip;i++) { - recovery_offset_zip += dtb_zip[i].partition_size; - } - for (i=0;i<data_dev;i++) { - data_offset_dev += dtb_dev[i].partition_size; - } - for (i=0;i<data_zip;i++) { - data_offset_zip += dtb_zip[i].partition_size; - } - - for (i=0;i<2;i++) { - cache_offset_dev += dtb_dev[i].partition_size; - cache_offset_zip += dtb_zip[i].partition_size; - } - - printf("recovery_dev: %d recovery_offset_dev :0x%08x\n", recovery_dev, recovery_offset_dev); - printf("recovery_zip: %d recovery_offset_zip :0x%08x\n", recovery_zip, recovery_offset_zip); - printf("data_dev: %d data_offset_dev :0x%08x\n", data_dev, data_offset_dev); - printf("data_zip: %d data_offset_zip :0x%08x\n", data_zip, data_offset_zip); - printf("cache_offset_dev :0x%08x, cache_size_dev: %d\n", cache_offset_dev, cache_size_dev); - printf("cache_offset_zip :0x%08x, cache_size_zip: %d\n", cache_offset_zip, cache_size_zip); - - if (data_offset_dev != data_offset_zip) { - printf("data changed, need wipe_data\n "); - ret = 3; - } - - if ((recovery_offset_dev != recovery_offset_zip) || (recovery_size_dev != recovery_size_zip)) { - printf("recovery part changed! can not upgrade!\n "); - ret = -1; - goto END; - } - - if ((cache_offset_dev != cache_offset_zip) || (cache_size_dev != cache_size_zip)) { - printf("cache part changed! can not upgrade!\n "); - ret = -1; - goto END; - } - -END: - if (s_pDtbBuffer != NULL) - { - free(s_pDtbBuffer); - s_pDtbBuffer = NULL; - } - - return ret; -} diff --git a/recovery/check/dtbcheck.h b/recovery/check/dtbcheck.h deleted file mode 100644 index eb9691d..0000000 --- a/recovery/check/dtbcheck.h +++ b/dev/null @@ -1,15 +0,0 @@ -#ifndef _SECURITY_H_ -#define _SECURITY_H_ - -#define DTB_IMG "dtb.img" - -extern unsigned int recovery_size1; - -typedef struct Dtb_Partition_s -{ - char partition_name[16]; - unsigned int partition_size; -}Dtb_Partition_S; - - -#endif
\ No newline at end of file diff --git a/recovery/check/security.cpp b/recovery/check/security.cpp deleted file mode 100644 index 8c48cdf..0000000 --- a/recovery/check/security.cpp +++ b/dev/null @@ -1,578 +0,0 @@ -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/mount.h> -#include <string.h> - -#include <ziparchive/zip_archive.h> -#include <android-base/logging.h> - -#include "common.h" -#include "cutils/properties.h" -#include "security.h" - -T_KernelVersion kernel_ver = KernelV_3_10; -/** - * --- judge platform whether match with zip image or not - * - * @platformEncryptStatus: 0: platform unencrypted, 1: platform encrypted - * @imageEncryptStatus: 0: image unencrypted, 1: image encrypted - * @imageName: image name - * @imageBuffer: image data address - * @imageSize: image data size - * - * return value: - * <0: failed - * =0: not match - * >0: match - */ -static int IsPlatformMachWithZipArchiveImage( - const int platformEncryptStatus, - const int imageEncryptStatus, - const char *imageName, - const unsigned char *imageBuffer, - const int imageSize) -{ - int fd = -1, ret = -1; - ssize_t result = -1; - - if (strcmp(imageName, BOOT_IMG) && - strcmp(imageName, RECOVERY_IMG) && - strcmp(imageName, BOOTLOADER_IMG)) { - printf("can't support %s at present\n", - imageName); - return -1; - } - - if (imageBuffer == NULL) { - printf("havn't malloc space for %s\n", - imageName); - return -1; - } - - if (imageSize <= 0) { - printf("%s size is %d\n", - imageName, imageSize); - return -1; - } - - switch (platformEncryptStatus) { - case 0: { - if (!imageEncryptStatus) { - ret = 1; - } else { - ret = 0; - } - break; - } - - case 1: { - if (!imageEncryptStatus) { - ret = 0; - } else { - fd = open(DEFEND_KEY, O_RDWR); - if (fd <= 0) { - printf("open %s failed (%s)\n", - DEFEND_KEY, strerror(errno)); - return -1; - } - result = write(fd, imageBuffer, imageSize);// check rsa - printf("write %s datas to %s. [imgsize:%d, result:%d, %s]\n", - imageName, DEFEND_KEY, imageSize, result, - (result == 1) ? "match" : - (result == -2) ? "not match" : "failed or not support"); - if (result == 1) { - ret = 1; - } else if(result == -2) { - ret = 0; - } else { // failed or not support - ret = -1; - } - close(fd); - fd = -1; - } - break; - } - } - - return ret; -} - -/** - * --- check bootloader.img whether encrypt or not - * - * @imageName: bootloader.img - * @imageBuffer: bootloader.img data address - * - * return value: - * <0: failed - * =0: unencrypted - * >0: encrypted - */ -static int IsBootloaderImageEncrypted( - const char *imageName, - const unsigned char *imageBuffer) -{ - int step0=1; - int step1=1; - int index=0; - unsigned char result= 0; - const unsigned char *pstart = NULL; - const unsigned char *pImageAddr = imageBuffer; - const unsigned char *pEncryptedBootloaderInfoBufAddr = NULL; - - // Don't modify. unencrypt bootloader info, for kernel version 3.10 - const int bootloaderEncryptInfoOffset = 0x1b0; - const unsigned char unencryptedBootloaderInfoBuf[] = - { 0x4D, 0x33, 0x48, 0x48, 0x52, 0x45, 0x56, 0x30 }; - - // Don't modify. unencrypt bootloader info, for kernel version 3.14 - const int newbootloaderEncryptInfoOffset = 0x10; - const int newbootloaderEncryptInfoOffset1 = 0x70; - const unsigned char newunencryptedBootloaderInfoBuf[] = { 0x40, 0x41, 0x4D, 0x4C}; - - if (strcmp(imageName, BOOTLOADER_IMG)) { - printf("this image must be %s,but it is %s\n", - BOOTLOADER_IMG, imageName); - return -1; - } - - if (imageBuffer == NULL) { - printf("havn't malloc space for %s\n", - imageName); - return -1; - } - - if (kernel_ver == KernelV_3_10) { - //check image whether encrypted for kernel 3.10 - pEncryptedBootloaderInfoBufAddr = pImageAddr + bootloaderEncryptInfoOffset; - if (!memcmp(unencryptedBootloaderInfoBuf, pEncryptedBootloaderInfoBufAddr, - ARRAY_SIZE(unencryptedBootloaderInfoBuf))) { - return 0; // unencrypted - } else { - return 1; - } - } - - //check image whether encrypted for kernel 3.14 - pEncryptedBootloaderInfoBufAddr = pImageAddr + newbootloaderEncryptInfoOffset; - if (!memcmp(newunencryptedBootloaderInfoBuf, pEncryptedBootloaderInfoBufAddr, - ARRAY_SIZE(newunencryptedBootloaderInfoBuf))) { - step0 = 0; - } - - pstart = pImageAddr + newbootloaderEncryptInfoOffset1; - for (index=0;index<16;index++) { - result ^= pstart[index]; - } - - if (result == 0) { - step1 = 0; - } - - if ((step0 == 1) && (step0 == 1)) { - return 1; // encrypted - } - - return 0;//unencrypted -} - -/* return value: - * <0: failed - * =0: not match - * >0: match - */ -int DtbImgEncrypted( - const char *imageName, - const unsigned char *imageBuffer, - const int imageSize, - const char *flag, - unsigned char *encryptedbuf) -{ - int len = 0; - ssize_t result = -1; - ssize_t readlen = -1; - int fd = -1, ret = -1; - - if ((imageBuffer == NULL) || (imageName == NULL)) { - printf("imageBuffer is null!\n"); - return -1; - } - - if (access(DECRYPT_DTB, F_OK) ||access(DEFEND_KEY, F_OK)) { - printf("doesn't support dtb secure check\n"); - return 2; // kernel doesn't support - } - - fd = open(DECRYPT_DTB, O_RDWR); - if (fd <= 0) { - printf("open %s failed!\n", DECRYPT_DTB); - return -1; - } - - len = write(fd, flag, 1); - if (len != 1) { - printf("write %s failed!\n", DECRYPT_DTB); - close(fd); - fd = -1; - return -1; - } - - close(fd); - fd = -1; - - fd = open(DEFEND_KEY, O_RDWR); - if (fd <= 0) { - printf("open %s failed (%s)\n",DEFEND_KEY, strerror(errno)); - return -1; - } - - result = write(fd, imageBuffer, imageSize);// check rsa - printf("write %s datas to %s. [imgsize:%d, result:%d, %s]\n", - imageName, DEFEND_KEY, imageSize, result, - (result == 1) ? "match" : - (result == -2) ? "not match" : "failed or not support"); - - if (!strcmp(flag, "1")) { - printf("dtb.img need to encrypted!\n"); - readlen = read(fd, encryptedbuf, imageSize); - if (readlen < 0) { - printf("read %s error!\n", DEFEND_KEY); - close(fd); - return -1; - } - - } - - if (result == 1) { - ret = 1; - } else if(result == -2) { - ret = 0; - } else { // failed or not support - ret = -1; - } - - close(fd); - fd = -1; - - return ret; -} - -/** - * --- check zip archive image whether encrypt or not - * image is bootloader.img/boot.img/recovery.img - * - * @imageName: image name - * @imageBuffer: image data address - * @imageSize: image data size - * - * return value: - * <0: failed - * =0: unencrypted - * >0: encrypted - */ -static int IsZipArchiveImageEncrypted( - const char *imageName, - const unsigned char *imageBuffer, - const int imageSize) -{ - int ret = -1; - const unsigned char *pImageAddr = imageBuffer; - - if (strcmp(imageName, BOOT_IMG) && - strcmp(imageName, RECOVERY_IMG) && - strcmp(imageName, BOOTLOADER_IMG)) { - printf("can't support %s at present\n", - imageName); - return -1; - } - - if (imageBuffer == NULL) { - printf("havn't malloc space for %s\n", - imageName); - return -1; - } - - if (imageSize <= 0) { - printf("%s size is %d\n", - imageName, imageSize); - return -1; - } - - if (!strcmp(imageName, BOOTLOADER_IMG)) { - return IsBootloaderImageEncrypted(imageName, imageBuffer); - } - - if (kernel_ver == KernelV_3_10) { - //check image whether encrypted for kernel 3.10 - const pT_SecureBootImgHdr encryptSecureBootImgHdr = - (const pT_SecureBootImgHdr)pImageAddr; - const pT_EncryptBootImgInfo encryptBootImgInfo = - &encryptSecureBootImgHdr->encryptBootImgInfo; - - secureDbg("magic:%s, version:0x%04x, totalLenAfterEncrypted:0x%0x\n", - encryptBootImgInfo->magic, encryptBootImgInfo->version, - encryptBootImgInfo->totalLenAfterEncrypted); - - ret = memcmp(encryptBootImgInfo->magic, SECUREBOOT_MAGIC, - strlen(SECUREBOOT_MAGIC)); - if (!ret && encryptBootImgInfo->version != 0x0) { - return 1; // encrypted - } - - return 0; - } - - //check image whether encrypted for kernel 3.14 - const AmlSecureBootImgHeader encryptSecureBootImgHeader = - (const AmlSecureBootImgHeader)pImageAddr; - const p_AmlEncryptBootImgInfo encryptBootImgHeader = - &encryptSecureBootImgHeader->encrypteImgInfo; - - secureDbg("magic:%s, version:0x%04x\n", - encryptBootImgHeader->magic, encryptBootImgHeader->version); - - ret = memcmp(encryptBootImgHeader->magic, SECUREBOOT_MAGIC, - strlen(SECUREBOOT_MAGIC)); - if (!ret && encryptBootImgHeader->version != 0x0) { - return 1; // encrypted - } - - return 0; // unencrypted - } - -/** - * --- check platform whether encrypt or not - * - * return value: - * <0: failed - * =0: unencrypted - * >0: encrypted - */ -int IsPlatformEncrypted(void) -{ - int fd = -1, ret = -1; - ssize_t count = 0; - char rBuf[128] = {0}; - char platform[PROPERTY_VALUE_MAX+1] = {0}; - - if (!(access(SECURE_CHECK, F_OK) || (access(SECURE_CHECK_BAK, F_OK))) \ - || access(DEFEND_KEY, F_OK)) { - printf("kernel doesn't support secure check\n"); - return 2; // kernel doesn't support - } - - fd = open(SECURE_CHECK, O_RDONLY); - if (fd <= 0) { - fd = open(SECURE_CHECK_BAK, O_RDONLY); - if (fd <= 0) { - printf("open %s failed (%s)\n", - SECURE_CHECK, strerror(errno)); - return -1; - } - kernel_ver = KernelV_3_14; - } - - property_get("ro.build.product", platform, "unknow"); - count = read(fd, rBuf, sizeof(rBuf) - 1); - if (count <= 0) { - printf("read %s failed (count:%d)\n", - SECURE_CHECK, count); - close(fd); - return -1; - } - rBuf[count] = '\0'; - - if (!strcmp(rBuf, s_pStatus[UNENCRYPT])) { - printf("check platform(%s): unencrypted\n", platform); - ret = 0; - } else if (!strcmp(rBuf, s_pStatus[ENCRYPT])) { - printf("check platform(%s): encrypted\n", platform); - ret = 1; - } else if (!strcmp(rBuf, s_pStatus[FAIL])) { - printf("check platform(%s): failed\n", platform); - } else { - printf("check platform(%s): %s\n", platform, rBuf); - } - - if (fd > 0) { - close(fd); - fd = -1; - } - - return ret; -} - -/** - * --- get upgrade package image data - * - * @zipArchive: zip archive object - * @imageName: upgrade package image's name - * @imageSize: upgrade package image's size - * - * return value: - * <0: failed - * =0: can't find image - * >0: get image data successful - */ -static unsigned char *s_pImageBuffer = NULL; -static int GetZipArchiveImage( - const ZipArchiveHandle za, - const char *imageName, - int *imageSize) -{ - ZipString zip_path(imageName); - ZipEntry entry; - if (FindEntry(za, zip_path, &entry) != 0) { - printf("no %s in package!\n", imageName); - return 0; - } - - *imageSize = entry.uncompressed_length; - if (*imageSize <= 0) { - printf("can't get package entry uncomp len(%d) (%s)\n", - *imageSize, strerror(errno)); - return -1; - } - - if (s_pImageBuffer != NULL) { - free(s_pImageBuffer); - s_pImageBuffer = NULL; - } - - s_pImageBuffer = (unsigned char *)calloc(*imageSize, sizeof(unsigned char)); - if (!s_pImageBuffer) { - printf("can't malloc %d size space (%s)\n", - *imageSize, strerror(errno)); - return -1; - } - - int32_t ret = ExtractToMemory(za, &entry, s_pImageBuffer, entry.uncompressed_length); - if (ret != 0) { - printf("can't extract package entry to image buffer\n"); - goto FREE_IMAGE_MEM; - } - - return 1; - - -FREE_IMAGE_MEM: - if (s_pImageBuffer != NULL) { - free(s_pImageBuffer); - s_pImageBuffer = NULL; - } - - return -1; -} - -/** - * --- check platform and upgrade package whether - * encrypted,if all encrypted,rsa whether all the same - * - * @ziparchive: Archive of Zip Package - * - * return value: - * =-1: failed; not allow upgrade - * = 0: check not match; not allow upgrade - * = 1: check match; allow upgrade - * = 2: kernel not support secure check; allow upgrade - */ -int RecoverySecureCheck(const ZipArchiveHandle zipArchive) -{ - int i = 0, ret = -1, err = -1; - int ret_dtb = 0; - int imageSize = 0; - int platformEncryptStatus = 0, imageEncryptStatus = 0; - const char *pImageName[] = { - BOOTLOADER_IMG, - BOOT_IMG, - RECOVERY_IMG }; - - platformEncryptStatus = IsPlatformEncrypted(); - if (platformEncryptStatus == 2) { - return 2;// kernel doesn't support - } - - if (platformEncryptStatus < 0) { - return -1; - } - - if (platformEncryptStatus >0 ) { - ret = GetZipArchiveImage(zipArchive, DTB_IMG, &imageSize); - if (ret > 0) { - ret_dtb = DtbImgEncrypted(DTB_IMG, s_pImageBuffer, imageSize, "0", NULL); - if (ret_dtb == 2) { - printf("dtb secure check not support!\n"); - } else if (ret_dtb > 0){ - printf("dtb secure check success!\n"); - - } else { - printf("dtb secure check error!\n"); - ret = -1; - goto ERR1; - } - } else if (ret == 0) { - printf("check %s: not find,skiping...\n", DTB_IMG); - } else { - printf("get %s datas failed\n", DTB_IMG); - goto ERR1; - } - } - - for (i = 0; i < ARRAY_SIZE(pImageName); i++) { - ret = GetZipArchiveImage(zipArchive, pImageName[i], &imageSize); - if (ret < 0) { - printf("get %s datas failed\n", pImageName[i]); - goto ERR1; - } else if (ret == 0) { - printf("check %s: not find,skiping...\n", pImageName[i]); - continue; - } else if (ret > 0) { - secureDbg("get %s datas(size:0x%0x, addr:0x%x) successful\n", - pImageName[i], imageSize, (int)s_pImageBuffer); - imageEncryptStatus = IsZipArchiveImageEncrypted(pImageName[i], s_pImageBuffer, imageSize); - - printf("check %s: %s\n", - pImageName[i], (imageEncryptStatus < 0) ? "failed" : - !imageEncryptStatus ? "unencrypted" : "encrypted"); - if (imageEncryptStatus < 0) { - ret = -1; - goto ERR1; - } - - ret = IsPlatformMachWithZipArchiveImage( - platformEncryptStatus, imageEncryptStatus, pImageName[i], - s_pImageBuffer, imageSize); - if (ret < 0) { - printf("%s match platform failed\n", pImageName[i]); - goto ERR1; - } else if (ret == 0) { // if one of image doesn't match with platform,exit - printf("%s doesn't match platform\n", pImageName[i]); - goto ERR1; - } else { - secureDbg("%s match platform\n", pImageName[i]); - } - - if (s_pImageBuffer != NULL) { - free(s_pImageBuffer); - s_pImageBuffer = NULL; - } - } - } - - return 1; - - -ERR1: - if (s_pImageBuffer != NULL) { - free(s_pImageBuffer); - s_pImageBuffer = NULL; - } - - return ret; -} diff --git a/recovery/check/security.h b/recovery/check/security.h deleted file mode 100644 index d42e412..0000000 --- a/recovery/check/security.h +++ b/dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _SECURITY_H_ -#define _SECURITY_H_ - -#define DTB_IMG "dtb.img" -#define BOOT_IMG "boot.img" -#define RECOVERY_IMG "recovery.img" -#define BOOTLOADER_IMG "bootloader.img" -#define ARRAY_SIZE(x) (int)(sizeof(x)/sizeof(x[0])) - -#define NORMALBOOT_NAME_SIZE 16 -#define NORMALBOOT_ARGS_SIZE 512 -#define NORMALBOOT_MAGIC_SIZE 8 -#define NORMALBOOT_MAGIC "ANDROID!" - -#define SECUREBOOT_MAGIC "AMLSECU!" -#define SECUREBOOT_MAGIC_SIZE 16 -#define SECUREBOOT_MAGIC_VESRION 0x0801 - -#define DECRYPT_DTB "/sys/class/defendkey/decrypt_dtb" - -#define DEFEND_KEY \ - "/dev/defendkey" -#define SECURE_CHECK \ - "/sys/class/defendkey/defendkey/secure_check" - -#define SECURE_CHECK_BAK \ - "/sys/class/defendkey/secure_check" - - -#ifndef SECURITY_DEBUG -#define secureDbg(fmt ...) -#else -#define secureDbg(fmt ...) printf(fmt) -#endif - -typedef enum Kernel_version { - KernelV_3_10, - KernelV_3_14 -}T_KernelVersion; - -typedef enum SecureCheck { - FAIL, - ENCRYPT, - UNENCRYPT, - TYPE_MAX, -} T_SecureCheck; - -static const char *s_pStatus[TYPE_MAX] = { - "fail", - "encrypt", - "raw", -}; - -typedef struct NormalBootImgHdr { - unsigned char magic[NORMALBOOT_MAGIC_SIZE]; - unsigned kernel_size; - unsigned kernel_addr; - unsigned ramdisk_size; - unsigned ramdisk_addr; - unsigned second_size; - unsigned second_addr; - unsigned tags_addr; // physical addr for kernel tags - unsigned page_size; // flash page size we assume - unsigned unused[2]; - unsigned char name[NORMALBOOT_NAME_SIZE]; - unsigned char cmdline[NORMALBOOT_ARGS_SIZE]; - unsigned id[8]; -} T_NormalBootImgHdr; - -typedef struct EncryptBootImgInfo { - // magic to identify whether it is a encrypted boot image - unsigned char magic[SECUREBOOT_MAGIC_SIZE]; - - // version for this header struct - unsigned int version; - - // total length after encrypted with AMLETool (including the 2K header) - unsigned int totalLenAfterEncrypted; - - unsigned char unused[1024 - SECUREBOOT_MAGIC_SIZE - 2 * sizeof(unsigned int)]; -} T_EncryptBootImgInfo, *pT_EncryptBootImgInfo; - -typedef struct SecureBootImgHdr { - T_NormalBootImgHdr normalBootImgHdr; - unsigned char reserve4Other[1024 - sizeof(T_NormalBootImgHdr)]; - T_EncryptBootImgInfo encryptBootImgInfo; -} *pT_SecureBootImgHdr; - - -//S905 SECURE BOOT HEAD -#define AML_SECU_BOOT_IMG_HDR_MAGIC "AMLSECU!" -#define AML_SECU_BOOT_IMG_HDR_MAGIC_SIZE (8) -#define AML_SECU_BOOT_IMG_HDR_VESRION (0x0905) - - -typedef struct __aml_enc_blk{ - unsigned int nOffset; - unsigned int nRawLength; - unsigned int nSigLength; - unsigned int nAlignment; - unsigned int nTotalLength; - unsigned char szPad[12]; - unsigned char szSHA2IMG[32]; - unsigned char szSHA2KeyID[32]; -}t_aml_enc_blk; - -typedef struct { - - unsigned char magic[AML_SECU_BOOT_IMG_HDR_MAGIC_SIZE];//magic to identify whether it is a encrypted boot image - - unsigned int version; //ersion for this header struct - unsigned int nBlkCnt; - - unsigned char szTimeStamp[16]; - - t_aml_enc_blk amlKernel; - t_aml_enc_blk amlRamdisk; - t_aml_enc_blk amlDTB; - -}AmlEncryptBootImgInfo, *p_AmlEncryptBootImgInfo; - -typedef struct _boot_img_hdr_secure_boot -{ - unsigned char reserve4ImgHdr[1024]; - - AmlEncryptBootImgInfo encrypteImgInfo; - -}*AmlSecureBootImgHeader; - -int RecoverySecureCheck(const ZipArchiveHandle zipArchive); - -int DtbImgEncrypted( - const char *imageName, - const unsigned char *imageBuffer, - const int imageSize, - const char *flag, - unsigned char *encryptedbuf); - - -//extern RecoveryUI *ui; - -#endif /* _SECURITY_H_ */ diff --git a/recovery/fdt/Android.mk b/recovery/fdt/Android.mk deleted file mode 100644 index 5982389..0000000 --- a/recovery/fdt/Android.mk +++ b/dev/null @@ -1,18 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - fdt.c \ - fdt_ro.c \ - fdt_wip.c \ - fdt_sw.c \ - fdt_rw.c \ - fdt_strerror.c \ - fdt_empty_tree.c - - -LOCAL_MODULE := libdtb - -LOCAL_CFLAGS += -Wall - -include $(BUILD_STATIC_LIBRARY) diff --git a/recovery/fdt/Makefile.libfdt b/recovery/fdt/Makefile.libfdt deleted file mode 100644 index 91126c0..0000000 --- a/recovery/fdt/Makefile.libfdt +++ b/dev/null @@ -1,10 +0,0 @@ -# Makefile.libfdt -# -# This is not a complete Makefile of itself. Instead, it is designed to -# be easily embeddable into other systems of Makefiles. -# -LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 -LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h -LIBFDT_VERSION = version.lds -LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c -LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) diff --git a/recovery/fdt/fdt.c b/recovery/fdt/fdt.c deleted file mode 100644 index e56833a..0000000 --- a/recovery/fdt/fdt.c +++ b/dev/null @@ -1,222 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -int fdt_check_header(const void *fdt) -{ - if (fdt_magic(fdt) == FDT_MAGIC) { - /* Complete tree */ - if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; - } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { - /* Unfinished sequential-write blob */ - if (fdt_size_dt_struct(fdt) == 0) - return -FDT_ERR_BADSTATE; - } else { - return -FDT_ERR_BADMAGIC; - } - - return 0; -} - -const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) -{ - const char *p; - - if (fdt_version(fdt) >= 0x11) - if (((offset + len) < offset) - || ((offset + len) > fdt_size_dt_struct(fdt))) - return NULL; - - p = _fdt_offset_ptr(fdt, offset); - - if (p + len < p) - return NULL; - return p; -} - -uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) -{ - const uint32_t *tagp, *lenp; - uint32_t tag; - int offset = startoffset; - const char *p; - - *nextoffset = -FDT_ERR_TRUNCATED; - tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); - if (!tagp) - return FDT_END; /* premature end */ - tag = fdt32_to_cpu(*tagp); - offset += FDT_TAGSIZE; - - *nextoffset = -FDT_ERR_BADSTRUCTURE; - switch (tag) { - case FDT_BEGIN_NODE: - /* skip name */ - do { - p = fdt_offset_ptr(fdt, offset++, 1); - } while (p && (*p != '\0')); - if (!p) - return FDT_END; /* premature end */ - break; - - case FDT_PROP: - lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); - if (!lenp) - return FDT_END; /* premature end */ - /* skip-name offset, length and value */ - offset += sizeof(struct fdt_property) - FDT_TAGSIZE - + fdt32_to_cpu(*lenp); - break; - - case FDT_END: - case FDT_END_NODE: - case FDT_NOP: - break; - - default: - return FDT_END; - } - - if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) - return FDT_END; /* premature end */ - - *nextoffset = FDT_TAGALIGN(offset); - return tag; -} - -int _fdt_check_node_offset(const void *fdt, int offset) -{ - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) - return -FDT_ERR_BADOFFSET; - - return offset; -} - -int _fdt_check_prop_offset(const void *fdt, int offset) -{ - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) - return -FDT_ERR_BADOFFSET; - - return offset; -} - -int fdt_next_node(const void *fdt, int offset, int *depth) -{ - int nextoffset = 0; - uint32_t tag; - - if (offset >= 0) - if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) - return nextoffset; - - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - - switch (tag) { - case FDT_PROP: - case FDT_NOP: - break; - - case FDT_BEGIN_NODE: - if (depth) - (*depth)++; - break; - - case FDT_END_NODE: - if (depth && ((--(*depth)) < 0)) - return nextoffset; - break; - - case FDT_END: - if ((nextoffset >= 0) - || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) - return -FDT_ERR_NOTFOUND; - else - return nextoffset; - } - } while (tag != FDT_BEGIN_NODE); - - return offset; -} - -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) -{ - int len = strlen(s) + 1; - const char *last = strtab + tabsize - len; - const char *p; - - for (p = strtab; p <= last; p++) - if (memcmp(p, s, len) == 0) - return p; - return NULL; -} - -int fdt_move(const void *fdt, void *buf, int bufsize) -{ - FDT_CHECK_HEADER(fdt); - - if (fdt_totalsize(fdt) > bufsize) - return -FDT_ERR_NOSPACE; - - memmove(buf, fdt, fdt_totalsize(fdt)); - return 0; -} diff --git a/recovery/fdt/fdt.h b/recovery/fdt/fdt.h deleted file mode 100644 index 48ccfd9..0000000 --- a/recovery/fdt/fdt.h +++ b/dev/null @@ -1,60 +0,0 @@ -#ifndef _FDT_H -#define _FDT_H - -#ifndef __ASSEMBLY__ - -struct fdt_header { - uint32_t magic; /* magic word FDT_MAGIC */ - uint32_t totalsize; /* total size of DT block */ - uint32_t off_dt_struct; /* offset to structure */ - uint32_t off_dt_strings; /* offset to strings */ - uint32_t off_mem_rsvmap; /* offset to memory reserve map */ - uint32_t version; /* format version */ - uint32_t last_comp_version; /* last compatible version */ - - /* version 2 fields below */ - uint32_t boot_cpuid_phys; /* Which physical CPU id we're - booting on */ - /* version 3 fields below */ - uint32_t size_dt_strings; /* size of the strings block */ - - /* version 17 fields below */ - uint32_t size_dt_struct; /* size of the structure block */ -}; - -struct fdt_reserve_entry { - uint64_t address; - uint64_t size; -}; - -struct fdt_node_header { - uint32_t tag; - char name[0]; -}; - -struct fdt_property { - uint32_t tag; - uint32_t len; - uint32_t nameoff; - char data[0]; -}; - -#endif /* !__ASSEMBLY */ - -#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ -#define FDT_TAGSIZE sizeof(uint32_t) - -#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ -#define FDT_END_NODE 0x2 /* End node */ -#define FDT_PROP 0x3 /* Property: name off, - size, content */ -#define FDT_NOP 0x4 /* nop */ -#define FDT_END 0x9 - -#define FDT_V1_SIZE (7*sizeof(uint32_t)) -#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t)) -#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t)) -#define FDT_V16_SIZE FDT_V3_SIZE -#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t)) - -#endif /* _FDT_H */ diff --git a/recovery/fdt/fdt_empty_tree.c b/recovery/fdt/fdt_empty_tree.c deleted file mode 100644 index f72d13b..0000000 --- a/recovery/fdt/fdt_empty_tree.c +++ b/dev/null @@ -1,84 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2012 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -int fdt_create_empty_tree(void *buf, int bufsize) -{ - int err; - - err = fdt_create(buf, bufsize); - if (err) - return err; - - err = fdt_finish_reservemap(buf); - if (err) - return err; - - err = fdt_begin_node(buf, ""); - if (err) - return err; - - err = fdt_end_node(buf); - if (err) - return err; - - err = fdt_finish(buf); - if (err) - return err; - - return fdt_open_into(buf, buf, bufsize); -} - diff --git a/recovery/fdt/fdt_ro.c b/recovery/fdt/fdt_ro.c deleted file mode 100644 index 02b6d68..0000000 --- a/recovery/fdt/fdt_ro.c +++ b/dev/null @@ -1,574 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -static int _fdt_nodename_eq(const void *fdt, int offset, - const char *s, int len) -{ - const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); - - if (! p) - /* short match */ - return 0; - - if (memcmp(p, s, len) != 0) - return 0; - - if (p[len] == '\0') - return 1; - else if (!memchr(s, '@', len) && (p[len] == '@')) - return 1; - else - return 0; -} - -const char *fdt_string(const void *fdt, int stroffset) -{ - return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; -} - -static int _fdt_string_eq(const void *fdt, int stroffset, - const char *s, int len) -{ - const char *p = fdt_string(fdt, stroffset); - - return (strlen(p) == len) && (memcmp(p, s, len) == 0); -} - -int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) -{ - FDT_CHECK_HEADER(fdt); - *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); - *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); - return 0; -} - -int fdt_num_mem_rsv(const void *fdt) -{ - int i = 0; - - while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) - i++; - return i; -} - -static int _nextprop(const void *fdt, int offset) -{ - uint32_t tag; - int nextoffset; - - do { - tag = fdt_next_tag(fdt, offset, &nextoffset); - - switch (tag) { - case FDT_END: - if (nextoffset >= 0) - return -FDT_ERR_BADSTRUCTURE; - else - return nextoffset; - - case FDT_PROP: - return offset; - } - offset = nextoffset; - } while (tag == FDT_NOP); - - return -FDT_ERR_NOTFOUND; -} - -int fdt_subnode_offset_namelen(const void *fdt, int offset, - const char *name, int namelen) -{ - int depth; - - FDT_CHECK_HEADER(fdt); - - for (depth = 0; - (offset >= 0) && (depth >= 0); - offset = fdt_next_node(fdt, offset, &depth)) - if ((depth == 1) - && _fdt_nodename_eq(fdt, offset, name, namelen)) - return offset; - - if (depth < 0) - return -FDT_ERR_NOTFOUND; - return offset; /* error */ -} - -int fdt_subnode_offset(const void *fdt, int parentoffset, - const char *name) -{ - return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); -} - -int fdt_path_offset(const void *fdt, const char *path) -{ - const char *end = path + strlen(path); - const char *p = path; - int offset = 0; - - FDT_CHECK_HEADER(fdt); - - /* see if we have an alias */ - if (*path != '/') { - const char *q = strchr(path, '/'); - - if (!q) - q = end; - - p = fdt_get_alias_namelen(fdt, p, q - p); - if (!p) - return -FDT_ERR_BADPATH; - offset = fdt_path_offset(fdt, p); - - p = q; - } - - while (*p) { - const char *q; - - while (*p == '/') - p++; - if (! *p) - return offset; - q = strchr(p, '/'); - if (! q) - q = end; - - offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); - if (offset < 0) - return offset; - - p = q; - } - - return offset; -} - -const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) -{ - const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); - int err; - - if (((err = fdt_check_header(fdt)) != 0) - || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) - goto fail; - - if (len) - *len = strlen(nh->name); - - return nh->name; - - fail: - if (len) - *len = err; - return NULL; -} - -int fdt_first_property_offset(const void *fdt, int nodeoffset) -{ - int offset; - - if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) - return offset; - - return _nextprop(fdt, offset); -} - -int fdt_next_property_offset(const void *fdt, int offset) -{ - if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) - return offset; - - return _nextprop(fdt, offset); -} - -const struct fdt_property *fdt_get_property_by_offset(const void *fdt, - int offset, - int *lenp) -{ - int err; - const struct fdt_property *prop; - - if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { - if (lenp) - *lenp = err; - return NULL; - } - - prop = _fdt_offset_ptr(fdt, offset); - - if (lenp) - *lenp = fdt32_to_cpu(prop->len); - - return prop; -} - -const struct fdt_property *fdt_get_property_namelen(const void *fdt, - int offset, - const char *name, - int namelen, int *lenp) -{ - for (offset = fdt_first_property_offset(fdt, offset); - (offset >= 0); - (offset = fdt_next_property_offset(fdt, offset))) { - const struct fdt_property *prop; - - if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { - offset = -FDT_ERR_INTERNAL; - break; - } - if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), - name, namelen)) - return prop; - } - - if (lenp) - *lenp = offset; - return NULL; -} - -const struct fdt_property *fdt_get_property(const void *fdt, - int nodeoffset, - const char *name, int *lenp) -{ - return fdt_get_property_namelen(fdt, nodeoffset, name, - strlen(name), lenp); -} - -const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, - const char *name, int namelen, int *lenp) -{ - const struct fdt_property *prop; - - prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); - if (! prop) - return NULL; - - return prop->data; -} - -const void *fdt_getprop_by_offset(const void *fdt, int offset, - const char **namep, int *lenp) -{ - const struct fdt_property *prop; - - prop = fdt_get_property_by_offset(fdt, offset, lenp); - if (!prop) - return NULL; - if (namep) - *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); - return prop->data; -} - -const void *fdt_getprop(const void *fdt, int nodeoffset, - const char *name, int *lenp) -{ - return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); -} - -uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) -{ - const uint32_t *php; - int len; - - /* FIXME: This is a bit sub-optimal, since we potentially scan - * over all the properties twice. */ - php = fdt_getprop(fdt, nodeoffset, "phandle", &len); - if (!php || (len != sizeof(*php))) { - php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); - if (!php || (len != sizeof(*php))) - return 0; - } - - return fdt32_to_cpu(*php); -} - -const char *fdt_get_alias_namelen(const void *fdt, - const char *name, int namelen) -{ - int aliasoffset; - - aliasoffset = fdt_path_offset(fdt, "/aliases"); - if (aliasoffset < 0) - return NULL; - - return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); -} - -const char *fdt_get_alias(const void *fdt, const char *name) -{ - return fdt_get_alias_namelen(fdt, name, strlen(name)); -} - -int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) -{ - int pdepth = 0, p = 0; - int offset, depth, namelen; - const char *name; - - FDT_CHECK_HEADER(fdt); - - if (buflen < 2) - return -FDT_ERR_NOSPACE; - - for (offset = 0, depth = 0; - (offset >= 0) && (offset <= nodeoffset); - offset = fdt_next_node(fdt, offset, &depth)) { - while (pdepth > depth) { - do { - p--; - } while (buf[p-1] != '/'); - pdepth--; - } - - if (pdepth >= depth) { - name = fdt_get_name(fdt, offset, &namelen); - if (!name) - return namelen; - if ((p + namelen + 1) <= buflen) { - memcpy(buf + p, name, namelen); - p += namelen; - buf[p++] = '/'; - pdepth++; - } - } - - if (offset == nodeoffset) { - if (pdepth < (depth + 1)) - return -FDT_ERR_NOSPACE; - - if (p > 1) /* special case so that root path is "/", not "" */ - p--; - buf[p] = '\0'; - return 0; - } - } - - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; - - return offset; /* error from fdt_next_node() */ -} - -int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, - int supernodedepth, int *nodedepth) -{ - int offset, depth; - int supernodeoffset = -FDT_ERR_INTERNAL; - - FDT_CHECK_HEADER(fdt); - - if (supernodedepth < 0) - return -FDT_ERR_NOTFOUND; - - for (offset = 0, depth = 0; - (offset >= 0) && (offset <= nodeoffset); - offset = fdt_next_node(fdt, offset, &depth)) { - if (depth == supernodedepth) - supernodeoffset = offset; - - if (offset == nodeoffset) { - if (nodedepth) - *nodedepth = depth; - - if (supernodedepth > depth) - return -FDT_ERR_NOTFOUND; - else - return supernodeoffset; - } - } - - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; - - return offset; /* error from fdt_next_node() */ -} - -int fdt_node_depth(const void *fdt, int nodeoffset) -{ - int nodedepth; - int err; - - err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); - if (err) - return (err < 0) ? err : -FDT_ERR_INTERNAL; - return nodedepth; -} - -int fdt_parent_offset(const void *fdt, int nodeoffset) -{ - int nodedepth = fdt_node_depth(fdt, nodeoffset); - - if (nodedepth < 0) - return nodedepth; - return fdt_supernode_atdepth_offset(fdt, nodeoffset, - nodedepth - 1, NULL); -} - -int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, - const char *propname, - const void *propval, int proplen) -{ - int offset; - const void *val; - int len; - - FDT_CHECK_HEADER(fdt); - - /* FIXME: The algorithm here is pretty horrible: we scan each - * property of a node in fdt_getprop(), then if that didn't - * find what we want, we scan over them again making our way - * to the next node. Still it's the easiest to implement - * approach; performance can come later. */ - for (offset = fdt_next_node(fdt, startoffset, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - val = fdt_getprop(fdt, offset, propname, &len); - if (val && (len == proplen) - && (memcmp(val, propval, len) == 0)) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} - -int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) -{ - int offset; - - if ((phandle == 0) || (phandle == -1)) - return -FDT_ERR_BADPHANDLE; - - FDT_CHECK_HEADER(fdt); - - /* FIXME: The algorithm here is pretty horrible: we - * potentially scan each property of a node in - * fdt_get_phandle(), then if that didn't find what - * we want, we scan over them again making our way to the next - * node. Still it's the easiest to implement approach; - * performance can come later. */ - for (offset = fdt_next_node(fdt, -1, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - if (fdt_get_phandle(fdt, offset) == phandle) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} - -static int _fdt_stringlist_contains(const char *strlist, int listlen, - const char *str) -{ - int len = strlen(str); - const char *p; - - while (listlen >= len) { - if (memcmp(str, strlist, len+1) == 0) - return 1; - p = memchr(strlist, '\0', listlen); - if (!p) - return 0; /* malformed strlist.. */ - listlen -= (p-strlist) + 1; - strlist = p + 1; - } - return 0; -} - -int fdt_node_check_compatible(const void *fdt, int nodeoffset, - const char *compatible) -{ - const void *prop; - int len; - - prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); - if (!prop) - return len; - if (_fdt_stringlist_contains(prop, len, compatible)) - return 0; - else - return 1; -} - -int fdt_node_offset_by_compatible(const void *fdt, int startoffset, - const char *compatible) -{ - int offset, err; - - FDT_CHECK_HEADER(fdt); - - /* FIXME: The algorithm here is pretty horrible: we scan each - * property of a node in fdt_node_check_compatible(), then if - * that didn't find what we want, we scan over them again - * making our way to the next node. Still it's the easiest to - * implement approach; performance can come later. */ - for (offset = fdt_next_node(fdt, startoffset, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - err = fdt_node_check_compatible(fdt, offset, compatible); - if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) - return err; - else if (err == 0) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} diff --git a/recovery/fdt/fdt_rw.c b/recovery/fdt/fdt_rw.c deleted file mode 100644 index 24437df..0000000 --- a/recovery/fdt/fdt_rw.c +++ b/dev/null @@ -1,492 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -static int _fdt_blocks_misordered(const void *fdt, - int mem_rsv_size, int struct_size) -{ - return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) - || (fdt_off_dt_struct(fdt) < - (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) - || (fdt_off_dt_strings(fdt) < - (fdt_off_dt_struct(fdt) + struct_size)) - || (fdt_totalsize(fdt) < - (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); -} - -static int _fdt_rw_check_header(void *fdt) -{ - FDT_CHECK_HEADER(fdt); - - if (fdt_version(fdt) < 17) - return -FDT_ERR_BADVERSION; - if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), - fdt_size_dt_struct(fdt))) - return -FDT_ERR_BADLAYOUT; - if (fdt_version(fdt) > 17) - fdt_set_version(fdt, 17); - - return 0; -} - -#define FDT_RW_CHECK_HEADER(fdt) \ - { \ - int err; \ - if ((err = _fdt_rw_check_header(fdt)) != 0) \ - return err; \ - } - -static inline int _fdt_data_size(void *fdt) -{ - return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); -} - -static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) -{ - char *p = splicepoint; - char *end = (char *)fdt + _fdt_data_size(fdt); - - if (((p + oldlen) < p) || ((p + oldlen) > end)) - return -FDT_ERR_BADOFFSET; - if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) - return -FDT_ERR_NOSPACE; - memmove(p + newlen, p + oldlen, end - p - oldlen); - return 0; -} - -static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, - int oldn, int newn) -{ - int delta = (newn - oldn) * sizeof(*p); - int err; - err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); - if (err) - return err; - fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); - fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); - return 0; -} - -static int _fdt_splice_struct(void *fdt, void *p, - int oldlen, int newlen) -{ - int delta = newlen - oldlen; - int err; - - if ((err = _fdt_splice(fdt, p, oldlen, newlen))) - return err; - - fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); - fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); - return 0; -} - -static int _fdt_splice_string(void *fdt, int newlen) -{ - void *p = (char *)fdt - + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); - int err; - - if ((err = _fdt_splice(fdt, p, 0, newlen))) - return err; - - fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); - return 0; -} - -static int _fdt_find_add_string(void *fdt, const char *s) -{ - char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); - const char *p; - char *new; - int len = strlen(s) + 1; - int err; - - p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); - if (p) - /* found it */ - return (p - strtab); - - new = strtab + fdt_size_dt_strings(fdt); - err = _fdt_splice_string(fdt, len); - if (err) - return err; - - memcpy(new, s, len); - return (new - strtab); -} - -int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) -{ - struct fdt_reserve_entry *re; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); - err = _fdt_splice_mem_rsv(fdt, re, 0, 1); - if (err) - return err; - - re->address = cpu_to_fdt64(address); - re->size = cpu_to_fdt64(size); - return 0; -} - -int fdt_del_mem_rsv(void *fdt, int n) -{ - struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); - int err; - - FDT_RW_CHECK_HEADER(fdt); - - if (n >= fdt_num_mem_rsv(fdt)) - return -FDT_ERR_NOTFOUND; - - err = _fdt_splice_mem_rsv(fdt, re, 1, 0); - if (err) - return err; - return 0; -} - -static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, - int len, struct fdt_property **prop) -{ - int oldlen; - int err; - - *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); - if (! (*prop)) - return oldlen; - - if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), - FDT_TAGALIGN(len)))) - return err; - - (*prop)->len = cpu_to_fdt32(len); - return 0; -} - -static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, - int len, struct fdt_property **prop) -{ - int proplen; - int nextoffset; - int namestroff; - int err; - - if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) - return nextoffset; - - namestroff = _fdt_find_add_string(fdt, name); - if (namestroff < 0) - return namestroff; - - *prop = _fdt_offset_ptr_w(fdt, nextoffset); - proplen = sizeof(**prop) + FDT_TAGALIGN(len); - - err = _fdt_splice_struct(fdt, *prop, 0, proplen); - if (err) - return err; - - (*prop)->tag = cpu_to_fdt32(FDT_PROP); - (*prop)->nameoff = cpu_to_fdt32(namestroff); - (*prop)->len = cpu_to_fdt32(len); - return 0; -} - -int fdt_set_name(void *fdt, int nodeoffset, const char *name) -{ - char *namep; - int oldlen, newlen; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); - if (!namep) - return oldlen; - - newlen = strlen(name); - - err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), - FDT_TAGALIGN(newlen+1)); - if (err) - return err; - - memcpy(namep, name, newlen+1); - return 0; -} - -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len) -{ - struct fdt_property *prop; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); - if (err == -FDT_ERR_NOTFOUND) - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); - if (err) - return err; - - memcpy(prop->data, val, len); - return 0; -} - -int fdt_appendprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len) -{ - struct fdt_property *prop; - int err, oldlen, newlen; - - FDT_RW_CHECK_HEADER(fdt); - - prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); - if (prop) { - newlen = len + oldlen; - err = _fdt_splice_struct(fdt, prop->data, - FDT_TAGALIGN(oldlen), - FDT_TAGALIGN(newlen)); - if (err) - return err; - prop->len = cpu_to_fdt32(newlen); - memcpy(prop->data + oldlen, val, len); - } else { - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); - if (err) - return err; - memcpy(prop->data, val, len); - } - return 0; -} - -int fdt_delprop(void *fdt, int nodeoffset, const char *name) -{ - struct fdt_property *prop; - int len, proplen; - - FDT_RW_CHECK_HEADER(fdt); - - prop = fdt_get_property_w(fdt, nodeoffset, name, &len); - if (! prop) - return len; - - proplen = sizeof(*prop) + FDT_TAGALIGN(len); - return _fdt_splice_struct(fdt, prop, proplen, 0); -} - -int fdt_add_subnode_namelen(void *fdt, int parentoffset, - const char *name, int namelen) -{ - struct fdt_node_header *nh; - int offset, nextoffset; - int nodelen; - int err; - uint32_t tag; - uint32_t *endtag; - - FDT_RW_CHECK_HEADER(fdt); - - offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); - if (offset >= 0) - return -FDT_ERR_EXISTS; - else if (offset != -FDT_ERR_NOTFOUND) - return offset; - - /* Try to place the new node after the parent's properties */ - fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - } while ((tag == FDT_PROP) || (tag == FDT_NOP)); - - nh = _fdt_offset_ptr_w(fdt, offset); - nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; - - err = _fdt_splice_struct(fdt, nh, 0, nodelen); - if (err) - return err; - - nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); - memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); - memcpy(nh->name, name, namelen); - endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE); - *endtag = cpu_to_fdt32(FDT_END_NODE); - - return offset; -} - -int fdt_add_subnode(void *fdt, int parentoffset, const char *name) -{ - return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); -} - -int fdt_del_node(void *fdt, int nodeoffset) -{ - int endoffset; - - FDT_RW_CHECK_HEADER(fdt); - - endoffset = _fdt_node_end_offset(fdt, nodeoffset); - if (endoffset < 0) - return endoffset; - - return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), - endoffset - nodeoffset, 0); -} - -static void _fdt_packblocks(const char *old, char *new, - int mem_rsv_size, int struct_size) -{ - int mem_rsv_off, struct_off, strings_off; - - mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); - struct_off = mem_rsv_off + mem_rsv_size; - strings_off = struct_off + struct_size; - - memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); - fdt_set_off_mem_rsvmap(new, mem_rsv_off); - - memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); - fdt_set_off_dt_struct(new, struct_off); - fdt_set_size_dt_struct(new, struct_size); - - memmove(new + strings_off, old + fdt_off_dt_strings(old), - fdt_size_dt_strings(old)); - fdt_set_off_dt_strings(new, strings_off); - fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); -} - -int fdt_open_into(const void *fdt, void *buf, int bufsize) -{ - int err; - int mem_rsv_size, struct_size; - int newsize; - const char *fdtstart = fdt; - const char *fdtend = fdtstart + fdt_totalsize(fdt); - char *tmp; - - FDT_CHECK_HEADER(fdt); - - mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) - * sizeof(struct fdt_reserve_entry); - - if (fdt_version(fdt) >= 17) { - struct_size = fdt_size_dt_struct(fdt); - } else { - struct_size = 0; - while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) - ; - if (struct_size < 0) - return struct_size; - } - - if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { - /* no further work necessary */ - err = fdt_move(fdt, buf, bufsize); - if (err) - return err; - fdt_set_version(buf, 17); - fdt_set_size_dt_struct(buf, struct_size); - fdt_set_totalsize(buf, bufsize); - return 0; - } - - /* Need to reorder */ - newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size - + struct_size + fdt_size_dt_strings(fdt); - - if (bufsize < newsize) - return -FDT_ERR_NOSPACE; - - /* First attempt to build converted tree at beginning of buffer */ - tmp = buf; - /* But if that overlaps with the old tree... */ - if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { - /* Try right after the old tree instead */ - tmp = (char *)(uintptr_t)fdtend; - if ((tmp + newsize) > ((char *)buf + bufsize)) - return -FDT_ERR_NOSPACE; - } - - _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); - memmove(buf, tmp, newsize); - - fdt_set_magic(buf, FDT_MAGIC); - fdt_set_totalsize(buf, bufsize); - fdt_set_version(buf, 17); - fdt_set_last_comp_version(buf, 16); - fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); - - return 0; -} - -int fdt_pack(void *fdt) -{ - int mem_rsv_size; - - FDT_RW_CHECK_HEADER(fdt); - - mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) - * sizeof(struct fdt_reserve_entry); - _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); - fdt_set_totalsize(fdt, _fdt_data_size(fdt)); - - return 0; -} diff --git a/recovery/fdt/fdt_strerror.c b/recovery/fdt/fdt_strerror.c deleted file mode 100644 index e6c3cee..0000000 --- a/recovery/fdt/fdt_strerror.c +++ b/dev/null @@ -1,96 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -struct fdt_errtabent { - const char *str; -}; - -#define FDT_ERRTABENT(val) \ - [(val)] = { .str = #val, } - -static struct fdt_errtabent fdt_errtable[] = { - FDT_ERRTABENT(FDT_ERR_NOTFOUND), - FDT_ERRTABENT(FDT_ERR_EXISTS), - FDT_ERRTABENT(FDT_ERR_NOSPACE), - - FDT_ERRTABENT(FDT_ERR_BADOFFSET), - FDT_ERRTABENT(FDT_ERR_BADPATH), - FDT_ERRTABENT(FDT_ERR_BADSTATE), - - FDT_ERRTABENT(FDT_ERR_TRUNCATED), - FDT_ERRTABENT(FDT_ERR_BADMAGIC), - FDT_ERRTABENT(FDT_ERR_BADVERSION), - FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), - FDT_ERRTABENT(FDT_ERR_BADLAYOUT), -}; -#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) - -const char *fdt_strerror(int errval) -{ - if (errval > 0) - return "<valid offset/length>"; - else if (errval == 0) - return "<no error>"; - else if (errval > -FDT_ERRTABSIZE) { - const char *s = fdt_errtable[-errval].str; - - if (s) - return s; - } - - return "<unknown error>"; -} diff --git a/recovery/fdt/fdt_sw.c b/recovery/fdt/fdt_sw.c deleted file mode 100644 index 55ebebf..0000000 --- a/recovery/fdt/fdt_sw.c +++ b/dev/null @@ -1,256 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -static int _fdt_sw_check_header(void *fdt) -{ - if (fdt_magic(fdt) != FDT_SW_MAGIC) - return -FDT_ERR_BADMAGIC; - /* FIXME: should check more details about the header state */ - return 0; -} - -#define FDT_SW_CHECK_HEADER(fdt) \ - { \ - int err; \ - if ((err = _fdt_sw_check_header(fdt)) != 0) \ - return err; \ - } - -static void *_fdt_grab_space(void *fdt, size_t len) -{ - int offset = fdt_size_dt_struct(fdt); - int spaceleft; - - spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) - - fdt_size_dt_strings(fdt); - - if ((offset + len < offset) || (offset + len > spaceleft)) - return NULL; - - fdt_set_size_dt_struct(fdt, offset + len); - return _fdt_offset_ptr_w(fdt, offset); -} - -int fdt_create(void *buf, int bufsize) -{ - void *fdt = buf; - - if (bufsize < sizeof(struct fdt_header)) - return -FDT_ERR_NOSPACE; - - memset(buf, 0, bufsize); - - fdt_set_magic(fdt, FDT_SW_MAGIC); - fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); - fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); - fdt_set_totalsize(fdt, bufsize); - - fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry))); - fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); - fdt_set_off_dt_strings(fdt, bufsize); - - return 0; -} - -int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) -{ - struct fdt_reserve_entry *re; - int offset; - - FDT_SW_CHECK_HEADER(fdt); - - if (fdt_size_dt_struct(fdt)) - return -FDT_ERR_BADSTATE; - - offset = fdt_off_dt_struct(fdt); - if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) - return -FDT_ERR_NOSPACE; - - re = (struct fdt_reserve_entry *)((char *)fdt + offset); - re->address = cpu_to_fdt64(addr); - re->size = cpu_to_fdt64(size); - - fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); - - return 0; -} - -int fdt_finish_reservemap(void *fdt) -{ - return fdt_add_reservemap_entry(fdt, 0, 0); -} - -int fdt_begin_node(void *fdt, const char *name) -{ - struct fdt_node_header *nh; - int namelen = strlen(name) + 1; - - FDT_SW_CHECK_HEADER(fdt); - - nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); - if (! nh) - return -FDT_ERR_NOSPACE; - - nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); - memcpy(nh->name, name, namelen); - return 0; -} - -int fdt_end_node(void *fdt) -{ - uint32_t *en; - - FDT_SW_CHECK_HEADER(fdt); - - en = _fdt_grab_space(fdt, FDT_TAGSIZE); - if (! en) - return -FDT_ERR_NOSPACE; - - *en = cpu_to_fdt32(FDT_END_NODE); - return 0; -} - -static int _fdt_find_add_string(void *fdt, const char *s) -{ - char *strtab = (char *)fdt + fdt_totalsize(fdt); - const char *p; - int strtabsize = fdt_size_dt_strings(fdt); - int len = strlen(s) + 1; - int struct_top, offset; - - p = _fdt_find_string(strtab - strtabsize, strtabsize, s); - if (p) - return p - strtab; - - /* Add it */ - offset = -strtabsize - len; - struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); - if (fdt_totalsize(fdt) + offset < struct_top) - return 0; /* no more room :( */ - - memcpy(strtab + offset, s, len); - fdt_set_size_dt_strings(fdt, strtabsize + len); - return offset; -} - -int fdt_property(void *fdt, const char *name, const void *val, int len) -{ - struct fdt_property *prop; - int nameoff; - - FDT_SW_CHECK_HEADER(fdt); - - nameoff = _fdt_find_add_string(fdt, name); - if (nameoff == 0) - return -FDT_ERR_NOSPACE; - - prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); - if (! prop) - return -FDT_ERR_NOSPACE; - - prop->tag = cpu_to_fdt32(FDT_PROP); - prop->nameoff = cpu_to_fdt32(nameoff); - prop->len = cpu_to_fdt32(len); - memcpy(prop->data, val, len); - return 0; -} - -int fdt_finish(void *fdt) -{ - char *p = (char *)fdt; - uint32_t *end; - int oldstroffset, newstroffset; - uint32_t tag; - int offset, nextoffset; - - FDT_SW_CHECK_HEADER(fdt); - - /* Add terminator */ - end = _fdt_grab_space(fdt, sizeof(*end)); - if (! end) - return -FDT_ERR_NOSPACE; - *end = cpu_to_fdt32(FDT_END); - - /* Relocate the string table */ - oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); - newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); - memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); - fdt_set_off_dt_strings(fdt, newstroffset); - - /* Walk the structure, correcting string offsets */ - offset = 0; - while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { - if (tag == FDT_PROP) { - struct fdt_property *prop = - _fdt_offset_ptr_w(fdt, offset); - int nameoff; - - nameoff = fdt32_to_cpu(prop->nameoff); - nameoff += fdt_size_dt_strings(fdt); - prop->nameoff = cpu_to_fdt32(nameoff); - } - offset = nextoffset; - } - if (nextoffset < 0) - return nextoffset; - - /* Finally, adjust the header */ - fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); - fdt_set_magic(fdt, FDT_MAGIC); - return 0; -} diff --git a/recovery/fdt/fdt_wip.c b/recovery/fdt/fdt_wip.c deleted file mode 100644 index 6025fa1..0000000 --- a/recovery/fdt/fdt_wip.c +++ b/dev/null @@ -1,118 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, - const void *val, int len) -{ - void *propval; - int proplen; - - propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen); - if (! propval) - return proplen; - - if (proplen != len) - return -FDT_ERR_NOSPACE; - - memcpy(propval, val, len); - return 0; -} - -static void _fdt_nop_region(void *start, int len) -{ - uint32_t *p; - - for (p = start; (char *)p < ((char *)start + len); p++) - *p = cpu_to_fdt32(FDT_NOP); -} - -int fdt_nop_property(void *fdt, int nodeoffset, const char *name) -{ - struct fdt_property *prop; - int len; - - prop = fdt_get_property_w(fdt, nodeoffset, name, &len); - if (! prop) - return len; - - _fdt_nop_region(prop, len + sizeof(*prop)); - - return 0; -} - -int _fdt_node_end_offset(void *fdt, int offset) -{ - int depth = 0; - - while ((offset >= 0) && (depth >= 0)) - offset = fdt_next_node(fdt, offset, &depth); - - return offset; -} - -int fdt_nop_node(void *fdt, int nodeoffset) -{ - int endoffset; - - endoffset = _fdt_node_end_offset(fdt, nodeoffset); - if (endoffset < 0) - return endoffset; - - _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), - endoffset - nodeoffset); - return 0; -} diff --git a/recovery/fdt/libfdt.h b/recovery/fdt/libfdt.h deleted file mode 100644 index ea1ddcd..0000000 --- a/recovery/fdt/libfdt.h +++ b/dev/null @@ -1,1478 +0,0 @@ -#ifndef _LIBFDT_H -#define _LIBFDT_H -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "libfdt_env.h" -#include "fdt.h" - -#define FDT_FIRST_SUPPORTED_VERSION 0x10 -#define FDT_LAST_SUPPORTED_VERSION 0x11 - -/* Error codes: informative error codes */ -#define FDT_ERR_NOTFOUND 1 - /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ -#define FDT_ERR_EXISTS 2 - /* FDT_ERR_EXISTS: Attemped to create a node or property which - * already exists */ -#define FDT_ERR_NOSPACE 3 - /* FDT_ERR_NOSPACE: Operation needed to expand the device - * tree, but its buffer did not have sufficient space to - * contain the expanded tree. Use fdt_open_into() to move the - * device tree to a buffer with more space. */ - -/* Error codes: codes for bad parameters */ -#define FDT_ERR_BADOFFSET 4 - /* FDT_ERR_BADOFFSET: Function was passed a structure block - * offset which is out-of-bounds, or which points to an - * unsuitable part of the structure for the operation. */ -#define FDT_ERR_BADPATH 5 - /* FDT_ERR_BADPATH: Function was passed a badly formatted path - * (e.g. missing a leading / for a function which requires an - * absolute path) */ -#define FDT_ERR_BADPHANDLE 6 - /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle - * value. phandle values of 0 and -1 are not permitted. */ -#define FDT_ERR_BADSTATE 7 - /* FDT_ERR_BADSTATE: Function was passed an incomplete device - * tree created by the sequential-write functions, which is - * not sufficiently complete for the requested operation. */ - -/* Error codes: codes for bad device tree blobs */ -#define FDT_ERR_TRUNCATED 8 - /* FDT_ERR_TRUNCATED: Structure block of the given device tree - * ends without an FDT_END tag. */ -#define FDT_ERR_BADMAGIC 9 - /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a - * device tree at all - it is missing the flattened device - * tree magic number. */ -#define FDT_ERR_BADVERSION 10 - /* FDT_ERR_BADVERSION: Given device tree has a version which - * can't be handled by the requested operation. For - * read-write functions, this may mean that fdt_open_into() is - * required to convert the tree to the expected version. */ -#define FDT_ERR_BADSTRUCTURE 11 - /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt - * structure block or other serious error (e.g. misnested - * nodes, or subnodes preceding properties). */ -#define FDT_ERR_BADLAYOUT 12 - /* FDT_ERR_BADLAYOUT: For read-write functions, the given - * device tree has it's sub-blocks in an order that the - * function can't handle (memory reserve map, then structure, - * then strings). Use fdt_open_into() to reorganize the tree - * into a form suitable for the read-write operations. */ - -/* "Can't happen" error indicating a bug in libfdt */ -#define FDT_ERR_INTERNAL 13 - /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. - * Should never be returned, if it is, it indicates a bug in - * libfdt itself. */ - -#define FDT_ERR_MAX 13 - -/**********************************************************************/ -/* Low-level functions (you probably don't need these) */ -/**********************************************************************/ - -const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); -static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) -{ - return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); -} - -uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); - -/**********************************************************************/ -/* Traversal functions */ -/**********************************************************************/ - -int fdt_next_node(const void *fdt, int offset, int *depth); - -/**********************************************************************/ -/* General functions */ -/**********************************************************************/ - -#define fdt_get_header(fdt, field) \ - (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) -#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) -#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) -#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) -#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) -#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) -#define fdt_version(fdt) (fdt_get_header(fdt, version)) -#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) -#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) -#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) -#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) - -#define __fdt_set_hdr(name) \ - static inline void fdt_set_##name(void *fdt, uint32_t val) \ - { \ - struct fdt_header *fdth = (struct fdt_header*)fdt; \ - fdth->name = cpu_to_fdt32(val); \ - } -__fdt_set_hdr(magic); -__fdt_set_hdr(totalsize); -__fdt_set_hdr(off_dt_struct); -__fdt_set_hdr(off_dt_strings); -__fdt_set_hdr(off_mem_rsvmap); -__fdt_set_hdr(version); -__fdt_set_hdr(last_comp_version); -__fdt_set_hdr(boot_cpuid_phys); -__fdt_set_hdr(size_dt_strings); -__fdt_set_hdr(size_dt_struct); -#undef __fdt_set_hdr - -/** - * fdt_check_header - sanity check a device tree or possible device tree - * @fdt: pointer to data which might be a flattened device tree - * - * fdt_check_header() checks that the given buffer contains what - * appears to be a flattened device tree with sane information in its - * header. - * - * returns: - * 0, if the buffer appears to contain a valid device tree - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings, as above - */ -int fdt_check_header(const void *fdt); - -/** - * fdt_move - move a device tree around in memory - * @fdt: pointer to the device tree to move - * @buf: pointer to memory where the device is to be moved - * @bufsize: size of the memory space at buf - * - * fdt_move() relocates, if possible, the device tree blob located at - * fdt to the buffer at buf of size bufsize. The buffer may overlap - * with the existing device tree blob at fdt. Therefore, - * fdt_move(fdt, fdt, fdt_totalsize(fdt)) - * should always succeed. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_move(const void *fdt, void *buf, int bufsize); - -/**********************************************************************/ -/* Read-only functions */ -/**********************************************************************/ - -/** - * fdt_string - retrieve a string from the strings block of a device tree - * @fdt: pointer to the device tree blob - * @stroffset: offset of the string within the strings block (native endian) - * - * fdt_string() retrieves a pointer to a single string from the - * strings block of the device tree blob at fdt. - * - * returns: - * a pointer to the string, on success - * NULL, if stroffset is out of bounds - */ -const char *fdt_string(const void *fdt, int stroffset); - -/** - * fdt_num_mem_rsv - retrieve the number of memory reserve map entries - * @fdt: pointer to the device tree blob - * - * Returns the number of entries in the device tree blob's memory - * reservation map. This does not include the terminating 0,0 entry - * or any other (0,0) entries reserved for expansion. - * - * returns: - * the number of entries - */ -int fdt_num_mem_rsv(const void *fdt); - -/** - * fdt_get_mem_rsv - retrieve one memory reserve map entry - * @fdt: pointer to the device tree blob - * @address, @size: pointers to 64-bit variables - * - * On success, *address and *size will contain the address and size of - * the n-th reserve map entry from the device tree blob, in - * native-endian format. - * - * returns: - * 0, on success - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); - -/** - * fdt_subnode_offset_namelen - find a subnode based on substring - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * @namelen: number of characters of name to consider - * - * Identical to fdt_subnode_offset(), but only examine the first - * namelen characters of name for matching the subnode name. This is - * useful for finding subnodes based on a portion of a larger string, - * such as a full path. - */ -int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, - const char *name, int namelen); -/** - * fdt_subnode_offset - find a subnode of a given node - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * - * fdt_subnode_offset() finds a subnode of the node at structure block - * offset parentoffset with the given name. name may include a unit - * address, in which case fdt_subnode_offset() will find the subnode - * with that unit address, or the unit address may be omitted, in - * which case fdt_subnode_offset() will find an arbitrary subnode - * whose name excluding unit address matches the given name. - * - * returns: - * structure block offset of the requested subnode (>=0), on success - * -FDT_ERR_NOTFOUND, if the requested subnode does not exist - * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); - -/** - * fdt_path_offset - find a tree node by its full path - * @fdt: pointer to the device tree blob - * @path: full path of the node to locate - * - * fdt_path_offset() finds a node of a given path in the device tree. - * Each path component may omit the unit address portion, but the - * results of this are undefined if any such path component is - * ambiguous (that is if there are multiple nodes at the relevant - * level matching the given component, differentiated only by unit - * address). - * - * returns: - * structure block offset of the node with the requested path (>=0), on success - * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid - * -FDT_ERR_NOTFOUND, if the requested node does not exist - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_path_offset(const void *fdt, const char *path); - -/** - * fdt_get_name - retrieve the name of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of the starting node - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_name() retrieves the name (including unit address) of the - * device tree node at structure block offset nodeoffset. If lenp is - * non-NULL, the length of this name is also returned, in the integer - * pointed to by lenp. - * - * returns: - * pointer to the node's name, on success - * If lenp is non-NULL, *lenp contains the length of that name (>=0) - * NULL, on error - * if lenp is non-NULL *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); - -/** - * fdt_first_property_offset - find the offset of a node's first property - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of a node - * - * fdt_first_property_offset() finds the first property of the node at - * the given structure block offset. - * - * returns: - * structure block offset of the property (>=0), on success - * -FDT_ERR_NOTFOUND, if the requested node has no properties - * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_first_property_offset(const void *fdt, int nodeoffset); - -/** - * fdt_next_property_offset - step through a node's properties - * @fdt: pointer to the device tree blob - * @offset: structure block offset of a property - * - * fdt_next_property_offset() finds the property immediately after the - * one at the given structure block offset. This will be a property - * of the same node as the given property. - * - * returns: - * structure block offset of the next property (>=0), on success - * -FDT_ERR_NOTFOUND, if the given property is the last in its node - * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_next_property_offset(const void *fdt, int offset); - -/** - * fdt_get_property_by_offset - retrieve the property at a given offset - * @fdt: pointer to the device tree blob - * @offset: offset of the property to retrieve - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_property_by_offset() retrieves a pointer to the - * fdt_property structure within the device tree blob at the given - * offset. If lenp is non-NULL, the length of the property value is - * also returned, in the integer pointed to by lenp. - * - * returns: - * pointer to the structure representing the property - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const struct fdt_property *fdt_get_property_by_offset(const void *fdt, - int offset, - int *lenp); - -/** - * fdt_get_property_namelen - find a property based on substring - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @namelen: number of characters of name to consider - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * Identical to fdt_get_property_namelen(), but only examine the first - * namelen characters of name for matching the property name. - */ -const struct fdt_property *fdt_get_property_namelen(const void *fdt, - int nodeoffset, - const char *name, - int namelen, int *lenp); - -/** - * fdt_get_property - find a given property in a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_property() retrieves a pointer to the fdt_property - * structure within the device tree blob corresponding to the property - * named 'name' of the node at offset nodeoffset. If lenp is - * non-NULL, the length of the property value is also returned, in the - * integer pointed to by lenp. - * - * returns: - * pointer to the structure representing the property - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_NOTFOUND, node does not have named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, - const char *name, int *lenp); -static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, - const char *name, - int *lenp) -{ - return (struct fdt_property *)(uintptr_t) - fdt_get_property(fdt, nodeoffset, name, lenp); -} - -/** - * fdt_getprop_by_offset - retrieve the value of a property at a given offset - * @fdt: pointer to the device tree blob - * @ffset: offset of the property to read - * @namep: pointer to a string variable (will be overwritten) or NULL - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_getprop_by_offset() retrieves a pointer to the value of the - * property at structure block offset 'offset' (this will be a pointer - * to within the device blob itself, not a copy of the value). If - * lenp is non-NULL, the length of the property value is also - * returned, in the integer pointed to by lenp. If namep is non-NULL, - * the property's namne will also be returned in the char * pointed to - * by namep (this will be a pointer to within the device tree's string - * block, not a new copy of the name). - * - * returns: - * pointer to the property's value - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * if namep is non-NULL *namep contiains a pointer to the property - * name. - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const void *fdt_getprop_by_offset(const void *fdt, int offset, - const char **namep, int *lenp); - -/** - * fdt_getprop_namelen - get property value based on substring - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @namelen: number of characters of name to consider - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * Identical to fdt_getprop(), but only examine the first namelen - * characters of name for matching the property name. - */ -const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, - const char *name, int namelen, int *lenp); - -/** - * fdt_getprop - retrieve the value of a given property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_getprop() retrieves a pointer to the value of the property - * named 'name' of the node at offset nodeoffset (this will be a - * pointer to within the device blob itself, not a copy of the value). - * If lenp is non-NULL, the length of the property value is also - * returned, in the integer pointed to by lenp. - * - * returns: - * pointer to the property's value - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_NOTFOUND, node does not have named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const void *fdt_getprop(const void *fdt, int nodeoffset, - const char *name, int *lenp); -static inline void *fdt_getprop_w(void *fdt, int nodeoffset, - const char *name, int *lenp) -{ - return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); -} - -/** - * fdt_get_phandle - retrieve the phandle of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of the node - * - * fdt_get_phandle() retrieves the phandle of the device tree node at - * structure block offset nodeoffset. - * - * returns: - * the phandle of the node at nodeoffset, on success (!= 0, != -1) - * 0, if the node has no phandle, or another error occurs - */ -uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); - -/** - * fdt_get_alias_namelen - get alias based on substring - * @fdt: pointer to the device tree blob - * @name: name of the alias th look up - * @namelen: number of characters of name to consider - * - * Identical to fdt_get_alias(), but only examine the first namelen - * characters of name for matching the alias name. - */ -const char *fdt_get_alias_namelen(const void *fdt, - const char *name, int namelen); - -/** - * fdt_get_alias - retreive the path referenced by a given alias - * @fdt: pointer to the device tree blob - * @name: name of the alias th look up - * - * fdt_get_alias() retrieves the value of a given alias. That is, the - * value of the property named 'name' in the node /aliases. - * - * returns: - * a pointer to the expansion of the alias named 'name', of it exists - * NULL, if the given alias or the /aliases node does not exist - */ -const char *fdt_get_alias(const void *fdt, const char *name); - -/** - * fdt_get_path - determine the full path of a node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose path to find - * @buf: character buffer to contain the returned path (will be overwritten) - * @buflen: size of the character buffer at buf - * - * fdt_get_path() computes the full path of the node at offset - * nodeoffset, and records that path in the buffer at buf. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - * 0, on success - * buf contains the absolute path of the node at - * nodeoffset, as a NUL-terminated string. - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) - * characters and will not fit in the given buffer. - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); - -/** - * fdt_supernode_atdepth_offset - find a specific ancestor of a node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * @supernodedepth: depth of the ancestor to find - * @nodedepth: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_supernode_atdepth_offset() finds an ancestor of the given node - * at a specific depth from the root (where the root itself has depth - * 0, its immediate subnodes depth 1 and so forth). So - * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); - * will always return 0, the offset of the root node. If the node at - * nodeoffset has depth D, then: - * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); - * will return nodeoffset itself. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - - * structure block offset of the node at node offset's ancestor - * of depth supernodedepth (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag -* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, - int supernodedepth, int *nodedepth); - -/** - * fdt_node_depth - find the depth of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * - * fdt_node_depth() finds the depth of a given node. The root node - * has depth 0, its immediate subnodes depth 1 and so forth. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - * depth of the node at nodeoffset (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_depth(const void *fdt, int nodeoffset); - -/** - * fdt_parent_offset - find the parent of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * - * fdt_parent_offset() locates the parent node of a given node (that - * is, it finds the offset of the node which contains the node at - * nodeoffset as a subnode). - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset, *twice*. - * - * returns: - * structure block offset of the parent of the node at nodeoffset - * (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_parent_offset(const void *fdt, int nodeoffset); - -/** - * fdt_node_offset_by_prop_value - find nodes with a given property value - * @fdt: pointer to the device tree blob - * @startoffset: only find nodes after this offset - * @propname: property name to check - * @propval: property value to search for - * @proplen: length of the value in propval - * - * fdt_node_offset_by_prop_value() returns the offset of the first - * node after startoffset, which has a property named propname whose - * value is of length proplen and has value equal to propval; or if - * startoffset is -1, the very first such node in the tree. - * - * To iterate through all nodes matching the criterion, the following - * idiom can be used: - * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, - * propval, proplen); - * while (offset != -FDT_ERR_NOTFOUND) { - * // other code here - * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, - * propval, proplen); - * } - * - * Note the -1 in the first call to the function, if 0 is used here - * instead, the function will never locate the root node, even if it - * matches the criterion. - * - * returns: - * structure block offset of the located node (>= 0, >startoffset), - * on success - * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the - * tree after startoffset - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, - const char *propname, - const void *propval, int proplen); - -/** - * fdt_node_offset_by_phandle - find the node with a given phandle - * @fdt: pointer to the device tree blob - * @phandle: phandle value - * - * fdt_node_offset_by_phandle() returns the offset of the node - * which has the given phandle value. If there is more than one node - * in the tree with the given phandle (an invalid tree), results are - * undefined. - * - * returns: - * structure block offset of the located node (>= 0), on success - * -FDT_ERR_NOTFOUND, no node with that phandle exists - * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); - -/** - * fdt_node_check_compatible: check a node's compatible property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of a tree node - * @compatible: string to match against - * - * - * fdt_node_check_compatible() returns 0 if the given node contains a - * 'compatible' property with the given string as one of its elements, - * it returns non-zero otherwise, or on error. - * - * returns: - * 0, if the node has a 'compatible' property listing the given string - * 1, if the node has a 'compatible' property, but it does not list - * the given string - * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property - * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_check_compatible(const void *fdt, int nodeoffset, - const char *compatible); - -/** - * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value - * @fdt: pointer to the device tree blob - * @startoffset: only find nodes after this offset - * @compatible: 'compatible' string to match against - * - * fdt_node_offset_by_compatible() returns the offset of the first - * node after startoffset, which has a 'compatible' property which - * lists the given compatible string; or if startoffset is -1, the - * very first such node in the tree. - * - * To iterate through all nodes matching the criterion, the following - * idiom can be used: - * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); - * while (offset != -FDT_ERR_NOTFOUND) { - * // other code here - * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); - * } - * - * Note the -1 in the first call to the function, if 0 is used here - * instead, the function will never locate the root node, even if it - * matches the criterion. - * - * returns: - * structure block offset of the located node (>= 0, >startoffset), - * on success - * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the - * tree after startoffset - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_compatible(const void *fdt, int startoffset, - const char *compatible); - -/**********************************************************************/ -/* Write-in-place functions */ -/**********************************************************************/ - -/** - * fdt_setprop_inplace - change a property's value, but not its size - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: pointer to data to replace the property value with - * @len: length of the property value - * - * fdt_setprop_inplace() replaces the value of a given property with - * the data in val, of length len. This function cannot change the - * size of a property, and so will only work if len is equal to the - * current length of the property. - * - * This function will alter only the bytes in the blob which contain - * the given property value, and will not alter or move any other part - * of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, if len is not equal to the property's current length - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, - const void *val, int len); - -/** - * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 32-bit integer value to replace the property with - * - * fdt_setprop_inplace_u32() replaces the value of a given property - * with the 32-bit integer value in val, converting val to big-endian - * if necessary. This function cannot change the size of a property, - * and so will only work if the property already exists and has length - * 4. - * - * This function will alter only the bytes in the blob which contain - * the given property value, and will not alter or move any other part - * of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - val = cpu_to_fdt32(val); - return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); -} - -/** - * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 64-bit integer value to replace the property with - * - * fdt_setprop_inplace_u64() replaces the value of a given property - * with the 64-bit integer value in val, converting val to big-endian - * if necessary. This function cannot change the size of a property, - * and so will only work if the property already exists and has length - * 8. - * - * This function will alter only the bytes in the blob which contain - * the given property value, and will not alter or move any other part - * of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, - const char *name, uint64_t val) -{ - val = cpu_to_fdt64(val); - return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); -} - -/** - * fdt_setprop_inplace_cell - change the value of a single-cell property - * - * This is an alternative name for fdt_setprop_inplace_u32() - */ -static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); -} - -/** - * fdt_nop_property - replace a property with nop tags - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to nop - * @name: name of the property to nop - * - * fdt_nop_property() will replace a given property's representation - * in the blob with FDT_NOP tags, effectively removing it from the - * tree. - * - * This function will alter only the bytes in the blob which contain - * the property, and will not alter or move any other part of the - * tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_nop_property(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_nop_node - replace a node (subtree) with nop tags - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to nop - * - * fdt_nop_node() will replace a given node's representation in the - * blob, including all its subnodes, if any, with FDT_NOP tags, - * effectively removing it from the tree. - * - * This function will alter only the bytes in the blob which contain - * the node and its properties and subnodes, and will not alter or - * move any other part of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_nop_node(void *fdt, int nodeoffset); - -/**********************************************************************/ -/* Sequential write functions */ -/**********************************************************************/ - -int fdt_create(void *buf, int bufsize); -int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); -int fdt_finish_reservemap(void *fdt); -int fdt_begin_node(void *fdt, const char *name); -int fdt_property(void *fdt, const char *name, const void *val, int len); -static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) -{ - val = cpu_to_fdt32(val); - return fdt_property(fdt, name, &val, sizeof(val)); -} -static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) -{ - val = cpu_to_fdt64(val); - return fdt_property(fdt, name, &val, sizeof(val)); -} -static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) -{ - return fdt_property_u32(fdt, name, val); -} -#define fdt_property_string(fdt, name, str) \ - fdt_property(fdt, name, str, strlen(str)+1) -int fdt_end_node(void *fdt); -int fdt_finish(void *fdt); - -/**********************************************************************/ -/* Read-write functions */ -/**********************************************************************/ - -int fdt_create_empty_tree(void *buf, int bufsize); -int fdt_open_into(const void *fdt, void *buf, int bufsize); -int fdt_pack(void *fdt); - -/** - * fdt_add_mem_rsv - add one memory reserve map entry - * @fdt: pointer to the device tree blob - * @address, @size: 64-bit values (native endian) - * - * Adds a reserve map entry to the given blob reserving a region at - * address address of length size. - * - * This function will insert data into the reserve map and will - * therefore change the indexes of some entries in the table. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new reservation entry - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); - -/** - * fdt_del_mem_rsv - remove a memory reserve map entry - * @fdt: pointer to the device tree blob - * @n: entry to remove - * - * fdt_del_mem_rsv() removes the n-th memory reserve map entry from - * the blob. - * - * This function will delete data from the reservation table and will - * therefore change the indexes of some entries in the table. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there - * are less than n+1 reserve map entries) - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_del_mem_rsv(void *fdt, int n); - -/** - * fdt_set_name - change the name of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of a node - * @name: name to give the node - * - * fdt_set_name() replaces the name (including unit address, if any) - * of the given node with the given string. NOTE: this function can't - * efficiently check if the new name is unique amongst the given - * node's siblings; results are undefined if this function is invoked - * with a name equal to one of the given node's siblings. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob - * to contain the new name - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_set_name(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_setprop - create or change a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: pointer to data to set the property value to - * @len: length of the property value - * - * fdt_setprop() sets the value of the named property in the given - * node to the given value and length, creating the property if it - * does not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len); - -/** - * fdt_setprop_u32 - set a property to a 32-bit integer - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 32-bit integer value for the property (native endian) - * - * fdt_setprop_u32() sets the value of the named property in the given - * node to the given 32-bit integer value (converting to big-endian if - * necessary), or creates a new property with that value if it does - * not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, - uint32_t val) -{ - val = cpu_to_fdt32(val); - return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); -} - -/** - * fdt_setprop_u64 - set a property to a 64-bit integer - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 64-bit integer value for the property (native endian) - * - * fdt_setprop_u64() sets the value of the named property in the given - * node to the given 64-bit integer value (converting to big-endian if - * necessary), or creates a new property with that value if it does - * not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, - uint64_t val) -{ - val = cpu_to_fdt64(val); - return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); -} - -/** - * fdt_setprop_cell - set a property to a single cell value - * - * This is an alternative name for fdt_setprop_u32() - */ -static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, - uint32_t val) -{ - return fdt_setprop_u32(fdt, nodeoffset, name, val); -} - -/** - * fdt_setprop_string - set a property to a string value - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @str: string value for the property - * - * fdt_setprop_string() sets the value of the named property in the - * given node to the given string value (using the length of the - * string to determine the new length of the property), or creates a - * new property with that value if it does not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#define fdt_setprop_string(fdt, nodeoffset, name, str) \ - fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) - -/** - * fdt_appendprop - append to or create a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to append to - * @val: pointer to data to append to the property value - * @len: length of the data to append to the property value - * - * fdt_appendprop() appends the value to the named property in the - * given node, creating the property if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_appendprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len); - -/** - * fdt_appendprop_u32 - append a 32-bit integer value to a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 32-bit integer value to append to the property (native endian) - * - * fdt_appendprop_u32() appends the given 32-bit integer value - * (converting to big-endian if necessary) to the value of the named - * property in the given node, or creates a new property with that - * value if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - val = cpu_to_fdt32(val); - return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); -} - -/** - * fdt_appendprop_u64 - append a 64-bit integer value to a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 64-bit integer value to append to the property (native endian) - * - * fdt_appendprop_u64() appends the given 64-bit integer value - * (converting to big-endian if necessary) to the value of the named - * property in the given node, or creates a new property with that - * value if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, - const char *name, uint64_t val) -{ - val = cpu_to_fdt64(val); - return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); -} - -/** - * fdt_appendprop_cell - append a single cell value to a property - * - * This is an alternative name for fdt_appendprop_u32() - */ -static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - return fdt_appendprop_u32(fdt, nodeoffset, name, val); -} - -/** - * fdt_appendprop_string - append a string to a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @str: string value to append to the property - * - * fdt_appendprop_string() appends the given string to the value of - * the named property in the given node, or creates a new property - * with that value if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#define fdt_appendprop_string(fdt, nodeoffset, name, str) \ - fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) - -/** - * fdt_delprop - delete a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to nop - * @name: name of the property to nop - * - * fdt_del_property() will delete the given property. - * - * This function will delete data from the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_delprop(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_add_subnode_namelen - creates a new node based on substring - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * @namelen: number of characters of name to consider - * - * Identical to fdt_add_subnode(), but use only the first namelen - * characters of name as the name of the new node. This is useful for - * creating subnodes based on a portion of a larger string, such as a - * full path. - */ -int fdt_add_subnode_namelen(void *fdt, int parentoffset, - const char *name, int namelen); - -/** - * fdt_add_subnode - creates a new node - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * - * fdt_add_subnode() creates a new node as a subnode of the node at - * structure block offset parentoffset, with the given name (which - * should include the unit address, if any). - * - * This function will insert data into the blob, and will therefore - * change the offsets of some existing nodes. - - * returns: - * structure block offset of the created nodeequested subnode (>=0), on success - * -FDT_ERR_NOTFOUND, if the requested subnode does not exist - * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag - * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of - * the given name - * -FDT_ERR_NOSPACE, if there is insufficient free space in the - * blob to contain the new node - * -FDT_ERR_NOSPACE - * -FDT_ERR_BADLAYOUT - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_add_subnode(void *fdt, int parentoffset, const char *name); - -/** - * fdt_del_node - delete a node (subtree) - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to nop - * - * fdt_del_node() will remove the given node, including all its - * subnodes if any, from the blob. - * - * This function will delete data from the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_del_node(void *fdt, int nodeoffset); - -/**********************************************************************/ -/* Debugging / informational functions */ -/**********************************************************************/ - -const char *fdt_strerror(int errval); - -#endif /* _LIBFDT_H */ diff --git a/recovery/fdt/libfdt_env.h b/recovery/fdt/libfdt_env.h deleted file mode 100644 index 213d7fb..0000000 --- a/recovery/fdt/libfdt_env.h +++ b/dev/null @@ -1,29 +0,0 @@ -#ifndef _LIBFDT_ENV_H -#define _LIBFDT_ENV_H - -#include <stddef.h> -#include <stdint.h> -#include <string.h> - -#define EXTRACT_BYTE(n) ((unsigned long long)((uint8_t *)&x)[n]) -static inline uint16_t fdt16_to_cpu(uint16_t x) -{ - return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1); -} -#define cpu_to_fdt16(x) fdt16_to_cpu(x) - -static inline uint32_t fdt32_to_cpu(uint32_t x) -{ - return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3); -} -#define cpu_to_fdt32(x) fdt32_to_cpu(x) - -static inline uint64_t fdt64_to_cpu(uint64_t x) -{ - return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32) - | (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7); -} -#define cpu_to_fdt64(x) fdt64_to_cpu(x) -#undef EXTRACT_BYTE - -#endif /* _LIBFDT_ENV_H */ diff --git a/recovery/fdt/libfdt_internal.h b/recovery/fdt/libfdt_internal.h deleted file mode 100644 index 381133b..0000000 --- a/recovery/fdt/libfdt_internal.h +++ b/dev/null @@ -1,95 +0,0 @@ -#ifndef _LIBFDT_INTERNAL_H -#define _LIBFDT_INTERNAL_H -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include <fdt.h> - -#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) - -#define FDT_CHECK_HEADER(fdt) \ - { \ - int err; \ - if ((err = fdt_check_header(fdt)) != 0) \ - return err; \ - } - -int _fdt_check_node_offset(const void *fdt, int offset); -int _fdt_check_prop_offset(const void *fdt, int offset); -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); -int _fdt_node_end_offset(void *fdt, int nodeoffset); - -static inline const void *_fdt_offset_ptr(const void *fdt, int offset) -{ - return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; -} - -static inline void *_fdt_offset_ptr_w(void *fdt, int offset) -{ - return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); -} - -static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) -{ - const struct fdt_reserve_entry *rsv_table = - (const struct fdt_reserve_entry *) - ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); - - return rsv_table + n; -} -static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) -{ - return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); -} - -#define FDT_SW_MAGIC (~FDT_MAGIC) - -#endif /* _LIBFDT_INTERNAL_H */ diff --git a/recovery/recovery_extra/Android.mk b/recovery/recovery_extra/Android.mk deleted file mode 100644 index f94b6f4..0000000 --- a/recovery/recovery_extra/Android.mk +++ b/dev/null @@ -1,31 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := recovery_amlogic.cpp - -LOCAL_MODULE := librecovery_amlogic - -LOCAL_MODULE_TAGS := eng - -LOCAL_C_INCLUDES += bootable/recovery - -LOCAL_C_INCLUDES += \ - system/vold \ - system/core/adb - -LOCAL_C_INCLUDES += \ - system/core/base/include \ - system/core/libziparchive/include - -LOCAL_C_INCLUDES += bootable/recovery/bootloader_message/include - -LOCAL_C_INCLUDES += $(LOCAL_PATH)/../ - -LOCAL_FORCE_STATIC_EXECUTABLE := true - -LOCAL_STATIC_LIBRARIES += libfs_mgr libselinux - -LOCAL_CFLAGS += -Wall - -include $(BUILD_STATIC_LIBRARY)
\ No newline at end of file diff --git a/recovery/recovery_extra/recovery_amlogic.cpp b/recovery/recovery_extra/recovery_amlogic.cpp deleted file mode 100644 index 249033f..0000000 --- a/recovery/recovery_extra/recovery_amlogic.cpp +++ b/dev/null @@ -1,392 +0,0 @@ -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <ctype.h> -#include <fcntl.h> -#include <fs_mgr.h> -#include "install.h" -#include "ui.h" -#include <dirent.h> -#include "bootloader_message/bootloader_message.h" -#include "recovery_amlogic.h" - -#include "ubootenv/set_display_mode.h" - -extern "C" { -#include "ubootenv/uboot_env.h" -} - -#define LOGE(...) ui_print("E:" __VA_ARGS__) -#define LOGW(...) fprintf(stdout, "W:" __VA_ARGS__) -#define LOGI(...) fprintf(stdout, "I:" __VA_ARGS__) - -static const int MAX_ARGS = 100; -static const int MAX_ARG_LENGTH = 4096; -#define NUM_OF_BLKDEVICE_TO_ENUM 3 -#define NUM_OF_PARTITION_TO_ENUM 6 - -static const char *UDISK_COMMAND_FILE = "/udisk/factory_update_param.aml"; -static const char *SDCARD_COMMAND_FILE = "/sdcard/factory_update_param.aml"; - -void setup_cache_mounts() { - int ret = 0; - ret = ensure_path_mounted("/cache"); - if (ret != 0) { - format_volume("/cache"); - } -} - - - -static int mount_fs_rdonly(char *device_name, Volume *vol, const char *fs_type) { - if (!mount(device_name, vol->mount_point, fs_type, - MS_NOATIME | MS_NODEV | MS_NODIRATIME | MS_RDONLY, 0)) { - LOGW("successful to mount %s on %s by read-only\n", - device_name, vol->mount_point); - return 0; - } else { - LOGE("failed to mount %s on %s by read-only (%s)\n", - device_name, vol->mount_point, strerror(errno)); - } - - return -1; -} - -int auto_mount_fs(char *device_name, Volume *vol) { - if (access(device_name, F_OK)) { - return -1; - } - - if (!strcmp(vol->fs_type, "auto")) { - if (!mount(device_name, vol->mount_point, "vfat", - MS_NOATIME | MS_NODEV | MS_NODIRATIME, "")) { - goto auto_mounted; - } else { - if (strstr(vol->mount_point, "sdcard")) { - LOGW("failed to mount %s on %s (%s).try read-only ...\n", - device_name, vol->mount_point, strerror(errno)); - if (!mount_fs_rdonly(device_name, vol, "vfat")) { - goto auto_mounted; - } - } - } - - if (!mount(device_name, vol->mount_point, "ntfs", - MS_NOATIME | MS_NODEV | MS_NODIRATIME, "")) { - goto auto_mounted; - } else { - if (strstr(vol->mount_point, "sdcard")) { - LOGW("failed to mount %s on %s (%s).try read-only ...\n", - device_name, vol->mount_point, strerror(errno)); - if (!mount_fs_rdonly(device_name, vol, "ntfs")) { - goto auto_mounted; - } - } - } - - if (!mount(device_name, vol->mount_point, "exfat", - MS_NOATIME | MS_NODEV | MS_NODIRATIME, "")) { - goto auto_mounted; - } else { - if (strstr(vol->mount_point, "sdcard")) { - LOGW("failed to mount %s on %s (%s).try read-only ...\n", - device_name, vol->mount_point, strerror(errno)); - if (!mount_fs_rdonly(device_name, vol, "exfat")) { - goto auto_mounted; - } - } - } - } else { - if(!mount(device_name, vol->mount_point, vol->fs_type, - MS_NOATIME | MS_NODEV | MS_NODIRATIME, "")) { - goto auto_mounted; - } else { - if (strstr(vol->mount_point, "sdcard")) { - LOGW("failed to mount %s on %s (%s).try read-only ...\n", - device_name, vol->mount_point, strerror(errno)); - if (!mount_fs_rdonly(device_name, vol, vol->fs_type)) { - goto auto_mounted; - } - } - } - } - - return -1; - -auto_mounted: - return 0; -} - -int customize_smart_device_mounted( - Volume *vol) { - int i = 0, j = 0; - int first_position = 0; - int second_position = 0; - char * tmp = NULL; - char *mounted_device = NULL; - char device_name[256] = {0}; - char device_boot[256] = {0}; - const char *usb_device = "/dev/block/sd"; - const char *sdcard_device = "/dev/block/mmcblk"; - - if (vol->blk_device != NULL) { - int num = 0; - const char *blk_device = vol->blk_device; - for (; *blk_device != '\0'; blk_device ++) { - if (*blk_device == '#') { - num ++; - } - } - - /* - * Contain two '#' for blk_device name in recovery.fstab - * such as /dev/block/sd## (udisk) - * such as /dev/block/mmcblk#p# (sdcard) - */ - if (num != 2) { - return 1; // Don't contain two '#' - } - - if (access(vol->mount_point, F_OK)) { - mkdir(vol->mount_point, 0755); - } - - // find '#' position - if (strchr(vol->blk_device, '#')) { - tmp = strchr(vol->blk_device, '#'); - first_position = tmp - vol->blk_device; - if (strlen(tmp+1) > 0 && strchr(tmp+1, '#')) { - tmp = strchr(tmp+1, '#'); - second_position = tmp - vol->blk_device; - } - } - - if (!first_position || !second_position) { - LOGW("decompose blk_device error(%s) in recovery.fstab\n", - vol->blk_device); - return -1; - } - - int copy_len = (strlen(vol->blk_device) < sizeof(device_name)) ? - strlen(vol->blk_device) : sizeof(device_name); - - for (i = 0; i < NUM_OF_BLKDEVICE_TO_ENUM; i ++) { - memset(device_name, '\0', sizeof(device_name)); - strncpy(device_name, vol->blk_device, copy_len); - - if (!strncmp(device_name, sdcard_device, strlen(sdcard_device))) { - // start from '0' for mmcblk0p# - device_name[first_position] = '0' + i; - } else if (!strncmp(device_name, usb_device, strlen(usb_device))) { - // start from 'a' for sda# - device_name[first_position] = 'a' + i; - } - - for (j = 1; j <= NUM_OF_PARTITION_TO_ENUM; j ++) { - device_name[second_position] = '0' + j; - if (!access(device_name, F_OK)) { - LOGW("try mount %s ...\n", device_name); - if (!auto_mount_fs(device_name, vol)) { - mounted_device = device_name; - LOGW("successful to mount %s\n", device_name); - goto mounted; - } - } - } - - if (!strncmp(device_name, sdcard_device, strlen(sdcard_device))) { - // mmcblk0p1->mmcblk0 - device_name[strlen(device_name) - 2] = '\0'; - sprintf(device_boot, "%s%s", device_name, "boot0"); - // TODO: Here,need to distinguish between cards and flash at best - } else if (!strncmp(device_name, usb_device, strlen(usb_device))) { - // sda1->sda - device_name[strlen(device_name) - 1] = '\0'; - } - - if (!access(device_name, F_OK)) { - if (strlen(device_boot) && (!access(device_boot, F_OK))) { - continue; - } - - LOGW("try mount %s ...\n", device_name); - if (!auto_mount_fs(device_name, vol)) { - mounted_device = device_name; - LOGW("successful to mount %s\n", device_name); - goto mounted; - } - } - } - } else { - LOGE("Can't get blk_device\n"); - } - - return -1; - -mounted: - return 0; -} - -int smart_device_mounted(Volume *vol) { - int i = 0, len = 0; - char * tmp = NULL; - char device_name[256] = {0}; - char *mounted_device = NULL; - - mkdir(vol->mount_point, 0755); - - if (vol->blk_device != NULL) { - int ret = customize_smart_device_mounted(vol); - if (ret <= 0) { - return ret; - } - } - - if (vol->blk_device != NULL) { - tmp = strchr(vol->blk_device, '#'); - len = tmp - vol->blk_device; - if (tmp && len < 255) { - strncpy(device_name, vol->blk_device, len); - for (i = 1; i <= NUM_OF_PARTITION_TO_ENUM; i++) { - device_name[len] = '0' + i; - device_name[len + 1] = '\0'; - LOGW("try mount %s ...\n", device_name); - if (!access(device_name, F_OK)) { - if (!auto_mount_fs(device_name, vol)) { - mounted_device = device_name; - LOGW("successful to mount %s\n", device_name); - goto mounted; - } - } - } - - const char *mmcblk = "/dev/block/mmcblk"; - if (!strncmp(device_name, mmcblk, strlen(mmcblk))) { - device_name[len - 1] = '\0'; - } else { - device_name[len] = '\0'; - } - - LOGW("try mount %s ...\n", device_name); - if (!access(device_name, F_OK)) { - if (!auto_mount_fs(device_name, vol)) { - mounted_device = device_name; - LOGW("successful to mount %s\n", device_name); - goto mounted; - } - } - } else { - LOGW("try mount %s ...\n", vol->blk_device); - strncpy(device_name, vol->blk_device, sizeof(device_name)); - if (!access(device_name, F_OK)) { - if (!auto_mount_fs(device_name, vol)) { - mounted_device = device_name; - LOGW("successful to mount %s\n", device_name); - goto mounted; - } - } - } - } - - return -1; - -mounted: - return 0; -} - - -//return value -// 0 mount OK -// -1 mount Faile -// 2 ignorel -int ensure_path_mounted_extra(Volume *v) { - Volume* vUsb = volume_for_path("/udisk"); - char tmp[128] = {0}; - - if (strcmp(v->fs_type, "ext4") == 0) { - if (strstr(v->mount_point, "system")) { - if (!mount(v->blk_device, v->mount_point, v->fs_type, - MS_NOATIME | MS_NODEV | MS_NODIRATIME | MS_RDONLY, "")) { - return 0; - } - } else { - if (!mount(v->blk_device, v->mount_point, v->fs_type, - MS_NOATIME | MS_NODEV | MS_NODIRATIME, "discard")) { - return 0; - } - } - LOGE("failed to mount %s (%s)\n", v->mount_point, strerror(errno)); - return -1; - } else if (strcmp(v->fs_type, "vfat") == 0 || - strcmp(v->fs_type, "auto") == 0 ) { - if (strstr(v->mount_point, "sdcard") || strstr(v->mount_point, "udisk")) { - int time_out = 2000000; - while (time_out) { - if (!smart_device_mounted(v)) { - return 0; - } - usleep(100000); - time_out -= 100000; - } - } else { - if (!mount(v->blk_device, v->mount_point, v->fs_type, - MS_NOATIME | MS_NODEV | MS_NODIRATIME | MS_RDONLY, "")) { - return 0; - } - } - LOGE("failed to mount %s (%s)\n", v->mount_point, strerror(errno)); - return -1; - } else { - return 2;//not deal - } -} - -void amlogic_init() { - set_display_mode("/etc/mesondisplay.cfg"); - sleep(1); -} - -void amlogic_get_args(std::vector<std::string>& args) { - - if (args.size() == 1) { - std::string content; - if (ensure_path_mounted(UDISK_COMMAND_FILE) == 0 && - android::base::ReadFileToString(UDISK_COMMAND_FILE, &content)) { - - std::vector<std::string> tokens = android::base::Split(content, "\n"); - for (auto it = tokens.begin(); it != tokens.end(); it++) { - // Skip empty and '\0'-filled tokens. - if (!it->empty() && (*it)[0] != '\0') { - args.push_back(std::move(*it)); - } - } - LOG(INFO) << "Got " << args.size() << " arguments from " << UDISK_COMMAND_FILE; - } - } - - if (args.size() == 1) { - std::string content; - if (ensure_path_mounted(SDCARD_COMMAND_FILE) == 0 && - android::base::ReadFileToString(SDCARD_COMMAND_FILE, &content)) { - - std::vector<std::string> tokens = android::base::Split(content, "\n"); - for (auto it = tokens.begin(); it != tokens.end(); it++) { - // Skip empty and '\0'-filled tokens. - if (!it->empty() && (*it)[0] != '\0') { - args.push_back(std::move(*it)); - } - } - LOG(INFO) << "Got " << args.size() << " arguments from " << SDCARD_COMMAND_FILE; - } - } - - if (args.size() == 1) { - args.push_back(std::move("--show_text")); - } - -} diff --git a/recovery/recovery_extra/recovery_amlogic.h b/recovery/recovery_extra/recovery_amlogic.h deleted file mode 100644 index 7ab23cf..0000000 --- a/recovery/recovery_extra/recovery_amlogic.h +++ b/dev/null @@ -1,25 +0,0 @@ -#ifndef _RECOVERY_INSTALL_AMLOGIC_H_ -#define _RECOVERY_INSTALL_AMLOGIC_H_ - -#include "common.h" -#include "device.h" -#include "roots.h" - -#include <android-base/file.h> -#include <android-base/logging.h> -#include <android-base/parseint.h> -#include <android-base/properties.h> -#include <android-base/stringprintf.h> -#include <android-base/strings.h> -#include <android-base/unique_fd.h> - -void amlogic_init(); - -void amlogic_get_args(std::vector<std::string>& args); - -void setup_cache_mounts(); - -int ensure_path_mounted_extra(Volume *v); - -#endif - diff --git a/recovery/ubootenv/Android.mk b/recovery/ubootenv/Android.mk deleted file mode 100644 index 8aedda6..0000000 --- a/recovery/ubootenv/Android.mk +++ b/dev/null @@ -1,17 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := uboot_env.cpp set_display_mode.cpp - -LOCAL_MODULE := libenv - -LOCAL_MODULE_TAGS := eng - -LOCAL_C_INCLUDES += $(BOARD_AML_VENDOR_PATH)/frameworks/services/systemcontrol -LOCAL_C_INCLUDES += bootable/recovery - -LOCAL_FORCE_STATIC_EXECUTABLE := true - -LOCAL_STATIC_LIBRARIES += libsystemcontrol_static liblog libcutils libstdc++ libc libbz - -include $(BUILD_STATIC_LIBRARY) diff --git a/recovery/ubootenv/set_display_mode.cpp b/recovery/ubootenv/set_display_mode.cpp deleted file mode 100644 index eec9c29..0000000 --- a/recovery/ubootenv/set_display_mode.cpp +++ b/dev/null @@ -1,24 +0,0 @@ -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> - -#include "ubootenv/Ubootenv.h" -#include "SysWrite.h" -#include "DisplayMode.h" - -int set_display_mode(const char *path) -{ - Ubootenv *pUbootenv = new Ubootenv(); - SysWrite *pSysWrite = new SysWrite(); - - DisplayMode displayMode(path, pUbootenv); - //setBootEnv - //displayMode.setBootEnv("upgrade_step", "1"); - pUbootenv->updateValue("upgrade_step", "1"); - pSysWrite->setProperty(PROP_FS_MODE, "recovery"); - displayMode.init(); - - return 0; -}
\ No newline at end of file diff --git a/recovery/ubootenv/set_display_mode.h b/recovery/ubootenv/set_display_mode.h deleted file mode 100644 index 41d0b33..0000000 --- a/recovery/ubootenv/set_display_mode.h +++ b/dev/null @@ -1,4 +0,0 @@ -#ifndef SET_DISPLAY_MODE_H_ -#define SET_DISPLAY_MODE_H_ -int set_display_mode(const char *path); -#endif
\ No newline at end of file diff --git a/recovery/ubootenv/uboot_env.cpp b/recovery/ubootenv/uboot_env.cpp deleted file mode 100644 index 887387a..0000000 --- a/recovery/ubootenv/uboot_env.cpp +++ b/dev/null @@ -1,107 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> - -#include <errno.h> -#include <sys/stat.h> -#include <unistd.h> - -#include "ubootenv/Ubootenv.h" - - -// ------------------------------------ -// for uboot environment variable operation -// ------------------------------------ - - -int set_bootloader_env(const char* name, const char* value) -{ - Ubootenv *ubootenv = new Ubootenv(); - - char ubootenv_name[128] = {0}; - const char *ubootenv_var = "ubootenv.var."; - sprintf(ubootenv_name, "%s%s", ubootenv_var, name); - - if (ubootenv->updateValue(ubootenv_name, value)) { - fprintf(stderr,"could not set boot env\n"); - return -1; - } - - return 0; -} - -char *get_bootloader_env(const char * name) -{ - Ubootenv *ubootenv = new Ubootenv(); - char ubootenv_name[128] = {0}; - const char *ubootenv_var = "ubootenv.var."; - sprintf(ubootenv_name, "%s%s", ubootenv_var, name); - return (char *)ubootenv->getValue(ubootenv_name); -} - - -int set_env_optarg(char * optarg) -{ - int ret = -1; - char *buffer = NULL, *name = NULL, *value = NULL; - if ((optarg == NULL) || (strlen(optarg) == 0)) { - printf("param error!\n"); - return -1; - } - - buffer = strdup(optarg); - if (!buffer) { - printf("strdup for buffer failed\n"); - return -1; - } - - name = strtok(buffer, "="); - if (strlen(name) == strlen(optarg)) { - printf("strtok for '=' failed\n"); - goto END; - } - - value = optarg + strlen(name) + 1; - if (strlen(name) == 0) { - printf("name is NULL\n"); - goto END; - } - - if (strlen(value) == 0) { - printf("value is NULL\n"); - goto END; - } - - ret = set_bootloader_env(name, value); - if (ret < 0) { - printf("set env :%s=%s failed", name, value); - } - -END: - - if (buffer != NULL) { - free(buffer); - buffer = NULL; - } - return ret; -} - -int get_env_optarg(const char * optarg) -{ - int ret = -1; - - if (optarg == NULL) { - printf("param error!\n"); - return -1; - } - - char *env = get_bootloader_env(optarg); - if (env != NULL) - { - printf("get %s value:%s\n", optarg, env); - ret = 0; - } - - return ret; -} diff --git a/recovery/ubootenv/uboot_env.h b/recovery/ubootenv/uboot_env.h deleted file mode 100644 index effda27..0000000 --- a/recovery/ubootenv/uboot_env.h +++ b/dev/null @@ -1,24 +0,0 @@ -#ifndef BOOTLOADER_ENV_H_ -#define BOOTLOADER_ENV_H_ -/* -* set bootloader environment variable -* 0: success, <0: fail -*/ -extern int set_bootloader_env(const char* name, const char* value); - -/* -* get bootloader environment variable -* NULL: init failed or get env value is NULL -* NONE NULL: env value -*/ -extern char *get_bootloader_env(const char * name); - - - -extern int set_env_optarg(const char * optarg); - - - -extern int get_env_optarg(const char * optarg); - -#endif
\ No newline at end of file diff --git a/recovery/ui/Android.mk b/recovery/ui/Android.mk deleted file mode 100644 index 80f0eaa..0000000 --- a/recovery/ui/Android.mk +++ b/dev/null @@ -1,32 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := amlogic_ui.cpp - -LOCAL_MODULE := libamlogic_ui - -LOCAL_C_INCLUDES += \ - bootable/recovery \ - system/vold \ - system/core/adb \ - device/amlogic/common/recovery - -LOCAL_C_INCLUDES += \ - system/core/base/include \ - system/core/libziparchive/include - -LOCAL_C_INCLUDES += bootable/recovery/bootloader_message/include - -LOCAL_STATIC_LIBRARIES := \ - librecovery_amlogic \ - libenv \ - libsystemcontrol_static - -LOCAL_MODULE_TAGS := eng - -#LOCAL_FORCE_STATIC_EXECUTABLE := true - -LOCAL_CFLAGS += -Wall - -include $(BUILD_STATIC_LIBRARY)
\ No newline at end of file diff --git a/recovery/ui/amlogic_ui.cpp b/recovery/ui/amlogic_ui.cpp deleted file mode 100644 index acd82ef..0000000 --- a/recovery/ui/amlogic_ui.cpp +++ b/dev/null @@ -1,205 +0,0 @@ -#include<stdio.h> -#include<stdlib.h> -#include<string.h> -#include<ctype.h> - -#include "amlogic_ui.h" - -#include "common.h" -#include "device.h" -#include "screen_ui.h" -#include "ui.h" -#include "recovery_extra/recovery_amlogic.h" - -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/mount.h> -#include <string.h> -#include <ziparchive/zip_archive.h> -#include <android-base/logging.h> -#include "cutils/properties.h" - -#include <fcntl.h> -#include <linux/fb.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <unistd.h> - -#define FB_ACTIVATE_FORCE 128 /* force apply even when no change*/ - - -class AmlogicDevice : public Device { - public: - AmlogicDevice(ScreenRecoveryUI* ui) : Device(ui) { } -}; - -Device* make_device() { - amlogic_init(); - load_key_map(); - fb_set(); - return new AmlogicDevice(new ScreenRecoveryUI); -} - - -int num_keys; -KeyMapItem_t* keys_map; - -KeyMapItem_t g_default_keymap[3] = { - { "select", KEY_ENTER, {KEY_ENTER, KEY_TAB, KEY_BACK, -1, -1, -1} }, - { "down", KEY_DOWN, {KEY_DOWN, KEY_VOLUMEDOWN, KEY_PAGEDOWN, -1, -1, -1} }, - { "up", KEY_UP, {KEY_UP, KEY_VOLUMEUP, KEY_PAGEUP, -1, -1, -1} }, -}; - -CtrlInfo_t g_ctrlinfo[3] = { - { "select", KEY_ENTER }, - { "down", KEY_DOWN }, - { "up", KEY_UP }, -}; - -static KeyMapItem_t g_presupposed_keymap[] = { - { "select", -4, {BTN_MOUSE, BTN_LEFT, -1, -1, -1, -1} } -}; - -#define NUM_PRESUPPOSED_KEY_MAP (sizeof(g_presupposed_keymap) / sizeof(g_presupposed_keymap[0])) - -void fb_set() { - fb_var_screeninfo vi2; - int fd = open("/dev/graphics/fb0", O_RDWR); - if (fd == -1) { - printf("cannot open fb0"); - } - - if (ioctl(fd, FBIOGET_VSCREENINFO, &vi2) < 0) { - printf("failed to get fb0 info"); - close(fd); - } - - vi2.nonstd=1; - vi2.transp.length=0; - vi2.activate = FB_ACTIVATE_FORCE; - if (ioctl(fd, FBIOPUT_VSCREENINFO, &vi2) < 0) { - printf("active fb swap failed"); - } - - close(fd); -} - - -int getKey(char *key) { - - if (key == NULL) { - return -1; - } - - unsigned int i; - for (i = 0; i < NUM_CTRLINFO; i++) { - CtrlInfo_t *info = &g_ctrlinfo[i]; - if (strcmp(info->type, key) == 0) { - return info->value; - } - } - return -1; -} - -void load_key_map() { - FILE* fstab = fopen("/etc/recovery.kl", "r"); - if (fstab != NULL) { - printf("loaded /etc/recovery.kl\n"); - int alloc = 2; - keys_map = (KeyMapItem_t*)malloc(alloc * sizeof(KeyMapItem_t)); - - keys_map[0].type = "down"; - keys_map[0].value = KEY_DOWN; - keys_map[0].key[0] = -1; - keys_map[0].key[1] = -1; - keys_map[0].key[2] = -1; - keys_map[0].key[3] = -1; - keys_map[0].key[4] = -1; - keys_map[0].key[5] = -1; - num_keys = 0; - - char buffer[1024]; - int i; - int value = -1; - while (fgets(buffer, sizeof(buffer)-1, fstab)) { - for (i = 0; buffer[i] && isspace(buffer[i]); ++i); - - if (buffer[i] == '\0' || buffer[i] == '#') continue; - - char* original = strdup(buffer); - - char* type = strtok(original+i, " \t\n"); - char* key1 = strtok(NULL, " \t\n"); - char* key2 = strtok(NULL, " \t\n"); - char* key3 = strtok(NULL, " \t\n"); - char* key4 = strtok(NULL, " \t\n"); - char* key5 = strtok(NULL, " \t\n"); - char* key6 = strtok(NULL, " \t\n"); - - value = getKey(type); - if (type && key1 && (value > 0)) { - while (num_keys >= alloc) { - alloc *= 2; - keys_map = (KeyMapItem_t*)realloc(keys_map, alloc*sizeof(KeyMapItem_t)); - } - keys_map[num_keys].type = strdup(type); - keys_map[num_keys].value = value; - keys_map[num_keys].key[0] = key1?atoi(key1):-1; - keys_map[num_keys].key[1] = key2?atoi(key2):-1; - keys_map[num_keys].key[2] = key3?atoi(key3):-1; - keys_map[num_keys].key[3] = key4?atoi(key4):-1; - keys_map[num_keys].key[4] = key5?atoi(key5):-1; - keys_map[num_keys].key[5] = key6?atoi(key6):-1; - - ++num_keys; - } else { - printf("skipping malformed recovery.lk line: %s\n", original); - } - free(original); - } - - fclose(fstab); - } else { - printf("failed to open /etc/recovery.kl, use default map\n"); - num_keys = NUM_DEFAULT_KEY_MAP; - keys_map = g_default_keymap; - } - - printf("recovery key map table:\n"); - int i; - for (i = 0; i < num_keys; ++i) { - KeyMapItem_t* v = &keys_map[i]; - printf(" %d type:%s value:%d key:%d %d %d %d %d %d\n", i, v->type, v->value, - v->key[0], v->key[1], v->key[2], v->key[3], v->key[4], v->key[5]); - } - printf("\n"); -} - -int getMapKey(int key) { - int i,j; - printf("******getMapKey, key: %d 0x%x\n", key, key); - for (i = 0; i < num_keys; i++) { - KeyMapItem_t* v = &keys_map[i]; - for (j = 0; j < 6; j++) { - printf("******v->key[%d]=0x%x, value=0x%x\n", j, v->key[j], v->value); - if (v->key[j] == key) - return v->value; - } - } - - for (i = 0; i < (int)NUM_PRESUPPOSED_KEY_MAP; i++) { - for (j = 0; j < 6; j++) { - if (g_presupposed_keymap[i].key[j] == key) - return g_presupposed_keymap[i].value; - } - } - - return -1; -} - diff --git a/recovery/ui/amlogic_ui.h b/recovery/ui/amlogic_ui.h deleted file mode 100644 index 51be193..0000000 --- a/recovery/ui/amlogic_ui.h +++ b/dev/null @@ -1,25 +0,0 @@ -#ifndef AMLOGIC_UI_H -#define AMLOGIC_UI_H - -#include <linux/input.h> - -#define NUM_CTRLINFO 3 -#define NUM_DEFAULT_KEY_MAP 3 - -struct KeyMapItem_t { - const char* type; - int value; - int key[6]; -}; - -struct CtrlInfo_t { - const char *type; - int value; -}; - -void fb_set(); -int getKey(char *key); -void load_key_map(); -int getMapKey(int key); - -#endif // AMLOGIC_UI_H diff --git a/recovery/updater_extra/Android.mk b/recovery/updater_extra/Android.mk deleted file mode 100644 index 589ffe5..0000000 --- a/recovery/updater_extra/Android.mk +++ b/dev/null @@ -1,24 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := install_amlogic.cpp - -LOCAL_MODULE := libinstall_amlogic - -LOCAL_MODULE_TAGS := eng - -LOCAL_C_INCLUDES += bootable/recovery - -LOCAL_C_INCLUDES += \ - bootable/recovery/updater/include \ - system/core/libziparchive/include - -LOCAL_C_INCLUDES += $(LOCAL_PATH)/../ - -LOCAL_FORCE_STATIC_EXECUTABLE := true - -LOCAL_STATIC_LIBRARIES += libbootloader_message libfs_mgr libselinux -LOCAL_STATIC_LIBRARIES += libenv libsystemcontrol_static libsecurity libdtb - -include $(BUILD_STATIC_LIBRARY)
\ No newline at end of file diff --git a/recovery/updater_extra/install_amlogic.cpp b/recovery/updater_extra/install_amlogic.cpp deleted file mode 100644 index f408d70..0000000 --- a/recovery/updater_extra/install_amlogic.cpp +++ b/dev/null @@ -1,751 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <ctype.h> -#include <errno.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <fcntl.h> -#include <time.h> -#include <selinux/selinux.h> -#include <ftw.h> -#include <sys/capability.h> -#include <sys/xattr.h> -#include <linux/xattr.h> -#include <inttypes.h> -#include <ziparchive/zip_archive.h> - -#include <memory> -#include <vector> - -#include "bootloader.h" -#include "cutils/android_reboot.h" -#include "cutils/properties.h" -#include "edify/expr.h" -#include "error_code.h" -#include "updater/updater.h" -#include "check/dtbcheck.h" -#include "ubootenv/uboot_env.h" - -#include "roots.h" -#include <bootloader_message/bootloader_message.h> -#include <fs_mgr.h> - - -#define ARRAY_SIZE(x) sizeof(x)/sizeof(x[0]) -#define EMMC_USER_PARTITION "bootloader" -#define EMMC_BLK0BOOT0_PARTITION "mmcblk0boot0" -#define EMMC_BLK0BOOT1_PARTITION "mmcblk0boot1" -#define EMMC_BLK1BOOT0_PARTITION "mmcblk1boot0" -#define EMMC_BLK1BOOT1_PARTITION "mmcblk1boot1" -#define COMMAND_FILE "/cache/recovery/command" -#define CACHE_ROOT "/cache" - - -enum emmcPartition { - USER = 0, - BLK0BOOT0, - BLK0BOOT1, - BLK1BOOT0, - BLK1BOOT1, -}; - -static int sEmmcPartionIndex = -1; -static const char *sEmmcPartionName[] = { - EMMC_USER_PARTITION, - EMMC_BLK0BOOT0_PARTITION, - EMMC_BLK0BOOT1_PARTITION, - EMMC_BLK1BOOT0_PARTITION, - EMMC_BLK1BOOT1_PARTITION, -}; - -int RecoverySecureCheck(const ZipArchiveHandle zipArchive); -int RecoveryDtbCheck(const ZipArchiveHandle zipArchive); -int GetEnvPartitionOffset(const ZipArchiveHandle za); -/* - * return value: 0 if no error; 1 if path not existed, -1 if access failed - * - */ -static int read_sysfs_val(const char* path, char* rBuf, const unsigned bufSz, int * readCnt) -{ - int ret = 0; - int fd = -1; - int count = 0; - - if (access(path, F_OK)) { - printf("path[%s] not existed\n", path); - return 1; - } - if (access(path, R_OK)) { - printf("path[%s] cannot read\n", path); - return -1; - } - - fd = open(path, O_RDONLY); - if (fd < 0) { - printf("fail in open[%s] in O_RDONLY\n", path); - goto _exit; - } - - count = read(fd, rBuf, bufSz); - if (count <= 0) { - printf("read %s failed (count:%d)\n", - path, count); - close(fd); - return -1; - } - *readCnt = count; - - ret = 0; -_exit: - if (fd >= 0) close(fd); - return ret; -} - -static int getBootloaderOffset(int* bootloaderOffset) -{ - const char* PathBlOff = "/sys/class/aml_store/bl_off_bytes" ; - int iret = 0; - int blOff = 0; - char buf[16] = { 0 }; - int readCnt = 0; - - iret = read_sysfs_val(PathBlOff, buf, 16, &readCnt); - if (iret < 0) { - printf("fail when read path[%s]\n", PathBlOff); - return __LINE__; - } - buf[readCnt] = 0; - *bootloaderOffset = atoi(buf); - printf("bootloaderOffset is %s\n", buf); - - return 0; -} - -static int _mmcblOffBytes = 0; - - -static int write_data(int fd, const char *data, ssize_t len) -{ - ssize_t size = len; - char *verify = NULL; - - off_t pos = lseek(fd, 0, SEEK_CUR); - fprintf(stderr, "data len = %d, pos = %ld\n", len, pos); - - - if (write(fd, data, len) != len) { - fprintf(stderr, " write error at 0x%08lx (%s)\n",pos, strerror(errno)); - return -1; - } - - verify = (char *)malloc(size); - if (verify == NULL) { - fprintf(stderr, "block: failed to malloc size=%u (%s)\n", size, strerror(errno)); - return -1; - } - - if ((lseek(fd, pos, SEEK_SET) != pos) ||(read(fd, verify, size) != size)) { - fprintf(stderr, "block: re-read error at 0x%08lx (%s)\n",pos, strerror(errno)); - if (verify) { - free(verify); - } - return -1; - } - - if (memcmp(data, verify, size) != 0) { - fprintf(stderr, "block: verification error at 0x%08lx (%s)\n",pos, strerror(errno)); - if (verify) { - free(verify); - } - return -1; - } - - fprintf(stderr, "successfully wrote data at %ld\n", pos); - if (verify) { - free(verify); - } - - return len; -} - - -//return value -// -1 : failed -// 0 : success -static int backup_partition_data(const char *name,const char *dir, long offset) { - int ret = 0; - int fd = 0; - FILE *fp = NULL; - int sor_fd = -1; - int dst_fd = -1; - ssize_t wrote = 0; - ssize_t readed = 0; - char devpath[128] = {0}; - char dstpath[128] = {0}; - const int BUFFER_MAX = 32*1024*1024; //Max support 32*M - printf("backup partition name:%s, to dir:%s\n", name, dir); - - if ((name == NULL) || (dir == NULL)) { - fprintf(stderr, "name(%s) or dir(%s) is NULL!\n", name, dir); - return -1; - } - - if (!strcmp(name, "dtb")) {//dtb is char device - sprintf(devpath, "/dev/%s", name); - } else { - sprintf(devpath, "/dev/block/%s", name); - } - - sprintf(dstpath, "%s%s.img", dir, name); - - sor_fd = open(devpath, O_RDONLY); - if (sor_fd < 0) { - fprintf(stderr, "open %s failed (%s)\n",devpath, strerror(errno)); - return -1; - } - - dst_fd = open(dstpath, O_WRONLY | O_CREAT, 00777); - if (dst_fd < 0) { - fprintf(stderr, "open %s failed (%s)\n",dstpath, strerror(errno)); - return -1; - } - - char* buffer = (char *)malloc(BUFFER_MAX); - if (buffer == NULL) { - fprintf(stderr, "can't malloc %d buffer!\n", BUFFER_MAX); - goto err_out; - } - - if (strcmp(name, "dtb")) { - lseek(sor_fd, offset, SEEK_SET); - } - - readed = read(sor_fd, buffer, BUFFER_MAX); - if (readed <= 0) { - fprintf(stderr, "read failed read:%d!\n", readed); - goto err_out; - } - - wrote = write(dst_fd, buffer, readed); - if (wrote != readed) { - fprintf(stderr, "write %s failed (%s)\n",dstpath, strerror(errno)); - goto err_out; - } - - close(dst_fd); - close(sor_fd); - free(buffer); - buffer == NULL; - - //umount /cache and do fsync for data save - ret = umount("/cache"); - if (ret != 0) { - fprintf(stderr, "umount cache failed (%s)\n",dstpath, strerror(errno)); - } - - fd = open("/dev/block/cache", O_RDWR); - if (fd < 0) { - fprintf(stderr, "open %s failed (%s)\n","/dev/block/cache", strerror(errno)); - return -1; - } - - fp = fdopen(fd, "r+"); - if (fp == NULL) { - printf("fdopen failed!\n"); - close(fd); - return -1; - } - - fflush(fp); - fsync(fd); - fclose(fp); - - ret = mount("/dev/block/cache", "/cache", "ext4",\ - MS_NOATIME | MS_NODEV | MS_NODIRATIME,"discard"); - if (ret < 0 ) { - fprintf(stderr, "mount cache failed (%s)\n","/dev/block/cache", strerror(errno)); - } - - return 0; - - -err_out: - if (sor_fd > 0) { - close(sor_fd); - } - - if (dst_fd > 0) { - close(dst_fd); - } - - if (buffer) { - free(buffer); - buffer == NULL; - } - - return -1; - -} - - -static ssize_t write_chrdev_data(const char *dev, const char *data, const ssize_t size) -{ - int fd = -1; - ssize_t wrote = 0; - ssize_t readed = 0; - char *verify = NULL; - - fd = open(dev, O_RDWR); - if (fd < 0) { - fprintf(stderr, "open %s failed (%s)\n", dev, strerror(errno)); - return -1; - } - - fprintf(stderr, "data len = %d\n", size); - if ((wrote = write(fd, data, size)) != size) { - fprintf(stderr, "wrote error, count %d (%s)\n",wrote, strerror(errno)); - goto err; - } - - fsync(fd); - close(fd); - sync(); - - fd = open(dev, O_RDWR); - if (fd < 0) { - fprintf(stderr, "open %s failed after wrote success (%s)\n", dev, strerror(errno)); - return -1; - } - - verify = (char *)malloc(256*1024); - if (verify == NULL) { - fprintf(stderr, "failed to malloc size=%d (%s)\n", size, strerror(errno)); - goto err; - } - - memset(verify, 0, 256*1024); - - if ((readed = read(fd, verify, size)) != size) { - fprintf(stderr, "readed error, count %d (%s)\n", readed, strerror(errno)); - if (verify != NULL) { - free(verify); - } - goto err; - } - - if (memcmp(data, verify, size) != 0) { - fprintf(stderr, "verification error, wrote != readed\n"); - if (verify != NULL) { - free(verify); - } - goto err; - } - - fprintf(stderr, " successfully wrote data\n"); - if (verify != NULL) { - free(verify); - } - - if (fd > 0) { - close(fd); - } - return wrote; - -err: - if (fd > 0) { - close(fd); - } - return -1; -} - -int block_write_data( const std::string& args, off_t offset) { - int fd = -1; - int result = 0; - bool success = false; - char * tmp_name = NULL; - char devname[64] = {0}; - - memset(devname, 0, sizeof(devname)); - sprintf(devname, "/dev/%s", "bootloader"); //nand partition - fd = open(devname, O_RDWR); - if (fd < 0) { - memset(devname, 0, sizeof(devname)); - // emmc user, boot0, boot1 partition - sprintf(devname, "/dev/block/%s", sEmmcPartionName[sEmmcPartionIndex]); - fd = open(devname, O_RDWR); - if (fd < 0) { - tmp_name = "mtdblock0"; - memset(devname, 0, sizeof(devname)); - sprintf(devname, "/dev/block/%s", tmp_name); //spi partition - fd = open(devname, O_RDWR); - if (fd < 0) { - printf("failed to open %s\n", devname); - goto done; - } - } - - printf("start to write bootloader to %s...\n", devname); - lseek(fd, offset, SEEK_SET);//seek to skip mmc area since gxl - ssize_t wrote = write_data(fd, args.c_str(), args.size()); - success = (wrote == args.size()); - - - if (!success) { - fprintf(stderr, "write_data to %s partition failed: %s\n", devname, strerror(errno)); - } else { - printf("write_data to %s partition successful\n", devname); - } - } else { - printf("start to write bootloader to %s...\n", devname); - success = true; - int size = args.size(); - lseek(fd, offset, SEEK_SET);//need seek one sector to skip MBR area since gxl - fprintf(stderr, "size = %d offset = %d\n", size, offset); - if (write(fd, args.c_str(), size) != size) { - fprintf(stderr, " write error at offset :%d (%s)\n",offset, strerror(errno)); - success = false; - } - - if (!success) { - fprintf(stderr, "write_data to %s partition failed: %s\n", devname, strerror(errno)); - } else { - printf("write_data to %s partition successful\n", devname); - } - } - - result = success ? 0 : -1; - return result; - -done: - if (fd > 0) { - close(fd); - fd = -1; - } - return -1; -} - - -Value* WriteBootloaderImageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { - char* result = NULL; - int iRet = 0; - - if (argv.size() != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); - } - - std::vector<std::unique_ptr<Value>> args; - if (!ReadValueArgs(state, argv, &args)) { - return nullptr; - } - - if ((args[0]->type == VAL_STRING || (args[0]->data.size())) == 0) { - ErrorAbort(state, kArgsParsingFailure, "file argument to %s can't be empty", name); - return nullptr; - } - - iRet = getBootloaderOffset(&_mmcblOffBytes); - if (iRet) { - printf("Fail in getBootloaderOffset, ret=%d\n", iRet); - return StringValue("bootloader err"); - } - - unsigned int i; - char emmcPartitionPath[128]; - for (i = BLK0BOOT0; i < ARRAY_SIZE(sEmmcPartionName); i ++) { - memset(emmcPartitionPath, 0, sizeof(emmcPartitionPath)); - sprintf(emmcPartitionPath, "/dev/block/%s", sEmmcPartionName[i]); - if (!access(emmcPartitionPath, F_OK)) { - sEmmcPartionIndex = i; - iRet = block_write_data(args[0]->data, _mmcblOffBytes); - if (iRet == 0) { - printf("Write Uboot Image to %s successful!\n\n", sEmmcPartionName[sEmmcPartionIndex]); - } else { - printf("Write Uboot Image to %s failed!\n\n", sEmmcPartionName[sEmmcPartionIndex]); - printf("iRet= %d, exit !!!\n", iRet); - return ErrorAbort(state, kFwriteFailure, "%s() update bootloader", name); - } - } - } - - sEmmcPartionIndex = USER; - iRet = block_write_data(args[0]->data, _mmcblOffBytes); - if (iRet == 0) { - printf("Write Uboot Image successful!\n\n"); - } else { - printf("Write Uboot Image failed!\n\n"); - printf("iRet= %d, exit !!!\n", iRet); - return ErrorAbort(state, kFwriteFailure, "%s() update bootloader", name); - } - - return StringValue("bootloader"); -} - -Value* WriteDtbImageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { - bool success = false; - const char *DTB_DEV= "/dev/dtb"; - const int DTB_DATA_MAX = 256*1024;// write 256K dtb datas to dtb device maximum,kernel limit - - if (argv.size() != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); - } - - std::vector<std::unique_ptr<Value>> args; - - if (!ReadValueArgs(state, argv, &args)) { - return nullptr; - } - - if (args[0]->type == VAL_INVALID) { - return StringValue(""); - } - - fprintf(stderr, "\nstart to write dtb.img to %s...\n", DTB_DEV); - if (args[0]->type == VAL_BLOB) { - fprintf(stderr, "contents type: VAL_BLOB\ncontents size: %d\n", args[0]->data.size()); - if (!args[0]->data.c_str() || -1 == args[0]->data.size()) { - fprintf(stderr, "#ERR:BLOb Data extracted FAILED for dtb\n"); - success = false; - } else { - if (args[0]->data.size() > DTB_DATA_MAX) { - fprintf(stderr, "data size(%d) out of range size(max:%d)\n", args[0]->data.size(), DTB_DATA_MAX); - return StringValue(""); - } - ssize_t wrote = write_chrdev_data(DTB_DEV, args[0]->data.c_str(), args[0]->data.size()); - success = (wrote == args[0]->data.size()); - } - } - - if (!success) { - return ErrorAbort(state, kFwriteFailure, "%s() update dtb failed", name); - } else { - return StringValue("dtb"); - } -} - -Value* SetBootloaderEnvFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { - int ret = 0; - if (argv.size() != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,argv.size()); - } - - std::vector<std::string> args; - if (!ReadArgs(state, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - - const std::string& env_name = args[0]; - const std::string& env_val = args[1]; - - if ((env_name.size() == 0) || (env_val.size() == 0)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed, one of the argument(s) is null ", name); - } - - //rm backup dtb.img and recovery.img - if ((!strcmp(env_val.c_str(), "1")) || (!strcmp(env_val.c_str(), "2"))) { - struct stat st; - if (stat("/cache/recovery/dtb.img", &st) == 0) { - unlink("/cache/recovery/dtb.img"); - } - - if (stat("/cache/recovery/recovery.img", &st) == 0) { - unlink("/cache/recovery/recovery.img"); - } - } - - ret = set_bootloader_env(env_name.c_str(), env_val.c_str()); - printf("setenv %s %s %s.(%d)\n", env_name.c_str(), env_val.c_str(), (ret < 0) ? "failed" : "successful", ret); - if (!ret) { - return StringValue("success"); - } else { - return StringValue(""); - } -} - - -Value* OtaZipCheck(const char* name, State* state, - const std::vector<std::unique_ptr<Expr>>&argv) { - int check = 0; - ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip; - - printf("\n-- Secure Check...\n"); - - check = RecoverySecureCheck(za); - if (check <= 0) { - return ErrorAbort(state, "Secure check failed. %s\n\n", !check ? "(Not match)" : ""); - } else if (check == 1) { - printf("Secure check complete.\n\n"); - } - -#ifndef RECOVERY_DISABLE_DTB_CHECK - printf("\n-- Dtb Check...\n"); - - check = RecoveryDtbCheck(za); - if (check != 0) { - if (check > 1) { - printf("dtb check not match, but can upgrade by two step.\n\n"); - return StringValue(strdup("1")); - } - return ErrorAbort(state, "Dtb check failed. %s\n\n", !check ? "(Not match)" : ""); - } else { - printf("dtb check complete.\n\n"); - } -#endif - return StringValue(strdup("0")); -} - -Value* BackupDataCache(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { - int ret = 0; - if (argv.size() != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, argv.size()); - } - - std::vector<std::string> args; - if (!ReadArgs(state, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - - const std::string& partition = args[0]; - const std::string& destination = args[1]; - - ret = backup_partition_data(partition.c_str(), destination.c_str(), 0); - if (ret != 0) { - printf("backup %s to %s , failed!\n", partition.c_str(), destination.c_str()); - } else { - printf("backup %s to %s , success!\n", partition.c_str(), destination.c_str()); - } - - return StringValue("backup"); -} - -Value* RebootRecovery(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { - struct bootloader_message boot {}; - std::string err; - - read_bootloader_message(&boot, &err); - - if (strstr(boot.recovery, "--update_package=")) { - strlcat(boot.recovery, "--wipe_data\n", sizeof(boot.recovery)); - } - - printf("write_bootloader_message \n"); - if (!write_bootloader_message(boot, &err)) { - printf("%s\n", err.c_str()); - return ErrorAbort(state, "write_bootloader_message failed!\n"); - } - - property_set(ANDROID_RB_PROPERTY, "reboot,recovery"); - sleep(5); - - return ErrorAbort(state, "reboot to recovery failed!\n"); -} - -Value* SetUpdateStage(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { - int ret = 0; - if (argv.size() != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 args, got %zu", name, argv.size()); - } - - std::vector<std::string> args; - if (!ReadArgs(state, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - - const std::string& stage_step = args[0]; - - FILE *pf = fopen("/cache/recovery/stage", "w+"); - if (pf == NULL) { - return ErrorAbort(state, "fopen stage failed!\n"); - } - - int len = fwrite(stage_step.c_str(), 1, strlen(stage_step.c_str()), pf); - printf("stage write len:%d, %s\n", len, stage_step.c_str()); - fflush(pf); - fclose(pf); - - return StringValue("done"); -} - -Value* GetUpdateStage(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { - char buff[128] = {0}; - - FILE *pf = fopen("/cache/recovery/stage", "r"); - if (pf == NULL) { - return StringValue("0"); - } - - int len = fread(buff, 1, 128, pf); - printf("stage fread len:%d, %s\n", len, buff); - fclose(pf); - - return StringValue(buff); -} - -Value* BackupEnvPartition(const char* name, State* state, - const std::vector<std::unique_ptr<Expr>>&argv) { - int offset = 0; - char tmpbuf[32] = {0}; - ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip; - - offset = GetEnvPartitionOffset(za); - if (offset <= 0) { - return ErrorAbort(state, "get env partition offset failed!\n"); - } - - offset = offset/(1024*1024); - - sprintf(tmpbuf, "%s%d", "seek=", offset); - char *args2[7] = {"/sbin/busybox", "dd", "if=/dev/block/env", "of=/dev/block/mmcblk0", "bs=1M"}; - args2[5] = &tmpbuf[0]; - args2[6] = nullptr; - pid_t child = fork(); - if (child == 0) { - execv("/sbin/busybox", args2); - printf("execv failed\n"); - _exit(EXIT_FAILURE); - } - - int status; - waitpid(child, &status, 0); - if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != 0) { - ErrorAbort(state,"child exited with status:%d\n", WEXITSTATUS(status)); - } - } else if (WIFSIGNALED(status)) { - ErrorAbort(state,"child terminated by signal :%d\n", WTERMSIG(status)); - } - - return StringValue(strdup("0")); -} - -void Register_libinstall_amlogic() { - RegisterFunction("write_dtb_image", WriteDtbImageFn); - RegisterFunction("write_bootloader_image", WriteBootloaderImageFn); - RegisterFunction("reboot_recovery", RebootRecovery); - RegisterFunction("backup_data_cache", BackupDataCache); - RegisterFunction("set_bootloader_env", SetBootloaderEnvFn); - RegisterFunction("ota_zip_check", OtaZipCheck); - RegisterFunction("get_update_stage", GetUpdateStage); - RegisterFunction("set_update_stage", SetUpdateStage); - RegisterFunction("backup_env_partition", BackupEnvPartition); -} diff --git a/recovery/updater_extra/install_amlogic.h b/recovery/updater_extra/install_amlogic.h deleted file mode 100644 index 9981f76..0000000 --- a/recovery/updater_extra/install_amlogic.h +++ b/dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UPDATER_INSTALL_AMLOGIC_H_ -#define _UPDATER_INSTALL_AMLOGIC_H_ - -#endif |