From 47d517bec82e1be5992cfd97fec317d0f0a4c65c Mon Sep 17 00:00:00 2001 From: mintsuki Date: Sat, 17 Oct 2020 06:23:11 +0200 Subject: [PATCH] Use URIs instead of explicit drive and partition keys in config file --- limine.bin | Bin 32768 -> 32768 bytes stage2/lib/blib.c | 67 +++++++++++++++++++++++++-------------- stage2/lib/blib.h | 10 ++---- stage2/main.c | 10 +++--- stage2/protos/linux.c | 25 +++++++++------ stage2/protos/linux.h | 2 +- stage2/protos/stivale.c | 28 ++++++++++------ stage2/protos/stivale.h | 2 +- stage2/protos/stivale2.c | 28 ++++++++++------ stage2/protos/stivale2.h | 2 +- test/limine.cfg | 6 ++-- 11 files changed, 109 insertions(+), 71 deletions(-) diff --git a/limine.bin b/limine.bin index 2d442840d2ffdbd496812d20ffea5377ec086342..28833f5ed1d39392c000972fe18790403a1522ce 100644 GIT binary patch delta 21888 zcmV)6K*+yN^}$OwO}4K!90L5T_y4`wxSGxSV!!dJqm6&aJBZ6H9R zOLR^$9Rrz+GwD*3k)%n(ghx#gc4o6DX3UNRvvISYmDytqV2)M;L&G?UEwVy@O;8zA zonn$UuzWO1?Y*zM5lu2@e*n~>>%IH+?!E86d*7{VY4YimB$jE;%4V4gKMsFK-}V3Q zWrlIo;Zw6Y)$rD9E`|{|ry7(e+qC`xz@MALGBE=HaNsPCtcjXbM*^XI^J}YICeN5cWiS!=Gg9d6mbF9 z^oLCF2JM*3@s#vr>KcdLQQ&{bbL2aU9L0`8$HC+U+#&9W&ar`Gmt1qff@T&M>~keD zj;543x|HmAe0y6R{xRS3caK9`V5s=ebyiGBfhkE~A{eH{RKYM_BLZ+FK9Xwi8VwaX z2eq58_;$N@R8YHT5z~(JC58&;613ttnuv|+Z3I3CTV8V!B3JlPPI^&v`!;AYa zutvjw440-OS%g+T122CrWe5;PZq<;Ei9oh!9cl(>eJTLCRejAahLNct6PHHUQ&yrf z??TtU2GmKLqmF+o2%hcd3&~%^LesU+d+NTu9sdGwP0Sq3bSblo*?*>_4Y&(Ln^`OY z2}}Oz+a;s{?nXoI_#kkdVW#s+nKRo!XLS0WXm42ez=df4dx0vqih>L5({l zs}ZCVC~n$MF?$_2vk9Fac*VE|##TANdA3-pWWg|6r;dtGnM#>ryH&OhSi7v<)^V$5 z{cD?;wR#SpVRe6qF&8;=L#$VGDX%@(D(6}Ua;;st*6v*Ec&_!YHmhv2cG;}mHtT@R zI&4G8xXr4eXN!vp^2j;T=1~(*X&`;=C!4qvJ*1aAHp89xZ|>N6Hdt|q0SqY&a3_4+ zu?yUZDel-b8{|&R#FPg-iiJBNbH@T6KMcCKV;@U~WY2$)X*B~(QIp%ZKfZ(Rprbx5 zn`ImxC4ze&$a!-lZxU@5F<~8miTUM{kTUKO3v9GlZWaYg{Tjd(7uYqsnY5CCV$(Fu z-EJYgg_N5~iAnm&7>ZX9g<02;4pKNw&eo@*P=1IzwZJoEApD?MWI~VT<&(l5$$TH- z`|?D7STcV{=4lBA@Z}~D>z+1=e4kj@BlP9CCoO^xcR=KaBKbk?M0{csL_c$WvZ~dY zWY_i>BtxbhM6jL2)@Rp+fDF;r_XGEoN$A|T4E73){P zj}-3%+tR@{?pRVh1!R_Wn9fK1tDA1^Bw$PO1(kf&w7Twhu4mZu_&Tmm*7e7d+|2XcVJ?Q zcqD#Mk$`iPI;bq6@vC*K9WyBJ*vIY=jJ>A75lm-0$ zZ91O_r-W_~v534`Ot8=)H3w0Ks-Y~FX+S$}g)w0mSRD^X$~7JBw7I5Zo%g$@O~MQH zC^Uwu&QdKhucX2r;=0I8&-%4P^=Zpc-xUo#2t01O{ARUB|j&m^OFzwG|k_W{T=? zA#itF(;;}(SgPxGg0eZ;hhB|ggn)m}*YtasR9iZ7v=p}zk*(Dts!iWn(PmN(07r4Iy=Qb|HB&He5zaXA%IxBC$66R z9M&OmVxgHt=o@RtOldPKNkCrav9o=w+<+|G;FvGhMI1tn+(Q87BwD)O*SPdsp!Gy+*fEtj0+8(>Ph^R=y8q z8E`(U>c zKwMD0a8qU>9Z;{REOuwNbY@2+>|WkY9dcj$!pJX#~w0p$0j6$6^;ukneKh@b}@$ahyv8) zd##fBj~F)RuS9*71MB#C+?2nP8l<~WZZCg+K55E78`G1yEz^>P-? z+29$?bwA@QfkFueL#Y!1UnN7S6nH5<-IcW{Tga-?oC{npYSF@Xs|JLq$igAfHuyvJ zwujVJS<%kh(?515z#dc^R&J`fKg+%Jg9&EtCt@}7eGaxvn}qC z6p0VmC4LMl^gm}n;P7Kz-+~BqK~AX7z*ws!k@U(M4hz-?)@7CqbCtUQ!JS%6eD3Uh zI_W(Ck+%9=Q&D@9>&M{ymYJfZN1}biQXhbsS3l2p0hKHG&`Zg#USt8&(VGQtyGeiWdMbDamO`)c0KD?@igjX@ z|0a3UGl+hA?jeBTFT?i;>Bm!G(J{ zz~yTRb;y778m_ObaZfJfUimeSN6dDeOD%V2qp%2JZ%Ec*ggzC9{#Y?zrzR)kt0O<( zjx^{CNUv5o(}*UNFNO1n>?vBp5gPSFIhcJf+U-TfI<=bMHSP<00w^EQDS=9l!re3q z!@j!VB0VzEnO>t3s%l>2$m}RAQ(Xla5{|)g!K{A+5v<1QJ_xO}$^R;p{P5j5lw+*p zB*48zyjB@fMI3E}$W;LNJc`*p#BRU&uGtBJ4!1PEd4~4B)%<6tu&uQY+*k71p6`%P zJ)arGglEtNh79qM3Yr~;^ljvVn3L%KXE{c-paiu-&ir!!>?unu)Fsr-Y6s3Q?!XfJc-5ru!DA#u&}Cpx37?sw6olS}KAwpw`~ysIat+C5hEFsF(;BTzsQ$v*Wp1%EZ?0 z<$H7``BYzy0}Q$`~-s@bjxYgoA2%k0nh%J0_o=UOWQRv85Iyda+kL=&oAuQoYeF80Ofnw zR$Qxk=0*w#Yx*#1>LY)G69GOwudCbJ92fGbmv3K;uJlFqISp1#y`lIJ-Z>uwRf+95 z>QYpoEdEJYL9wtM9DbgZd_aGMrV#e3u09?;&DP!&1#&X^56I+lzDcwl|HXR}e_o0= zQPJ1GuID<^8@i8hr!0`~mbrqfop(vQS%_EV5iCvRJz{we38qY#`@IE3D@KUrH&!kgI%~(FHuoRf-h+oHNNkMo0U&DiyuC!$3-U#HH3Q{|7kz z2Ll{3acNbzu(~B4B2Y~hIen2T=x4+&2ExNtTD^-R(YS6%-2OWtOe%u(fFw&VuyB!v zD`@o_Xl4%BE4AP#o%eqU{T&M#|0r&BXkBv7GqqAp4zFwNQt$b?P0A*4x&H%X`#SC% z;tpY-u@_bO7fJx!)054``dY6q!R$NantXHkwq_f84n#yo4giatM zNBv65Wz##H3tjuPXeYaMV|xFd{~@tR4DB7<(`)P+T|Vya9wOPeES zo|b)}rD@35T*jBELR&E2g%-S5g{nbY_Ky&J4qc$6(UI>!>*AQ;I4TUS|E7Ws&rg=AL4 zAE)Nm*p7#h)&cfv+;k1!s3Qs+sRQA*{as8mx;=-f1p8tQuyg_V-p&0@< zK%+;!5)Xg6h zyBkxkq-=BtEzT&oJia)3<&gR%NaCvAVM4`s&WC%cq)`%J&BJ23C3uZn)dwhdX9{3K zpYmhz`bEFxV_kCLNA$f%zWyWEy_>&!pH*k*`AL)t&7^P)Tgx|~Oy7uqGxz@b zMGyv_D+V$u{R+cBy-zTnWSB(^`82=Ov}-x!r2^$qg}M+f;^4rD_{bdhWV|p@*)7~= zw-To%T5c&mRCOAd<98N}tJjWf$jj&i^CWC};fGz@>SArrX&ud}a#i?YfZ zpJ4|15PdK(AvCAbUENF_wM`^gg+iEIb|P`Al72WAsedbRx^(K5*l9qZQ)&i=+`dwlHyTO`Le_5mUHL#&~6ekt~6bi%L( zu0b2hSmp-FP$ro-NRA2?!ZNhgIOhq5Ei`L!hHZs;l3|Nv-lj2>MVUA3QK^3-Rq=Iu z2+*T~GYx7A+&SHQH1A|g@c}G}QU*I_CoaFmA5OCR%Wt_w zCE0WNtt0@}E9q;c!3dZ889;1pyhm753Hf;)G49u?$IOc2{YbGeP?g|XkJ8Gd&bt=F z9M#1hD&g1(uf-qv3yCYFIib>H5eQS}J`KSg^*YVxXP`~RKcW@q4O| zEjjioV{T*9oH zmN071zmg1%vl0x)R}J+Uj^~NTZ;PC>TX9@8xT(0uw~7`sgT;T`z7@MLHb|LA?l-o^ zWwyaIv-Q-+>(s~Du+Q!HO2$?xvyE|rqlxpZA)W=56K`qzsck?Fd?xa0VM&hiGY5zU?mI2Pm0x+HDu92dKdl{^b9dk|{ zkA|)oA*c;MN``-*w&Lp>T|=Rf85$qDorN9EZf*bgV9a=m#{1vMye2_ATd|xeWf@3@ zp!2{Dn#qm47xfA6YXJt%3>%oa%ug?+%)AcFYRL>zdZP@x`-&vn3sk`r2eKDAgm$gvZEX?Fq+ z^tHY0^keL>)L(i`D{T8TtnOTx+88=0Gvcw#_WOUhs?QZP|5R22Qw5z&G7sge78Q>K zu>lReBZBiZO>L-Tijfkd{rm&x6*mCfMs%g6_{0{U*qmyT&u5@MtOM2}8E`QJyI|&h zd~Kop;oRnaLv@^aAFvo^KAvD~WX*Ag;~+%g3G5$Zg!&RQZigGeM&Rj%dcff473&0P914#B$A{TE4zy#70KP1lk1ILG3XKs`Lfs2NQD^`T;xTOF zz-{w^%3^4B%0ZF?P>~TW>^PvAIY!?Et2PYKB7w#uZuA&7VR4ONW0ZMQs)?PJLS*5F zG68m2vyG{#KC#srJOFI;97$}D97lgfi;c04<7%;DkYl^#INsmUXwN|0nF)PiG&ZVg zGGW!zXx`uNG1PM09U`_Swz|`A7GL`gCRJGTJ~}Q8jmS#%=uvy(C%(^XXuOq<&~?pR z%hB0qE+QkSgyMH1(NWnP)*zI;kF%CMm$`5swBGeB1{DA}W3D7WQDpx`je@j~{MlnDD(RqxvxNFm&r1BKcUN5oiXJWsZN4+{?+f!6uZs zZQpY3R-LN&+v_yXTEejkKR8DU}@SB#xEwY_*n~8O~a@vq?3&Blen9Ls=w^y-Q%E zkzl?S*Y8)O47{bc0_cq$3u0T&(ITmLf z@}Ii+3>4R(SV{Xqe85@r(@g|!xa0~&!wz}tUk4SbRrWhlQ%%-lWEj;QN(MsI)pHMH zIXO%s-K({%OMZX-20=5x4~<*|^#D(g!he<9xSm}D2nGQJYk?WbqW}(a^FOS9DuvV3 zdq`7;R{6ej=-mg@O@vJwniM06Z!_CaNqnE#bdqB)dv*ky zGfLP|uWn#TW4yuCDC^7Hv`F)%uqNHE?eHm2Mzp&&z@vZ1RrWIyo(fsnfQ$^2bvHoL zzDdKih$_r2dU*UeG1NyTz3q~#5q%B2o9pCA=2{2OdLTp0)0jggD&(Ftd98LzNv$|E zJtNia`U;Xv@~=+<*DRTeFDTEv@ehv^$E0-U-`OMIovdcm5)`a=y#x^B_s_lvHca= z7FK`T8oWpJwR_aGXD005FyKqbEorhZF1j{W99wcmaN(8+JK($)@J|_g}xB77Z=Cq1M0>P)ZWp~u5jV^sDn7WLY@zWx+U0&yYRoAH)EgDIKR=AZU}w@ zJD=t)-_swn%JCJJ=l^_(0E&5jk_nb}248=NnaE*P>xh^)1qb17e@U@N$ySEOL5Xa{B!~U-YvN>3xl<|{xY4&1#|HawVqJxDdaD&c)21&dAEP6 zuFsLkFJi_LzbT03pI@KldLJmWptLtg<|D%P#-O@yg19=NxBxwdeE}P>8gyB*5xqf} zQZ1SHX$(bC<`TEDky{f-d}0G=FdOFhtqIbYxh`48%p3f+6q*rIW`iUixj(ZkPTasU zE19@60W6x6agLo}QUq+9L};aAB!+)Y3nfFzGzE1BjM*5s3DhRkM@b8FPmjnco)UhU zi-F511||x-p9umxEywvxKb8F%{U-^=3Wtz)H9`{CCD^A#6l$ho33e^^bRhv43jnr13Jq#jhBC3W{XR8CIanuPI>x8&MN&^N z*Fqz4hC_vSIO{_Zg)=Hahi!kQy)tOqS^tysq>o)ouL?nu z$}tnPVFYjZWyRbHh4lgnMU%&gA&LB%V#DRV-y!=c!e(qS)jHyG_{Qokzr`9nu8lYR z5_JAJoiR)x+b2lK%m)N^0%>OM`rrI^BD&-erG-2erqwT4_R}ZloG~ zPgt!LoGuJ(;y`O&O*Q$dFyHq94$=2P3?XkBXcSmp-^5kFG91-l5~@03m+NJCO_Z;E zi({~3+>}2JBZ;aoMLzx+DZglV)`sevl>R2N&N|=ljP$;J3cISX1ypOXONrW*-=xiw z@nE?irU)yt>7;+ZTcy{|Molof>Bv{-tic=*B5oXdRT;HeRD(DH%@irbp60AAqOxx1 zMkthm;PjcoMX+8ZCz{eMDO#d}IU`jaWJ{kFio@jk!3NaOkxr>!4~RTu5dm1mP;K8mbU3Oq`VX6Z4K+l0BB(c)wChO)j zN}+BsZx7{dIkhKILPGKgiQ11#9%Y;Eo;M45JZZj!cPgq$emE*U5kyRRbTdDC_!Sy)etA;RP zUnb3qmL89x{hT$4087-%GZ1X@G?91d_;0xvkzi!ySPdvZ{_rBQdX_vxS~D4k@G=Ij zGc`-m>T5lObqa+f0wZ(|;{_Q_p|pmI(V_)1~wo?udW8 zkf*B;NI_DnRv|-8@}#Kr$pKvTliP9Yn|JP{RX~t8d*5JBg?eU2%=;VSnig<~9x}D>*}>A1=pXE8!g6O+78~Xm!xQD z9G$!~qrHxvO(`UG_6Ha~CV4+g zet4Wc!W}(vt#%^Vq?fz{>w{G4uZn)75<|UOy-$Bee`T*mz#Tj}qmhP|uJ?brqZ8I@ z6QDehi#KiN!&AiXpxTy0c={qiWe;J^a?0mEU#a1uTboccS!HjQr+tp{vO(Boz6j_@ zmkh1)rK^7YZ>aThr5v}Y^Y4ESDu0>dAK zH=SMmRteP@vCOUtZwh-a+);lR%X5J7#_~8^$~bqoEnM()*nZY`2s=8eSHfbGE85Tl zvvnu#s*WeaRa&(6I%}?z@76cx)>>G|a&-gKuANqV70Zj~Ji*ma7N6^b5jeHS(8_J7 zwzHL?uS$clsp6?vr~pIf*KZlAnovu~<^{z9k^YcE9aqgkbS#hycOraBhpsjY=Z_yM} z2*@93Z@uRpW=;iB87@&ch)r%9BLS&PN~X8Ek22!*g_w2r$YSZn=Y9ew;P3 zYjxj*6rV??%gn80t!+Pbcb)fc_9@Iare?M%se|jhgZ-(139bE3_zV^!v583Dgq%Sh z@m6_0eYeOn>AQcq=&+MTH)Am8bIn?R{ARCNJHd=cims_+&o~bT_ZZZ@w42i6F*I`e z##jR%25^Z3d!!YCrhA3-XTT&yn}ZMnyy8}(d<~i?u2-pa7z=~p%4@JdSeMwy>p(3k zhvrd6I(H&)6OyOz?Ok8TxJsBXcBMF93q2zyEd{#>-TIMOfs8Y51m;;GN zGc7bKB_i188?JITsk-xM=aak}_ZwQ{a4!_y7<_ZJ7OCfuEsYr)lyGbM3tcz)S#~+jYa06ieJyO7{3cat{n!g0qo7p|8KMfVdRl6xU($%ry3H0h z3U!ZMgU04T+%x(EE|}GVdR3&f65#HiG}PX&-f&Uv4Uue-@Sp-DCTpGYi1-7x^diSa zmA#*|=)?%GR$BD(2;eFy%d{D3^3{(Nq5*&YAdUf2ougHsV#ZeeC-H_>dvH)_qW4P4 zC*mEcX&Kh{aLm6r$%73CPxo#ynKG>Pm^g?h>d*AruiM2;~P#8+)IeDE@XIktUf&wB5xxdKJ<%Q97DNNK1cw znN)Dx%lc!z7fXeF(Boe$? zmKr}Jr)*=v0(hJjK#oKYISGbV!8wyt_hg`MOw6mD42#3i5M@3BBv!sMKp^tECQjP4 zH>M`)#tPoQNn(-YC~^6o4nqb4Z1jJmN>hcyjjEx&KfcpT<|Qk~xZQ^JVZ!Olyak#`Z=`g>c?ICS3URJ6Y%p5JKzl9a!u90!~ED&<#!ee@>`6`v$h1*xm)pdWJv?F-MT_}wC zAN@9^2)kV0LJ1Rme}~`JPHfW)1pe6Luns!VZP}_7c9(yT4yZ1 z)1QA+$-fKp-+}yvk3zmSkdM1Hm_G^gCCGo|F~|=M&`mi0Of&C+?hJa;5U_3djU#dyi9b$j7=D@JMp0TB8QyN} zj>mhBHq6SHah)t5!AZ6jfuUo45kB^mz{g&^JEj_MijjYvM0!&(LD>BumUx41kO6sg zj5DAT;B^PobeWKssa2W{U>0x?rO#p03#8eKYWf%ph5`{ zuT&yC{i=z+i3cVMFJh2KFa@A18ZQN)<0+HUQ`N|ZS+Bi@y3V8QSm!Yw65rVjl{!z~ zQ^$;3?m2(PGPjWz17pDW=8E+<2uTP)q8wbs;18X!w>4aF{=iS}M0KY7ok`y3@NCRbU?i;3&C~&1@v;@~7}<*Fq#^S~%KR{rpE25scZ+PrBj3V~y1d#5 z>QP<{oo&UdYG9>p9YtM|^z#JcZ9v{Xs#IyqbRd@I)B zCsqJm(+y6BO>aC$;q~jdgQ^5~U;RBeLRkI%Vx@PW(ou9Hz%%+ppd&{FJ9@vd0!t3@ zCh)6+fZeH&0r`wRg&+=*_~l93W_T0U{Rtz#06?J|KmhGI2kYqko(`ZkbhcxB7ZbNI z$2R>Z7)O>EZ`=ZUKy0%uOxS)ZsLp>Igr0MK6ZV5H!lIJg*($X_z2@1}{b@VMB;#bQzci}lgJYS#qGPC7i{qvjbXqgWh1 zR6kF16WQ=*vXA|H*KWQY!$J73dVHKkUS-t#-LnMeIou)~eS}@ajny6s{WYb|o%P&w z`y?m9xJ_{WkIHY0*D-gr-x?3}hPpXbJNq$79Ca5vEzjSJ?3i1TR7ZbY#Uo1eXW|W^ z>}>4G!n_1{I2n7kFc-iO5BbDeiLk4*_J@!C+u>+WXvFzs9t*U%Le`{_(X@ctk=TzKm=Z>MRdjkI#I9D5lE>W^poJ4$0XPPTyJ6hTPjwTJux znr@TeJWn%soLwYk-({y*l2jAU9F<;lsC(wxY|rtwVb)VpT1-}h8>^-uIX%RZ#~3O&v7hE`vuCzD+x?61r0d8RmA5uN-n@ttzx zX3+h8;!pAx<%TXtkG6WrnvhP?g7uj+w zZRQK0eL^_bQC@$<#Ki6QqL0ioeS(HoeV>3 zg64Ihnl;PDBP8kZ7+da!~F(`gV=#N@uzL!)7M7a zSvvPlpZCW^?|B5^Erfb4k}by^4;8-rPIU}Q`<72Z+FO5>3suf|4C{0<%FdD)a@7`@ zrWw=RRWjm;05NeW=m>AdCZF#Otjb(CxV(cg8hQvEyu))f-Z{_cHf?so4NJTh*i->&xqi(NuLecJlIDi3!12)fUH(@fBY~9xZ{9kr8*T&wT?Z+7 zD4Y2Bux?YIx<{-0vwfG6@*>sPN8!Gr&|V#kwjaI*E2{44K8>vNHzJg1@qUjBcaWGM z*s6F)!M7TU4TYrrwO~b&eg_za<}UVWZfXD~|0sXP5lpgj^z3q<8vXm!xbXqj_*SWL zqfd=fJ8!M=Db?suYJ^4ITH`N$YP?D{eo|@-?o&hTQ)4OB=u&Fv`qW73Q{zFZab2k~ zwoi>geQIc^hKhTltnqznoc-X|8b{y98d{~sj6OBq{Xn5F48KY2O6bClrb9T{nj6?o{e7?Nj%`0Hgzyl&}A$Y%*I{_bDCnL4XJ`l-^JOe~2WSxL~qt!*%!tDb~%M$Mf?RlyX*o*j0eG$H?5;h~h6Nj5jR(!V}g`T{_TxY~z z;?#c!Z|&}D5u%r8T6OkQowsuqG$PUpv8as2BS$K z4MP%kov}|xpk9s+ECLYSo*e;NEL2v>=3WK<++83A3e;;Rp5>Jzf6cEuXJmd$;P*N0bG{X;8U%YVpE! z>)Y6Xk^AW7r|`f+9d2~}?gf9r+4T6&LxF5g|A@Iwo_TfCg2z_~TVIUvR z;i>OpYs)e90|2G;J)bZBpsgaQ$9-1w5xh&1qQ%pK_zF0**XcSVl;9CF_p?6r<+Ym9 zBwrHH)Rpdby(@bxl{aX#uI=2HikR4en9?cy4t><}koN-9@iNYK4uF63k9U2(sWP+-|GXc9tG{s?MLxWUFXkQ!BzYZz8n%j zg0^RL@|S&mfLZ&lf9fc@^MjjU7zAf*}F89oQo>=aRn~ zRKTxD8}Wiipn|+-FXsgz^#rZTgtB5;%$^q^(_J3gJ)+<6cxr##f`y^muek7hh1Q-Y ze+omD>)`{PhQGzwbyG(A?OM3bIkI;$64-6>4_;DEArT<7*GmIij|0p8hhG~sft8JD zv+hRtukKMC=KBbf8vEoIhB&*__7TpmATb`RU&rbrk$k$eobzVg2`NzuL7m3ze#*-T z%(?m#F5RjKbfJG#A$-<1AzA+Y9^ATXzTuC1YzaKI2A|oe2djz9WjNnMiNVgt9Ait^R z(KJ;EiLVMQ}Zm!^Kh5+fKnkAL*>o&SZ zy&cd`+L1j|n`-A^YOorklI6zz2%|eOlDR6BWh4wymJx4DKJQmJL~VUiBy~4zh_aad z-4P?$6DZi9BSe~|^$t)n7grD?{WgMY3+YOUNF`enuth^tQqtRpg`kjVz2R3B|B7yU zdnEa~$$fv#lhf0A$a9MIQGiI^xEuF9swt=(6{m1t)peqbuA6)tSg!sMU%L}=1@%%z z1|u_@$ez_|C_kzO%ko=GJWl^_8hV@?lqW{h)=f+j%?gWA_Q2g#g;ApOP>in%v1NT0 zVf}U&ZtwZQzY+^cr*`3vp05fg!Ww}ZhG!Qi5u1P3H_>`8rd0V;;9sb9GA6yb3xg{6 zalYSYxZ4JOVz`Qcc$XhtSR2 zg}XzpJ7DlRTZ14+az*1M6kx~R7d$90c)!hM~-{$kU6!39t z7xjOAeOQ2+<&Dq{MZy);5F@ci@kWE};U41pYUS$GJrw>{UP}|zh(mnxGzN|wM{K*f zGU0D)YX|l7lhO~}#IseVv~QKPM|-gh#EGw}g;pW0W@?c4)_y7+kh_1m>4Gm%0_`ISB$PaJHINZ?rkCKk>=!&k z{+ZyZR0K~237#!nj%)!*6}IZ>7Caw8&Gth-{4>E*!7EgB3!V<7hQyr#!LzSh@aXp3 z6?2PN__$qhq$#531<8f1(AlbH^>j6qeT6&|1}jhhA|QiM0^O#mXZ%fhr_epOeM|h- ztCUcGpz4-Fzl5UgUwz+0{-i*P{4}Rq=g(a7{EU+4XGQXC#47K6kC(YAl1B|ovi;TX z`Fx6)y-s;KfG;n6Pm(8^$OviHIs@16;1B*!lIK@`$&+NVs)4=TR`>*g1?e45utnlQ z?mh+X{7R8O97_@ZRQ^~H)MfAYl|RLpkpdZidn;neKUSTHx6g)82g543G&IrsQ$0`~ z3YxWL1yG`-$sPvw6qHHyeg~%1uz(r-6#7)_JgRlB3ufSktDT!4^dv@7+ND+EZ$n!-Z3T0nEme10+*P35blg*a z81C#AhH+c{s-&_Eo5&C$Hv|CYG({_VJhE*0(cOX4wYQgz*tA^#reEZRb5plIv5$mQ zU_d7D%A2>Bklcm!hF?N%Mu5}0B_w5^`!wL$NJ&Yvj>VOH&5PkoICGr`NkT>xUqBIA zd=O=1w{-jfr}ddiX#Xpcj6^`bs^^G*cvmBtG=p$_4fmvaB;qP(r#3PnwD?{1ph+9P=$vYgo^$YC%`i`FR?jM-czN3e{>yM)BBw2G2ydU36t#7>b z9!&qJcRJowWPJ!T(7yC>cM!-vAO7w|H(5zFIJx|O1~&C}#MM-VE5xH({rE$F;Xqh_ zS~KKzId=y+EIdhls5B{*rA4q|w`+)1acVFA%PR(GC~n!szjJ}hrbT+D{cq^~w+cuh z(d$d0rSG0ymM))ohx<^{qA_^Ihy#E3y@xG<@Ifo)hCv8)`DS zlkSH9cPS2X`Tf&=QUAZdAF2U=fWhqj{qw2`dsfaI_a_C`h1&uGRpE^f>YHHQmLIr} zluq)lp}Z&EK+y{3Qcx3V1^%VZ(JFtSp!KUe*1+gq?|kVV`L6fSNkA8W#o7Gu=3R;5 z*F|*586RMgXi>Cs&dq)%H-i=?gju!Wv!;n-dw97A-v=>Aa}c*K&W3N+_?rkHj5!f?_%$N7zuy zZU5?Jw2+Qt$G~TP@o#~DZvP#|5~yk3Xz2P{c@anePf`qNxLsfsM{qwbd5DI~RE0cvRLmR;Y!N9|DdO z!bv+iUF(EhGlQ5KJ~eEb7V2hlog^j2WG%pP?Rp2XGgIRuE#Lcpn3I;cN+?19r<4)e z-F#W^=GRj5(#!~^#>)URZI% zzuhX&Bv!5iqmJ>hY|T{G2cPy3gOXMSWH#{ayH z!6dc(N2l~xNYzh&xBeQlKEbS{P;@4G`ac_C4`v6Gybn;MGw35?vw`$}g^2{%0jVm5<1WtfiQdg~KPKvWuLJ>>wjtdR#|t_=A6s5EWo5Nk#k(vu}WzIxh;vKXhP- z0{d`85Qe;eIPHt!JGL#ijJDNE7EM{1p-Hh*qrd*9yKrpaM26rAOaS%rdSVK}|JP>bJvZy+I7N-pHvwXQT3+qtO7r0?J$r!@a_rC^zCF?w z-V2ltmgaSN#v&3cELQqWsLKY(Qb6&BW1< zJRi_me}z>K%CCbMao+UV$Kpnkk~MuN-KLpOS*`)e<{i=_doN}~ zhP<7-wKr`d3=6wptfSXcTFN_Avpjhdt!mdh$QFVDu*&eg z$2BU|_m#T6U*I)7>sA4Ck$PBdZRyd>Azp`hc30e;tyT&zTyvE zirwfBUAp#)KXhs8Mt|ti!j1mWC7fSa73+{*{scrUr*HBHkh)$)p_Lc-`H&BsQ}M@t zK~y6C*kN6(R{jh~Xe%aB@S_qey4JXJvhf39&0Tcg+)n(Fkq5Di`X+`%vVJUGtD$z> zbJXxoDyGk{(|It+d+3&nIn^V2Tme4hIrNjgrT}LjmkO*Q81ZVdzKXz~*hU*df5qp+ z+j`DR`!F!>+OjKx#A}uBex0p6HPVxR+J3F=iP8f~+EIUQX`{0t=<6qxUNTZ!k*fpr?S8)JjsYZWyg%oEVD(q9VfHRbw((CPsO7)Q7bs+YI-`N)7+}W!Lnn_ zBZ7+=Ht|Dk*q4Mlv@`##YxS_7J6i75}Nb zGNI;E=cVBQg7`@M!NSn^PT?iIA)8`}y!AO{Xh12!yq%Y!XJZ@g0YZm$yj!U0{craw zRp%+^F;(XoJ{A}SKu_n#r@{xn*2CC5y5ZObcCEDT*f(LP@gB>}=F(HgE;2_W-u!tI z(tm*W^XxJ_dBcvOq0}iJXD8Wz!A?tK{K>+h_JPWf+JA+oT*}rOn~!}RUvF!N{^xiv zlZICjhfyezcxo9@fB&Ev_r#eTdkTs}{ld8ud-LM;tRAPY~Ny zg+fv9m(agZQ}65;&J2J@NG}XdaI`!XDP^`v#+K1nV=qH-06;Pv$MWxgLV1_38?RUJ zG8w>YXQyOn@v<^MF1xXqLgOVovV$<0qmQx7#?qt5zGhv3GC8b+PH#fOMM-R9ry=co z=o|2O0a}D)IjmXAY(acofL7U$h}UDC7hw`l#2+ghXCDduk8S`kzglZ-JodHZXl7TT zQa$T9=4Gebuc9PhrHVIywAoI;_vo%T^Kn2}owp%?>!EaIWt$|@m6hgbSCbeWe|c3R z^mSS9W7qtLbK`$p6{!bhx;rHYXz-e|bGVoo|6^eo{$$uocq0%$+}6xa0j2k#z&aqm zj?POMh1~{Uojuzj{EY4b(9h%P)ze66FneJ~nXwfTFR&jmg_&D_;N@$W2%^LjFhi_^ z9qtrc*-=*Cc_IF2;a&C!)}i;cFOny;8GpdmUgl2rLB?-rKJ>Ni5B8+Dq5P*Q zC5NBhn#7p+v#Sp9&j&GxivW zBABxVfWluCU}9H)dr}ZC$7cM!L&D7oZ+V%r=2~IRoyQShgUKO$7+S&_@yA^at?&wq zubJWRsQ``qfaJnDIJK-bwgPco!WGy8lwxVdKwcn~QTBUT!|0CKpOI49kWyNSQix6h zb6jUTeZQeO4!S+b>b;+JuScYjRz#5)DLJCqX&A$=W*w65Qh(s<3s%|r)8%Vbfc;44^eEoR5 zxwSCW4q8DBC^}hmP`vSeGhTtr>em{N;1ponK*+~rz#Dsr&Ge(7-NV;y03+?YaF?MB z?8Qp=BfilcI74_xTC;ZxWZs0#GJn-|ia~I@KkX)em8$UdzW;|o`lImw1Nh%>bML$~ zt0v=2Y+wVKb84y`ohn*F$q7kDveI1(<}_qsfvPH)j9$yXrMY+6Ec4Fc-46Q zgo%?L{PjbVqf4B4p+rJHc`LAG;QAOBzSr#LBAsIu}R}sOwp;P>GBKm9}sO>PcFCUER!dU*IDxI zg-`2pZMxiiTW+>Rm!(s3ZI&hW+=BeEDx+mZ0Tfx0wNhtUZOsyGc1w03HEa3uf+bm4 zP?wXHyWEnknvrYE(^(1&3km_0vAP+BxvMOH@H9p@cltC;30LK0*(XkzqLkO!3v`8+ ztZdzq<=8S-(&ZEutib+mQ*?Pj@1l^jf*=W$rN(%LF*-5dvU(*91S(qqM+G^7x=XBC zx%uHLL-K5$X?bt|(9?YTG}m0{rm>>3)fJq=Y>=&V^bXwW9ETv9vL1!Cb6 zi|&b$wkN0r)g7yvmAllcOunBC3ks*`=8JZmXP%*Y!7w*jWm%pxMK=#>X7RdzI!L5G zffy;zoS&Cp@KnCeW?c*zwBCt-mCAb|xCs7VVbyTHPU64%0VV1Na7D?nG61#8bX zMz^$}fSA(K0)MqM0FZKl#DUfdb7=t?7o?`@^2HTTBF_@Td(z|FT)Ta_&3sG^sjP%f%o*tO)ALG$z94ty?uy)e%h)A3OMCT1g#e&zV$v2YKf{nb%{+I(V#B-zsgI}@%r+Y4 zn-{2NrcN`>nw^xUdfH-BEtq968WvBVJ1uFB@|uvH5-&i z5*yky6Zj?D3dyK_Pky%kUee2Y^bT44js=-oo}8uWATjC+3AL!2`Ct5 zFPJ@lUhl*OvsBZKs_<}~4y5a^SHK)1K6K;9K8Ohqtq2bfSEX5&BZo!ii~@EFBw_JM z4}mD2IDQ2(JCezNyn-K(C^bMVA}T#Ie2DtsF7-=}OyXiKaG1vbkV%tPLfs|ULo zqx+@hm-uSQ25AFSy@F-|CrLG6I!qZ(dX{J}fW?@*1b8LN0HDM%x|O)f0LrIzd6uWC zL3_bU5GodEMa;Kn1E&K50exb^oB{ALO*O}mI?ph7aguR=#@yNS41k2+=u{(Zs!)H1 zDRusW`6~KMnm;%2z*jFw;@q5EkTN!VE-+$Cpc10A$MY?vyVrlgN?=TRmco3?a^gKG z7yOM)(Jioo1WGcQyO*u9taZPh^uUvV8Dtq_yUSxyl<5yXu-vi=T3iY8wwo7(tHvrN zt=Wa$m2lC2!D`C~@c>H_TZQ%4z4*Edjufd+e@=kEhIbc9#`IhcY7f!WqmeW&d~`iP z>A9l+WjV|0B^FDzjb@WX8n9@3wikjN_&1dSD%%R66u*k`FB|9<2sV2buuYVG3ww-n z4xcd_j874l-E#)yCfcB;!ts$X0R_C2asCYRTmvV659K*+LF(*zGrM#A3$z;qm}C*q z`c$sn3Ns2Hy@l^RJvyHYd`b~bSOpafVu!aGm{Me1NO1$`;j4o;G`~VFt<&e=(@0F zj1SB>;Oeg^TkD-xfqgl@pkY>p$ zb1{s#Im_5Iq7O_><1paZxNGn#Dk&}g+y(<9<1sT0fd;u@ph0Qy zbD4716t_(N{7JxBUh&p?%3gY)Un<1h@;H$Fycb4 z$q$+EH0_AX@uc)b)(VH+QRIIpa1=U99How8$Nr2t+yU;8&aswb7hH3}f+iLh47k!5 zhbMD}F6BEOEoa7^**XofT6vVMbd7^P&7GkL@rxLvIwnt8eV@~<^Uk#xMc%6CI;CObf^iSje`K>mIaz!3?oxPMlPGKrz}Nf z-i5Ax1*nrfL!IDO5PYMbFD8E$i;dSl@7ep^?f4gf^Dr|olNHQPX3v@OHsCH2Z6>iC zBrN!+@0O4axao%6aWZtBVI~VIm@{SNH`?%$Qv5zbe4;bUEIxmjl`?#A$D?hf;ah5vv4SbJTVzY0rOVQ78MSDZ zzqE-Pme1fbERTOM<|Ai*g!QX@%4^TJ$oZDOd`nlpr90m;ns51w%_7?@T{cU%&C+MH z4B8MfYO`qQ+0v4t0&lTj z3PgTTGR1!uXsJEm%S|BGJ!usAfLPok1oGVDX2Fj;Ao2sTd_Q+QCCvlT&zv8xZFMfO zYtI=ZLyjFpu${yfuMrnHc%;>V&hO;S$WVurA0O#T&)X8MFHX(q=k)SFI0}2V%H$KR5e5u z7=GKwhwvc#_z}>Pi7Jr}-WBPZtT$?l#1AP?PtlEvGn~Fu|vvQT`URJ$j%gB96F8q zB+efhDR1j`mpxkE))9v;VuQa05UlMUGAe&R#APX%>C*K9WyErmvH}of4c)~hC=2+5 z+jTw>P6^!}VitLmnChoPY7U|dwFdyugm&BtlcO-OIt7lDYcj!Ub4?~W?{!TYg%=x9 zXd+detGS5Ezja;HC=~KZqLzf1M)XF06Ah2@YhA%V0!dMkwgz$P-PBEzU86x{Z54kO z6ciLzFv>Fhlv0K%U??oivjaF$2dmF0RshzO58dj0-A-vEtFK2DK)0X126~|)R_b!W zJnedo>QC3ti9>CK#QY|lDYdYMvH*Tijkd-bfYqn^!S!`}Syv*{=Fa_qMzD#ZI$Q|c z)#f<>uX=Oc-p4@Myxaq?CNe@u=ktI39wv3>jyx^Xt;FPN4Tx&fcUH6+m3_bwp=3Zv z2a{Q6XWep4L`Y4SGr<>E6VbaXxCh9=jz}F2{_MsS|AG%{bn~fh%?AKt=^p#)+~=?k zNfwJuBu3v@J7!9oNm&Bqm0mj=VC5!c*$&4%T^DfxHF6Jxp!_EM`d9+XyoG-N${s;+ zfZ~q-7IEIohIs!pfi6D@C1UX0jlr`JgQu{zi>twOs5D`~2V>MHi;7O5o}?2r9aghu zOx)vXLbCEA5Grrt&o1~;S44thZ6qkxDvtoTZXdd?dg4uvVV+A?o|!_YP@e%njdy!v z2-Sv$*7~W)=Ax#ow|-Gwn!A5BCePX_j6l7Y?7w$~Z{Ho~R!Y@G$$lCqbKS}hpezH< zZ;@T$_}#JGsn+QPMcSZ5bk`@sR%KO&6G+wI=>)K1>@(6KRt>TjH*u%D%0W z5xL+Hf0gC%ei_TXuZf#7qpWP;zdfo~5%F5&`o-+}#W7A3_ofV$TH4HLYJ5$fGd55Cvqc71v0m_5 ztVN~_^=a!D-9&22+X#Qe1|S)v)T9-Bw;_f>{;?U(;|IxkV(W(lqEHFIU)5t2yVmUeXeT@74AR@v+4NqOJc&>TM6G z%Qhr9Z?}HzOoctDGc4Uyzj+Z0LuvKW8dE9sp0O=OwX$=Hi$RePHif{7pL`VK^>3-Uz172~gl#L{bQG*nnWSe#Qn$kprw z1b1pa@w;=^>7@4nMB3_iO~micXl#emRB23*wk7z9xlx9hPe0>#0hKHKz{?q~@OrM{ z4Y+i>m7EP`?v;O6VF=#WvT8HoOuE8lT+LJr(*BIAISmU0pNYYugMwGXg1$HudJ_JF z7g0#AhbA`2HrZA^yC@l8e-52iB`C=-X~MCX`!M_}EX?nwNOjA%F<-)Swq_ShV=2%Y z+A~l20Dupz>>z7q2*RqWlaLMt%U)q&iCw!G>|wuMtDk>U!B5{Tc>7I)*HFPbusr&d z``}ejP^uHF{I`i*JT=2mZYpZ1E+$PEGfqoVscy1eyAWIrtXdMzv?O%sErRjSoqIA0 zS{(s3qT*IM-7_b@3Ez#oC@4Du!goP|MlI3SAVKgjGU6OcYzkZlD;O>HLEJ+_)?7eA zb78;i4$ptx%>k}ZOSL1ZfRt;IbK=m1s)cYykv&sO-ASWXK)MSO&thx7K`>aeo%2Pz(fz!Md0|dV>9l$!^5L2hB7{(zcO;wqh zqpZVvPPoI-h_Ergqe;iBt8&H;$;t)mfVQ>6Zl1>1;fN6m>?r84Qtv1!WVXXlt$!xl=KPErxiyGptnDw z34@w2a6`t7mJX_`$V#uf0O4BCI2Yz>m?O;6!z{TSt|Jt&QSI-DWy+@2+(7ttsFWZ1 zc)WB&ht=1dga*sQ?~+iwzvU$4eCK};S~%MFkpSG!>RmFx>NcldgrK35iY&>M%`|V zXKE=ETf2|%(UlA|8+0ZA1D1&Q3tUS!t+q0~_o@}-yja!l)s~WR%Ov?kw6%X*Cdk>9 z9k=^V+y-6L1K7jYo zM?h6#JBGTH6e%Yjk18k@w}XGf&y(_#MDRqg`+llx3P(?~wR_@0P7Z&PjHmM+(RS>Y z?@9c5DaA-dU;n0_tH{O39fdn(hJ3fk6<+SVOWMUkyeiwUG*$J8RXrr6ekv9ZdT=|G zm&b4`S5Z0Au9$i|>k2>4)!YX=_42*0a4}ai4~O$z;muslXP8^UMb3X;1lO=QdYG$S z1p{e|k?=j@T(Q(Z&XHDFE%?8bQh*^>^ERUkc!H}DDfn6ElHdp(J4~?|?9=4$}jY zA-%}LC9)Pf@`?-zPI<}$%y+~~-<Y#gY|jp*HS)f?QqU@J+CD=*{vI`z0ds*NkU?1`QYweZ`Xg|TIV#>bgKr}^HT|U zTUI(~XRqHi&6<#+3Gi#u1Y@DL%c$8+?)FT26D@TQt&^(!&GC^V=i^84BaFoR?e+?@ z65oq$QGT=_L#JJ(cR@7H9+Rr%8JvTd@+3hnDXCbboc$PEra)alRt$eg7`;^2>%Ppf z{yP30uWF>wx<7x7UUFaI*fx>x_bNu>1=#3i_azP@`wvgl`A07iZ#~}+(EmypyMdGOOp0QS<9<$D&9}ANy7EWIcaWM-(5W4usqKQ?hv;EX{T%_kvdQix1y={(p>l zgV+v2g9LwWfaZ^SB?WX5`82{GR*LYjPv!}C;RYIKY~T=nb{oKt@=(`g2!T{(PJp(} zN42YsSMRWNAI-d)xzQaqJLBQ<_|ovz1L~I`iK~5wi4@-%AM>U1qmlq?9u%w0;cMKo z0HEBRnShCW-cQ2o7yZ7Eb;*Sv*2P2L{J>8}NgsdF^2N3JwWH3&eD@c|eBT@l$cpTe z{S_;;@BjZlL+77WSGp%Ng{+8fsF-+XX$7;tB2D}L&0oULs#Em*q)EjlQapm~<{MC^ zr{mwmy}xE2gn{>}fecH(!SJ^Rgt!w7Gmjyk7FHN{_Ca1MQZ_5pg>VrE2gant=DEjH zgt32`Zs9h&y=dnk&?vu)e4I#fx0$OaHH~AQ`%eoLs2N-99?A+!xR)b4uOSP5HxhNV zV#AbsM7L?BQzgRwtJ47oRnV>7@J+5e~C~KA3L3_^KBs?W zccpAsTT5!$a+57lG$~MH$k;+KMWv)<_0jYPwH2are&?L~-T>nM`|;74_wK#t-gD1A z_x!o{+&j%N=|_a$9WFZMxG7$&!HgqzG|_D%hCshBqT{6|4`T4-JfcF`^+g|ugCxM) zvI{U{I+m)JOf^#ak@2-7o1rsoZU}!{7VbCh=@<#*dk5&Oi97rrc6sE<{NYHP9Lt_) zDSglUjziSb3TYqp;yvmGHC9-MV6KyzXS)h7kVWj=!Nf8ty+RUqNX|0$HWBw7gisp4 zIPwQvm|^wYf;N`0^evLHM6zs=oaJmVTdJ?ZF^@Oypizr4mgVP2#vPKSOlN;AiL`9l zuhB$k;%fI3qQ?YRDj*LcsuSf6fx|d@3$R%%=q(s?o8s<_b=5@2H9AIkszM;iLnE?( z5G}L&+Sx709ez`l-&obr1e&V~vt!RlrmddEer73;OD|u)PKscbD#@&8mObn=I~!-& zy8ahAm!hTTsF%>cz1Uj3sfvGHj4|!84`C;v(+pn4J+pkra!y7U9>S8SWw2p(;_|Ef z;UufO{HjM(lD(H-O#)N;vnxYvFrpA#trVKSX*k9C1oNs3W{1U!w8+2&{jpxcl|u{G6lF zaeu=MF+mcmB$D=u?96#;YBjP8HdFzF#ZuK4MaLn70l@_J@zkc{WS$3;xnn0b zVXBwX8}2l<#iX~xFtg{VjhCp6v!Ne5ZkJ4LQhGb%3`Ya!-AFPEfD^8%`_VGs20juw zHPMnOf)!&?FhwM>m2IUeDrjb=*GS?Kwv`&Iz{b=egPyqRqC0+r>&<}Y5-@z_Cws_H z!~G3b%bHy?JJEm96~hIs@secxZYRFJTn`^$RQPczTG-v<(GQ6W#*9a)zbjC9O@(@P zVmb5T)u0)^`5dG{3oR`lKzqXX$AAE5#x2ZJqVh{Ivup;pTC#u^-@z%5yfpk;i*XjBx&`LO%LoZjXi$&9=h_~97PHi)a62SYe(Gb= zaaWA>TE~CwKu-ejuM0<%F6=#GwrxNnf7}gJrM@xhDVL;o8Y^NfdnD)9!VCV< zAaI=JUL!7&Y2L-|#QN_P%VV6o;yT%}k>A_(=p>rcK$GZ#v3q8a);eQ_S^jyO->(%b zhCBBFG99j~xZ2y#Pj6;Nr6JOTdZFyY(Av*KwWfcN;pyQIrgz-IO?_^lsY6)-LKSQ> z$uf%1S~NW3#d>t~8U)vA8rl%a94#e8sqzEI6*mPuCR|Ee>=#@8VoQoy-js&+umMDi zWW>n~;(}QY^0|fjhfA9~ja4z0gCJs<<#@cQk+sAakAo70C-8qv;o6JLvo`CzJ`EmLJt?K|qyZ_31TTV@~T(XH`X74yKqT zsLN80@EUS~bz)5U`++=RUeQBXh0Sm@{^ zhC&i3R8iYK8trBazQ!R{kHi@FZ7jpcl5 z5_9>*J$|u*Q&K*Z!rgit>#BE9e0iSmgLI2+ig(ttM)2Oiv$*rxYcXihQ)Qpt&x^( zDQ0$B8Y~MxDFfhuIop_$;uqU&@56uW^JPh5z2s~dFE);J9@mQH!=1Y%=kX!VM#oa5 zorTC3N_`_xvl&7EfS`AJjWwKhM@X!RZJxBNg*{)xpb8t`!i5WCBZ|_CILjaYj_>^% z8?WUfT)JlNHMrPkDIh1Ph+=voaG|m#v|cEB3r8(^0dwQtXr22B3^V|ACR~3>ez?H# zvn**NuG?lo%FV*QMleL&CxtDCvRvH;;f0#p4i%Ro0BT%U4O(E*!f~-@JkA|}+S1g; zFc+_;@VV$-hviCfV@`7JkkZSfh0#^$CIEe3J=ENGrPkok<1QB$(N+GzxX!axu>rw2 z-ztINCgGnSrmY#?#Gk#!k^+CC(iZZ{tFaRr$1q`E@-i?jm1JNMv@eC-C$(Vsmf+SR zJE=WeP)(f`XROw&Hb{h^L*`dkz_28e+KS|WZEX|1}-;l?Xp(* zW&v!%HL!zf+XfAU{jvug^9nF10lWb^BkXR}9_zAh)gDC|hRgcK2;P5}C`6jUU|GT? z&l>V=unJ{tJ9hM3Yf}||^&^e5o@lJW&yPIS;qblxCPl*lp34(|x|Ke;r` zQ)=tQ;L|RA+yIY5j0I9Dj{Fcy5nvMv_S|o1&J;_|%@U`|B(_1%-3(Wa*43mL-#M~J zs-`T`#=e!%(+F^13+vw1q7J;KwLEBz9p++oQbF|^;w#CuI zRV7b3uB4S>an>pSzMGFgVKu6i)NjSRT-D!QMdU_H?hthBP`3VMc!5^qxFIFQY)ix? z_^M7N12O9EyN7?Vh89dBJR9_^TYl*$!e*$7ja&e5K&J=bzs6&Fj`aWr!vTX$AdKX3 zfCnw}&(J=)nDbOF@|3Yn7SOmm1f-j~$@s_Oq$pvZX9Fv?RXH?4u;{ zEoL`J&I9a;F>L-gVRxOjo+VB21yiMLpls74&lkg-^tgX_!KXY8$?o0)k6w4l56E~L z6lFt~E;ZX81xz}&>9`e9iMa(cCfzND_^G6?LvlCbTEo7US~-HbH^Xx*up#E@EFlsV z@=Tq!Nk6@)MjVy4G{xio43f<9?I%HM7R|&L)Mvi98Fz~l7Wd`{^~v`nYZ=u91?$|; z!h_ZqF{gjfAB^_oA9)JQ0BpRrEh6+V+rEwZa_&do7fPRoGptbGKkuRUN0JDkDp=x`2^UT7mU&5|6o} zl9;A~;Qkd>RgLAmgg7?6X)qGWPpA}fByok3YSn*q;7&=w(?bNoeE`aqCpd0Ou^|Ok z8$8rgvwZFos(#aG*SXO-XNG!`E`xRg*qJ(9BYSoO%A%!OPbHStcJ9ZmKY8t^fa%g< zp4qo{ldmN&r-V_EaCJYf;>q(N0Tcw{Ah>b&xeBWTE-*Omsw)a^MwOKeHT$)+XC}P6W$34nTh!!OQP49{oLF>5aO0K;JLKva z{Pd7nbwwj~K)%7(8QbLQ4taX;0h}D;4{00U*80Y~y2FIupbg^c9{f}Yz!qU6p8P+# zu8w?E=lar6ye0T$Y&_9dx_<~}mEtQ*&;5U&B7$O$$}+*yp5Py0B(hlLW@6@T!9lp& zUlgo|uY&4ldEf8AL9N8$+>i1}s>UgF`BkZuYWX4}v{|aeB=*oGPYLcF)P5Pt(x$QG zslF^fHRbXeT-EpxA-HkBzas)gl4o1*RGj)xl}`Y{TO~JUVE`AmUuF@zU@rcl)f0bW zdlBW!3qEehP~Nqs>yxDN3z(@$bp_G=Q|(!9_kl4BMti+vX%Kcb2GxEU#LWq13D9di z81NCRz?LN+(HDd%Rg&eP&R7s>De{;axi`_^7wf@-nel7Yn;?ss+ma>BvPJc!(2bDN z>m{+_&h(NPaSKbYVB(&5@MuoPIQM^mOA+vG5}=myu^37%6pbR+6wDoPW}`i3Fq_aG zB`eG`D?F=kde~*I2Hr+BFh$t+co6t$S+2(iX&jHoeh_aecM3V*hfCt-c*pecd|jgN zE6-xT`vZ}rbv;tE=}W&qrzu?9DD2x1BCXTA&xk`MYC(Px*WM2EK1$$V?XG_lc021a zMz^!eTCY6{mhCCYGDb4)l4CFN@ZZxNndquC#aqf9BXW+0OW`50XW~pXlJm&Ov-!GN zzVn`6``t~BxSV6qqy(8@F+(OUmF6SmBbj2E%!Y#H(ou7j z6rCQMGy!?$E@!41RtrPam9boBsX>zst-E%GNZ}Wi@>m#smijJhyY_#mCw#kxWCZR| zVEHzsd}}8X)!@5ZZA1jPb<3C+Ay+NaUb+_GjZQu@OvO4=75AjTn+40ZjoNC{p61J= z;A(P!$2)P?sX`L>Xw$2PiwDuy)ctflUvo3Mm!S30({&eN1m|o2yv7Q-k4^DZZzY=a zwME$Xo>V=U0K+(PS+0NTCh~2Gj`so`l^#7XtaQSkCTB_+Mw;)tD{-v z8kA5;(M!?z^j9KEQYmJFHH_$uzO1-AAuwMcp=qdwA zIecTamtSS|Uia3YRE@d~p7#HWOi-|?unnqalV---m?GDFM8+>Vo;4w{O-g%HSXZro^wP9}Z3=rU zu?942u}O*Qm0y3M&5}vrxge#8D)NkzYO_kKU5&b6T&AP7I#)I3fD-Xw*DFh?&Vp*B z30S7cA&yj6O#zklxVA!}#fZ*;AzTjgMRK7l&61)dDws7^(@DOBCPB>RI$;@3#VSt8 zKs_A)0*W-gNQ}@i>ndtH_ZA!(B1%UVu89!Z1zze5{`r4y;KRtrP}6ZADo4ugyKH5~ z)d90UMG9db*8VU$b+M-e(M$1H5IHN5oPIEG#AwL^^D#;?hRgSV-y0Q6bLuNv$7iKe z(IoYZL80!Rje>XnrE5&;yZ%9vV+@(p9`raorL)QJKv?yNeQ(41Wi$44{xd-9P(E&L3@-XPhe@2`qrhy z7qf*^*+bK?N|ro>r6rIQ!cty$1ZOjN3Rj*ux+tH((ZEOF*ReIyc6{0t$y2~;99GbC zw>W>X&W&+c8sA|4paq*0xdBZ2XuoRQk5Zm|^T8;@+yvj>m?wnBX|czRDe@D|*da`t z;z5kq(J9*zpU~4nQ8B<4^7>HUmQsBZCB!F>k*NNd{o`rK!#*^hsbf==a>BrzC~^A=u^(GW@-sW=TH#k+f!g-9N3AMI| z>rHQ6xAm#ex_3?#*QS%Mvtu|H%@f;uz)Q4R6x-x6*2`Uus?Z6;*Ec>!5s2cap?|rL z)p8=)GoM1PZ#rf?h7iUYZZQ=917mivz>f%CK;ZJkV=62Owh-F?Itx}tG{S!@K^Wr^ zTnJ0 zk1a@>u$?~(P;uS2v5lC0Lu_N8kmJ6)*R;**S>|V!datn|usdC&tk=8GY{<>|Fxs`B zHfO~ZQXz#-{Fb)bX}^C(S4bfszoorh+VXZek87U3$K`C-JbgFc%?S9Q_4o3SGgGUu z`)HT7l@_o+j)#iCZ#nLanD2WI8Ez)>XKO16UmNcB^W868=>&JKll91tw;_MRY;9Ss zNt2&E0yFhQD=s7UwSN|SMm0*ha;;-9MQHeLIe>Ll;fLIXi;jPXTt^49NN*A?c0TZ6 z-(X8)JD#m`hJ#biaLXP1^5d+L_0)bjxbO=Uy3Eo>-rBBHx7PY@Wgo(LV`_S>CJzmoljcbxYO7cgL|R4jKMco zYmj@6*i)IQUJ19RPma>h0VV#<(bXB-A}#GI!l8W;E=0)yPnLG_t4;O3oql73t2VlW zh6X4fEje4+27SK}E-)}wN0FgvsgfT$0mdaV)PYBa;gWHc+8NZZm1ShrGO}tVGRU)}YAl--zhQ>px`DfR3E+^dCwpX2 zY?DMA2D&-pB9~48uijG5w~XXf+>m!Ucj+CWS$=;4@V$Y%ke$&(jO~ucvFk2WBN=@2 zf*A{#rHF5P#2E{u^rD#Uh?6}{C$>d8+tnR&`&)oQG_ooWs=-D}ltwQd$Np}`cDq9y zf5uILH<7wG^YBJeB)-MSBEAaAgl)KLLtM?8I1gF#ZtVBSmi*@=W5Jz-h~!yDRx*-J zXWD-enO-K*)(Hy_V#|Z{9U0fz;>P1#Ubz~b&BM57^jn-T8wBn82x%SQJtS$AV^E#( zg4Q=!vPZxJXk#f^?~=#F9kQntI4@`%gQVpr#`yHo^5@5ZR9U=Qzcf|;$9oFXfP4@q z0ISZ|Yfmv#TkHpM#x_TAP)LIBO3?@64Jm)AOKnH7&p$iKgAGT_^6fC2m)gF-#Nj+K z_RK&{9nKHG09Ov_J^1o*Y?E-{!U%gzRX2j;8PK=1SY%VeSXY~FhE6CwRNUDAuO&rkT>wH9}tE)1;i!UXE?A}%sh)oHKG|SfUha3W)v(|Qk^H{AccR8zc zg8L3X1xNWSmrxbh6Ti6CFBbX50(Po*)Ux^d4l;Wu9)cJHW}##`LbZtDIvRiRNE&ge zn)m^O83(R`dvOW;BN&3IoGJFmw;$`z4twMs?+;{$(FM-^TK6r?jwx4iH{t9M{r&`9{vp~p|8;|K} z7HKpdH*Q}sclVEE9lth1`J{?k#=gN8DV}7k+`K%7wk#cT%$Z)gP&IV=-0RqCM&WZQyuMswQOFP0*h# zHYmj`>>F&hJpL6d*u@kK%xL@InP^^{`S zloY`IzH()=iQ1AhS#jIu}W@WB0MTL_BtHI0aL42>G^6g%15`yl9j!N*{O zoMGD^=6p?kPWp4Nca1auXIRzijlJ=BPtt~22{Ub$Qv^!24vX z@b(zlMXWay6NG*DV2PLMRvFMo&0GK#fvh{Er3;2M1;T$TGY8|>#tO9fySvV#6H^7~ z7sP%5UhCc#JOPl1`26-`6awW+fOv%x*{PZ)u}wTMQFsP}Jc20zU9os603A=66rZX> zG0ghyHPm(;W6fR7JS4uW1%SFv-&V^^J8o-c>1DKvfiYlwbH(-mVlo&oQ4X$R@P|P- z&=w}RzU6->a&2}j(*6-%tFevj1>by(OzJ>8$TKy@^Bit_1Ei&xc|Ff*m6sx@WQg6M zqFcbbS;xZ}@gTs-80W71kfdqp+aBHTy9F$;*jmY19DDM%i+4DSLO*ucgVAjP^nJ$= zi!F%7Lmv^r-=U+mSJOihyZ^9JJ$LB8K{k&d775S&8IqK1TDH0%h5 zueMQgZe`AGamI3C^E|8rn_KJ`%Ym=yRwv`OmuFCT{bs&EScJQ;Y75T6tnN;+!Z&|R zX(*}@@ELz1(2z5n9lO(1jwNsM#q;ZgK-_7YfqllGLKJV3_=QUP7I+gj{~ja1070P_ zK|t+EC+qC`h7O?CcXeQV7ZZ0dXIbnA7)O>6XW9XFz{nPRsIco)P^~WrSI%Rb*k_?1 zIetaUA0G`r%fu4q+#)$k;+#7qu`GW^+>#$9i6xSA%Xo3eNM{*Zj<`}U>}u2=`%m3?>tL%Et1J$?%;FWBJsLvHmz`(NmYrscB2)N1@;xoJU{bA%1_Y{N-Le zM~LU^6Q0NADZD&jUMW63j53yt|H*b>O-0^s_6`C-)66s9sAJ{>_-w zg_7gg2UP4`x?^V%xf|7wLm7X?S&Cdoj#3O#OMk0UeDz*LgeRVq= z{Ry48h}?rwgl#mr2lamOpkJ(#Xb+(u-IKoMts8tJ6FcsMly`M>Ma8>xCL;LVAUa%l z?J)16VWy3=Qt}-8ISAVKuXPZf-al|4hmnKOJBmZ@I1wpl$11EE_!Fq zI&@n>czTM0Y0coGREkC9p5}h*WW`w6%x6KzN1@zMc?lEaA<>gw=GBj>9FC`}IXr8T z=YFo%fQLzJ75#s6fAM)>8|mp#Tn*dfS*K;4^3n#f@A)Q_gse^#&PrWKA>=ni(IG%J1tLfS|2 zBUdPY#d`HPmu!I^$s68R0$=2DAEFC_VMRMNP#YF&gO2Zy;QLg3@{if8Y?NXpHbN{=AjS@Wcy|Cq1wohgqH?JUjs6$lD5k?Ex-G=+9p{1iMG!ueAeU zi&a<*=8EbMdpE&WD6p;punRb>wEYMVZy&0pcl}M-KelZd02BRofECeLR#M;po4U*U z7leP{F=Z0XE4i>2A{3oYn#~nnb>5*8z6a+Xy9io7wKX8t@XTKo_DFVN;lsQ-rUQXC zi>uHw`CVG_3tt^%+kXS9&@!|9*k1xQ{DEu7n!&wHz~aNMO^ElQb`eP)EHkd-BQJa@T5{4U?mhOlt=CPN1(Y0 zUJ06~{4y)h5eK20a!3u>s`@df@%hL1ltpoACf&~QegE4z<}0^zc>CYZ5nHn z6XqCJT%x%JY~GoEkRRfgbp`mQiQkR_O&o1D+wk4?HMHcr#eGKnISz4Xq*l}Mb`PyW zQ1+QQKi+Pe*^cu3mP`bY1<<5hdS-5f*j6^RBB_q3C5a8ou&- zNH$mFCoX}J*+fS*k`%e^^ZDsp>GY?)V%~R5qG$OBus!`F&=HVsQPsp-kpV^r^}4Mh zz;&5Q$n5@p1)k_FkOT$lbeax2n8zFV!+&fbUWFG811rBZkg0=;NqZx?+K_)=`P}N1 z7w_iAShzVYO}^_jzrRj@tLB0Gan5kYQ|^dbu`JD2htRL^<#f3L&lc3;o>cDBf~)(V zj_I!MD~{20|Bb7AsNjBEquwLcf`fY!8uC5jKI3?QK2QAsYpcc7w*ik2-t_z94%^F< z`dmF#wwo*`OPR!{z`dYud>enEif24e__dce>57y5Nx(r@dMos;>oYN4raroN@e`NW z{|_U3gH7l#ki6o}zyP4<>stx9%!IU=SMkciXGdVjQ`Dg1C4;nahaI}PFm0aD7Kh*3 z2g|E(_Q$dWRp1XDXVAZNUDXTj^Z(?WzZBGS$M3rMOUnREKKX0E=#_uZaXMu}=>y%7 zsMe{B>94AMM1*57d}63P3YlPk$t%(BUyjRfX#SOMTu`U-?usYIC8i2#M z2>VS4Hz^9wKfa@!slk5&S~Cjm)zSO!hb)g0>PSdm-~tbKHi0IND-{2wcjU;9Ry^Sa zAGj9xD+~!YFHO5%4X^SVeAAF8u9Ls!QXfP#w1rB&vtsW${;BE$GdQnEJKJ-J{VNBQ zb?AdcPMu@g(>J-gwT>~a?jSJ^!J85MbsY3=Jr|ABMnK9|g$;lHhS`$x@&mp+^-r8; z6zu4)MEq=z0f0R10PcvjT~)&g+XGK>;OQ&niT3UgNrU6({2@V{X~xULJRX@&ptW5M z^m`oWG~XyBO4xOBfAtUEL5dBN+;mLqaA>n5oKY!8c%&{(v%QE&{(e6XQmI5t{FPXn zZ4YKVz8_ak8b^Pr*Bl-n6}XGZOSI!1Kt0zoii@_>0Jk3v9jTOVsWO(yHLnM(gild` zQiWRA2&%0LBYov3-$MjF2@%X)uGlo^M<_vIydrtT8|u{3*Cjw1sA;?5wvnl zi@`iOEzM&pTWpKH5r}1~!Yu?$jU~e+%wM^TxM7L1qbjdGh_AhgIBTTRs$SHOqS%?j zp3v(kKa%fC(gh%1m->@|Ue^}oiP2E?GLS?g!J?JzWDkKTR^pLpe2zeVixkdjAyL_n5L)O@V(QHen3z zh^OzvJ0?cqRhSJ5w@4(tckZCXG9^)-3Vq$#25)RcJA9_5m~H=us14eOyDaXBxc|NL z5ajRx#hph+;Z^C};N)^d>zJ~5v8@i$ZJ4_&S2=paU?R?9&(sk*Uk!RXOGej z-DR`0oYHnFX%F<14oD4uWjjqcnz&RUZ%raG-%$+S`2o+30mTvZXVvCM#gP|=eBVc7 zB%Xih)flu+5z-p)Ur}Rps~Tg}ztR{LipD4-jj@eujBULdg(Tf#esh$w2iw7I+4v?M%NEqW&D6D;|E1$qo!E%gq#((Sj+~Z@D~MfG^9GmlyG6{hXrl?E7YQ`jtUS%Qm05`5p)0sEnb*i@1XC5oCHq2Q@NnFQb0;G~QSIFhUOqqz2J zHoMPRK%{MOZNJBx5J7R|2^6~gasi5m5qPkVC5EuY;cRFDO}Qd<8d5!@_p4TbSM!nn zv)7@ntoFS5P?x5+F1}8q-2B^Di&ZIFtY>F`z^&!FtWK-CeJ;StWsXuTWfZ!k43yF} z*H>y-ubfa8h?M4zXkEep)z(Kptl#;sRNLrRRMnPVmdeL6pxRD11kQ>qUYu$RM%MoL zD~#&F0qZ(Usx7?m9O|~h!>HU8wYCX|ay|P0pOH!*Vcuw4dK`7Fj7?5W!o-ny}Kfys2cEHuIQtvzQB|d$`j754bi8HLF3v<( z9FJ2BsQf`CZ?q>wUkZ&jWn`MOq~wS!mJ|)&H^BGJ@Erx;w|eGBds0W4&7P!xTjBrB zxNt02ogw}FKTr*I_aC4O2Y&OEX7c`ZbMF4Vf?>w10nbPgf%n8V!3-@ubVunPbr}kk zG%0jNm0R%4j+<1uI;lA^FYZx@`PmH{p3%f3if_)9XnspVr~L39 zj4`%h?Pl5a{C`8`v-Zg=_J@prs8Cmqx0eMLMT8<<5Lyt3Os0a&*maq4fXvEM$EL=9 za3wiH>j;t0oWO9NdRG5p==_M#)F|nx2-gK|Yz=oEG(u_39i-K`rHbi99AQfhcc-fo zkty2nI9VM?l%M@aq&x6#FF|W8qkhNM$TpDj-lS+UMZ3X=5ASsfe4{CU`mw0S;Zv^f zE@;pTlXwBzHhpS>l&sfw#(C`<@%92o=!{Uu(hl73#~W=MkIAu(d-DE%^V#!d3_JMXjW^4qL--pklyM&{i}bT zs+Z=3Gc8{5o2UoE1pAYJqJ1{r0!Hq>hb=q|EkKFYT7Me&lsKvP(sr7EA4j;wtD3%H+<8+h z-qgi5RKF=^zIY&&R`hz5w}4l5;MSW1#^|%#l+B5tUNe+9`M`%5J2i3_ zAy=wfmj6sst*{#3=Vs=o^7D&hpyH1B^QZ{EQ#c5qwE%sQuEF_^L%;rKCBl^oiDA4n zE%VY7UZq73I8I4_NS~_Lu?LvsslZ5``yWiRt-y>wVSmVx>y&q(_&&_Y&hxq(uBzdy z4K$|pR~4Oh2rw9j7@QXhzv;wHcJ}s|APm}c_23Cra9do1=wjee!rsOdx)SbbY-mW2yo#q zd|6y0&54kfM%_uH6H|()rkJbn%E{O!S^p+-=fM2FT{?heG5+&4tS|~(V%yQ16{{z< z38)hK$9`*BCvb?iwsW@Zyt&WH7b*HPe^5&YON;aYyX4sy6}u!&x=B5cd!*mdRW1IY zM}kuCP4FUr>(wsywJOkI(L&e8|8=0Xfw!7y)doQscwNy!B(b!7lL%`PdD^A=T;_Pc#*T? zM}B@Ju1wy#RoyIku7A;kFZLtmRP6NpbKJ6Ai9m;cWgpstSN)E0xLbnhzpJFv{~EeM zX0>L&=1C3ijIb6t0vOhJQ=hy8n1@Trd?i%=c018i*b6H>J2Pgdt%gX3KnovYEM6jj~y`RgJR2u>|&CiM$~Lx5{s9 zS7ROBFQTr=3H;KD-F-$VepADv3sIAQ zH@ll23-7YDDe;=DnRz9##eD`(-?zs#u1{y3U0q<57+Xlu-;h;;ceWm0KUPV>LmZN& zMKZOyKX43IYEe&zl?c@zx-O0e6vX@E4(Er&bqUYnP0kea;;YLl!QW(4f=;_GL(8Ui z-1UM6Yk9K(>HCvsy{7Awt69@^hW7=3dI8weIp>)uE68y&wT!QCKF4~BYn#6eJ&pG* zrneNIYQDgnjd(-lNl5<|-oId%;mH@;jLuA#c$}SNhr6teaVPUfIff}+>i7k&MwM(b zwKSiPtFw1N`}2M0N@CA+;ExQITtnY}l-<#XvL}GDp(Kx6CKu1W=4~}=XJ{lpVw@aqh@!yZU48;Kf z$#@*g{}sx+{k?R(f|s5EUAwv@W2=vqsI=^*;$rGA(UBd7!5rVr(i@A9HJ@kQKr%VB zlTH~z!UaieXQv_U8)zHocn)fRgk(9iMM`f)dYyw>*(IcFbJqnJ#1nDN`FA_ULi^+E z0nN`gnHrnVOU@SdJpk3Q&SoDw-SIu@>-CyAW4rwXe2?#ru^b12)%xlKv>rtgt6dW5 zYDG(wyGe|SySzRD+PWO;XFcj6(zr|OBVxh&?M=x79_(>-jTRH)F6D=R;!j&Wi#ONs zLs%{B6mWVU4y;98*mV)3h1=n)t8YC-pYh#*`WJZ0@-%W9j9%z5W@>}PbL73D zUmw@?Xz2K>Bb!10z?jto7HUzziGAOfgK#>w;BWO2ZBF<~OO!d+26OHU>~Rka4$;Hd z8rq0IOloX{SD1V)41f0nc;s7T7uLzSWs|85nCl|Wz*gWCYYPT{oC2$ibKK7A$9InW z0Xd}|Ii-y_h4>^e#G)ma9}!2edgvNoJWV4rGaS6Y3XIoR>_GRbe^?f3bG>54M`sQ13VxhQ3`@V z+k)f<)~yAZcb<+}ACI%N<)=8nAczK|CW8(%H{NN%t9n^~-6m554guB;jNB{(-PnC> zj!J?KFQ2yoigfI~inxN0SK+zeKfV)32=DT0@$G=jtB_fuf^JrpfTu{1sOC2L2X(j zzeXQ4OdG6!8$4;lB+aDQ$y27@bMJlA;xZmtnQ6_^OxmCsmn*JWGhUODI@@4gl48(g ztX!8p-H@Co=4Kio(QL?Y7{+c0)5JVDC3dYjapAlqc)Bk>c5TdqQzxyRZqOtea`STU z673m}tg#xb(cBa*kVNh~^?bel!?7ZBG8k2Qx9u!%dvCd%K zV9OBg4r^v0HDk@1ypk!0I(Hkl$RBNU1`h6&JEKTljj-Ci787o^K#c`tjW$atjoxEWMh9c#$`*eX{gBl z7=Wxb*fQ);pj9jI> zS~3eL&&%|}Ko&IV$j@H41_nDfGdmxM!b|n*lhSE17xMGgTk|=e;9%NSBzaXS*8dZ& zcA^6IklQpXj7f7>B&V*>SXbJz?9&bQ>{Yo$F@w_4Fg52ow3u&y zOj&4Luwr(~yfmZwf&(>g$-G4i2P6=r9Y#7kD;s(d$X+tH@AEaKlJdkgnUt2d&YEk; zvF7Jm*AOn6x!J313S+4(o|iw}ut;4t?+M}~n99wbs7!041` z$<4{ldoqe+noH2b++u4 zcEfs@G}!MzjyXRsQv}Y*%~)%_PIA6=eYR4$nq{0lZ?+-R>fn>mzB1nmq=rdeH-s(Lq42c$|WX#I2)A&FMdk!Bc zp0PAP+hM(HW!~CHVDbYZfyotrfTYQpnP=q;kMnE|2-iG^4Y144fO&17U|5xxM*?qE zo(h%<2vROgAK=B`GO}TygCqC=bQ3zWlf#+u>May$i-L8-&EQd`V?;4I8H2 zyW-xd|1KBgTA$pcyxgqpReZ(cFfLq@a=&KDJd<&eWr=1^N}_r0 zyrfjkV^+In$y}q!xMJ3V#H9JkbBb}c@-!#KXk4h4NLjQr@VvlcR31%0y{O@g7XLZ*5pum?qV_2BkL&epKGmAqk65y${sb;qjqGpmA1S*yLAHQp$Bi!}6^v}i%#;ToxKcVvSgwyNLL4NGjG zn3Bwv-WjLNNW;BVZB9?F+H23+DEJOsU(%_4MQJP`cB4wTh6*+ zrPZ2gr-2}C1k#nB9r+-_{{t{!WnT+}tXdxbwt`++Zg*sVfW$+!wX9D+=W~T?hyE#= zu6N9UQ$#yJD#99h3P`|9nHJ5qEHLuPqCBTANtw5BPH&Dnw|Y^4K^B3mk7he;Frx6$ zUvJ*lr||_KVic`{APRaMJN9o9-aIj zn3M}{4G8W&5dVR*CjTqeG6eq2z`E1n8||y!)Kn1XxvQpMlRC=^3<8A_o!(SqZYEZ6 zO<%6Vvx(+;NgDgwb<+(GZoubs#p+rK3LrZ(!(lalB$~OifsNlKuA69BfaMJHW^+4< zV3QN)EileT@vjyGFeNWlT)7hHmL;OrcqBhhTxD|@`WAR_!{q<3mgiV=!FNF_Ix<$- zfq+XgRvGRXD;jtS=s74baYMlATYzt>0}yaicp);p0I8K|Vm@w=5 z`KTd(K@;XV@>b@p3E139rovq70~R?9pUNT}8RCw43+F9KQH+B=&)4X^K#nT=k^@dN zxi{#E=4S@#=dV;hxx#2yX~;^swqDgSRyxrqtJgRI6NGx2iQYaZK&mw(pIhfRQY(9n zIcl@l?zZNV9h*3L5?K{=1e*5GmETAIF`ge2iyn+8A%2IuqWtgw0ly}8XW*N&VP2mh HlW<<-caCA9 diff --git a/stage2/lib/blib.c b/stage2/lib/blib.c index a0deb5dd..ee53ec7f 100644 --- a/stage2/lib/blib.c +++ b/stage2/lib/blib.c @@ -12,36 +12,55 @@ #include #include -struct kernel_loc get_kernel_loc(int boot_drive) { - int kernel_drive; { - char buf[32]; - if (!config_get_value(buf, 0, 32, "KERNEL_DRIVE")) { - kernel_drive = boot_drive; - } else { - kernel_drive = (int)strtoui(buf); +uint8_t boot_drive; + +// BIOS partitions are specified in the : form. +// The drive may be omitted, the partition cannot. +static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition) { + for (size_t i = 0; ; i++) { + if (loc[i] == 0) + return false; + + if (loc[i] == ':') { + loc[i] = 0; + if (*loc == 0) + *drive = boot_drive; + else + *drive = strtoui(loc); + loc += i + 1; + break; } } - int kernel_part; { - char buf[32]; - if (!config_get_value(buf, 0, 32, "KERNEL_PARTITION")) { - panic("KERNEL_PARTITION not specified"); - } else { - kernel_part = (int)strtoui(buf); - } - } + if (*loc == 0) + return false; - char *kernel_path = conv_mem_alloc(128); - if (!config_get_value(kernel_path, 0, 128, "KERNEL_PATH")) { - panic("KERNEL_PATH not specified"); - } + *partition = strtoui(loc); - struct file_handle *fd = conv_mem_alloc(sizeof(struct file_handle)); - if (fopen(fd, kernel_drive, kernel_part, kernel_path)) { - panic("Could not open kernel file"); - } + return true; +} - return (struct kernel_loc) { kernel_drive, kernel_part, kernel_path, fd }; +static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) { + uint8_t drive, partition; + + if (!parse_bios_partition(loc, &drive, &partition)) + return false; + + if (fopen(fd, drive, partition, path)) + return false; + + return true; +} + +bool uri_open(struct file_handle *fd, char *uri) { + char *resource, *root, *path; + config_resolve_uri(uri, &resource, &root, &path); + + if (!strcmp(resource, "bios")) { + return uri_bios_dispatch(fd, root, path); + } else { + panic("Resource `%s` not valid."); + } } // This integer sqrt implementation has been adapted from: diff --git a/stage2/lib/blib.h b/stage2/lib/blib.h index 7e657ac5..af00263e 100644 --- a/stage2/lib/blib.h +++ b/stage2/lib/blib.h @@ -3,16 +3,12 @@ #include #include +#include #include -struct kernel_loc { - int kernel_drive; - int kernel_part; - char *kernel_path; - struct file_handle *fd; -}; +extern uint8_t boot_drive; -struct kernel_loc get_kernel_loc(int boot_drive); +bool uri_open(struct file_handle *fd, char *uri); uint64_t sqrt(uint64_t a_nInput); diff --git a/stage2/main.c b/stage2/main.c index a43a8c72..801b055d 100644 --- a/stage2/main.c +++ b/stage2/main.c @@ -18,7 +18,9 @@ #include #include -void entry(int boot_drive) { +void entry(uint8_t _boot_drive) { + boot_drive = _boot_drive; + mtrr_save(); term_textmode(); @@ -63,11 +65,11 @@ void entry(int boot_drive) { } if (!strcmp(proto, "stivale")) { - stivale_load(cmdline, boot_drive); + stivale_load(cmdline); } else if (!strcmp(proto, "stivale2")) { - stivale2_load(cmdline, boot_drive); + stivale2_load(cmdline); } else if (!strcmp(proto, "linux")) { - linux_load(cmdline, boot_drive); + linux_load(cmdline); } else if (!strcmp(proto, "chainload")) { chainload(); } else { diff --git a/stage2/protos/linux.c b/stage2/protos/linux.c index 9848e95f..d525dc74 100644 --- a/stage2/protos/linux.c +++ b/stage2/protos/linux.c @@ -51,11 +51,18 @@ static void spinup(uint16_t real_mode_code_seg, uint16_t kernel_entry_seg) { ); } -void linux_load(char *cmdline, int boot_drive) { - struct kernel_loc kernel = get_kernel_loc(boot_drive); +void linux_load(char *cmdline) { + char buf[128]; + struct file_handle *kernel = conv_mem_alloc(sizeof(struct file_handle)); + + if (!config_get_value(buf, 0, 128, "KERNEL_PATH")) + panic("KERNEL_PATH not specified"); + + if (!uri_open(kernel, buf)) + panic("Could not open kernel resource"); uint32_t signature; - fread(kernel.fd, &signature, 0x202, sizeof(uint32_t)); + fread(kernel, &signature, 0x202, sizeof(uint32_t)); // validate signature if (signature != 0x53726448) { @@ -63,7 +70,7 @@ void linux_load(char *cmdline, int boot_drive) { } size_t setup_code_size = 0; - fread(kernel.fd, &setup_code_size, 0x1f1, 1); + fread(kernel, &setup_code_size, 0x1f1, 1); if (setup_code_size == 0) setup_code_size = 4; @@ -78,7 +85,7 @@ void linux_load(char *cmdline, int boot_drive) { void *real_mode_code = conv_mem_alloc_aligned(real_mode_code_size, 0x1000); - fread(kernel.fd, real_mode_code, 0, real_mode_code_size); + fread(kernel, real_mode_code, 0, real_mode_code_size); size_t heap_end_ptr = ((real_mode_code_size & 0x0f) + 0x10) - 0x200; *((uint16_t *)(real_mode_code + 0x224)) = (uint16_t)heap_end_ptr; @@ -116,8 +123,8 @@ void linux_load(char *cmdline, int boot_drive) { // load kernel print("Loading kernel...\n"); - memmap_alloc_range(KERNEL_LOAD_ADDR, kernel.fd->size - real_mode_code_size, 0); - fread(kernel.fd, (void *)KERNEL_LOAD_ADDR, real_mode_code_size, kernel.fd->size - real_mode_code_size); + memmap_alloc_range(KERNEL_LOAD_ADDR, kernel->size - real_mode_code_size, 0); + fread(kernel, (void *)KERNEL_LOAD_ADDR, real_mode_code_size, kernel->size - real_mode_code_size); char initrd_path[64]; if (!config_get_value(initrd_path, 0, 64, "INITRD_PATH")) @@ -126,14 +133,14 @@ void linux_load(char *cmdline, int boot_drive) { int initrd_part; { char buf[32]; if (!config_get_value(buf, 0, 32, "INITRD_PARTITION")) { - initrd_part = kernel.fd->partition; + initrd_part = kernel->partition; } else { initrd_part = (int)strtoui(buf); } } struct file_handle initrd; - if (fopen(&initrd, kernel.fd->disk, initrd_part, initrd_path)) { + if (fopen(&initrd, kernel->disk, initrd_part, initrd_path)) { panic("Failed to open initrd"); } diff --git a/stage2/protos/linux.h b/stage2/protos/linux.h index bf09bf34..6ddec45d 100644 --- a/stage2/protos/linux.h +++ b/stage2/protos/linux.h @@ -3,6 +3,6 @@ #include -void linux_load(char *cmdline, int boot_drive); +void linux_load(char *cmdline); #endif diff --git a/stage2/protos/stivale.c b/stage2/protos/stivale.c index 2ed45dd9..50cbeb23 100644 --- a/stage2/protos/stivale.c +++ b/stage2/protos/stivale.c @@ -24,14 +24,22 @@ struct stivale_struct stivale_struct = {0}; -void stivale_load(char *cmdline, int boot_drive) { +void stivale_load(char *cmdline) { + char buf[128]; + stivale_struct.flags |= (1 << 0); // set bit 0 since we are BIOS and not UEFI - struct kernel_loc kernel = get_kernel_loc(boot_drive); + struct file_handle *kernel = conv_mem_alloc(sizeof(struct file_handle)); + + if (!config_get_value(buf, 0, 128, "KERNEL_PATH")) + panic("KERNEL_PATH not specified"); + + if (!uri_open(kernel, buf)) + panic("Could not open kernel resource"); struct stivale_header stivale_hdr; - int bits = elf_bits(kernel.fd); + int bits = elf_bits(kernel); int ret; @@ -53,20 +61,20 @@ void stivale_load(char *cmdline, int boot_drive) { level5pg = true; } - ret = elf64_load_section(kernel.fd, &stivale_hdr, ".stivalehdr", sizeof(struct stivale_header), slide); + ret = elf64_load_section(kernel, &stivale_hdr, ".stivalehdr", sizeof(struct stivale_header), slide); if (!ret && ((stivale_hdr.flags >> 2) & 1)) { // KASLR is enabled, set the slide slide = rand64() & KASLR_SLIDE_BITMASK; // Re-read the .stivalehdr with slid relocations - ret = elf64_load_section(kernel.fd, &stivale_hdr, ".stivalehdr", sizeof(struct stivale_header), slide); + ret = elf64_load_section(kernel, &stivale_hdr, ".stivalehdr", sizeof(struct stivale_header), slide); } break; } case 32: - ret = elf32_load_section(kernel.fd, &stivale_hdr, ".stivalehdr", sizeof(struct stivale_header)); + ret = elf32_load_section(kernel, &stivale_hdr, ".stivalehdr", sizeof(struct stivale_header)); break; default: panic("stivale: Not 32 nor 64 bit x86 ELF file."); @@ -92,10 +100,10 @@ void stivale_load(char *cmdline, int boot_drive) { switch (bits) { case 64: - elf64_load(kernel.fd, &entry_point, &top_used_addr, slide, 10); + elf64_load(kernel, &entry_point, &top_used_addr, slide, 10); break; case 32: - elf32_load(kernel.fd, (uint32_t *)&entry_point, (uint32_t *)&top_used_addr, 10); + elf32_load(kernel, (uint32_t *)&entry_point, (uint32_t *)&top_used_addr, 10); break; } @@ -124,14 +132,14 @@ void stivale_load(char *cmdline, int boot_drive) { int part; { char buf[32]; if (!config_get_value(buf, i, 32, "MODULE_PARTITION")) { - part = kernel.kernel_part; + part = kernel->partition; } else { part = (int)strtoui(buf); } } struct file_handle f; - if (fopen(&f, kernel.fd->disk, part, module_file)) { + if (fopen(&f, kernel->disk, part, module_file)) { panic("Requested module with path \"%s\" not found!\n", module_file); } diff --git a/stage2/protos/stivale.h b/stage2/protos/stivale.h index 7cf8e1a0..d46ad6da 100644 --- a/stage2/protos/stivale.h +++ b/stage2/protos/stivale.h @@ -6,7 +6,7 @@ #include #include -void stivale_load(char *cmdline, int boot_drive); +void stivale_load(char *cmdline); pagemap_t stivale_build_pagemap(bool level5pg, struct e820_entry_t *memmap, size_t memmap_entries); diff --git a/stage2/protos/stivale2.c b/stage2/protos/stivale2.c index 7856b646..6c215398 100644 --- a/stage2/protos/stivale2.c +++ b/stage2/protos/stivale2.c @@ -49,12 +49,20 @@ static void append_tag(struct stivale2_struct *s, struct stivale2_tag *tag) { s->tags = (uint64_t)(size_t)tag; } -void stivale2_load(char *cmdline, int boot_drive) { - struct kernel_loc kernel = get_kernel_loc(boot_drive); +void stivale2_load(char *cmdline) { + char buf[128]; + + struct file_handle *kernel = conv_mem_alloc(sizeof(struct file_handle)); + + if (!config_get_value(buf, 0, 128, "KERNEL_PATH")) + panic("KERNEL_PATH not specified"); + + if (!uri_open(kernel, buf)) + panic("Could not open kernel resource"); struct stivale2_header stivale2_hdr; - int bits = elf_bits(kernel.fd); + int bits = elf_bits(kernel); int ret; @@ -76,20 +84,20 @@ void stivale2_load(char *cmdline, int boot_drive) { level5pg = true; } - ret = elf64_load_section(kernel.fd, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header), slide); + ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header), slide); if (!ret && (stivale2_hdr.flags & 1)) { // KASLR is enabled, set the slide slide = rand64() & KASLR_SLIDE_BITMASK; // Re-read the .stivale2hdr with slid relocations - ret = elf64_load_section(kernel.fd, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header), slide); + ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header), slide); } break; } case 32: - ret = elf32_load_section(kernel.fd, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header)); + ret = elf32_load_section(kernel, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header)); break; default: panic("stivale2: Not 32 nor 64 bit x86 ELF file."); @@ -115,10 +123,10 @@ void stivale2_load(char *cmdline, int boot_drive) { switch (bits) { case 64: - elf64_load(kernel.fd, &entry_point, &top_used_addr, slide, 0x1001); + elf64_load(kernel, &entry_point, &top_used_addr, slide, 0x1001); break; case 32: - elf32_load(kernel.fd, (uint32_t *)&entry_point, (uint32_t *)&top_used_addr, 0x1001); + elf32_load(kernel, (uint32_t *)&entry_point, (uint32_t *)&top_used_addr, 0x1001); break; } @@ -169,14 +177,14 @@ void stivale2_load(char *cmdline, int boot_drive) { int part; { char buf[32]; if (!config_get_value(buf, i, 32, "MODULE_PARTITION")) { - part = kernel.kernel_part; + part = kernel->partition; } else { part = (int)strtoui(buf); } } struct file_handle f; - if (fopen(&f, kernel.fd->disk, part, module_file)) { + if (fopen(&f, kernel->disk, part, module_file)) { panic("Requested module with path \"%s\" not found!\n", module_file); } diff --git a/stage2/protos/stivale2.h b/stage2/protos/stivale2.h index 307eff1f..68f66066 100644 --- a/stage2/protos/stivale2.h +++ b/stage2/protos/stivale2.h @@ -1,6 +1,6 @@ #ifndef __PROTOS__STIVALE2_H__ #define __PROTOS__STIVALE2_H__ -void stivale2_load(char *cmdline, int boot_drive); +void stivale2_load(char *cmdline); #endif diff --git a/test/limine.cfg b/test/limine.cfg index 380682f3..20cb5e2c 100644 --- a/test/limine.cfg +++ b/test/limine.cfg @@ -19,13 +19,11 @@ BACKGROUND_PATH=bg.bmp :Stivale Test PROTOCOL=stivale -KERNEL_PARTITION=0 -KERNEL_PATH=boot/test.elf +KERNEL_PATH=bios://:0/boot/test.elf KERNEL_CMDLINE=Hi! This is an example! :Stivale2 Test PROTOCOL=stivale2 -KERNEL_PARTITION=0 -KERNEL_PATH=boot/test.elf +KERNEL_PATH=bios://:0/boot/test.elf KERNEL_CMDLINE=Woah! Another example!