grml2usb-0.14.2/0000755000000000000000000000000012234405045010220 5ustar grml2usb-0.14.2/TODO0000644000000000000000000000407511270602101010705 0ustar TODOs ----- * if 'grml2usb grml64.iso grml.iso' is invoked there are two identically named boot entries (both "grml") * support installation of new ISO[s] additionally to already existing grml ISOs on the usb device -> add "old"/already existing images automatically to bootloader configuration [thx gebi] * support installation of "dupes", meaning grml2usb grml_2008.11.iso grml_2009.05.iso * write bootloader configuration snippets to boot/releases//{grub.cfg,syslinux.cfg,...} -> this could simplify live dramatically especially when supporting "already existing" images [thx gebi] * support integration of Debian ISOs (like netboot) * provide simple output being between default and --quiet [thx gebi], like: # grml2usb iso1 iso2 /dev/sda1 installing: iso1.... OK iso2.... FAIL (error) done. * provide default entry of all installed ISOs on the top of the bootscreen - done for isolinux - missing in grub * implement --kernel option to install specific linux26 file * implement --initrd option to install specific initrd file * implement --squashfs option to install specific squashfs file * implement --verify option to check md5sums/sha1sums of files on usb device * implement --uninstall option to remove all grml2usb files in a clean manner -> implement logic for storing information about copied files (register every file in a set()) * implement --create-partition[s] option to generate a default partition setup * implement --validate option to validate partition schema/layout: is the partition schema ok and the bootable flag set? * the last line in bootsplash (boot.msg) of syslinux should mention all installed grml flavours (attention, the line should NOT become too long :)) * code improvements: - use 'with open("...", "w") as f: ... f.write("...")' - use class design (like used in https://fedorahosted.org/liveusb-creator/browser/liveusb) * provide a Windows version (for example via PyQt4) * provide unit-testing (any ideas for useful/test-able scenarious?) * provide progress bar when copying files * provide graphical version; any volunteers? :) grml2usb-0.14.2/images/0000755000000000000000000000000011153000035011452 5ustar grml2usb-0.14.2/images/screenshot.png0000644000000000000000000001260511153000035014341 0ustar PNG  IHDRbKGD pHYs  ~tIME;{vtEXtCommentCreated with The GIMPd%nIDATxkPv*YdO9[azdΙRMBBn4=?_ǯӖ߿C{]ں)&/-V84=_Z -zzb2[n]$I$IR飗~Bc;ck^Rф-e- O ҕ?e]ktbwn) Q$I$Ifj%ܧ`l#v{X(s_yh=pc:Vw}`mHlr6̰ CՂ!s_3q>h%&/-Vv-_LL;<\G=ŕgyeT.)A({ua}<_=_imk)翷)%OǟZRΒ$I$IR~ A~0CFSzlyn;;P/Rp6{sd{6Kpl7Up&37c~s>ofJ|_n` 7ͭkk-k3}3CkT%g d'&g--wn8ЌƱ?|J,?=4}ϸWZzk{nty(j?j,ߺʷ$IO?>?w_[._{<2!oZhョпu3R"8#8=[:j-?—s$pi.wu s)~FS`}a5]s5}]h3v{뗎4QS;k_/J=[9?-={嗺#[kv;;哓6I)Vw;nwty 发C*Z_gJ*64kP1^ n%#51-kcooݒ@ mIJ[6s%UZF~c`|i83&}/sz|=V{V~R^Orjok?){k]ϨP_Լ_Zv$IRZ >?W]VkP޿=iKͳ,@[YA{iP䝃S+1'Sc;|ը_g⵮Z(x}kyO 6J?PJ[F:`5*W5ksw1]]Z/s5,uTdlP#|2RaPF_Hi-n1{u Es}޿g]G\0~K$I9$M0"(= }MM@t;PST>kC9umm 5z{C?nm?f˒C 9/99>}Z#nYj?M=woq?fjt};G^S[|{9NZwi)-Ԯ\-?:2zлm i.jɠQ<KOm<!,yrı"$COF~W1Wiy8F4^fkv-y:ꇞnZ~׫k)]~[Q=tC;bNn')yqh>pJGc[?:%.yB#F_쓢;zʷٺU!NﵮOii\;?}(wW ݗi}9ry6{>7ʹMkY5Q{jw|rWbSmW׽eZS=|O&ׁc>G):y%xL e ]츏ܡיRgߺcf ͪF 1s+okcf/M-3pn쫹5{KfU[ޙ{{طԯS[?=n?M?׾޿[\v*֯HaUڛgL_z'/^ViZ)/goOkѯ[?Z3_h;KG//G{17B_w%|}m<'V#=o4[MZrI_*ˢ 'cpi6]&5h)-yz ]{~r?kտuZ?o]>#.=__GtMJ*#-_3B|q}Y&3ⷚ>GC1-_{-Z޻}ǥ;*FQs|ʕԪzqo?~cS˽1_kc`cZ_o[OZ>?HZƑ2Shy#`/(1v [_lڻ~K_oߑ#zɹZ_uߺzxy )ͣ)I48B\jd+I9}LhJKnwnw<9f@tHAsƥ--33}>iui9W|>Ϲޑ3[yoVM.Gnxm5ӕڲtc:9e[kp^`|lHlbG奏5[/_qﭟZvGv[B﫽-7uyLt#Os}u[2uԸzN8"BNu5$}joGޏ,T'Go+r\~~hqo^{<'~=aP:s -V1#[YVs#\o4ѕ>_@#wut+hhߖm}^_8_kٗ`4Fn25wIqtbVG雷A_Neh8~iTkґLB~n;NGOY?t}-+T[QjJZu{ںۘ眧IY;/| I e)Id&@4y 7mn: ޯ|N&iznҡj|Ns:t>֘[1v=7ne>e.hi>wgyo eoYh˖e qk/=uKyn<`ϟ8-{}-|yv,}^o|k턶98K %I$IioյD+5WP#}qj*x_|?~h32H4[;jDcvW^ݦ_E }(}LMW?sqt}JhDeNõLVj*˾o깲3 >6yw[1榓|tζ-Q$[ ٔQa fsp{rەK* |O=R$i݈\DU8{KԈ9=H!-=mU,@Y =WuA9)t"2!͞el?hvő= K}(@'|eɺwa%*~ieԝ 5;|rv_~1x_\+PI4r ll|.!lo8p}X\ 1 $i[ƶk<59R]xΆs߃7#cmQd6FILҍԭr^nvnUߏK 򗱴g,2\Zxl[XeK2`,B^Hڄծ8Yw-?$*']r!i?I&i/$mh&U!7o?٧>~9jU~Uz(;;*P$0 bk#v|MF' #$\Arym֙‰\BϔL.3ݏf)֬]PoGxsƁV-Wg&sNj`Rěj*ʩF]fεNjtt#]\ Db=Nl2_8qZT*/ȑ#G4>_GkUCۚr2^t44zA+3*qj%Hr^ns@T*{/{hRhIENDB`grml2usb-0.14.2/images/icons/tip.png0000644000000000000000000000505211153000035014071 0ustar PNG  IHDR00`nsRGBgAMA a cHRMz&u0`:pQ< IDATXGXmPSWN3δ2(kU"7@;  !BB7AOŠNYNYն춊ֲu٥ ": ]}n\%@w{\/}}ŋ/z.z(4T d?v]?]xN2XrffٳgOb6l/wڕuԩOMMa<»dkY+zhhHծ_ V@+1.k3t֝088"79b%z!֭STccc .-q Q0`"4Qim.(ifGHKCEEiBvQiiJxZ=<<̀yRޟrJPP{[KAS [y,i($ @{EP5Ll DHm2{Jb:tww*̶44]]]GlqJ ӌ,^n)FR.E@%/V(g }}}FFF 1m_h4ҌbD3F^(V [UɨܗYUZ؈-3 FX_>Vqiмm ibbTJNffUǩk8Rx 3 d4$/Ga.-Q'?ao[Nwb%V]rho޼ =a~ <B)hf &Npgwtzf&CϩKȭ˪ JoFag1 2Vco҄MsnG_yDu$"Ew={bB#pL@_X^&xmו;OM30` Bn伃 ٵHxn݂g.& qËնfArawlv|t}$Lܜ:)MPj~c8_vZ{CI Bڴj%Q0A 4tn*ξ7N=?^wBqqCФswwAIwt[z)&[S^fƝqmhŖHٖph%e9sf34| cEwi/D5\fraXN?kݽ7$ĄFh|rJdj^&(|c؜? DIgEnsՕĂYpP# `RXۙh [M首{].{$LU ӀcӉo Oz D)FaƅFX&2d\tΝ;$X |&66]_O^rp}nPWꙞ˝TЄ0RJ__tCETJWݦѸ[plk/7nD(VQQ.)>",lOC===4 =0 W;{nSSANΗ _ܞ1#@#yh)481.44nJf\M6v槟@=aJ(QCVr,IS%ۼyw ADgφiQA +wg>}9LshdMGdXf͹s_ũI-C}b aT諯oр{&40)@#+nXq/zeT{ PZ[+eu`Jxr&a! MqUىDuG\;;;U1)Щ`?+HkBm|,1n1e't{Iz{{UK+˂Ѱ?Uڝ$)blNNG 7n>~ժUG=V\x`B4L˵u֞pCX,k֬l~mD@"ƍVsЀÇCCC `C"2M㒒D+|f:ti v0 $u PnVt 0h4:F?^ZTN@o)1###xuɓDѨY.\vm]]LaH4ð/$ENIdɒ @"͛e,ݻWIĪ(RS% 1@1͉F0iiD!pw׮P{! m۶4Ҷ/ˈBueF;O,Q&9pR2u~ٲe~Jrr7)OI)!buh^!z&YuG~J4- DgJǪcn0ZΊ+d~ Bo߾=4R9Ot^XY (97ל9Q25o"±f;۷ˀL&,vA~o)FH)*O<-mT{20o~0ɣ7Vw>TƄڍy؉%ꫯ|VkCB>t2isj(S5V*0?ԯn:1}nԾsȄ׋`0̞=[Rйٶ߀IVs_3nUHPvJpX8MK2|AeUeV_u՚ҟhm|"Ɩ c@]zh<" jאN{u%Y@7''2<+?=wn6~h}j8vD| tI|%9ZMS6(;^t< @ȧke9!i7j;$1DkIŤ~-M׉,Ρ>MK屔䶛]7-<93;m ''n'D% ' "i"Vܬd֩:{ZKNgu^U7UV(:8DIzTIku E "hY0i\oTRq^yb}EQqVfgEsT6ޤCb1eF4NI:A%߈et8^_x>q9&+cͤ[5o~DH6ZDاsg. ^ ~~{80 .l?6;ZXZEn6s7"jWunɮwY߃ߋ͛{-w]Xb#a%%!L~G\[q;a_@M6v*$.Ӿޛ6|.დco߮/^hR"c!kzL\׉@Lj$m53\vttpUw5{^sL@`d~"!n$kE l"!eWDӱjmDQAEl^~Ҷoؕ0* 8F#&EiUUWϧ͌7/C$bܑd34NxgҨj\.jmm4>7bc5 ]>l驅Ed DMa q2yY=XV}bjִF Rq XS^Fم+_#Lfkd x?p! X;Z7xD&6C#M(Nmah۴ ڑ:}.h9ѾѽŋCipJ0cƌtlA tҥ0̝ +Y}z~88D"'BET`T'H%NKKS(`I_Š ;je0ΙelנA/R, '&Lфđ gΝC}؁$Zyy̙3#f`Y~)SL<9333bĄ:^SPP½xXC!O"CdB-Pq@"½x31 ?VRIENDB`grml2usb-0.14.2/images/icons/up.png0000644000000000000000000000245011153000035013720 0ustar PNG  IHDRĴl;bKGD pHYs ,tIME ' IDATxڅKlE3ױ Q9@U$AU"!@܊7qA+aW"(U)}$vxڵww۴47ܠ*0c'0nT~]ot M@w;0+t<]2x/gocnѼIshJ8SொfZ5?t(zAOn'm{$ KM Ҍ[_9xt^8ҵw7/í)p AH)(9329f4olŌ6B𲹭m*s\.U#^hAR8Jҋ ۟-^xl'ܳ>:Yc 7+r_LFžQ7sTdEXݑOo+)^ #vnQ;!owG|R{6d5Y?;ΉVi!xzSV @72G}'_EQ[c[-զiK&{sΌ۫ 72Co*01& 0!F/)ݬo~0J@w61"0+t|l>gA^fre@ O%\\2_լF8^wO~}?ɱNCy﵃[Glj.^g%D,\\clPٛT*.HϿ xa\g' < J[]6{FC[fXДwR[:;zxaJ(I76z1=y Ye ;|wI>mca["V+Ik6N^V{fnc !pl`AQk9JJ4KVzv2#dj}f1¶n/%)fl/hHX]斵Ȋ 0dэi22’R;<:,hiZd>4]F0:b=wέ).+A k)I Le*h&Fw?`.#eB<9QXnBFIγ8/M=Hv.U ^-m0!x˥: %&uzƟH>7M-oFKƦKw+l7/m6*u$nVY:kZY*MG];!\;Dmuy+t|"4*Yg05%fG 5@6ccI 5Tl^%z&' p,\c0Ti&D_0gWmpuCVEdmAϊE`=ⳏPT̎N#Z'#-95(iH)Cp{]qakkEqк.Z͔f=܌GsiE_QRej#\`|xIV~V}On+94^ӍJ4fv,2-%R1 Bk^o~џ{~tϳ@ /e%R <hI['jӾ&'w/?=vzzZN5-6EZ w}}'o˴%v\IENDB`grml2usb-0.14.2/images/icons/caution.png0000644000000000000000000000477211153000035014747 0ustar PNG  IHDR00`nsRGBgAMA a cHRMz&u0`:pQ< xIDATXGiPUGEI9AKQ30STY#E4[!A+qA0F0e" G-ƅXn%a2,AdxeEAp?݇qsu|˗}ު@o筢Q.xSz~#ݻw,]ԩSo{oKDW@@@z`ddi,>z`/G1"_PPPz t1ccc>,)rq9{"SHHH/z߯_?>\ۏ[)2Ver!L{)S>,|+Pz-jWLz] o߾| h*#r6ZZVl^6Qdڷo_'Ҹ8N6rE$2ڜtB?x^MKvҒ"΄ &S@ke 4FO<lqްܺ%ׇ״/W+)22;L]EGGN 2%WF)..51ىC[M+ ڰX g]2u!Ҭ\8Uaڔe*J[I)XOאR G:a3uՈ3yLSie\kk*V]< aƓ%y啤仵,DN 4kXMД(4?zOs i L4_Knhۚ/,21iֹMWh *vE @&Rz@YG.^~ *\ao7[b@Q9HKRߗc 5*UmB-2El&XȀO-`r\$m$3Q)ڐt;Hi363WH;6U?6jS7Sm云K7_HY6Rh>%iSƘ l3ZXXu0"00/b7(.oJh -j⍠!JXdkn$w)w1h$hiO2숢qȡ>zL" 6pZ!+.Ajl&W6҂ `-U%Z־VS9DՔ1:;:1nfH]p>E6m@Cב|Z[s5hVyNVI!S*4*EN4u_iNNTV=&@t!CtQ.9b.\dpMjWJ6!kpN:%I 1dqѺq; jQ;]4 |WpP\?^>a·>~ٳg`"1q 뭬tǚ&}I; bWTm~>2j e.88؏|ZZZvvvQQ10 f3 n޼XZvvv~k SRi,--9r | 8{ 222 N8+xy@ﮩA Edp:a *<3ssX\q@C 3a(LfDbDccuN#}1b@IIIPJJ hrssYʰHDFɷ#R`B9 Yg:!"zzzwQ333`@|F{)+ƈS" ²u[;/ܡ@***X|}}-c4h G 3 SEf#ng^&x 36?~̙3q9x j BI*xēᇐ.n\'0aA,}W 1um8 aZƣ4l#k⑨뻽hs(̤B\fv6z B PObm W,R/}8-^lw 8ÏATedd!2o5DF~)3N=K-2G6%t]S fpv1LIENDB`grml2usb-0.14.2/images/icons/important.png0000644000000000000000000000514111153000035015311 0ustar PNG  IHDR00`nsRGBgAMA a cHRMz&u0`:pQ< IDATXG͙iPUGǛ,&$ ~͢MH  # (DȢ2*F7!`Cr qɸ|Xze]o=sgÇO%Sx64z4FcQ˗oݺe4O"#DT99s}|0isم nܸa%2FG4Bi47onmmmoo?!۶Uvr]8ts ;TJYdG >|8P=)9s',%13gdI4fqAݻ XcsIzE)LqqgϞ~eߙa1€Fco_WYyqZ#?WTd?b QWPpyt}s3HF66VACwpXQ^~A`4LkRϷB5t2E9hxF ,fsuU&2:qȑ+Wܽ{פ Trv63"b׮],___ooTq}d|AtSș& yyy"Hܴi,F$''GEExxxt=22RODԒH&߼y8?_S`d6ʳ_ppp^!(b,?K $qc=$#:&Fė5x9f̘(hxtҬ>Jzcp!VQL{ .?zT)---DU0///5Ii]̄dLpsۻw/WN@&Jbc8`n"%$$O>j@x;8Hvq'NyH<f 5K ҪQ锴 :-IcT_Μ:dڴiS,4p@ނ,9rK/ )Hz@pqqtܲe 6VJ,X0b)&&F=jƍJ=)/&<)dy0@O6[=Yts, R6l@( ܃%S]Τ"I޽{f~GMo)Hs(JpCvKQ~3 rZ{Qkݺu˳>>2+b!eH}byV;!Ib==5 "˦+i\\***!tz Uȁx!BhZK%RHd(ݗ/_ FId !j33.oSe_rQZ?jX2#glOOvGMnHL|(=]=ZmOw"#파+WI chR54LS0f}߻vqο ~~_nҁεKN|t4@63- ZZO?w/Z?8+Ky80c;_۷wfjB~ڀ#3?Ĥu0 ivv3kqLq JNNCCHdEetI4\+V3gOȬ PIA6o86laIӎ;+..ΉNGS ,OS/A @Dڂc'3g.\{Ç\@ΎQLRB^L,r͚5+C|Рw w-5I_Ӹts>|?V쑛;cƌy[bΕ8KH打+ n;;w٪UֲeJKKΝRM2%;;;##شL,_PP%̙SRRdP^b CO A)`ANL@yhW__Ī* %>)@$pHccի,gɓ'q{{2/ Xk .QK!dYj!1-{ u -e =K_cfa< 67%CL l! p,yџ~O-d)퀹FE*EW"0y_f hIENDB`grml2usb-0.14.2/images/icons/next.png0000644000000000000000000000242611153000035014255 0ustar PNG  IHDRĴl;bKGD pHYs ?@"tIME )(IDATxڕُU{kު{vbpƱ'1.T_ .o@#Yh2сapY{ꮪ{}IK:ʯ'2X@uu 4]T1z=k}끷@ H#8VEׁ}1 p5ۉx֤\amkri:ռbrbBM\W1K?ߜЇANnY>FC6scpy]z3/]bHz Xx^D2+})%c!#O1se/poL;~ubٴ1b)( b6tG82ҕ4}FfZS-Ɯ3ѰȦPAƉJ72X#f+@S4 In2:wN+1||t;=qє|Mm>P" Xbr|QrN/pڀd2%#$TK2U ,l̤h)-}qVį5RtcHH캢H%ЁVG̀"welpmY{R4afсaM l,يbcCϪO4;|f@!*΢+EILF}zV/ZaɱL&w͇/EPg) RJ4JF6eKF{Ao$V@X!wG _|>oNQ?  UT\U i[qcex1[0~hY3-jk$95,3ԔN.b5tb͎mIc5.lS`0Y\`|x-83-I 4TvMOγ׈MR5#f QSJCf* ]sl`Kח<߽Am& olduNJD(@ =7 sǁ0d@~ɢH1(lAMxv3eLN%{_9ExIENDB`grml2usb-0.14.2/images/icons/example.png0000644000000000000000000000446211153000035014734 0ustar PNG  IHDR00`nsRGBgAMA a cHRMz&u0`:pQ<IDATXGyLG^dA V,yYGk@1EGqfcdѴرIFS踋[wmwi<~|>wAA>Ԉr,Ȉ~zƌ~9>>ۃz5C>jk֬'g gϚ*-Q"`(zH/%o>S;wnxA7n(T/./UX8@A~~Dkk>իWe$w PXXP7:.W+S__o]v!hʕCJo߾K!C\ggeggfe ddsӣ Νxb+**9r˗/}AA!Ȝa]}mmVVV&`H RӧVXU͛7~۷s=z~puqe%p755nڴaɓ' ^+C?M`) ,0UPeeʠ7`WWd޽#up@1?=쌡evI =HJJLJLLHO.?TA͛3g(|Vw]zuɒ%˗/gNK|2s… z6J{79 ,qQ11QQ1|m bQ(zZڳgϖ.] _ǩӦݻwpɗ>17_~((A$<9bĤI>P +5:h#/_O:%##Sᆝ۔䲲/^(7550͛7۶m w&L AHHg5pUU,{RW9sڵkXVN.uV{$Kk׮yyy9Y!AP'Hmo7.Vh&-tYRٳglذA8҂Z0%{M۷l٢V==쬭|||0L?͸ ٨ueR Oչ0{>4TIܸqZ4g#88F5f?z__.:XZйU5]pk&RЉ=$XzeݝIllmm )'i\2sL vp r-0ax 55mmiD2u=V7W7tتT*'''ggeݻ7;''/O. ro/O'hRRVVV|^tqAVbsj$yO q \yA/ae b\+2G/Iޝ: !Lr VvR٫meDmaiii.aanxu'.E]N zJ삞ʈ YrIXX 0S^yYXhRx){'Ge꒾S%-,,-ħLЏ5$觩 .<?y|L^I]o>,8z M&đJ31gN$@)0iHA@5;'ޝv^}s%滊xw ey%}ŋt :(gk|@vD<-W;z@/\O\._Om7?PG|_Ŝ$U[SvJEiU# Ӛ/,V bt90դɁ~i9*0v`#Q \p'C0,He ).5\aBZꫯrh6O'MGyx fY%M/.ݺɣ`) đʳp҄hM:Nȉh׃ZdP%yigϞAP5kfp%UAjI8>CIUN5Yb,9N#׉rGGGZbaʮȴ[6-{jYO΄ɵ5>|n`oh,ѮL4G}9MNS۲e˽{Zz55⊼~/IϦuz;&{G'(/"Ou gDŽuX4U;M5pݺu@֭cq*_VXiV L43>7x@:kM2 C sb5N6o|]7ڰaKZ5ň슢39N + * R@I܀kA⚰~AB?ҝ 23h%c⳦ZgZ!֯_"Wird3a-!^H Q3DeG7t;ˢs5( VqF/_~,kK-beM98q%Ǐ DTd 8oeC5BE#<b0!53F-[EBu*DutmwpW;U';]+g EEg24TM^UWG ktk" <ª.)t\ۓQu5K եeW. RasC얊(fkq ΧheLk׺i{)m5v-|1.(tS/J $Ԝ#R܈ ;"iBbh,XJȦp >ת)ؗAIYEJFpzDJƁ6'F9INF82TG P[}bHЮq A_@֑@yq̩.\Na4]ˋhLkōA9ޫG8PH}%'>m @KBqIS*B0G l~GA'L(ơ+7 uU%LU0ԐH-I]24#阠.  P__^QJ$Z0U][d\j۴%v}]Wm :'QhDdRX+Kh;ͽ 8'CJY$Bo cӖY԰ZY4k" ., 2!0Bt>JHHHK ;-Y`|xCWiו>\fRPnVU=G2P[u;`at( Pyq(vZ:YBLc6#+J." rQ#56]@M NZXK/c5k8ۣ5w02Iaa&U + u`=liM:K7k~Lr(D(=]E* F0kjLJd8ħV! ]߹sg C㇦'N +Gi5CtA&RVm& (]_?/":'Ě{'Ea0˜NԀiҥ(q U_PwY̔cwp;}@P2e.Vp ,XԀە+W%91ΟH`c\x1[/ٹЧŞ(+Sܜs'C>?!%̻h"??*>/D"Qss3 6444**Μ9pܰk\>>>G 2Lܿ Aӯr4M`@B׏b!anSa,X,U$I=п;@лj% [PB ,*㱀1TApдF'F?O~̽s_Q,#IENDB`grml2usb-0.14.2/doc/0000755000000000000000000000000011671415215010771 5ustar grml2usb-0.14.2/doc/pycallgraph.png0000644000000000000000000046007111153024160014003 0ustar PNG  IHDR (QbKGD IDATxye'-+!! !$l$LOm{z~ M &:m4؂ڨ [ ,H Bš*+; BRo9'[MsϞ$nu U)S$IrNr̙۫ٳggill<<<L c1n|wQth7\@|%_|qf̘Qth7Jr\t:;vd˖-Eh\t:yv.QWWwH7lpI F{+g<p8UG VhE VhE VhE VhE VhE VhE VhE VhE Nyw\>2й)pT,پj{Q۳pڵ(pЪ@T[[Cz[vNmnTڣkݻwgƍYjUN93555EGsG[3$S6)%IUUUM$y`4]p"802ڽLiӥH&ӧN;мyinn.:r[9ĖLtڽDoZsyq˖<6~q`h߸0x*05F.:[֫WL9lظ1/.:r|2uEN̤ 8e`qd'gUY|yq`{/e_?W! +:a7tȐ466fE!C{P.y3G33⿌,:3rĈܹ3͟ :昢#@ bЮlY9_P=$c.Wt#n1<8~8l):P.ض~[ 20N6&|r>m۶(N|vG~t-8%N,KRQQS&ONnܹٱsgё@ ژWޟRE2kSٵHm2ӦNMJ̝;7w NN B576gާLcCcRtؘKsssёĔ(LG-OlɴoHڢ#6ӦMˋ[K\.:rYyާs SsTz̔SOO?NJ B,'ՙ)p; )'gڵY|yq脔hsk:KbB=}pqڭƏϒKvݺT>_ї28ވر#,HMMM4Htv.lX~57N?6㯘NttpI4hP7/l):rG\ÊU߄SR,;TR)'NL߾}3Pt$:82meG}rTTͪȔSOM=ܹٶ}{ё yҥoLTv,:Q2ӦNMMMM;7;w,:rG[^+KiߚEG02c<0wn^~#)p޶;^uvomfO#u85551cFwݻ@\arS}jn?=rVS[tkל6}zmߞKsssё@8lM<-3}h#uxݻwiӧ-[2S.@\aQn./=iߚzիWO><roY?gy:S:=}OWtNo߾:eJ~<6oroM9YeïeNi 0 SN=5Omؐ ro^9YYu98혢uz )gEE(\Y{L9c 4(L5kdE(\-]I_85ǞYWt`Ij~$Y0~=>sKZ~~3}ʔ3&?O뮜<~|fL;n=&LȤO]wْ=Pɬhr\.:l|ڢ#9-O|&_=\2{ܫ>QϬʏgky\,M̼\7IB97I>/~ef󫓲5-swOr·==r~:vϺ3GNGd7auuwdXz޽;͏o5v̹g']ty眓?s>[Ϛkִ̿nÆV9\q9mL8=fLTo7\tQ=^_zk 3fʏ~0 8sftuI_}uV݁-}ݟnק!=ko*gݿoʿQxGAܟ$I9L;%IiGffZj9S]Q}șVl[ͽ8IRkE_<ݪyjSܘܴv˜1ill?$.4eΝy%K.I˖}]ԪX9s2g_>\s9 R]1s֬_5e+gyf:\.gv۱?9-Ų$YbE%}Y|y9Vڵ9m̖LJHeYpn{_+G@˽/{n[2(oy$j1ke,ߺ"7sΑGqfր{׊?坃.He3/Rތ<kW^ȷo#s-}]x 80o]9j}4ͻr;̺pC>g֭[dȑ2k֬* 4(WOݏ7n<ɟW\ѣGh{.,=!=Pw"lڭ69<;@_2[n=ŲǏΝ;k9bkiX]^ց+ع h\Ɓˠ-ع h*N@\NV޽}9 @\I<빌c!{gsEt@ۘxEG7eĉEG\F濸 g q9{ܛx^sf¯'r\?љ.\rÂsgg937yW_9gp|s&M93[u65v.h#W,*XSUΙu;g]g##>y>uƏ2׉G0-+ȇs>=?i*7aC?d9˗-.UsdY~}ٽO}*MMM}(+bG䖍?ISi7.)ߘq/j^vK5/\?бf92rKٽ|ȯ,ַ/~em'E̻mg9RQ c?wZ>SBP}__};5bD>̖7|+sAsYged}}~/||жJr\tEGsUԞ̽~#2/jkӯOc<;Њr(ЊrV_t8,ra%o-)g}n>*g}n~{?ʹq~~Ysӿz.=՜6?{~>*d-Vo_w|Ty{z^bE my;ߙy;ߙ5Wt#R.:-y25y,~iqf_eKr>1{3O؁_/~>\pϝxVs~ώt_4zq>{_Xw{y%zj_a[`\/}o\ӯ^^5m܄^'eӰ!$sUkؽ5=*TO˃j7wӃKR]Q `4^-| ky|g҄ tɹ;9.I&O3gC^ e^FΜٳsEewy3}ʔ3&?OZͽ7Ν|eP>!kO:N.\(A}/榓$/3~qI9n̺|dći7g@M̺xƿf@MwυYq$ɧ]'|+}kzk;=:_l|1W,*_=VVo_% Kw$3Y|8<quя兗7e\i,7kݐ=$=zaw[^3XaC>|$u={$T>kys,iO?AZ lo|Ƶ{r\r=_MH\;||'̗]q_].|k:9T_|jթ9񿞔[AOuγq7ʿ_7};=;{u1:?A׌:l5~9&l5׌A}c$_|'>|K_|~vhC_Z>O{]sMn?jTn\}o\{eo}}I={ƍGd^x+֦_Hޢyv.2ZQ.2ZQ.2ZQ.2}hnJT.:@!bKKYtɲ<7~SQiGӎض2߶[jʢcpp }xs׮,Z(6n!C2ƥK.mؼpS|I9&ja <͛sਡ\;k֮K:ӧM1ikN2S.:_07oq1ʢcP]$;Yp#R.:,[<˖/O=YһwcTήv耔NM2ܹ3cnjq#GT*u%6ٹ 8N1/Y5kf1dƴi-:֛u`mv\~e@Ԇ Yxqɓ3Do]M.2۾}{.Zg}6Çgر.:aѵlZ@\tXr9+W'HmmmfvZWtêgMt@e@/fy!o=:o=:E:{VgV2S.:,}≬\*͙o{zQt#Gu#@ 0},X(pI>HG\u476igS*V@ޮ]SOeH]]ƟxbtRt6Qݣ:IҸQ 8uSUUiSdРAEGjS=_+uе4@G\nݚ fӦM9bDƜpB:W\$@GpTknn+eٳgN5+}z.:Va^s\56mڔ f{ 9R*Uڪ*Kisp)^ccc,]5kf6eJuVtvGN h6nܘdĉ:dHёڝٽM 8viΝYpa~ 6,ƍKMuuѱڥՎ;2])YfM,].]32ckv.2hhhc -[2jԨX^#@ (\sss\,WH^OO^uԨQ/*:(z2ܵ+Ǝ#R*uTQ`B466%Kf 4(3OOmmmѱJU=Ӹͱ\6lȢŋ$L!uu':UN/`6cǎ,X(dV\e)֭[ѱ:>5yea\/lڔg׮]pI>HJ~]\Vr\.:pڽ{w,]k䘁3a„vZtmo6d͏WwM˵M_He>O˵_NꊈI's,X(MMzeߛ;vd-)SO9%]t)"f6)U+RUE^8 եycw^={Q"r͛7gʕ-?_ ٵkW=H7/g[`έ)wq9u mD={g_QQaC}FڳGSSS~=/˹4772ӧM1=HQuK)^)IQc= KO+:N}sbOd)\.g׮]YgX֎ pxRYj}=(ؐR*w֭[ۇ)IM6eU{-lۺ5~dKݹC{P7Ҟ%RHLrq=vq,HCCC$`t5}OGqT*Iu@kU"RWI8Te@,]8̽inno+MMMma{~[kN wK)IӥKBpP{aӦZzŲU[[^z-qz]d)2lȐbCpP)<^**RnnNT2x >ԴqJWMN;&}.I2pT߈eСyZ~)&^ؼNSSS}d˖-o uD(Ў)@'/ѣӭ[ۖm8r(о/۷oo))@'T{v8{T*nȐcp:REWQQQt\@+e\#W-ner:3g1kVn9~EUVWOQ;xUmËe8w[n%0{v-_u6<~cުu6mÅkHcnrG71cǦ:ƍ},\ ƌikI`{9|x:=֜wtwByi-5 ]gڱc@% :r3O .>|9o[V;<8t}h C;B{o?CEq>4gZk<}hXL""""""""""""ZgǎC&Ɖ|IϵlXMm- كwTᄑ{t:uYc^mm-롇004YB}-5UVV_K/yݶ`O] mxLJ?j*))oE-v^v{q|7gga˹b$k<}hc2""""""""""""Zn}QW_~|(--G{I{* ǎ:|ӟ>Ycs;=|1=?<$$Iž<0_?3>s=zoh337݈b.5߳gI?#Zh;:Gmk4l߾ǎCqqqݫ}{qmy{)jURw_3\{}rx.4z$I""""""""""""*|##rPP*V0 +r+r^*:am\kqLzb۟?s.Dy:z(>7\ܓ~8SEi%-uv.#""""""""""""""ZzID" mmiA"?~+vrfi9FD$v.#"""""""""""Uee$ҹ6v.#5up4sBcو.?T{Hn eDDDDDDDDDDDDDkبߏ--rA?9g. 9C-wDDDDDDDDDDDDD3Cg/yq/$";-akP[Ujֱ_jۻCa[[jq6.;<|Nut8؎k^UO篙ug/A뱷oY6T?Q_l3;pnS^HD1s"я;Z=7~^/r|=ϗE J鳞ߏ/~<8L'#pk_ 8p5+ݷO.;xGcv?mZmė~eIw:|ƥ=8>cĽhcRH$]K 0 +r+r^*:am\kqLzMZ*JK.h!spppmeer@Ur@$ h9.#""""""""""""a5}}}Q[]n}}^~UUr.Ϫg֖ ظV#S{kQDv?-?;gsu(Zxz\}߇'pC_so]cì_|׼p//3{#"*D њ` |wxη_>|8qnz}VXOw7яp||{gճ111q~ Zj|`g>+ ŏ'o½>?}?vyqu?{ &Rs nhۃy +,{Jַz@Ď;fճa0ّh{f>ύXp VU{-:3S*ڇۇ[ݎ/c/׼< vi'<ՌF~?c"hZl_"cu{k>kXhB!o| zH&ӓ8:4*>Py4J >T2q(W9 g0P)T܅W'^;kͅ{׭cDDH-wDDDDDDDDDDDDDglV龯|?_qyoAW^~9>z˺ΙӟFqq1rG,.{'_={`w8p]wn/bf3׭ıi؈8K e~P5+ __w}qpwGu3}QuߠXuoD _}w1\gK~ti}`αX?'} IDAT.z;SuhlK~, âzgNѯX źb 4Y˪e=^xukQ!bօ\kWB~o݋AB%Iv\z) twP( ifD#-D"|Pa9VشA書ˇ9^b,!} r A¥S]Ww kts_|aїԊ?2^3 ؇7onǡ_ E2QXfD2Xԧ{?cTqhU_e^v3,T:l?gY+JDTH8$͆xҋ/ju{?xzsrzCC:]".};_t/g֭ıO|( Jeil翯4TK2V-nϩm+:,W]_zo?{<`Ͽ'ϼcÿ\hb>'(Iʞ~ӱ%4~U>X,/MQcs=W~ Vܲz  Q!RH$]e# T*:ó<ܓX={]';q]svg[Wg^ xf*ȱ؈|ꓟıc؈#ybVoO~.lil׾|ڦ-֍h!Ev;ò#7ys_J±~~/`$>֧.<7z Alg>溥?4*9Yxc^43\h(9[ʺ319z?)hق7ݗ'h݂] L^l:88zSY:5'>>R?aq;xy{z\UV ѪXn Z Ƴ^eT.#5u$"""""""""""""""""9.#"""""""""""""""""9.#"""""""""""""""""9.#"""""""""""""&DDQH$w)DDDZVdMTnpap@]њp;b&ޓ~=:$4*W7]Qژ&b3|Sݐ$ =6lPTrLDD&0\FDDDDDDDDDDDDDkZ$?@ãҧ40(5]&a6cH&0d"TO$ , اBgf BADD.#""""""""""""5%2]ơ*Ed F=*Nוb2( ]3,I^H Yut3P*FߏjJJՊH$@@AZ9vvUHN cD**5C.>%i w0HO#I$TI[iZ2jܨ,-Ѡ^{}W A6?V/[g}}GJ`1]ʼF[1͏Qm[* 884mقX, vH"nmmm0LØD =NSΦ:m6 B$I" U2A4D,BK#N,4L餈T"r*\Ao @SAVBSAgPCWCkPCokjjZ,Z-JGхN1s:L6Beh\@ZĎ\>PE8y==X,hkiᐵ<ؾm*.e^T GÀ׋d7doY*d톳 L@S@ D"BٜlaZe.#""""""""""":h,w!85!8Zo0k``rVJޤŦag#I @JȤȤDHD4bK3H&2H3HDHMO%raF 3F<`i]$ 8Fa 16PRVX &N QDʈ*+AUi1*KKծP>A@Gg'ҩ6oތښ5Zih@$4CZQ$ >A@8F톫=/H ;Ad2T*lY3(+#""Zˈ"`t @BpXP*`u`+12VYqw3Y)#\kki)DCܺp 9JE UCU]]U CM M ZX c BdaGNQRa\ #`&@J"T ,#>A@Ey97s9K zz{q Zr],hYTjvf5ID&'' !IZnVe eDDDDDDDDDDDDg:9 /7_ zj+\UVTX`tpl#iDgp b$"$$8i*F&[.fn!4%ΰv:XmDRVBhhCa(4 xp *+\ k :YQ BgP2B  $ $ L9DMw3srrƌ?Ro=3YB)&#^SAXY1V˄"23Jd:cX@VvPSFu .MW{vcc8сx<6mB}]ʳ]kclhwH`Ev$IDY4V5>sX*, "JLF#lSa3gDD.#""""""""""'0C&05h *uvT6rs*AgdRg$bX(73PuK3sj\3FktMo0ij1jlټFY25>SEl6xnxnm:$IDBù[(XMJY,}~eDDDDDDDDDDDNM 1yދ#/ "4G&Z./Gr7d@zz}&en'*ݨpf1\DގI`Po\ZViB fY'Dz n%ltk&A8A(BxF,Jt:Й \0chI.#""""""""""#Kh?ЩIX4_V++,3]њ'I|cz}1 CՠUT@-p(8yNuwj;A!\tǎC\%%hmmX8`0 gPT:_3LrD "  ,f3StFDT.#""""""""""/8ObÃ*Q,1}D+)10A@2`w4+v:W-\AY(ΏTTTNg&DD2"""""""""""Z[㯎'z0|*;./-R1:щ zzǃPU.+AM.~|Z#IV֖].˒F Mb8 APYQ榦0"Pjxn\.dxtHphpHx$AP@d2l24f42xFD60\FDDDDDDDDDDDkC*O㍧ $p;X{P:8ŧg(ȍtg}zc{haV7chbw$Si=C(ҙ \NJQWF"wkd D"h&4׳".;;ߏi4nقꪪuP$IAχh,V TURRp#E$D>l_Rt~V8FcE"*0 ʙ=hY޿vQd%=Ð0(w;QWA]f^ מt&.tu] eK#"8vlmk`Lp>A @Tnt}d2gad2J.hz!F"ZO.#"""""""""" /oO'P\nƻ?Ԍ&i"Aׇ4j]V#wktv"͢ rn0\  E`kQ[A]U%PXL<G{GA@Ue%9jn.[>IߏcǏCѠZDQ(Fߏd2 TYT]3$Y6gvAbE@.|fμ"ˈԾ wո`0 Bb7zDc ,FUzP[AH^?qz[[[t`%Ittt`xdeehinχ$ȈόD"j4pOt@V]暖Jfݜ M?dk:ܑS4Ȯ{Dt!1\FDDDDDDDDDDD'IOBs^Tlv7]c,Jg?Gπ}~RPWF]%+@D؝<0\vG::NѸe ]h4>A$ Nx<rف3RZV;+p~6F0GDKp/uBR4ig9ݩI !P.B}uUXLK\w2 Go_EEhkkdu CE?q==p8hkmbu%JA1?: Qa3mVq/L&3olzg2̯h4hdq`!J":2"""""""""""ZDO=o vM5:#`Pa +7: JUQ[^jÑdY475B eV(vAM8zdY#Hh0vt2شBDQ:FŐJ "7^dό}DeDDDDDDDDDDD ֳӯd[䮊3Cׇ@z5.UzP]Vq>A@eE2w!1\vI~tuuAbkk+JJJ.k] rA3A@(FBWI 4%ntzV,". IDATht:ݜngff3p-Mx"aåuZl0d% Cqxs"8,& Hp:,&w% p{;0654`SCJe,V h@&ASc#.`i~?|G&j6k$IbDD"D"NO$R јgصhcOquvPݷoa2Zzz>x f(-qLu(f1]bd2:~}}(**Vf*x Qu8zz{p8E J68| CvAɠdΦEh`6`X`6aZa1a`:2"""""""""""q耘͢ra0\# ma 124 PpFDZxdT^/WM$XWtZ-Z[QRR"wY-'0>>(p:(xPv|, ! #95bSVl:bbh0\FDDDDDDDDDDDEI<:9k>ЄK$%=0&:UebT$IBo_^C[k+pSoD"#AEy9ӱCJK|~ݎRǻΥCgӷyBgjjjarp{zw]m$EIa|!b2ʃRP(rYY1`hE6Ado5a8^8lmm]wʫBa֭\ea$ |b1LNJ N<G0Bh &6X``ZaX&eDDDDDDDDDDDYh,G-}A\W ڮ$9R ȏT:w=(sXdZ)PϿ$IB}]f$f2hjjBU%8y'ND6lջwnQ qxFgM PT㓓x[`SC\`0AC0F{’d  OaBٜrfZa٠j.Hn mT'??> C(.g7Z;N E6+]RWa6.EQ< 2 $IBW_ шx"|@scYfʊbxfy) lٲ \$Izu8t:Z[QR\ xAAd>߾m*,wCbf>&&'P(*)A` I"gPdaZaa`ۡw0\FDDDDDDDDDDH O`*\fhtAD 0R4TyPSAWK*^@"lj  Nsp /  ||ݵ``(s-83,*Yk v(תI& |($In7F%*J&T, Gzvmng eDDDDDDDDDDDI*?zZp5UrDd(|jԨ.wʃr%n8(ŗ^B0|%U*GEѣ~o vW%ce4ceS̬PBRe;waXƔdňG:ju4x`Z.dN_8h4f1fFb 2"""""""""""8o:"I?\-ErD<8(D0N**=,-J K$k=gR*X+d&Lg.kmiAMuBN:c]]S(Pոa2V2f16>>A@"hu4xPp@P]&$JMd2;m6l6 ӺpF?xfܻbF FWR%I°=#!b2ʃ*\E`~h?rfz%txW0>6ߠ _ϑmkP:3>t&B^5@$A`DDqq*)R8TPմ$@nT,LBPl26=Rsr3DuF" #tɋq-Sxv0E׋b1tO$Qd3cs]9JrVlZN  tvvv5$APd(i:q$2IL&ʡCueE+3BݎF#|> |Z.Y"J>(UNFj?qtJ2?NÅO #>bjkeDDDDDDDDDDD*+Jxx>\(†h4܎$IRDj\yt&Qt7( 崡uU2Z![zNKs3jkW":WLO<$pٶ[QQQ!wYtX,g_zBWI .ݱ!5*Ha<n7zOLK/ȍ K`1DQLNNb20$I^G\noGf3ZZP\ Zbx$G|)N@D"b1dY( ( d% QP m2TLˑN E(ua6Gݝ`Ӗ-h~( rILLN"JAP些9gKnv P( IJ=47_ha0\FDDDDDDDDDDThFa{!+JpU[]H-> ^xzt$IxuP`bXB@ei1*s2T: ,cH>?{wUu=$$ H-Vj k[mWjjj+Z+XS$ [oBd!l$$;Nr}~r{甖i۶m$,b)???W~|nnnlgiKE}Sڽ{򒏷;=oo  얶.F}bh:t)E9fFuK[EUMujjkUuCcb4`nyt?[eXtD:U\ mM&{xhbR ({ SSS|Kiٳ5 (Hڜfg!6m 8XjMf ]jhl9L,MM4Y4wƄLf4f;hV1d2iРA bQf2-oooY755ٳ&å2L VHpվE^bQ}}6edhxlFif,}tjuuJ^JTrr$ź,jkjeV 8P KA/2\B}K 5ev3 HSEk3jWtn1. X$<]ڳʫRkp=Cdfy{{]Txd;߶>"ŏ`u|||㣈!C$[rǮ]*d ^ne*afg19g( _,XfΪAŧO۝%9Ţ3ga&xY,Y,Rڵ:uT$Do(v?C)wctʙf&1eXt +RZdXd6d6evsl+77X,UTT׼򔛛&&DoòR{oy#5#^( p(4K#TWߠF7Z_744l]nTMm<݌z.777]nfMnnnٳgUޑAC**+LL_f|||+_??~榪 ZapЁ4 ,CL&P?O"#L秀^^^mW]Sڞ^e1em-ǿ١1y(2')ܡmv}Gdv-EwܼMGy&&%iİav_?`34ϙ믳* kF4iSTdm,s&uO2z#;Oikەty.eq'\~56: p}=:3 ԝs\@QUf*~]y{d2:Q ciJ61>^SRlM499YcϏ_~[}{-2Vdxjkk[<`8}N ҙ9ݻviيҬ3ۿXZI J?^k[d5jp-_L ,P rݺ|[526V/v3u4!1Q*MHLvޭ1qq֟l/^c֦k||NYglձ{ik;|:GJҭ7߬_<횲u#I+{OO=Dyl-uG6ב~w;bU}N~j=tcSϭ[ߗSҚnkoNR._ h Ow\?Mْc{RbrwX?yi%'|4lo}*˴2%I_yI/=?\ow{ l[o:m]ۜpJLN= yklt`u2Ut_}upc* mGӌiӔcgzHSSS56.:Edx4=dtwhSVZ.www͚9S7nw6t}|5 yY$]q;tM7ݺ}Fj{\k-hiW\CGX/TZZ~ں}{ۑ:siEh*}{Ejs϶y{>J;ӵ֩;F%eeigڪc[rj_Gk֨L?XX[23ۛWUwurzM7].⾥׶^V?h{ mmC]m>xe$iOS}`ML$.:iݶjr|oN䫡sfi9r>yǎ{KR zYUbru{uu-)h_r;yBͽ|/[|_Tm$+Kϙ#;5}n߱ѷׇ| ///͛7Oޭ_ Z<\MMMn+bQ3\4nT\U\\ܡq 7Cm_k[l}W~v?Yk9[ul^vSsH9r(׫FΓڮ[^;}Z݁eՑ:X:w .I55Z_nS٩j}TxK}s| ۯKmAڿ'SmKYYY*--yLG[w;VO'鶧*(8]^C*aҔ=G%<'^+n&Yo3ezdoY??|xx-9uvu/nZPtF[3/>;|>}СC!Ct*.YW˽y.ls+?~iXlHO$=W.B۾1g_njKHPPPƏ￯믿ݶO|P7xk3tsֽ=>lgl7UyY^o?w-v>}T^ #uj~vgbX {wЦ]yכ4'4r`׾2ִ \ otH%ee2oo c8uj:/",!ykjTRV搶]{yvGHm6f.?\.ۣehNRx?ẃ+лD]<YǫVOVint|L[gHHuP{p$ D}up6h]s_B}*9}Jf.)г;ڃ#Q_p$W/+=Y[]IFA'0'pa/<FH닙0Pc}VzB"5QFuߥ{7&Eol9-kZ'hnrfҙ(vڥ9g+&*Jf گWPRBb5;-ͺe Q=8G0wZw.!7wMxg~᝺[7ͭc?ߩ‚NxMrwoY_wT~^fL;__?j]x$tFHr,+~RKToJهu,h5lՊ[u׷fvd.yXoJ/Lַe> zHJ>]i3f%zuUW靿\/WQ=8GeN~k&^1T#&5^}s|z/:7]zUWX,&\ИZR-kҥzg_t,\?DzU=̅jo%MB/8X .r׬FW{Wޟ^䡺{^u{Q-Z~Xڹg,M#?U=t3^yE}uii/nZPO<ֱ|,DG;ު'~Af_Pw0 GHԗc,%{'ߩ۞!Ã}9e*,1: 48[cvIYk[/80[]S2ރ#Q_p6k3Ѓ*Jj{5bb`0 v) [4: v1 wq+ֵEpn+=N٧j`qΜp#ES_yB/8\@X~PY+zbڜVl)9}Jfŷ+[.[h-*?hMWtuZ'}Ѻ{^6.ǎW]h]}U9v-}UNKSLtf.V{oɓ;th}RwR1QQO?C{BϏ?nu=îR_>#uV]n۶MsfVLtuڇGNG_ .-5qrpk:?QХ:?/=ncoV?կP8JƵdcf̹FoY뾼#z_ѣ/ꕧjx sa}gуzv0^Gu8}i]{:F=l۷o~a=/"wW%MP_ow~#= }#e9;/>`s5ޥא$>tHO=d6ыɑ/٫{}$uӣ=CYYZxMzG1rN1k,NI!F|5u+cjͿW_O>֮_q}Niƴi.e~($$D3MӇ}ͽ :r}ttwm***{Ћ/9ǎXNzq8p@!!!z駭/u?΋VcQ{goߓ?~Z)]f3C[ym?3g;k5^3:~:iw|}i3F^?;1 9S\MgqD~SmYbVL' ~={bQ|R$lmuޱ#z$dޑ5W\p:8COB"gGzVjO5ՕWUU|~gڿg~Χͮ5Kugo׶|/[nyX{~&ŢsUSs [ח~~~*++;{\VVcZK|nv_/O-箻W/u+Z}kZx ڔѩ̮x }?5PjНw߭ۛQ_mgN({٫kN^w$i]ɏlz#bYLd2O iFGvUsؐHܺA;nPXD}s|z/.}:kHT^ }>~ܺe1kkob{GtvnݨFTǷ![']O>|G GXٟ}W9jllTr۲+o+1ϑڸa6nؠ(-]T/싎wVLLbrW eo.ӻCzw[,e<{O_o怈j}Ǻ֖reڸ\]VWWxPy\ ug8G[*;\Vxefx( *",!VԨ!mHƲtkrUzZnmt.Fg凇4X2:et-ʖdRUÌ@0 nR}2>9FʣqM6̒_fF.cpݠTv|q2@1 n߿<(t E%'Sn3: tbQcc10b1:+0 .ڰ"FP`RI)cE:uJN9g}i}*--5: E髃dttpzF7+)u#rFjlt1 / %I'5  Ԁ[_ WDנ`M&VEHgtN-oocE]!CB}}rsUpN,dt$Ba2`G5dD0kS z[T&%3S~~~J7:N+J4Ieeeq2.Q*x\4: \ ͘6Mcnjѱ}_ϸرkΞUI2shJ%#*8q8bYL.ѐAbtɤChm4px^$(,ɓet"#"TVVvOFGsU՞uz@ׯ:ujkkfZ+tH)$w,?vhkf8p 稂4l@@ 0@3g8e=5kתIcXMMef*l` 5:NfM0Aڱsq2:A;>Q$i1L&b Y4 (H[nՖ[U]]mt4ijjҖLy매㍎i^^^4qNlqlVʤIjjjҶL555 p(`C*?]q3"._ӦNU¸qӚku)c@wN[nU@@ƏgtRRTV^={p(`Þ/" /K4*cen߮g 3rY$%O$%m ׄ$)QC@6-:('O'Le))*-+5:9UYy.KNV?OO85Jש"2ph[,FA4kLEEFj=Zq***}‘GII 7:N0bp Wff*++t;І}kTJ<7773F3MSSc~~.TQ߯ѣFiphqz秌[UW_ot[1 T=EgIL0T5}4=ZG*}Z>mt,p9ږp>8lVJr-3SMёn2.S=54>(L& Ѭ3种6iǮ]3:uuغU~~~J?8V~Rݻ8@ap9Rd2R^\TV *G^< $ICjkܨh f!: ɑDž*-;W_Aꫮ^CF}u&,_ 7:!],ooo3r  Ĥ$uuuryzxh)rss;yvڥ+.\f3C)ms7:pI26eUմ9u螈뫦e}M}9l֨#]vi_j>|8^P3gf:MLJRA *ix#J4I7l]4q5Y,:x𠲎$**Pmc#j*UFLࡎ+_|=Dp%ǧQ`ˑ5-5UG,TIm IDATKmȐR&MbItP{ t$;[d6TXXhpB6z $em?)O7 bt8XͶg'2MуJ"#"~e2A}ɤX͘![^PSSS)#CGSsX (IǎZÝEQyy4Y,:QXhp6 .@B ?Pn_np55~xdш=dHx݇EC©)S4.>^rrnJJJogΝ2**t'ObHMMڔa =btYVWfM3ῐ}^c})fI>"(O!Aښ]ʤ t,???Km^f2)_~~ԗFGk̙цMw>)77:YcSdf z ŢmcM˅e2W3e_޺ f3Kci1 [F&1$f}@WDFFxn))J?^nnnھsgeL-**w>S+++S]]g:T>Q32Tl̶455xAA&:e>S QCF okY,]aoKt:[WV, JDaa%13L2G`M?{{ 9 .yG+f@cxi3L& $_/xyyi@PP˥1M&   .^b&I;wVeee'ɷ$tn@NKӰC{4W_ᡉ&(y$yzzg2XNe>>^ 6RDDDX6rX,jjjL566`:tid6l6kر6u|}| H5;-MCC%baL8%{]AFGAj0ńۿ_gϞm,*++g߾J]sՀ%ɤ5{LX Ԥ5iDyxxU̚ 2@vtODŽƃƫ llRԐat,O 8P&I&Ie4Ţ S񹹹ɘpI g&ӹFSkp:4Y3gd2KcɸX,S72: 2*f埲SĐ!:y5g2HIReeOVQqU__/$Ţڽ[3&8FuׄDo9~)y$/(={ب&E'NЈÍX1 gfN1Bb3k4:![>UVk`xy)1j׫oWkjf}9lֶ֗BCC1*))QfIMMMZٳfͭ8x7:K8tsF (L^v{K} 0@SLUT\r˫_?GW_2@uto((o/WTcGt I38[c?TVU֗Uv֗"TL@U[[]w+zn}?t# wN%eeFp ŧOKƌ#//^F9V_Sαc:%836}AFG N}V&I>>>Qhh,eJcc5j(L& ? @%FG\jtp&͍1: `tUL&ZqssSF@7qРAX1 '8&c8ltptwcat}REf2lap9[ݠ dt}NRY,E0WЎ+ ϨdlެII1lXgt$kw}.>PF=[5usr?e>'P(.Rp%O>~k:mtneҝuw572@sP"F 0:K|G%Ӝ=_vvRM3:C\*OwjGbzwF:4Aw`pO4Ytp 4:Kx~HWOVnϪy&Gyi-Λޢ$jnJVKͺzJ_2֯`xmۘnw|emZyu7SZ;sn*YMS?nCvqt]4glDEi̙--^H#cc y&MNN֘8;Ԏ$x==vD:ի6=q{v֘8֒iXDGkvZZsnfzn׭]Ҳv,ۺ{߳x"nemI҄D eˬǜ_7mwV_;qnf>\˗- ͰoTL&561.KT]ӹuwƛnu{dxjtڶ\-NKK(0(Hwq6edʕz77ސl>p3RS?[y55iV#ccUk֨L?XX[2fg=gmϢZ'kuz5kL߸Q-2l}S_ݩyyy1msrlY_p{];j/nNt|͜6M~CB4+tȑ6oGmѝ"nOWOsiEh*}{_"vMw{ֹQՇlso\GW%T`ɒE'd.yXn5okU+k{t _ ]14vUR\dv"?Wɩm9!h&O#w;/I&e> xy^rZ:yB-e9sws\MMMn+>d}M7߬[o0r(׫Bsiѷׇ| ///͛7Oޭ2l};ZlU~pm닛߉9,Πَvݶ_:Yg)66V' ?n\mtscYL@rp"FI07]zUWXWA1ᄍT>K]~ϊ3ں1]ì†Dj ڹu"~qlcjLdj}HT^ }>~ W; Ѫ+ءcbb+{r_ /RuuuEFFj ڸa?"^^^֭[[l_p>W3ϴW^^t PڞÇZ֎;Ԋ+ޝGUN6H2=@* R*ZUQqZP+EK 5dȾA2I&f&5/2{3gf>s˔)ufeoLv.))IK~ZR=_jl5^|f{M8>_zS7?hӦMfkHc?j\hSvȎsqCvpCBu笅^F]}K3.'*gu<^=xOn.}JMMU|.|b}\3zӼҲgq8O3II -4qx !Ն +,4T.mwss#G*/7WϽp*o5K7OlEdTbccᡈ:c7&\;WOĒ%aD X=ŋ5rDOvpދu{ gbWτ*ᢋnZ]{ڿY@5j-0TqnN\α\_@ou hssU\^p}> <3KJkt0XdN2. mF{SgCA3;wdp$p6QuNjFs\\Ksxh)ڌ} PL("CSˋ\Gs"W\3^ZR$C mƑgt0f[Bhӗ(\Tx 9_hNڄRPXf.ù},Sc0: L]ԃB k͉<p89O&IaC 0!E~_s5D~t\h$)]_~mUGkh0Fц+hܰicض7tM?W\h f~KcbrEvNHP\L2ĶeR3/WF~΍0քo6|uaILWta8EA5/{ݼS3Ru뵃uܒrte2+1QNI7 ΝJKMekkCݍՃp pnќ/&\h2!0pߣ+;Va5+5K5T^V83,Vٺk(lۙmۻgƍ_+Wjȥjéz|b=4{5JoT~1+HF~΍0ք2+-.SnV:2sӧmPeeE^MҬOu84Uc&7,mohYLظ8mܰA5+))IK~ZX~8Q_˖/ףʯk#k͉BkBqe&K3YןȾ6vm̹KzsqC5osWQ暞|)󊏍Cض?dn8Qu, 4B_} a4' jZG?4:V烹:Sbt0P@ou hssU\B~e> <3KJkt0XdN2. .<(.̔FYBqYE d6: e] 5:cxpC '|/Fs" (.CEpf.s-Q6wx=25vh:>w4zFucז&Ⱦ1k(e%71JK\NNN5F).&F׌Mꗕzԝ{Mj=uŐ!Ch;#mh+WC9T_^k uZ#gz uɀݑ[]ϑ4Y9>?ˆy(.cxet(."-;s;2j^{mΙ3y}ImXBa&]G}o[~nWkS~v}a'.PXLjFI҈DqJvPۏ;&Sݬ~#Uzl٢ }ElV cbrEUnQt颕+Vhۧ>4o_]صiSuM7߬_\5EB͜1C/JοyyyW rhڜ X?{U_շ_CmVXn nߚի<#6*J]4kשs;^C ΄j_s}~Ts% P?9e*bIsl ^ť5g%I?9Oo~vNHխֵ68g{[}OA!cҕ}sIjnՐ883Ғu`.]6v(rޥMO\h;v}mՏ0_Kܥ-$__ skΟgʯ/$}sRSu2~~t3W!!!|`=hWjzh-OJR@`z~;*((R\fywi…׿>yyy?1QK|ҡY_gO]9t&']t5Ek~jyڵkBBB4B۱OA~V.m\zGjF~5ܯ9??h(.c #0\ޡ;=׬Ԇ+t$#Meeg}JVz'I:^ZbkOMާY$L&vGܸzLEK_UNqv-Hj+ O0M+_}᭮6__J kQQQ|O^s)))d rVX4T~W_%%k}0v~wl6PfE Mwukjڵg^޻w<;ƲSИΎr<$9t^_R7r<<5\^yUEDF?۷붩SkY4e4-=jրٯ9??hXʎW(X#\+#-vSDv~M;٦Nvz5I?W}Ҥ4VDt|y>>]nв%_t7r={oTEEJJkqPA?^uo;֣w-Vɢ;g﯃ɶQQQr6}mKJJҧǟ8_gXqqqz{+%T~շ$UꭷTVVZex|~OjFV}ڇ|^jW_3"_(..֦M46p/:(..QsJ9xPz套Y{x`j>Z7.+pd:˹gbM4Bz]EZ I҃&7s=0}.ؤ4VK#:.z_K?~fg.9cb=1n-E/8v~͹{JSBo2ڦ'.s_}B惡Ol[X#GT=?ڛ0 IDATO3kyR~O,Y&NԀי7֟.}JMMU|.,wީ%O6: _):8a2K;Z,ж{1 M竼"UZF JLq/WV 2K*.%a Jr EqRx3h{(.r8w->*(*Qjt(Тv p)'J+0B>PEQ\p)elϲ8w-b#EqƹK^hsv p)ejϲ8>/,2: hQ\Jyy<(.ùoa2meRv\*.Tqq"gZV)>Y'iC _$DIUUSzިPD*+**)UQqJTiJ;rL_X:~LqQ4zh_C@VRZ? yzzHKJN~'N)O ^hTp>zM?=c_266 N ~I&IVkR2j[Р}{e>\g[ZơZ"$8"AםUo#e:yҪJUV1EcpPTDߡQ\pZQvOEy.$"wyn ozDE q,-\epY;$¬.q-(w7;f&cXL-b,{&77DElPp څD&<#gUTZls7)KbwfIL4eNq21TEU$&&4_QBV;PpYsI&ǀ(.8#k|ɤ@x\=ϓLh@D@|(kcLbIL4em@jqg'cBe:|1,(@\f@Y;URd83:ipzsaL5mU .oyV[NIUdULBվ];bs z\!]ͤ!x\B]VYYi奰ҘVIёGgFq%\зm2U9%1qnL&]ܳtdR@}Ҙ&IMGq%PEa$wJG$)8,/O#ѱmNaaMGKZuS%R)@f;31=X,mq7S'B'ʌ0?*CsWw{Cpzf!Vk՟ z7?&sWtԾM=t PG/*=qBGrr0~˕CGrٛ%Aea2&wѡ+4fѡ RIIN. 4ej (h&aft@L&:G\~.dOh>Yps,BqP\hc71>P%-2@Ga K0e6o}b!ټ%ihm]Ƣ b~n|6^iĤ}cmeugRMxn~oSq>s'?ԗ4|cmh EڙՁG #dN5ύrhܰicoxcLK#hSX~UcMDֈowv3㍺f`>|&seY%kLF+]֯zw6U}/ׇWjj5Æi{x4M>-|g>ѶwTf~Y9XWZo[jK#j~B:-s4cddtc|mCz|FŅ}1٪x?|07Lӭwާ0^#WC-yHI+7KS;gk7Tz`];ieh%wҽF[QA6{WcLO\\-~.]}ݍM푹i͆G;K-MJ@OU׌ZGC{keiuP\h1]J ض}s>ܱBYi*(kz^&n<='#{'I2ԨoXl yF$,I:Q~KiԘ0N^U9t,T͘XIgBW_wF}7Y WHF㈔{uWóv7ء1b/PyYf598UU&xnjq'N}/e4m\^?_%>`ѶQ\0;ۓt('Tw` s>ۮx\=7lh}Rm+. O$I5&ZLUc&*yﯺme?e%+<2V$_5ןv?0~ڵWj^j+O;ȘMm섉;avvteqqdboXΝ"-yQ-|zm `;-#'{@O8K;Y]#sK%*3/UA]8ϟ ՔڶOHs$鞑IqCvpCBu笅^F]}K3.'*brӞ1K9I]Eُ?YWU3#U9_8XF]1TWhX.X`Ǟ\9.]O}kh?%ժ?ᆱ]}jޝu>2䟣EsIѡSc1y KJt$'0`NFe2@0vYx'fp$pE{ם_wTء=tx'.hɰD}7987(. 9UٳӟZ(% N_ޒrpҘ2$ejK=mDLJu`& I0:Zi2:!ohޭ7: \hAy&<_^m+41)FX8FS_NЄgb4! ->1Iq96 ]uq^_3& 陋bauύk4nXFѴClZ:s ut+tALR\u`^7W4|Κ5Qh!HVTXfг/Z *D5Ez w;{Vս;k[6*.%a҅v̷wpFnvT=!%ܨ.]7u)0{QKnx_w_\m{CbmӧmPee|[jfZs,߮3QϽxd^^v*Z'6.NذA5U_HJ⧞[;W;aֿl?r\e1gnѶ1sUsSz_ꥏWxPn*Ic=~Gth?1T9)/tgc3Y0kSZ^-{~EJf]OTŎm*~Y >~ur/}JռW\|VIҢ'Ioc窣+4,Ts,lLVjt{w!C@+wrx7[vm]u lh’5: ,>!8oYP eZ(.Bqଌ]nthÆ&:u\Ώ2@h"u_/7h31}c[d=j&<VzMbw}oЄguAj7$ejK=jmol̰%Іu'XKGFШ͚rݥ/FSL_lСֿMa8ZnvyDd]w(uuWRFkj[6mXۯKDxZe8Zu`g>1sDrϺo+ZuM8K~tjc={5zߋ쎓vlVl_k{F>%^>c0l^Y7$M{KkmoL"-;s;?6Ȱݖcὔ[9_ƋUZz}=c{fyBo۫;['P\i/5%zjaͼhK-^:"3ߛ窋Ykƌя{j5Ģ[ׯmwn=KϨqCˣ ڐꂯm?`i/_[&&+},\{n|>ܱB ֍累tǫ}u ]j]/[ [ۮs<=5"fuc(ԳFRVx`$ Jr-Cm)/s4fgQ]uYۿآq4~E˭vIUY#hOgxp}ImXBa&]G}}*WqT_ҮMn{WɷmWц՚@a#l(]?NӮ=l떠_~VEE2Lp0?+*6^VU9ѫoꂯg(Az]ϷnOn1zsEu8]"5ey^bn?^~G_ԹJ]Mj]ooׄ'S7|kj[Qa9CϾ\PCq]t]G0:@Yb//U;>1Cc(fZuf|VO)_OzNeꞕuu祉:ΙW!g`=:=辿]g$e$s@-x]0ơ(Iyz5}mE "I2xAXϹK$醩h[~AMzQqiѲ/^cvSIU窋?~ՎJKMՕ?Wӽ  ѕ}O!!3J\uCs4)I>V]3sՂY,U-f nQ_=2o.XkoQAAV]O|8(.'PZ\e䟼(+@'Jen.MHnzD 9/nvԇ;V( MeM>^U3$YeU~%}n$$m{Ckg+͗yN-eVBy{YT|Vu_U$νi}{-\7A/ݶ6GƬ1;Ci)wg{6Y WHF>jGWz*Ri't*Y^s372,}U:E۵ qj6_aVxx3;[eݚzoˏ;&jhRSR4`PչjJsշ^_7WPzZo:W_չjIɩsiflV՘~Mm{wZӋbN'ՆDzЊTVXu4@|k~ڧ 3h}OSg B[ IDAT`5:lRmm;ۓt׈Ottn^߲_@yWkIR2mq1'fn=_:VxHe'jo+#-vSDv~M;٦Nvz5I?W9gXqz5t}khYҒb}Mjlwt9͞k7_B%%=uqPA?^uoOPYQ/|'ݲZ+kPC:q*Lݏ۶mm IIZ`cgXqqzcIKמS-yqZ-i۫ԧo:_SgnoJ=xPz ͏ Eyǫf!;9#YVj TQV)7w;eQa1 SXE~޵q31}]X5Bnz]:d I=#c=~Glq+KTf^"hPKRYª n|pV}bBk^jtL};Tʱ_MFP[CΜ\3{O!www.u"-y*|4nspcwR=H**^s!#d_uٙwΘXO̽[{@Qzh %hݓuP } |Y=yZ|-y١ܩ{U.4I,x|~;btm΂]wjOknzź[ׯmMGB4Yii7`xzY=#V UU*+TYE%I姰h?EYeQHE->C>\@S0\زkc`@SHNa`ᝌ}ep-QVV}PVyx)$Ңh? ;YL'?/2hf!;mY2I¢,:}BW&782Ҫ#LͯQHU,Yv (4O/PhEaQ~jß_spRIaYȎѴͤ ˣȢ#1pAhs*+:^`,35_Y)*)$y!OϰhE+4,/w#h9pi9J)UVXp¢-;2Na~ 谁s'@?gV0(0 @^FGpp e'*t4P)yL-8eJ $I SExF)$,7wִk{_dj}$ooYoS,YfLP\Xܬb,dZ)*O/wDZ!OB- 򓷙Y.UInFGR\J*<$Lފ廊>:~󕛟|ԞUYY)///+$8XBCe=Ь2Uhers}hk(.j)V@VoVjNK&)0GaQ~p`¢, S`f_:D2uVŞ(Y3B& .-h) )L>gt(.< ?.z8ЬڵSXhBCm*+/,Pѣ:v?$oo(4$Da!!j߾C1U0S oɷ\Ve2"KRdzv& éL~Y,aE@`ZVжUVX}HY:̔e+h$¢- SX_ϑycZu?p@GlV\l"#Ѻ~o_.ԒG=.P[WYQQ'PJj*+PX5yJeڊͲssUYY)٬($8X^fZ:t$'s+˷B} E FS~YSRt 0:2oʒ:*6:Jfo).Т+3,d):^JѬh:D,&/谝FYYRRSu 9Y%%% U縸3U&{Oҥ TpP뚭tկwk2rd*$8XԩcɯBǎe+Qe=|IReTVVJKK!,Lcc򭼼\o&ww Y˪YVm_PKwFTKaQ84IRtd:b6@qQYaeVw\߮jYFYag,h ud2)*2Rqqq2e&۾Tu1:m[he}+,Hf۷W\lb٬p'N0LIUQQVYLWǰ0(( PnngoNG]* NWV^/m_rݍNJNI***VPwS0CpP\БyL-БUEd2 UQ^)w7DZlEdZ3:lgZʒbcj"Ls}}uI~g=VK(++gvivjEEEڟ|Ζ̴ehHssOlvL%%Pp`B~_/($8ؐHoۦ`o^VUdj߁:zTf__wSt+Z@Q\qV;Th+ ;r0_*=9Y@;ECLUY?w2ͽ9rҗEEEUK_*,,)$i);'[W\vڵsBÂm DG)GqH%3C9%3O8'󭴴TaeaQ2c:vLrwwWP`B@@c_®];;oWxuqH~A8Դtq1:4MCq8U@ef# 7 ¢,/sVXTd[jږF(ߟ~֠bt8o^[QF(5V\LbbYo~~''+-=]n&yt[y'+ prVkVn'my4Ǚf4N4;ofoI'i'm3Mm;nL$M[dkK$ }@H$sxcÏ:ϳP,$LL;d2uZZ[ڊVn?&I8tmƻvsؾm̦2 b 1J=v۲|r vS|R72w~w` Ь/l/l3؍l M ,Z qۋkv9w[t;3YMx.T4mCj8/-80H_j619x"LNC[}+Z:_PG1׷3u V[rD$xG0p`2ZBɴaB"""""ˈVd,qW>O&sE01E.[L.FQ}}EfYr9xp:ڊneXr^=x ߻g>9|RXA?!82$IŔLAILbZzmz=Zz464gϝ@?ZYgIxp 9ԒP8A#^( جVtD466V4"""""eDDDDDDDDD+T09Sk/}Țuddm*WNDNnIdnZviw3MLаCt<Z=v.˰ї:$r<R4&L&D IѦחgjj֟(ɝ݇Ύ%R> R{!-߽:Nrt!ɠ=vZjFDDDDD7chKų/{w#kl),u"3jY͙Áq "Duuu.mQ8n9{FtZ*`CoO76[Wr Iu#3& 0b2D.R^CNVZD#9v ==XvmUꭔh,Cb6M]]+ PZ=v;̦e#""""Za.#""""""""Z.x>W&+L&-J-hKjX>/Fhaѱ,`%CccZۃ3gb};YrJrtNn4fsLÉh,^n ]U HH4@)l LB(evZhnjZSmVXjh xGGT(alv( pQ-J%]i91E6L.@\FfUd*?_.d3|8fFvi.ՃPWW}{WThns/~յ5t2(J%D6QDW1Q_Wj&L'HȤӨknF$A zzz:Jޕ.^B__պUJ*UtM@ΑDDDDDpQ5IX>O1@sGD'M UP(ٍl9ĐÁq&}9So?]N 9vt  Nj=|8ND"hZtl0ud*Udсn mmX½yF^C҂|>P8@0@(@0Tnji)t::U-*(I?d2ZB(ő=v&ry#""""ZM.#""""""""Z*d܉.{ȦdӺb̪uqVB 9D"t 2 0Ny{wDG{{˩t&JݻXp8p#V) bD JBMlb;9].;vzR)B!LP(i5iik5 V tJ;U8nxGP(`Z`VtX0\FDDDDDDDD$IBȗĸ+ 4AԍIYDѢFE$T \.Nt.rȧVEc1v0lV+ݸ,P(CGnaӆKrNI0t 6պ$]B0NGF f3vT--?w DZkgA$ h6 !!A$A)JZ:% ȱcwܗT: ˅t:Ύvt0Tk pH's{3Z=QdR9]GڭőS_6v[YNBYWW}Y___ҖL>ǁG ɰo]a\ܞa~Mܷ};̦'r!Hh0.hooJ'l6 ˅x<C[6:;*SO2C嘹8P(`(`8X<IP__i5ڪ޵ FcUkY*(AU*92.#"""""""" y"Nd>OA_&EieiU E% B#^/B0 vtuu`y<^< Vނ>hE=v(Ӊr KqL`KsNIߏ!GZC}=6DeXBE>C?řapx؉Z:KϜ=1?opGY趉@DDDDTA (*u#sG0ލ,,v#v"AjJˣ/ :K/u:]Kao:@Wgg˩Ipq$I?ЏOY0:BPհ"& Vݭx<ۍ\>_k.#gΞ( L6P(P8P$`(x"IT*hfZ+M.ѣ}Vet& ӉT:v#zvڪ]rpn!bZ'(]a|IHF R'2 FQ Y rBp8BP@ZaPҪ*Ճ`5M.ҙ :sG]n7n7,:;;aЪWB(FA[hjpp/_Ʈ;kjd.C8-Ռ GFP(HШUЪ3J Zh<.lټyQILPT`1v1\FDDDDDDDDC6/v#D0*tGNȬjJߵ&2fh*HїPvfiUQPGgRDqmC?~C.Q_WQaE4,Xj p8\./3Eͷ9>>OĆݽޝBH4Zp#  QQj~'Ob֭͋4p$A## m;R 'k 8VWVנѪFnd4T: ˅t&Ύe9Ξ0 qIlp@T6B,G^͆N*4R4\nOy͆vqhGAgg'nRO<@$E()"XMBZU -Kp:1ZϤe28n8.$S) tmh7*6hal&]a<і(R, ڶ&NdF :#+90:: R jMXjΈ׋OƮav95(=vhq[0ˆ A`1`U$ cp\hjlM!Z-/ujd28t0Gֺ\>H$ZI3Ip1i(iِ `-U<""""Zp-$|c-cqHb76s E V5V5:-L>N'‘ 6L}9xhjl.B0*l6,&Ӫq8].9tvtBZp5$I_uAx"Q E嬾N#ǎU};vT0t$I0mAT4""""ZpՖ\(424r],tMmEw%H-r:;a٠]ZM+ 8p>nP(H$b6Qyxp8]C==Xrr9D]"ds.gMfhk3jBV+oӉH4 Nn NgDDDDDE QDi(]b(%(h3 MjM+ĸχ(>kyƃ\rjVA066ӉI&11pୋچ@ l]ahh^hy(Hr9ԪXMj \&&'1tbtl Jh](n Qsd>wqe2[aY0jۛ!a_S0b8Z[[a̛wt'Na6uULrrdn4&ǡ#Gaw: IDATDqױnZE6{Ӆh,Nn ]]]Ԭ:(lقD2Y 3 űjuqĦZ UK˪ܕLttNgގnP҈2""""""""Z\PHRlr؍L`Qh)ȌV55[؍*/tbxd$l2nAVWe'HՃa2af$ 8].V6MMM'M٪Wpb8|0۱}۶nU2P(aX`hf2 :UK v5c,f*F$A()u;"P(@&jiYcCC*$xF1pb2@Ks36Xf%"""Մ2""""""""3h9@VkF"R섢5cbU }G3drv#INj'&;Q(pH1$v#UfCgGǜ޾z߾=vh\kW&#GPTo߾[vJpypHR0n>#HC!9zkz{{ny_IJJ]΢Q$I@R FSRCѠyÑN v DDDD1\FDDDDDDDDg.&F(%2̪rhQ]Te*drt6 ÊATڛc;% Ĉ L (BRNoV1+Y>cǐf1ׇ.$u?1zDՊ W]N'.wd:aaDcQ r94jt-45j jՊ f9= 9hk-H::!(o""""Z.#""""""" y b'rG4Y[_B^kndT3B0F^8BQdjxGp>tuvTrzpQaEM&( W(pb?п捓'111w^pp{<]u]^N> ؿ "(BB0B0‘(rAZ*v7SkJ31,*.ZgKDDDDTC.#"""""""Z;' p\r ]-Zm٤f72=BQ8NAU*l6XfjbDQz0좈{7nv9UFp0<<|SWlNwWfs8t``_ʅVK/cph{vB[[]/_(t! B(j1|r9<|uuuطg-Ǎ)IO$ fppLqdvssjM9th}gD2 ˍl)muuh`h+%Js;w@ggM/d#Y4$IP*j5iik5hjZ>P8 l2.ZӮ0# -GRAB`,~}';dФ+v"kiQͬ\z ʒD$NnGWgUI1\r{vDScc!.}wh0T+Ht@cc#DՊ% ՍɓXn-*$\t T;wXZ޾rwDFqtcmKZS wt @fI먆scdd\~ÛgчޚD   guuii5Z4v@>32 UݥM,cHV%ˈj]*U <˜!C&R Mk٢[hp\p{<0uunC Kӧ1w+q$ ڰoϞS$tbrr-Ͱ쾲$I¿ϐd渇@Bow76_t:#ǎ!Y;iK]$Z[aEtvtq:}|[~oZ%Hlk{܍ۍD"Q^O]'ۍ7Ϟtl|殮.yVdoݙ.ai$A 6nͶ-q.T F6 \c'^q_An4b};&3,Ο??0FUՎ\.@0@rJZurLB!8P($`E:񋃇f ػc[2"""""""" r!Ф*4ZU0Uk>"[/z $ v & %@?drtرu 8zM.> f6Q-o9 |m\9CV/mq W^Ar@a۶mh^ASI0>+3jk{w>8:6!ˡ0Ko+i]W#ID0b2$d2Zzmz=Zbp8]p#Aܸd %^u@""""ˈhIƲy]aL ǐ!;#-b̢Ȉ+xʕ9of ۶n]ªh>"(^yMOuUڸ~=z춪;8|>?g7zK`}6O<U\\Q jؾu+k`}U›g5<<(P8EQ_nWŹg #o)a2,&'Ckk1p/$IɌm7A(vqFٽv}Im """"""!N_O G hjѪUe-[$s \## WF 1<-˦ׯC^ݤFƩSML\\q! \M7NYbVYDc1㉪,ˈ[U& `u讑U Tng{S x,``^466.QD^sctlLaMooUu KOP@ d8rѦחiT9 `wܷ:׮ B&sQxہE|DDDDs-+\!2;x8 hhQ;jv@`72R(pi6@qw]*L?@F۶BU#<8s,,h=tP-;rqe 9HitW$IK`֭+[.y_ G5)(ϝ?|>$AVc@Z$IB0d1p ͢ND봰N).\+C呸L$`M}n ۷nl#"""c1m\%P[hҮ1r@ >O>w)H`r4B^\)T J!vMjydjAځ(L&A\rFy3\_+Wr!BZkիڦbnXg2 B6l@O [H|G\ͮ^wi}ZCvדּ$I8r8&&'˝mܽ{&VR&K111@C \  Ih)lV 3( thkmA,2t}ϻvY(n3oVYsOEՆ;ܿn2"""""jv Tv=u[uG%UZ6p >w$dX~uk#V bhUA|y|H$IBjA1xbJJ bWgGPWZPI,/^D"7v>bCP@TBYZ[rf1رde ^A"dž͛T*] k͆Z_a\dY3dd2Db1#99YdYd2yrv''1rbE 9[-sH4@qf0F,qslL W*shj3"1LBrrgsfsf]~ۻ`X5NזIE+ """"""%Oމ"0T V5ksլyxZ[S|Zk֭j$IеQ4"3L5k!"LT,_CӢgmm6EieKR eSӜ/ v&]k+Tj5B`KY**Ex<FIB!===ظn-:d/I$IZ6.#""""""Ȥrٸ;RNж5(~O'V5V5tM-Fg( rjqATNHj9hi1ejL&+4% mFcXUFƋ3o4|~lڰ pI%0 KPߨѢ¦> 5 g """"ۥˊ$IB(ci2^ h_qVB^?u@kl*-$6SHM!tM0ZԸw8Rք[L6#""""qW#QZ;[`FkqOhUY-Y- ~\:@5DDDDD Q=.9M??x:Ь-Gl'uG* 8҅ ORA 9 01-DʁX( hVhUAЊ`Q`RA-s# _O??,"0 27T*URzq|gqqm8 ;""""chpU%jz㓿=lsWOT9P6].Wr\ԍ,;( y r m,jnj-j4klTls|w=WazjCD5`a=_e5Y1\FDDDDDJMȪR!J&kŎq pC\@ ?IT*l1``Q20k/ -`jc C+|B1Y91|pj܅\#DDDDDDDDDDq1g?ۂ7x\jFͳ9gu8zn[Rfrx\ IDATy  ħq֟vnߎC.2Ulo݊nQK/߿³?C/^y6oƶ-[pfcӟ-S>q^'qxx`זؽu N{zL]s^>M={aS׌Ruup9l)N;];e:˴kaǽp=赘g<~߿2vnٌ{D?ۻM]sZu?MkzWsnS>go|]*qU/]7gwǰq^0u=]Xco?1l^Ӄ~ט?/ ߷GngfݶvG皺}k}V+v.#"""""";{_''a7n*Gyg\Ͼ ؃O؏wn]3۹/_">Kݏsz|- : {-kXJ/ԂSIhlQV*ʗ?7}=|~woG><z 'z9\.F6E:©'|}+__:aƍ3nD"xҥ?6ߏDk[裸288ŭ~M {<ߏ}'P(p |~ǁss=Z\ԧֆGwq}cµ/~|} 5|s{{|#^v.Qho__/V]k_ _Ǟ}}رi/6noM:Ǎfoxأx=w'~O?9u[K|z9'g^ϼd|vQ!76Y{Q / zW>J|au2A& nݺ ' AK-O׮GR93$948~f;8BP}O?A*{z >7K$,ubK& q.Kx1<<~燏A&/?q =?*> ;_Xsc5,-X76¶[cq} %D0abO_5叾 <񠧷?/ny?|y qcJ%oߎK.l=Sغm[U?x_:سwkX`٠P(`2_ŧ>YC=}O>DՎ/|x7s5~?)l~C18рҗkK<|xGA"' :ֻ|܈f\wKy|+_~oi7z/}y;o&HmhQEVqºq +d$PXO|g>y?ŋgOWYƒIo}t">gpoM]V5WM$1-^Sej'ٹ=wT+eD?)b،`k--[6mB*Ev#kǽNEon4^TA;"""""ععnN;Ur\F˨Vc2Z:\FeTI\FDDDp 3݄2"""""",kIDT릏k%ѝ6&gqDwj¹F)/5Y/Qe0\FDDDDDD+B(ÇtS "+~[6q/_cG>_% 2ֈVDQc_(vYBܸEE448aE8v ?wp}eDDDDDD(z}/8^xx[">o7:Gyn"Ν=Gzv?s/۾u+E/x^~6o]L{JvYph\_{m:c}/cזX+xjt$Aعզg?5ݰvoۊ6?{Wy QMUIS%^!bv1 $'` tl̇mځ$di`*.[uFݖH>|X]rH5֜s^=3yo5cDu˯Zv/Ӊ̯QECiBdu]kȲ듏>i6a:M/)Mg~uǝˈx5UX8adҮ|w1TՔd]۟s+K4{hܹj~bsّcPZRkǪ˞z lqIX:qg-??e=n[Q6zvhinAzml2d~}O?K򫿶`~z/Jf_olق /O\~}~M /Wm1:""""w.#"""""śƗ<6 MXrK3q:; ׭o/>[]Έ貽y3~A<#HJNƎ;7mŠ1{E]BDGEuۋ r6 mxi3] #$' xn&1kסQQxrA]hb<={陙o_櫠@՚įZu%׍_׷׹z50h(=f<Ѓx;n܄;W,ك˯,E%[/"""$ bADDDDD4 C7s)bA4h p\bA"Kqq C_U̯1!4Tnhyט?4EDDDc!$"""""""""""""""""X\FDDDDDDDDDDDDDDDDDD=z`qlAD6:/:I/B/J /"""шeDDDDDD4(Q}m _8\ώc.+` ~k` λ}㪿^I) l+^1[Ev]qŻsn1H|QfZqӒ%LiجK>o+`LX`?ػ#%b4y٧v;t_ t)m!QfZoYt %(Y{=߼ 7^; v_o 7\{ 2&,ֵϻe`ldZ]1ipHf,AɄ[ɯλcPuM3o9|;j2byO{\Oohw!|{BL-\/p٬V|;Ki6{|?⺹1. ,\L K.םv=^ϑCpӢ4ߖb&z<3&X\FDDDDD4 J_W4`X/ƚヘz }c}sӗ1;fs}d4݋߈??n^c?:!] ˘]1"jE^WZ ֯[K"7?7|3[yO[osyyXCxXaA^{MMCuwj<+_ͷd J__P6uiRǒnƆ>xq2/< v~[sXq#Nɵ5ײw|}!OSdsmLԘ#`pXÐ_?7/]W]15e2?ӵ|^yn/7قB.v9vi8yX稼.IDDD$& _6:|p;~DI8fy@kՊWLK>YـoIG?/ޚo:9Sߙ6{ؽy!Q )qS8SEo\&݁3BOsLKZql? Bc]^h0ty2q"Ly0ud$Lض;h0+m[be1u*v}sqnۿofϘ cƊnCPPnd}w~;CP`)hW|l / 99N̘1FDDd2͛λgܱ3'MĬɓM[~v̞2f z8m%&[q۲e;m*vwʯ}p:WEo|ekެ#xwHm˅I@v9fLDV+{8q!ԹݐH$nŵ? O] C|nŪԘ#M{ANݍv؎&bf<%l{Wow')ހ;o[)x?s&edN_QRZy8G~w.pz|/dt:160>o(_un7[9^ :sv̞<sL®<;e2,&&pm+11-oۊ;n]ӧbO:5kfv]+z;[>w~}џ3e;55uuxշq]ۍyrkd1>ق$"""\h>~6Ogpw^l^^wWCUM :KuIߧ Taz<~@#߀(h^_={lAD/NX:YT7\-~㹆f7‚0E݃o0۬wPPy 迿qeöOVU?Zw]Lj袒r$ ]v[3ͫs3O=yp1ꮾ綾^Ƿ'? 7 un{ʖ-Pk4;ݥmnJek05k1ɄLg⃍/ݎ̬,x<_g*(+Grn\= 6oiͯO?v<5f>~O~u}gAz\|[뻋ozDZyl՝*W<<)cvk>/s|k=އ#Ǐ#ikjóO?99xr1۬8w6Kni ʑoRgr[~=Sؾkw@v[~-f>~O~u}gעk㣶y 8-j ~Niͯ[n'Zkߴuyc]Ն瞹=LϵO<ϽpqYSxb:L5ǘn|o[sHL,.#"""""λ1>qBMq}yt8U&HF|.d4{;; $t磸'wM"M-uU(RQhv/WDxp$JxO <]DE& 4/ss_۶ ۶nEiiU۾{ 1unkl8ms[kCRz^~~>Q<䓘2uU9R9roKoKopq<_FbD~[QvkZK~`e/_` cWO>٥[;2?uBG~z'"##U߆]Z2".p0;|Woۆ~#A9\J~7UG~WPt5=6|<أx|/)ű#Gp[A_Ó_@u{뻷܂ﶭ'q܁o۶|̯ۗ ֺ}|A 0$$ЁlZVii_w.[ps{8G{9JwtqoL""""1-&yhU"N=V<[Ɨv\Tq ^F IDATppYܟ^n/H^O|Q6И/9sak|;nw>[yG!܃ MMM[obFS~?܌\ײfa޽|hllq㾡wy1Gͯ׶l/a̯G((-CAmaλci7z_(j*+snI_ß_@i/Wʊ ͘yq-kh躖_kۥ h-lk]eE6[uʓV߃5?z.eH ܹhɢ xŐJe9Xp=^~Ky7lc\œ>g_›jJMw| ynG 7vm)*>i/6ڳΫغ)GK/o~㜟\~v/`&^8u#߆ Őd8umly7mŠ1{_^z Y$A=v-]6nDff&^{~vw/_]/ƽWٳ[o%$ :?n{|lpŐd8r&O_hͯͿym܄`9f 2_%<LQk K7"#3[=~\#Jh'NĪoCYi)fΞM/[^“zɩx͋k7œ Ix嵋#_>ƢŋV<ߘ#ѳoMm39xfz~b<8w,33Zma~ ~_nn]W}7~򳑽>}~:]GNg7n+cW//n˯|6zxyS׺ }~dۋkٽ-ʲpOƏ; 5wظBDDD$ bADDDDD4V557 ̕jѠ546r,!.nHƭkl'kK2 ]~U1< P嗻_c^Jis0n7N'' N;<""""""""""".X\FDDDDD4DZ<8B2 ^rZƄh5uء2"""""]W  w] "<:33jTB"\W!RDDDDDDDDDDDD}cqe|p\-.'Z<d2hT*`&Z ]2 B}CCۮdZАhdA@RA* < QcqQ7~NW NgdM͐J%PTHOIVAhH јԱ#Uߏ`Z)IIj5ШTdbKDDDDDDDDDDD4,X\FDDDDDc hqiw8DH: Zbە e?n 0. ZC D9H(2"""""Z<8:9].x}>ɡh`2&BBQC.п"7BhDz#B!=!VduT'sXZ-v4])λ8DDDDD4<OdNv55|V(jVJ tt2fˈk}ٝ; )рqù"ʈL< V٘(vHiIije&Qj48sFD^""""""""{X\FDDDDDKKw]A2":&c"tZ-"uX++Ph֗y}>| "0oDù*␑#'O"RF#vHZfH6P&BVC"p `;""""""""F]"""""R vMMJ%ШՈ¸th1WԌblhnnFlLo}ٛ]K]L&v8W͸tjja,23''o@ F-vDԉ\.GR 2"""""""" H,.#"""".^/NWkK ^AAAi5H2iQ EF@Պ A0d2!,ldUFDX\UN]!|kHRú*[fǸ yV+nhj%a7@6J^+HV઩; """"""""^hkljmW2ÉZ0LʄN2"DpEPRZB5Ш՘2qFqNi9}3'f!.J'v8C"(H3{p)L4:~dH1b6@^SgdJDلQXI4T*TTVQX\FDDDD4w]GÉH$"#j VА u(Za+)CbS'MF= cg$1."v8C*RČ)!h*$Lb4$tZDhljF͆|k1Tqѣ+HVEACCèF6b>Κ펶6Nx<rh5jjը!A@ (Zq aaaHKIhB;!z}!DFc b3, JKñSR*jiȄc|zRSQZY"+vˆ2<3,(hPEFB"U[2"""""""" 8{DDDDD4x<^8]5 VAVztZmǍlꪥlhhh@LTؘ̘1~}sqB&ΰJOƢkI q0PSFՊgDYj6C;LQO.#<, 550ƊQ,.#""""Qp@ݎZ @N Vp/˅Beʤ0%&"lFDxء cgrQRq߾v6CGwqUofLwƾ`\HRCH%OI(*)E^bDHtX 7Ud$jݵbADDDDDDDDˈFFT;`w8஫D"*2Qz2Ҡi<Z7^)ߏrYt?f[Ǒ3=yd )fэH JebADDDDDDDDؼcBDDDD4BPmomqYewRXZZbЀ"[1x=0aBVYLY7"bDVYpD )SAD*HKN;$QFGCc#lȳZq&/ H׉"ѨTF~HDDDDDDDD#@APS[a@sK 2Z-DDtШՐdb;\BՆ@ Ʉ`C]Ss {ZU$N/v8!.&33p2'ʈDhBC1)+2P\Vܢ"l߳H%RfXnDWKd J!""""""""ru;xPA"-%: DpG$[I 6Cb)0A*{ } L9''ƁGpݼyTT sb<̉pjWdgp<'XLPrEDC"2"""""""" (,.#""""&^vUv;.|>BBꐕ(JeɮB͆rH$1k4"#-=rΚZܴ`BbpMz=x͟`#ЪU5e&DQq -"ZEŌĸX*]TpubBDDDDDDDDˈHѶ3NW A@xxZ-L i;Q󡤬 V\55TbBV lחSȳbќШSNoR)ΘB#?k&: V($TVU#Ȇ}BdS"M&&шz """"""""wXfT;;vAD*HX"vE6l%|äj-V^9>>FC`f׻wةӘ:q!D(EGbL^ 1H5]%vDDDDDDDDD]27@j (KONm:_@Ee% mVTU,vxY#H6cBzH%fN!RD,vH+,431>= /b Cلdc"قpQ,.#""""ZekAYcSdR)4j5 tZ4`BMM(`-.Fss b1wLDqGjjnTbb3bc1>#O2"1QQbФR 8 qu!jÙ<<{FCR,&DqAaaahnnDDDDDDDD0*""""^WMM[ւr4X&u:hjHRAjYm8 fc",F#oD:|~?;{2RSPvcXx5P҈ 0)+2[mj^UH1`NGih o]9""""""""V-BNEFj tZԪH5LZZZ`+)Au봘1e q,L{B݉.%l&MĿÞn<e2$H6awo38~&xPG*Hm ,.#"""""""2""""^/N' ~!!t VH%BՊrHR$&$`,Љȳ`ќШ^^ Ly3g{|kd2qt5t5Baq 6"lB!4HRQP:ƄT;;`w᪩ ^h^5Eiy9 6jj9[]2:usL#v8BB9ӧc=8|fN"vH#B$d$EV;r GNA1f"87f """"""""4DDDD4*577nGudn7$ "JuZ&'C!$$XPǴZE6KK`0`j4b6jTTٱqLHOFFIpFUsO Cbң b؊_(M0D51j!!,.#"""""""2""""Qڎj:H$U*FGc\fZ-u(@͆jaaHOM91 BFںz|0b0}< B^' E|WChH&da\Z**+Wd7dIF#BYLPppˈhDjjj3Y{1FB\l &負jR1ףV [I <bb0o,D܉ x>75@=Bx74ةS A\L֣ @HR"R  qH4]W| g q\.cbb6!&s!!pbADDDDDDDDA" vDDDDDi/&kߙL(z:dPqEV.TW#44fc",F#BBBof$$Ew<ſŃ`79 `<"746bρJKC|\~eȷPew "< )&,s73ي6;ܸXP(@455S|ӅxC\y--U%VDDDÆ#Ѱ:;oDDDDPU]ݱ3Y]}=bxC\k1db؊K҂(̙9a**PfsLHOƴqJ%u8ju,,F'O؝GhH*_GxPZQⲫ@*œsb* j-x,. pDFr""#aq N;9VLըaLHhݙLb21x<ǎc洩+WUfC P(0%&b4!< UԄ*b11Q:=45d,@ 8 f>457$ Vdews EbT\&)1fʈ= :cw6nYt 9g[XhF3\Z՘2. RYm( )f#L ;Fո8_] & NcA̗@c\Z\eMSgrz9"Z0KDDcG"""2"""",mdeuJ%Ш5HLGNVb箫7c+AP`l2V[1j1u$ \EVACSs%I̙2e`BV&BCCq)*+Y\& 9R-fZ̨r8P`-ƑSgpt H1WdT"_h- `xH6EF?TLeUXh( .W5F*LlEDDcG"""2"""QB.:?򵴴ؙD"FB|\ztZ-,b1\55ؽ?^G!?vL&1!MT)ug+T*߳I*"H.Ǽia!+bFlt4; Ӊ%e嘐9QWQZ-ZL?E%ȷڐo |xBkفc'z$^4&H|}LIc1!NsxwV$"#cq(䪩AHXd1<O[1Ydn7@(̀^jk4'dgA@ "7.Z]PQIY/e 1;eBb6Eaܹ/dNB uY  '[l`++볱SgbBFڰHcDAw 8?uk N`"""G""";DDDDHKK Μ;"[1Atqlݙn 2RhYit WAC|U8o>hjnFÁaRCm]C ̟68"vIDche~E8u.SǏhd!M Qz=DcBa#cq( l8},|>o IWMM|>NTP]QTB!-%Q: ~4WV"aƵT"A^~bKL $ yS'_fp\7o.p*, =Jʑ*vԉ ^wPZx1sDH$!"opHc1!Uv;XTNDDhhh;8z$u^+ \^ ߏpDuH#$)Uqi);ޖ'\hkGQi J!0oX bE}H$HKJB\t.f55 FCc#BC8vb Rx<7}*R1$a hE=G"""!ƟCsG0h VA.qLJJ!Jz7O>8N|>!JhD^А@}c|Ʀ|I4Lj+D"E;~5R~竪QǼawHäqYV7"$ lHƮD&i`-.Fn~>A@NnmT>^gM-2>_%RINu/qu߂ ?!C=X8-2bbb#H0ׂθ>v%; """%X\FDD4ZZPtBQ5‚CPPT3]}*TJDGc!UYYr@pp0dr9AA!#H.LF 2  dWP/^/|z<x475HJI&ȄoVߊԨqAP<#"v\ EB-vDDD4Jh؛zmU֍ )!: D @#&&v+,Πa ? ,$$SN X`$ B ({SˀxFt9|> ̨_ 2O:p}$""":,.#"""ZZZ{-LךcD"A F }t!" &&V(* QW>2ʎ&Hk; ""hH;Po6J$/ݢ^w$"""+!Wv?9BDDG"""IDDDR)bb-QW_ףF]}<OAzVW@DDDDz!Q"""""""" ,.#"""AAPШ=y^Էe"""" $>$gKk"""""""" ,.#"""erU*<.rfQE``dG@w3}Z2;wziK˭ԎvꜶSXʖ,sQ@a@3À |ޯν\ߙr]}`i{s""""""""9LĨ缙#<GSS1.6BB@Wb8yb1){|% Ѐ~Xj*&"fȱ$pq:@w<-Sc=G Ʀ&cqa ^{Md+ XDDjۆ58pe/^XWz,(#k7DF~((1b>׏i⸠?"""2,.#""A3`|D@AYbUÆs(*.(@RGfV6666̤r}o>7P|oq<]?>ر5o;##0))Qg;iG`bbCC7,Ř䓮 QH}[szާ-S}fefb|1k^={K=wڿo##0e8J}20&0|/vaƍ]܁--qH;_o464tkK]jļ)bv~*): bq@?[]|Om觞xa~}H1vvmc[YȠ@|c-Z8ܯ?o4va3隹#Poص IQ0gmOebD}1<^L¤h}_R :vaK??>}<{pRO_jW띅eR"3]q1CGrtf>fK=?R dBRpi{jƪ6l&F!J.í)Su#FX[[BP!t]k^kvs)RD;pϢEУw=ezƮ/ sIDDDÛZV PS[_U}:[Ͽ 'gg,[G2Nt^Ra8[Tw)Ӱg0>91a][ӦbMprrƃԴ^cPUUOLLƺ^о C:F>u7o >3usOǽǒH,z]{=hn}4j;[>csF9WTVVGhmi ws`}sL}͑11߀0f~SL~-e:\v?." 'MĮ>~8rtuw_3KHDd.fsr$""eDDD&w߃;R&&hHO}r{eL8j?z]H8r׷QR\_ u}iqEDWP՟ի8rPs7{b]ף#FR@UeAvߦfqu\fw7h8`q۸y k Ə7hWett+nji6Z$<4Za֎~o7O=b%.D_9v.6l6yI}i_[hϓ-uϓfS=O␗AuuyzMW^_&>gD"ROw^u[K0X'W{A|B1s+[(Uݿ |ߧӧnݛUSS w%X! vuMfS zoo{- 7۴]w={C""2 =q& jZ-tDDDCMm}=.VV l^F;wkk+OL ~Cn!%y$"2'a2|a0;) BeX2gj-yTʲ231oz Bdݣ0?>4JBL9WoKg* OebD}1Z<h>{}.LB\[Svҙ*!._X GC!ie? IDAT#W^@Pc>G""""ƙˈߞYXK"qˊ'QRa{g_Ƙ.D}<$cڸjݻ  {~p$Εp̉Xuxn3U+V˱XKu9i"K~n"-֬\{_;(+Ua䉸g<۸y|n1ό+pqvСµkL0k/鉈G""""ƙˈ|~;1c$̜2ͽgMxa*,7|9#yHT--vbѬIX4۰zf&*w\|dÛB۴_s'fM_:ŧg&#P*@K}N2uO5,^xy? o43 WY0hµBU_y˖, ""2DDDDeDDDor~5Z[[زUWs%oa]!<$ӷ_G~v*>cX~Ϳc v;kؾz~,& m~:oߎM^;/z[1پ6,n[;y۲Ի&UPhyDaAZ[[q9456M 0DDDDbQm޺ Ϭx?4o7ow-Agv4* >׮3C.51ɘVoچĦ5OC&Vm؂G[D뮹PRXWww p!l_aSObO?v6f=T~@.G""s9-ܝ\H---Pq/OC!""""""""ҊeDDDDDDDDD8,--1]PbqΝDBBDDDDDDDDˈC bQ%2x 2φ%1+ :^݈#2"""2`< *.*ys,aἹ().Һo{ɓ')wm8~s X&Ý k?lo{4L)};Ξ /R&&=pw|sїkӗd,By7zK ǐm|.!cF2x=TEﶹ*}EiIAG"HлÂٳ"ŌQ8~ T& z5̙62L_٠szKncqwQpkTDe5e*i6?| q}{c,D}1wr2O8Cq-t(dDtonǝx-㎾7_ MEL=""gDDDdX\FDDd }sjz_PV~S3a8P`-i=ظy3N+z:<ɮm=0V^3 u7^|n??1qmo{C\S(o#WYٕ+k_rMqZtEN=?0~~@"{ﱧn VRKxvzmߴ3oY߳>g>o`6v "; -b+1rE> %^V`-XG=xfjd)Xԣo9so.N+_b9e]v~ 5_=Ǚ3Cn*Y3xwql>]>*Y˸UXĶyjAvBQq1\sU~I:}קgwd_$"8>gDDDdX\FDDdf:h}EBtc>6Bd`ǎ>sY@|cYpp}ҎDoKKÒ KGSSQ[S L>k[mM FH$d?zT9>ر' D{C 󰝾W^@Pcbw޽rMq9,Ҝ!о9㢑z``$هK=g{lRL g8_G`Ć=pnmbSaG"1rݷCcжU_?jU{'aܾ{qXA4pZnY9{־_"): bqҶ^'Ç_ڎ}BB`mmX89tNM =Μt|K%]^L¤h}`r\ exi"NOyIaWpusY3qFsض};1^_MM vvvѺÏ{D3xtm۸塇peKp67nŠm7Pj>Jq&[Up,b׽-٦jgDY &O=u癮5=x{͛2O{?vkϳ ?ͯ٣so5<ϮVWc+~ˍy/Ϯ]D]\0;t{psuq v}n3j1G>c$"""s2""!@UR;(+-3jMLwm/P*;_0uGmmmC~q>888 ?/˗݃Gn].\SO>q܉e"Cڶl{pCC{'32lbOM?G!\w\'}mT%מ_ezvw\W_j1cA# xK_ڞ/?Þ/;`KW}RJqdw1vkϽQvvVWQv]9I߶Nk'XzD_3; _J% y}ԽKc_G5B۞ѷ) Yfqqa\Xbyon3SB5㉹/ND4Tp|4gDDDd,&rttDIqQ׿}R9tGھ[گvO.ǿ 2(K˺^7e$|GhnnƮO>4qmmE~n8sqZܱhQׯ]v-]nyx>‚shjlVPVߝ嚾mnQZRoo)S!=5~;7O_=+_?9`ː=-yTQڎ{P*FcC>tos>ܻx^$|LjK0h_{mw~iRBj/߷oǦmb _{Kː,.=G]Gu:^^km?كwz  z;gkأ2$s-"!>F۱qg}%™2)g^4Vww'zE{sh7JC8^߯z={[o2""q| nNDD4Lyn5 b's Xcmo׹[p]K4~|M݊gWJB@` ~4k#㯛7#,, ^ֿ?4t'+OPm_}9f̚''Ϋkʹ7T1g̚ygss}נx{5}嶹yf&,uDb`Ś XT{~ۺ]~6l-A\az T ħ`aQx|Y)bamҌYXP" $ ޸{O<kxߺAax 9&O!_k_ބ[;ٰOu_[5mؼݵ_=𧻓i_"2}rΘ5 O<0:7zQa~2tmhm>'Cu9sLGvZ&>gD"ROugDDDd,jZ z\: ܝ`gkks3y|3)_Ý\팓_J_ÞR]uS8556yR%oxE #P9-ܝ?I8e1 aa ٩ӧ/OC!""""""""2ˈDBeU""OX\FDDDDDDDDd$ :BCDDDDDDDD',.#""""""""2N !BBDDDDDDDDg,.#""""""""2b **H$t8DDDDDDDDD}2""""""""VSS̬  ˈZ:Z$ttL5fC "x:*t8DDDDDDDDD2"""Ŋ \: AQ{i'jmС+eAH;XddbTW9Q j4xU,.ksgBSfWT#t.ڄeXQ8Ʀ&!X";[[ Yt<@.8w`|8rO7Y"c4<\],.c1r7R8_J a'VֆkWpDqs!565PZ&"C9[?hm0޿˕8psvĴqy{Bt]Cz)ȼ=1[XӧQq&'0 o]9DDDDdlu֭:"""ϵy{A }xJU΃F ؜+\ PU<_%'?.]A]}=Rq*'#8`'QRe5RA$Q#l~&~ޞ9f*U\8}#l<6 QprܛֆJ’}S(,@b|<݄f2n,,,:d9 G{8 [Г</+]Gg Q[WkkkBnFUM-J/\BD|@kaajdɁH$̐G565 DcpQPR~"W2m$2sa?j$&A|D 8/cq,DALd$>-r.IDDDD4,,,0il4"I 1/-,,Ow7GF %*=xvFB.ׇK~=j뮡bh668q 1f۠uV K K t(.UV͙S\v9TY јѮBՍ 9bi yy9dBCDDDDDDDD4`X\FDDDD$ X$c'Ҋ`admm`~Z plkY?!9򣥵g JuV&ɥ ݨB֫܂b1kb"F nP'0j(L#FѰDA$PzIc_]]1()?~O= #__(06';-T Z{v0}R2~?cʸD8؛~A}c#E4* U"9.BpMsK r8W"2$#mͣ`re5ROALX |<݅gHkmklA+Etd$D%8 bDKk+&Fl_bRJQ[w L]] W u2hK"ڎp :IpRn8X@Сt@th2s?&#l /Bmmj66Bff=7Ć ΐvj ed qqѠ!""""2ar "~KKGKK+&%L :ٍPD\Ep,3 Yg nf[H.Nv/k++L3p*&$kAkF(16*biZ)Dz"GY 1ںk8WBb#,6VB'j@[[V`jki IDATSCT"7/NNNehXaq zy`ƄD=r cZR,[xc4QTV~;\*fڏ +WjqD"LLc'OcHϠ0e(`mmP_CXP_d+h*kuV2QaKMP'Q^q MͶfN*+p)!4$A,#"""""""aeDDDDD&J2 1kEX[[!X`֠HU e e3]p m[XX 1666H8& pr%H 3ٟ1A~8Ws.]AY%J// _kkȼWXeI|%Kdj3^gGlA!f95NUNvB{QpwCBsRwfblTYk@ 3 &""""""""8ˈHP,.#Ᶎ&476bΤqp~+!u.Y\ZƦ&xB+ fH:j̘0VP#ihkk 0j,bյu01! ~ROr%=EP5אD~ VV$GhߐűZ=vr^ݐ2.NpV]5+(V0bLJEeDDDDDDDDD2kjnχj5̞G.֦FyD"|%I}0E:R,"t(7hhlԣhhl0̋\Y;L1BW/pzy^Sg(Tn-"C'HdWkkZڰ e"b.5EW"_Diy9FEp@ |>f3 KDDDD4Y[Ya$=| ??Ipwq:,AYZZ>hhlDqi JTPt-)z,\NȨCss Ll666aůc$8;: YR]U9Rř]a8*A_S &'@. ?8|" Wkp$ѥ˗, 1DDDDDDDDD}&Zn: ""y'%>T\D|vuH[2 bn.mjp&OKvFA$5b QSI$A퍋 ;?.i3 0>vС[ZlE!"ai989%pX&Nv "GaS(Bf)5ΜAUZSS(`ccD;DDDDDDDDDeDDD$(tl1)!ZpLRSSU(*.Fm]\]\o//X 1P2""""!b#!I"K! F+(R"3;'Nd2HF6Zႛ#N* Xd6R|T8z"-- 9 oOwx ʀāS(PC)q&bXXX ,P1Aa?۔Zƾ 457cL/,j/AUZs q2_LDDDDDDDDD ˈĨpXE8q - Y+<\9.P鰲ϻ}LWgmj26ȰPXYY!#4:GJ׌IB2`b$Pjm*(*bƒ/Mp e;BpLBի(Q psuAlT$%X|GDDDDDDDD4(h X,FZ"*$P̊X,~Ro\GQi9 KT+,RH0۲56VTi>e+Y܂1aB$6Dzr!zQp?:&1|U8DQ9؍ERI!]ť:ԤX lihh %ezvvA3 - ˈXD8r'>"TH[[ <(+P*EBS9psW OrurzpڋODk[+"#IP*\ì B2= Y^?w2N*Pv"\05)~>^hGJ8~ ѡ:AyJqeX[[[ⅸh8; b;"""""""""h H,¡Shni]s\؈p_@aI)N1K|%^K}WgG0R%񆥥R3N@V#>*Rڊ3yn 8HOw).SPSJT\+fMJ GktG|D *ZKRyhKai"D"""""""""S2""""a H&X$c'Ҋ(t,-- /O466}̽`-}}{ܜq&DF~I%XXXHz9rL^![$t(F',B,mj5 Kʑ@J<1?%]ִ0ScKk[**.9P& *b $c*"""""""""SçvDDDDDÄGXR҂):!}yΌF}$4-WY; ޅHXHH ԐFH†f,@eYJ7rd˒G}![bٖmIr~C=~mݲtҙNEIY9g8|G$Ғ {$>àم3ztKN'w<ރpq"fL$$8 8|(%=)Gљr/DVaw#]i+á*CUM Tzۙ<1ĄBCB]\\$%>չ yknQE]FHY7Le)TqGbcIOI&).daZkl2ĸ8.` {10좾1aX19O @+J+Љb;JKf֒,l.qTw$g*yI6ccMeu5Ub`q0$4v"""""""""c0 EpS%g khl NMfzI ^xQěGظqB"bjJʩ# Bjb")86$,4 fW][ǖ]Ieܹ| *kXehrL#?7pCVKR QzI̘xٌad'v7/7D7=p)-!!6ߥ* Mq2Rș3\0hjnX,$őO|EDDDDDDDDdQLDDD׺~kBCYj0U$2nNY`*N-.J))АP[:]ޠkh`]8cb]0Lye% bN-w1ť\Fryg` []+:͑ ҙ61YYS>)%-m}6bcܸxvSSSCUu 5tuwJI||Gz :v$'Nė fɓ&2uҤaLdjk`| `͒EoaPS@3/ %';:Z !AF6'n'#%{ӳ ->JU4^td2d2od&gb!CW{@;9RxE%M&M`jVAF[oGÚC]o#(ʭsE.NԄd"&:X'qDl.QDDDDDDDDDe"""2\aeirlSYMMx Zf ) $Pm{㽫Vx. oMͬ߾'Xf6H#o|7>~ ݶb1Α3x+ͽu]>QSgX61ұZO}a>֌Q|\m~BFvnZkj`bcutઈ }7PDDD-< ?7af WLBeiolkvzI6ё.k\rFGrtvuQZQIIY9$$8$2R[PGgg+xs6V<,mˠ'UQ]Mjt (X` jW7MIY:QӥY̝6)ia+)6CmC#q6>@CS32GCc#u@L q7"""""""""2)\&""".-5G>o9'"he͒l^kw:w!hwQ+* 8(ILH3g));b"l$DHpp{ vشUy9qiye% ^,;d#' ə7gk ͮ˞7L8v- :2:Ƶwwv`68^TpsxEg bba!DQQ[pe:J,Y=rd àں:joh +3yQ:Bv)=KpSB6aݖ|V-Ogtwv.Ό)1e2 sG!-9XN.3|wuƖm]D:CWVmD2ϠS':r:~[c ٌDZR<b|0k4ZyuN-.!#9C'Os,aa!,;dWQ3&*;V|NjX=X~mq΅ꨫov3q:bDDDDDDDDD.aLN}c#ƹd"n';"泹`onŊy$qad2Q[HZR|8cqD3otVPRZ m4|]]]e;+gcWQ|~2Y癁E̟9cx M.e,}0WtiMͼ)ݻמJTDKtψH`c>G>;2Tjy}s>^` `0]C(:pc S׫]̔DN4,lqoh:::X,8pq]"""""""""2>)\&"""~C.:&"#d"wL6ޏerFbcmqMMtvu]00<^o:G${!M--=YHye&Nj3}ڰ6P^M&0abŢ9dgkykn|>`::;#)DE`1mhV윶NmabYC Ϡ'Lv.Pv@Nzj*QW5TDDDDDDDDD? _Z: .ID? gMj}A'Mcř1 c_+y^6Eނy$'\3``yZ[9VTLIY&7dfE%gaD+iji kM& kqlwd<ġ.3DGEPSHfnhex<446RH}C= Mx^3y$1DF3 >DDDoRo0 5v{szbct=4ZGخx}EUm7 h,S$-&sϯff᣼e%gbTsBC|륩&ihhD͆#& 8 W """""""""ҿzq֎74  u EFX,l)؏e6&(뛘zLdʄq^nꦫ;;ꢩIe])%N0]m2\vD1<{q}y<h8$kllDdD$(&dfmv.l/"""""""""2(\&"""~ew "r R)w!oo/`Vdb11%6΁cEtuxt 7F> mNчіa?څhj%Z[aI9#gtғihhfhmk0 BBBG1ibQv"##X,._DDDDDDDDDd@.8=+`͒lض7bX5mmh$9>Ո\ZTDͮV1l|>'K{)Ζr jb"!!{dv{!.YDDDDDDDDD'?"""""r͜vnY%չ .[GpP p.-2<.3 Ʀw:5Z0|aV3AV"{٣4RDDDDDDDDDDDDDDDGFp˲m;X$ 5&ةow"a }ziiqLss MʹX,DEFFUS++l8`.i eYe'mlBC]֨ŮJ aBiwWsLk[a@dD(2ӈf oaVLDDDDDDDDD DDDƀ̤DN5bkc8ڹ>YZZ9Z|j؟/2^ݴ5KFh -DE1yk v˗>K{{3/=j+Bv{:|U{G;As];: "22x"#",іmi'PV-` o=_ 9y~ ׉6!Aܲ,7aQ+*"@ku ӣ|c?aq(PhH0]c墹[\vJTD$iiDEFAFvvunK>n^M2/EDDDDDDDDDdPLDDDO"'7@2Krxk.^ۼrqFGQd2ጶS9S&=X o d--cȈ 2"卭zܺ|1VKsDDDƈ/|3L˚_y9/{,3)lļY߱ 5e ߮X7c:rܧ2kʔ/z"3):.RGDZ)/gu[vRU[F;u.cXm _L>@O<|[ ◧Pgsil~w)=ܳל)=Yg^_gCؾ>nݟ}'ߟ:Z|]]] \yvoh3?xM۶^gٹҲ2|ArR 妕+x-7|IsfdBF:1,|m7mYMعm"""""""""":'◿G>xS^Vƪ%y|O?2{~7֮%*Χ8};O==ǢŹ̛>9ǎ]}ijj?ǝwuk|{Crz1@˷l=ũy#"}X,ʙϦ]xc.V,GJ|u;zc 2߿uZBCŏ3;{Ǟcw~|^ofŲ{[a^⓼/õw8N.şV hjm^/%<|7Le }[,ft\Gjurrhqr ȈdD"]Shl `c>mE.aCN21bނTWWͯ/rn?UTozOzƵ]ɩ"n\5Ϗ'vEE,(+-%'7>X\^\l6<{.d.MFr1vfLHMw9w>5|>/yw4.ރ6n7DCC9OJʪBr(X0!g/hj^0u4TI ENxz^h]qMCkk+ͮ\0u{FZcوu8lD 6[5KGچ""""""""""#e"""c kde^cߞ=أ/yMzFO< Ns낃).*oEffW;X,ǓSRرmW\RzD&i>үx`GQU0neEwRQq瞿7\CS&݃Z_as'/ffK^7.UhAQ)N900Ac1ϟ>@x1kΜp? wqGof3r3MM^5<sN.eU<.GDDDDDDDDDLq _66q GcG{>={]ʠ5UNSpsMf֔.gT(ͭ}  5׿DQҲ&(8QXDuM &š 墥v 24"l>,Gb?ЉSX4#"""""""""2s\̤~:[?>,jzDƛ&` `øϘFhL&u %qk^5k`#446b2.,rf3$1(}=rC'N<{e""""""""""PLDDDەB]{ ~="є4l-؏a飦?ZGبRl،ٻ4YI[wm= Ks &y>I.EfJBJ2 IX,lKÒ10xg4U.Cƀ(|>+-D=74z{ba\>hEeCY:t=O7&S]Ȉ3zi:hK_R1w!UY{|Y#K.iy wW8!]{oK0}TbcZ=WL(qѱnut'u9s39#刈H ȨU[Sü]\X7/YDu}olWx1Au]KWZ ~n5B*z2|KK _ދL&Qdefpݼ/c֌$%&xBsٻu=pفE>xssCVFw~EDDD%{l "m疥9%u[vrSw-@Hp0HwqO8i8_;|}lE6 FFZ7P[_nsFNJ(8|ܹ32!刈h\&"""Ёܼj%RY|Yssf39=_zWX0k&Xby+@O_؋BCCIMIf$'%9zQѹlž`ټ ίX_ya>zc eEjI'.1m+&"/"<[-f|^ݸ5Ka wY#F33x^,6/aV,l<~x;??!Ā>|.g"cPʚ%٬Q[vp;]%:wꞻ˿y&ģCɤ7O>SDD8O Y3W/}$%Nӟ|OPFبV0ؾ'KY=EDDDDDDDDD0 EgMvt (!2b|>6GYU +#%>%թ 6`^ZfEƳ!{j= BU3ؼ{?%g+Y3yCDDDDDDDDDh,hfsLNdNP%:0 ʺսLFfW+0J+YP2px&Ʀ]8q%MpP ёn4\ͮ.s{iK*j]nNl.n7ol݅[DDDDDDDDDDF=u.2]Ȁ͹a gMcc=rEb:]u~?]]c H?7n,WLDDDDDDDDDd(\&"""6!3%%~-LJK[oLImx-n\iܴl)^}ނn^Iii|QzL̤ċE_/xLLKee^.W iY͛E xg &1s8Bh5%<[i<[+۶o>Ls/zcO-xk?䉧x<~Zu]a kjiapۊD.j""""""""""ce"""@KrzV\z'#EEx橧o?, O{sk&G>czp׿=nɓ|.zީb9^|o?_җ ),Ϟˉӥl޽0]Ұ Gh́7 _?̟>~"͹?獷~ƖmK_~:Ͽ=ߓ~p_gY"x7 農#|/[į~Ah \u}#1QjdžmpۊńH2Q|Y׿͂Y3Y8{7nusf39=_z骟s:I|>1_z︃ukw ofM?|nV+wsv3gV ĊUzϵ\cXͥ`׮~xS}/=/ŋ}%s `pl%wa렲f:|]ؑffqK^gsilx/\ wCYl?X{_\g9Yk_ SXO^XY m#wq.:6l|U+.~jLN.gO1}Հ̧Ą>4|>zJ+ymNܲ4@_]\Sg+LJEk zl:})/+cՒ<>O\s _|UKx/KmoHQ1}|oZ|ޏswrlr_p9/ro?]PPnv_tN?ƭyO'}GٗoRZL~y)"C/)lھbU,.k%pxm^iݟا+~{?ֳGy^/㱧Xϥ{n}[Ǟ/6g+_ޏ%4^8]ypܳS[w?Q#"E֕p漳\nW3(/?>;|L5t=$9%el-8HVz yf`2@21\JKK/yo~+^~%ΖZu2 {Tq1w}}~{Zxx8ml/>6Aɓٺk7v{:p/?ŋ_|cXrOuEe߻A6̿"2<ܼ47-;Y1(blu-SRC]])'?u6n7DCC9?2&??|G? JpVBB,V/N('. m+-f;oG7AeI~yۻTWUuW>c8Cie5QCBQp8NdlFc1EDDFHJϔŽmرmky{絷_sVzF+lˍŜtPr IDAT0?n^zlWꢨ$~FUUV'wx{{;|Sg+zο4ORUUIwWɭrh;wICblU=344ں1)(Ɖm8wǾ1_Xg_+wˍ̚歿quzl/++'zn*v^Ww;{ƒܾ|*nwU'1..w7^NW7l dϑ,;]2a"""Гy^M¾x쩧҃u~9Нd\s3<_Ô1!+j>˿=,SNe뾿_!>n}ofXMXXrc?z'O|@Oc;]7/םm064Nfʥ{{mhIPxf2 w"""Ymc'<$]4ź;v{XM-% Y%6~UB?YVtmG)᎛nQptݬ[HLTĐ?SDDDDDDDDDD(XLsBubByuꛚ]ҐG |Gcx}> ϔ31=yȟUSކl},f alڹ-):SN[ @+kdc7!le2|NW09=eHsW7{V,&,$xH'"""""""""" w""""0H}z}D!!A3 )2jY)w!nK>+swY*9ɒ2Z]GJHK#$x}GOIOd̩L!{\e""""~d1룦z*k(,)g#l=AXh \ ̊EZf9'%Ax.,w̔D?W#c]Umuo!Yi~*Y΄DbQHZDDDDDDDDDdPLDDdzf B̄d\mTQQ[ǑS>Fznf ":1iV+;Y]uq#  F2g*mUeKJ+Y8s*'e""""""""""28.n7ՑL]mM X?W2Be2)#:;zG ">6sla~Z&gb `?sgN&g u̜<:pbc샲f;ɚ$ƎqDDDDDDDDDDa\SV~@&dfF@˅s\fM-hQ]߀%,4X bTaWVUÆ{He9ͣs$߉S˺jh</M Rw)ήn9ɌI, hQ 7d=}#"""""""""2)\&""2rzQQ,7Q;MF>L#8G4NRS@EMU8u{흰3'%957sZGH[8!T+\&fX̞u]봶wa^]\4APDDDDDDDDDDbabN&fMpa#SCU]}ff{T;QIrZ\ےOHpʆ{vY$ߥP]7lgd%]:UlGhH+se *EDDDDDDDDDdi,p|QT\L{G ̙=H&+@jB qtvuQY6;]^X,fbv'\T[/fݖik,",$e X3]3 y\p85 `ѓ?VDfJ"ygʑ""""""""""e"""vs ŧOqIIIaL]HFrYmOaXsD ihWlaܺ<'`qk,""|t|wxkh"V1:;RH[{',.xl޵FϝAPDDDDDDDDDDe"""CS9} &d1F\(,4dҒhimC'}(A$8czfQ e95W7mgM"6uEQQU۠p\چf("g4CC’rv?LxH]KLV&0 !""2QXTLYy9V+23HO# @ s\ *kꨬChH0=aQ4jP/[w܅8G~`kν,YRdr{"zf1lXX ;nK>rwYacx}>,{*ms˲꾲b6sE$ Q""""""""""2.$U5*HϝKbB<&ߥd"6NlYS&zolV[ljӥ#m$:{fqh'#baemX=xuI l{z.GF’rΜeلl|aׁ?UdrfOjoB>rNrthNj#O =1nÅ0M8sc4clba;,`'&*fGhQ^% #'ޡ0ͺl1eUuxBdMR#.`ZZ[UrZAAAQ!R`(ܙ\g$} lVנNӯ@%v6 !0/[6v>*_/ktICۣ`Syu2jjlnuSm皮^9tTJOѪH2DQ֩RCC"#"tb$'lf9>(኎׼l~[O.٠݇*<4dWX%D /+C6Mo?>Gk\4ek5LJMWyu.4LQC+=JR tՇV)%!npT^Q"wuW+..dR\LbpN^ꚚO.٠’r~EGF()n`XltEVzlVv=(OW/_ 0.:Uu2hV]נlV%;EGҭڮڣ m\JsXH>^/eehyCkcmPVzV.@*LOMm.544*2"B9JIN+Aa*iijVנFyxbѩ+բMR0{ۿ,#%Ѱ:`zsdi<:^ŊК `6RB 0;x^WTvCqqR\\ѥz0U~52M*,$XIJ:6ΦG/G>O.^mh(w)41g2ӵn@BײyL#l82۫_ir:nti8p ϧh6E>OQaJuhUN-yJON8G q-[%ssխRIqvY@ё#"\YjTvAt*-5N-S2}jT]נF5d2)6:vcdX.=TФ+֮Pb}k]  %+O1~bY2_9/i¹r$]&`#\^+*rѡXegf)!>00SqY}Z;d6u2l( >O;:]jҒ&رb,_s2r %UVElk+(fSxh/PVz-SXH)eiNEn (--LK! MWnF$C5';9Q}W`@JEљqFXhlu]ܬInvzv>*_6 $HB٩xbQFD0y}>WU\vjͪJ74 ~5.y y< Tb\@gX]6⹹ ٴ1yOuM-kPM}\e| Ur|bgWP`ѥc 94٬V</_,ze~utu+,$x®荷FfYi 0{.Nb7(<,L ,PZZ,fc6IzUؤFU7L>_ёJUR|cc`]:"#%IV{<a {KMS&WYeO501^s¥E|JG몋W* q 8&7zUZ^.XSVS FI!IK 9<~44Qu jnk$٣"Lj\)Tجw=*R].ub.ЮGU]ߨndp[k{+.5x^pбBx(TxxѥaUUWtHIRtt඾>%'%MzL74oTM]Z;d6=6U\L,EU/O!rJ+UgwL&Bofu.󕗨M]%o$}꟯RS{29Q^.YH,Ybǩ e8`ti$-ƛ:vÇ.VTdWN]=kPM2]X,D z Yij"s{EsZtySG .RO2tO\sBC/}|>W\#j󔗙ntyمp`b|~UUW.VsK"d̈́f^}M]]]_6IRue4zzdZX%!aIխ#It*G۱K'ݨ>J+k*UM}f|>߰>vE]|>T zzVFGj% 1DC 0>x< _7>]R^%'%*=&f+Tw@b6I )'nۧ1J+٤KoUo_>bD]==|2MZe _E%:_%ũS]Z2?Gd1F!\[ǣW^ۮXXtc*.U IDATVyEf2tf(d4|zeQ s0U4jw2lkWɰYtD8 ?ڣvImj_m\eUJMӺѭ `V+Lm=ڹ{TYUWPPjr^a?oSSeVIϸF b#yN~5~`C;Q`@2.(׫>/Cz}whQ^ΘY:?W=:.sY<ەW]%I.rUp~;pwd.[TYF0|QWwڹ[ݽ=*.)ܼ9$׫ jP\\V\xUzz &>SdRLdb"# %,ȱP=ێ],BJG ݚma5K[5#.M~g3wyv=$/+*"\~_*:^Nehҋt8HWhnfV,W':& bΪC;wQ_om6.YN*--UjjNEDW^=d2i+((Ƞ|P~_Mmaچ&y< l6&atv蹿"4bL&_4Ws2u~Wymڇ,) |?b٪LoxW~@frJIӡjmPVz8*EGiG} ~eaZ[[s^y=dmr:3p(0 :1sf&I1ѺxZ+p!6KlfW!:6( @X:W|  i6zrOɳ]l2d2Ӓ0/KU:_(IZ6?WyY jjj֮{yN Ԧ+.<))-ӑw.[tEp\ҦF7QOXF$h[E%}l2I_š[koߧSQ(٬ hᜬ QqX/$_$e:GݣyZ2/%0S2iuڳx{Xz&2D}KCeWo,3r2vEGtϜz|P-+=E] y}>O >OTiU`̤џL~{E21 \`l6=}^t<KVūZutKɑrnSHiWiekT4;ztf&h_jQcKQ[$bn5].jUWVIeZedZeYeZed9ggj>52 sx$)o]-48X3vM[GjTШ&utub6+6&J 1J+-u߭)B42il-{e7{=լbYmAOg35N>WE_Ia+d҂LZ4{~eƍpj<ғ&iZ[Z%IQWbe=4khRM}::e6dTb] 1JQͦ7R~_L&QtR9 "-XVk9󪽥Z1P tz=j/R#Y:斏\u֐#S2G Ᲊ0eriW .٩>OטM&-]|2RNMpjᆳvjdLa3ɤU )88HA RvF"B(󱟿2 5Ce&GHPr&KzzTФ5~>_~ms@9t^4_ٰ,4FV[R< PPMA ?G A  GJ[d6sQIjuelS$5@񙒤+`v0]z`$>utwϯʊI `jsYK>/|OfUe\`9'qcػgV,Y9F ؚ\-`f)udfUpPCC{6luv?g&H}]6^v=:}`mяvz9UZU5&ғO<^r:uWNʵ[o֕Vjffb1fd2uՍz2pLrb[kׯ$/q;>2NʗwOk3%6:fV&3Xm)/+K=/Vá޶mp#9ǿZ`֮\9uޭ5+VhA^ cZ`֯^-gj}-}gכnR^V~_~w.SVz._}UK.ԲECx#9Y===5YHm?;gxEČY c wֿ^B,O<07}+uMkxI*?nL׬I?~zNjeG:/L~otn52Pd7o־C(/׆UTZ:W^z{f:]7:sy+6lwyD-h޽v套ꮯ~Uk֭7=5d2 yv/|A{v mr-ozuKܲEzk?j^UzRy#kliQgw9n6V~wjnb#c+48X((t]7l>h=[??_) 0XإQunѦorzN=CHߏvf ~0)X!Ig3۶Bg]EE+dF $d2YHWnts#rJ9x<#)*,G7o~2]n3i$+8\EE׾,]:y[ Uto^Tnkc_^\+<$Xv!S2yrV=+6.NN` \NK,0 `alptZu,5$0`,_XMMMF8-r>{Etݍc]efw.SVz.!/^lCmۘygtBe9bÆc-WZUu^uSc #t͚t}C^k9sc/Y}bB]֡߰aphKgvu+84LEӱ#>]L{[ 7(uԷaUk3<7|$1`:uMQ97?r}cuG7_<9㟳7nSks2s橿s^&2BQa>y/yFlۦʊ yqMSD$^->ʋ u5gsTW]qw~zu7o9뒍KL0+d8zOɭ[@/ڸγE }硇t0S1`HIsj7tߌoξ~=ڲ4U'Еl>!\`Vx=wݥs2ʎ}T7pVY3\yr݊{q_T@ƑL'&(->|oߥܣTG~Iҗ]t|sKUYV=Nʃ_nU0L~otn5] dt 3NcK:. =*2Cucq<4mZ`Vϲa!\piőlt 㪕`r.0#MFPDtr8OW_ҒQ / xer8SYi>Gr쓤:-Y`X ]2F;h| ]a]a^}}cg_Z9{pAMf_z닟ڨk֤]7_ྪuZժ(wa_w/ӵksש3Ͼs/ֵwF oVҪt΃꟮N'kֈo~s;n]NoԖjٶ׿֒Knjjj:a`l ilv;vL?}iꮯ~U_җw1OWzPa8xC^4 cْTV\p\|2Sz-ڣz;_CW^?^__l==/c_OZy >tGܮqz6]w~g}O;<|ufί?TG~Z5ъ}GU,ͦ˧?M<]]<ӱ#y*ldZ;\UUr$' :=o'$=eY\֯-9].ccu({l>|:rIwغU-蟮nkooWxx$),,Lg=[=VZ5lÏ=/v5w[z.ry짏ozP ڵeduv+4l`^ SgyD%|3h#߸M͍̙<7|K\G*8~?وpIUVV ~?_>ٶM$|@w ߯+WJ].IL&B5aaaPXx:::*{n3:]zI;G_ʰׇGD~V?#r<>Ojt>azbl [c󻊊}M_aKJg6~_(%5U?eFT]YEʑ?=6UW٧~_<0g+J]sh^xT(A} iY,yF%%y ~C_ӿݡh˗o/_x{ĚXTiIiiiڵsvܩ{rV}?Ћv^9WN~*TIeі[j~+ǣW!jW]]o=>y/vJKӣ?԰L]]] /O~l}lvOc=_ 6&WZݻvKa#Naᑪ(91%MGԑ;>q޶Uw=JIw?~V[==g,?U ~l{ϫ-׫jy<}/ZjȒݥ_~A<]j=<>O;M}}*ulF2ۏ<7nb;z[]w)I֭#n5k:׽w߭reegqo_UUUr\jmk=&F+WPB|L&$I6:Mɤ4JEEJJLTnN""".,&2`x<*-+XJNJҢEiti0Lss NɤԔ$'FJLHPnn. ܕ2y?`:"\Lq]]]r\p8`+5(-52fɤ$%'%Vz7ܜDG]"Y&1.Z^7)!+2`jniRuM4''GCV+ӣ.]ʬĄ׫@oܩX]ۍ.,@j0MR߯%"#t%'%iY&IQQF2)>.N *((Юݻ%]d2)1.Z5͒F2` x<*++D===JHHкkeiYtZBbvŮYfj}Tnv 00IQ:VPatXή]y|Td!{,4 A JQ ZAomZj+k_U _jA+*T6Y HHB!d&df̽9C#9:2 JNPNN?.___ 6L1566\1116 0@cnjѩJeff{!C)g `Бp@'tF*!WT(88XcRRrdzr5662sW1|2PBBb9oo/2e)7/Oyy?}ZFQIII 0١@+-- :_~JJL԰aÔ~̬,%+6&5AaA*:^09M! N)''GRLtbcշo_gSZZʬen̷o_9RC QΡCTfV'oog E 7:(/O\t!ɤQqI5jHEEF^dibcS>}tCt!e(&&FCէOgÃШ#wBr\UVVj0gݦZ\փx{{kaJW^^rr( IHCɷ\! 8555:ÇРH3F ]iY  VÊЄ9;D..",HEK$ˀsPZVG 񊍉C)--ՀYT\lbUPPlkѨaC!pQaA{Dr`'ɤGӔ@1`d4JKKĒ#G7m1"BCUfІ1,X[v}jpH.:P__Ç+'7W ׄ.RHHC9  SPP TV^8gnd09x:RTLmڼY5l0 !paP2srYũjSDXCYRWDr`EUUrR~A$):*Jqq׏zZ}OeMM$ir5',YYʒW2 l4jѨG2lP4v^^ ܂c*9Y̼"WIfNMurtˀ6JJJs萎?.___ 6L1#}ѣGw & y{{^*(,d`ޯҠp '4Hرc/PXX J! ?bSyEC 2>> Q>tH օ))4h à :TYjl=zId2} #TTVuD$L˳! =ʙ3gT__/___)7/Oyy?}ZFQII 0 6i Лxy`2dj=8${ 8PaDefj֭ Cjz}~Ƨ,5淪GVe,c׆?Whh.LIY)䨠P^^^V\lM(_*+ᡨn p ,>> =;Kd/)5Hӧ[cc8*i=&Iyytq5<2^^Nt2G/h2u$n =]ۥ1#"" _ njSMmm"m9*(,tpTZڸϜ`e26 kd;^<7L*.)ѩSzAg.  lRcc  g7g2,__߳3EJ߽{U\\"^^~>򒷷w^^l埖3(-uVv  T?__w*++״ UA*T]S㐺Ѥ$h:!AK>PIMIg55QmmTUU{jӧ#Fo}=Y_^Ƿ$*"1 { \dRHh[,I8KPp鋀fKHH S~oL}δ3)?:y⸳6\f0H\0 20@%\7R@GEZ. f$'2$H.X `vl߮1Gkh|FgT-3}pk~ކ>Yo]>ʵmR;;]~!gP_JRJ5U-uO벴4貴4}vn}j$x=*|_hĉ]?rhݕ$'ɓ~^w6=3_꽥l8e/235o|soǝjɽѺ$lƍJ5JH۶iرzoZ(Qwq%$hʕv#R˗4Z}2U[[kg+׿6;ګJ6_щM7:mמU+Wjtby-hXBkվ}ɓ&YZڱXmlH-7߬a z7ZmAkۺ_mkc'cof 2D+/לٳ56%EټUny~[~~_?5lp(yhw }~=^omZQ}4D髖k)ڳcEuk?;6+FfZs_lI9djF':Uɔɓ5o|]/I*o/x~՞zҘvۺ{~suRZRCY(08Tw2U雳ϖy]KzdhPq~v8ffMalZǟ[1Ǥ;ITDcv%;dge+w9ٺa,Iرc%Iǎ|^YB+/WAAeh|ӏgR߾}uK&?ÞzРnY}GP}}JJJ۬?+3Sf϶b[=Zߐk$ >\*..TmYjZc'L&Ʀ6vQ"swU_߻&z糲tz5:%zI=`;{[oU+Wnռ=**J[l-[m޷o_eeeiΝ9s֟/nB?LqmwUCCCcF[Myy6nتmZWgVwǴ=>{C??~{YKv%H緳\姹 IDAT1 {ccTmMy[pܿ[e812z.u7*yV3,&8So@~iVPTtNK[*80!,+SuMMMz;׶FFD8$o<7qLNd2IJ5J vURBc }p<`iZ5\IRJ5a=c }p<7_7]k.Ѽ_PQaC\IRJrN<01ކ>8 h/>w7e7'wvH=\W.S\t&Oj_JrcbbYrF'&*.&FwR#7.cm1K鎛.u MW% 1J_何D]sqnfnkS󗧧.544覛o-?$fcm1K2ueオB髖xQ1.Q=}jlhд77>.&]1S)i%-bظ8Zm_tZDn`W=ߞ~ZZؼe1ކ>8 48*N{W˗7S]=^\zv\ZY"BM>s \"_{т{U|B6l(IzuӜ9Ev3ed(l@=ho~ye42Kz$zl5lCםIh>]k|~+4h }H~UTTukϯMqpϟiF?W}Ix/ygG-Ҍ3\?=H˝h /L͛?_o;Wy1}-Ҽ{tp1nj1IJINɓ'=gfF>v[c]>}>';[>2srtp/~5lC7|tP٦ٺk9q=}ťtzwS&NF/-=~9}zrjEE7]>H?W׫˚_F֯DNJҦ^rh>OzFr>dV,_9gklJym4~X`vEr[ڱ}{˝O >\>>>J=ZA}ڽkN:%)St:fXud=ɡRn-{}&}r=$Ie;vlc`u\oƙ} _-gڹen2Q7MKUE{ǷgZQ}4D髖k)ڳz6όZSS]ޭ|iPdLL&*K52l_6'T_l_޿-Tؠk+Q11N:u1꼜39(E?%I?6}E$i޽*ץ'ny=(44T&N5kiS*#;[K~shƌw)HuԩN;}uyz'o_Ծ}́Z+1qcyp"gL{c>q9Gfq11qzE?WzY֬qf>8_ѴTc$e{X.n!햓7?ګcEŬyqan= /gM__XPuTon`>MG nm/{t]7篚J PUU9L/)|PݡfWrY3?1z关 WիŔ(/7=**J[l-[mҥKԒ%tÆs:Og鍕+uP kcYqz뭖(jyr>s>^zdCc>C)##Cv s%lMt |;n]999jhhѢ">}kcuqfk䚿}h-48j7/=.o7.Yس+юB}츰,_1iqvn'T_/LKgq뭖>8[u_{/M͛CСC2t{ M[ut됺 R=cchf-ƶݭRɲ2U=;绿ϯ~mKo5 G̳HϕȈoƙ}=#5׷ԗ[>iXT^4r[7}S?LHo4'AYi-yzOtHbhImն\?|[krU\c# 豇ԡ̃z s>E$l|2z9}-G\A;^qLNz}r*zjr`MOM.l! Y\) =e/ Dre $,\@re $,\`0L&gp) `2H.X ]bŝ]}Z⬸\zy9;4ٺuvܩ +11Q\rrD(OOOFM>]Nɶm۴sN+((HKnW 'OիuQ 4HfRPPE.\nzuvy8?$-[bmܸi,^j2Pw[pΜ9ݻwk͚5;lطnݪoThhwIݮZO4rHvmھ}>͙3ݲރ%KteB-Z zwyGge0QFqF),,LRS"UII}]hРA>|hĉ{6lؠ}jY6mڤM6)--j}z嗵sN)--͢m6mRAA})""B{_IիUSS#hqlZZ<<<O>D^z_z%7m5Ԋ+uV+885m{f͚vW{׵e{~L_6+,,￯~l׮]ڲeF)IzU]]-Ѩ>@]w|||O>D&Lho޼Y_|rrr!rk:e.ԩS zIٟ>]{տos$7NiiizWaZw}WYY}Yj…Yoݺuя~X=VwWFWVJJ/AgΜQ~~fΜiӧOk۶m$Ǐ3ݙڻF:IG}s,REEh5: RԩS}̘1v/))I7nTuu<<m ͱiZz.\e. @%%% 3'L,*))+QQQ)gsNرCjhhJJJ4tPyzzh4p@544Rᡔ}7:s挒/^,///kRרTo) @ owZݶd= SCCno>y{{+))Iޒ7'YӧOjÆ v2pkڵ9sBCCuVCBBtUW)>>ޮ-yf͞=[zgR٬/ @ׯ$)99Yk׮UUUynMPPrss͟;c4}t 8P'Nƍ5{lI֯=: m:Wmmrss[]w{7ߔf͚eݻwkܸqڳg9IMR~mM2Eںubbb-Fr HMMx UTT(((H'O6я~t)44Twy-?}tk$ꫯֲe X/--My ⋪_oH;vL~~~^6vkM5kHyF4{%%%)$$Do***Կ7μuGG}-[ZlS1*88X0`yW\իWk ou?[믿2hƌV<+Ig`2Lի5i$:d-]Ύw}sN ;e `2br+W(-m=s8*Dr:!//O111V9H.vu>_߿_?~sx9;t~[꫕lN$`pB-^XC Q^^J3\f…cΜ9:zݫbM:Uzjj̘1:rURR`71kɒ%W\Tm;#6sW^}g^kozw^}gQHH.2JOO$]wuJHH02w\GO3]bbbj_ZZ^{5 2TB (GUID Partition Table, GPT) MBR Signature ~~~~~~~~~~~~~ The 2 bytes 55 and AA (both hex), known as the Magic Number. This signature tells the system that there should exist a valid MBR - otherwise you'll get something like "No operating system" or "Non-Bootable Disk". Backup and Restore ------------------ Clone whole MBR: # dd if=/dev/sdz of=mbr_backup.dd bs=512 count=1 Restore the MBR again: # dd if=mbr_backup.dd of=/dev/sdz bs=512 count=1 Clone MBR *without* partition table: # dd if=/dev/sdz of=mbr_bootcode.dd bs=446 count=1 Restore MBR *without* partition table again: # dd if=mbr_bootcode.dd of=/dev/sdz bs=446 count=1 Backup partition layout: # sfdisk -d /dev/sdz > backup.sfdisk Restore partition layout again: # sfdisk /dev/sdz < backup.sfdisk Write new, clean MBR: lilo -M /dev/sdz -s /dev/null USB modes --------- * USB-HDD: usually the default and prefered booting mode. * USB-ZIP: ??? - can be set up via: # mkdiskimage -4 /dev/sdz 1 64 32 # device = 1GB # mkdiskimage -4 /dev/sdz 0 128 32 # device >1GB and <=2GB # mkdiskimage -F -4 /dev/sdz 0 255 63 # device >2GB and <=8GB For devices above 8GB (taken from http://www.knoppix.net/wiki/Bootable_USB_Key): # mkdiskimage -F -4 /dev/sdz 1 255 63 # dd if=/dev/zero of=/dev/sdz bs=1 seek=446 count=64 # echo -e ',0\n,0\n,0\n,,C,*' | sfdisk /dev/sdz USB-ZIP requires to have 64 heads and 32 sectors and less than 1024 cylinder count. * USB-Floppy: ??? TODO ---- Check out the *real* difference between: # mbr-install /dev/ice # lilo -S /dev/null -M /dev/ice ext && lilo -S /dev/null -A /dev/ice 1 # cat /usr/lib/syslinux/mbr.bin > /dev/ice # syslinux /dev/iceX # syslinux -sf /dev/iceX # mkdiskimage ... (USB-ZIP?) # ...? Partition stuff: * How does a correct partition look like? * The partition should start behind MBR at 1st cylinder and 63rd sector? * fdisk -l -u /dev/sdz vs. fdisk -l /dev/sdz Resources --------- * http://de.wikipedia.org/wiki/Master_Boot_Record * http://en.wikipedia.org/wiki/Master_boot_record * http://michael-prokop.at/blog/2007/04/22/booting-from-usb-pen-troubleshooting-and-pitfalls/ * http://www.ata-atapi.com/hiwmbr.html * http://thestarman.pcministry.com/asm/mbr/index.html grml2usb-0.14.2/doc/Makefile0000644000000000000000000000167411664237073012447 0ustar all: doc doc: doc_man doc_html doc_html: html-stamp html-stamp: mbr.8.txt asciidoc -b xhtml11 -a icons mbr.8.txt touch html-stamp doc_man: man-stamp man-stamp: mbr.8.txt asciidoc -d manpage -b docbook mbr.8.txt sed -i 's///' mbr.8.xml xsltproc --novalid --nonet /usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl mbr.8.xml # ugly hack to avoid duplicate empty lines in manpage # notice: docbook-xsl 1.71.0.dfsg.1-1 is broken! make sure you use 1.68.1.dfsg.1-0.2! cp mbr.8 mbr.8.tmp uniq mbr.8.tmp > mbr.8 # ugly hack to avoid '.sp' at the end of a sentence or paragraph: sed -i 's/\.sp//' mbr.8 rm mbr.8.tmp touch man-stamp #online: all # scp mbr.8.html grml:/var/www/grml/mbr/index.html # scp images/icons/* grml:/var/www/grml/mbr/images/icons/ # scp images/screenshot.png grml:/var/www/grml/mbr/images/ clean: rm -rf mbr.8.html mbr.8.xml mbr.8 html-stamp man-stamp grml2usb-0.14.2/grub/0000755000000000000000000000000011153000035011144 5ustar grml2usb-0.14.2/grub/grml.png0000644000000000000000000047032411153000035012625 0ustar PNG  IHDRK pHYsHHFk> vpAgA!#IDATxku{s{fA_"E3z8cVYDJ'RT*q\9,vHIH"H*@/`f03w{Gw^ݽVwsܽ_ݫW 4+@Rj" "@a*GꨵG L/\3vFq='{m wЬa+ϝ I"=Rמ.͑ުka8"5z zA;^3q0[\: ,EK$`o:": ͠R O(5C1]*%|k`+x 0:GDcm# 55jZnbd#,)ne>7j:,]n`,>}G~8At 02NΪF9GffP%Yq4X&1Ƃ@O;7ot' 3_4>[ŷ5)lmS=móY.eQ0Jct,&LJ5p6Rhd2,R.qgWaԱᬑ kBR_۟QVPE#Bɂlj 7*4 Ox嫾mFv 7 W7a\Tv%]1_c$f2is7GuP8@uF#'QC @A^m}0Tf!ӐT`,drZޮ`!ڌO\)K~JD}tRr~ϴ XOT!4#'R6r؎r`BkI IS+!V4.J]R H/IAtSz~J87=.y"%04D \8$ܮĐkjk/E+]D-tG$-\rT+S,,yHIPY--Zl gL:%_yEDcbe^6]ADhjڅ'WrQKC1>Qc(0k8@A3llbIf"Ҳʨ)Y2u4ۘu_)d4#̓Kjh؄hZth#/N<՘ ƫi@o-F۩ހ]8Z_P 7)n#ʰ'tOd**6h8vFk12OQySRm}#Hu~NQyuJx Գ,c0* .=^D\_V>(f j! V "KUc^rH|6&b7Sa{ʓBt~ 6OaUU%X-Z3J>e۸"FX`LFԄi=;Z?=CP'C PX.f#vn`f7%k=lv^yf30kPZkP>X.N4a+V%&ȜzdlK$R٢mK|B̌0OT\d5Z`3iDOhB= }kj5FU ߣg o!Ϊh~WPO 4ѱco*p|`h ᢭[cdbNV̫:PI~aߎe%W4ŠЁ8R5}}!ΈCj ڲRUځEdˢ؋3 &?(PK*rSD3"M:VZBREÆz_QTnjU1ن !Ot 46kfN&E1 gsI[(=.4[lA-8#8r$1#c~yeiCJ:mDML/g7RRE?sh71CM5~ eiW`zz&Im`, abݨDhCYab-ehsZK*^ [6Aϰ6 Gd6Y4ÉYnX,cw[-M\ 'V0`j<Ֆ䵷/6WU682xE  qu@ HfP) {[f*;1#g"[zC\A@2-^ߛ BC{?(mc7N=;/#鳉LV4MBUUBvǽ`q ]v[2Dށ`,SFF]|p\%"t ʠuuDQ&O)A<2(9\-[픉C$2w]i_ER4~*؜b^*?/Zm%: M6-&fb@yAn'Z Q[@tШkI-* B(RN(bT"& E{eTՏ4$Pm*)BHy$z&I,W n|˥`+<%D͉ض␰ XܐA\ՇAq5V%4| Q4Bt(Ec%">܎wСϾ"YTR*]i`qV>1,̴zI-jaQ&ڊ$oEq|:(iOHy3c]1pkb*G]%fZΩ!zU8y]DU V%ʥ:tQXMg(4\ dQSM¬h:{lTɎ+)g2btܩ=cF<lbv]6N $γ#T~%t&%WNbΪ~+Yhx`Y'y~e~h[N]ح<(=Ѡ]R`fwK6edc];C k-J+rl.pM&j`{Nȋ]aٵ pMDԬ Jed(R+KLS ;#k.dzjQ [j"ZVY+Tg)ոWʟP[f N'v"6QښY!۫VY:AX@q/BzСK5"cP#`>?1?|7X"31|lffykDEs{6bw1G״$S }BQL"wpxN6ZǛ+qRi<!b$ yUjLrÆfY!13&EЁ<$n#W@P&^}t]D%fvݽX(l0s8 P{6f ǰLk mWRԲJ,~9EŷrwvX&Wl؉l'7VxSMSN_ٺDFo]zBن! [VC!r&'aNB2sS]>;w /;% CIbRd qMǕ 7>ق3݌f,<_7D?5`!X"5eC|+K2-}E.O^*yef^N* 06j(BYB`x{6A72-JPD O`-J>?;3TիI}xeTqM6S=uBWJJs3l]F:`~%s<X>RLX8UZ}D8A0c/*CQ5-hM^(>#|r$ͥnN逜2:?Lީ4ͪ@ii8-n +K"6@V 6MdH4'4tC 7;AhgN ; ;%moJPւħbl`&-)Y3`?ؽ px{Bj>@,y33N@˵5^ӳeOiNJg0Y*k$m60K|qEu7 bb3؝TR5z83Az{">QYP;>" W5ˍۨNOIh@X  ].:whΞoEvtX"5h S:lzsFe .\1igo"2)>{ "kfEe;[fmz,izGqlɑ\'*{*ۑGpUG[f  MjmjՌvzFh2ȐܾVlJ^ym>xZ^X~Z@u BRc֌ S'o"Lj9 ,E: Q}̲.'L/G5xm>5y 5P[ek9l"ϥ4(HRcպg=Kh.of ^~>:jj6 i{BqOT"x+}SNGo39r@m0S#4ܱB|J FI3,źLI H#?SM#C(P> F9bmon2%.BrГh%ov6>$oS>ߤɋ̽iKa!d,o"#0h$k&%G"a2y"+E0jY&D [O| 9geHeq}9b"PY&FZj-IlZ4*L< x>R㯓:cė.̃!E\ SyN]b; #HSW-P :(qe3eTJ9D ؐ {PRh-SԽM⣕, Sr D+S4<s3q~H1ۏlSBM= )֊n:zVtVvBîzm ܂K3X$͏#x-RȷbX JZ1bu[k*,3X*acgW00(3FҢ'2V+źCWըjT;FbxI4a N1bbR |x[a*RTiW &DLL"OUF]HGJ3#53G 'GX1hRmXىHOX.T2|CƏSNhѺαiA%L.bYQ@>d$LudS{@ZS1!Bf@jVG1t ٪(DbH%I4v8D= 0l]zNǙRvl\FIyoF,~w ӡݕ2QmJ+ﵙ[((+mh5)vPa{k e~ ViC [2ǨqַYaM~fN:J.euP(Q46qO+Cˬ0Up۹ߠ.&ڔtH38e4Oqήm{TRgFJcѧf@+%p'5V`Rkn &4VJ[iDNv^=%9ڐMvNcg)b #bc}jxIGKnpE4OϬ6ɧR:TŲd^[d xH^R8k!md`Q]%hL2F !N,8^ +6 ĭi!)$V=?]3K4 -lA#TVlh|4TH%Ov_7w<_$RCDW0Ґ,RvaÔSv\Z> g!,Bu`9٫hM;zI&ku]-TÀE61SC@*b="èDrMORg&Jmn*ic>Tyj^щE&~;!3H  Q]G`<4%ԧlyp_5,űcxvI*#]3@T/_*Igd8Ue0eRkJmy48ƭ\g$&8GW*3ה*`k@X'"Z&R1 mzI79a%sN'>q4I5u'>R"gBha'PꗐcDdh9`""˩e%OnYv^tK}I_<(L?䅪1a 0 Yq0"pR9FMP76ɀjrwܦW,S0dlBVBr18ԙkԀ2CD3 ̐'1_d5MWRv\J_<5l]Z?N}R2ugˤX.%wvO5BhzYtk NmR, "6R.@Rv@*0k4,TL4lmXƍW$Nz4Kѹ/s~6涋D0Q)8,j/V42ŔV v#c_xHah6N!W!m|i3DO=|}D0OC"4?[MQ&7K 53LˣGAf敒-Kӥp_&ChA< JŇVI!y N ^B MCBqnbq[J33Q} 2[ dy]/lv%ޙv#[Qa)yH<Òs¤WlEbj`*;¹?zIs9C?ݯPP )aF Y k AƎmBAdej bp.S-&zGkIMD!zlW4I/NQk78=Rd{IvqiBpcKͤ1}3w' = x=)tro(%V#I /gjk/j-,'P&Ke|XoSid'] /+ʼnMMϲE?m\P VzaN1AM5'hl#οa m~[EH4̢榄'T bFm j)]%lp˲7U~S3-W:P+I da( B,Ug[/2J($~ v.`C]WL*s(Tge#u%ɬ) mr|a[B.1{,x(CFe;&1 3EoP ^W< /⭽0}WSc $ϋMՈInEC;K$' 4ZUkh ΠUf?.qKli@e5GU,vA[Zx_ʣ(ڌvbF½9 9p:`8DsW\ Aw1gq[);VQY2bR0{7VpDzu֛XZ_іKWC)W&S.ڄ };$EX=ZRX_ŦS-V"-Y*¨t4lKoۋ[7fZ?h=YXE]bT&{ 1IаY6 (|o&G gj9̪ G&W#R/@F Qv4[H\V2}n:4Y%qG\a:_֔j/2Դ>}4EWS*` ,=wP'iAQ-EB;#w[e2OӹK|[AL/BXʛPec-M+hjh C=*&Wn > j4]"lfk@U VNGZ͂Uqn%J 4+)60[Jp,Cԧ{ӗh%YsNBUR*Wh%FWd*ež$/Fp 4[^T^)%_*\NU bϾa?9ҍS,ȣXߪ}7hp(TT[xAi!eiCP.|"S8։pn%hڥQTZ_]EÆ]j:1Nk^*$^e倦^NPaiu.zCoꯓbL|gfưrKH 6,abگg䜧7W2VMetm Y^ 둔JHF-պ *Pkێ5iKQ-J|3Ҍ_-ث[hFA)}`kH–9u<)F ߈CPs Z'` yml/{@b5"27MGhФ>ںͥ-lWy w@0U({?/e ƩVZUU+25K*Q5j zy$EE6|6FŠ6o6Qid%lxEww65I(UjY G v/';OBS]xH'&nY\Cdrq`Pţ/KQg@WuW0M)CނhaцKH_[nO[$M,(:k(hKa*/E{S E5.ظUCP[s/C[ R~QT\`8\Bʇ6$@~* :NxЀM%|Er$m/P Y&@Nl񓡯7*8W]c\=R<4Ok%f;5F"P"j}UzKҬKˮx5 ZNahTqQ-U*|s|KyԞv=}#rN t0f2h=c&f DavP:< +)h4&N{֚ 3l>`z]tGqm 2lОܲM⎫rmY\ɂ|@+ #dEN#yw\qq2ʫZͲՃ}*`&e!f^1sb ZI[ϽA5(pRmi׳Z(FmmW.4DV-^ֹ1d>ؽ*nzFHV~MfJU(%<=h ze9y[ .EHz̘{68;D*}_Z\ITڢHV!u_PK`+h˃vf[j(_wZ Si-+v2굵ϻ01ȹMVSUiu4A2Q 9^Jj,b3_jn~~}4PGu=8?9?kdn۩>ˣX>$5)dVZ]T2ruk<Is$i^ZZqE4s E?+p {N~R_*![-`XV`&mBn]SDŽǵ &*O/uGoR3o` %V"eQ*c]IZYkD9%al@':JX5JYy6lc|k !v O&6 9N)b%sY"sf+Kep̀*Is\(ڊmlNNI5%؏Z;lFnSs-?~Ձ)!Ɣa!I91 #գl5%L#geIT~kX\LO1 "dESsxdGą ioť%(5G w S,ШkwMWj"&Z]ШrHQ3i>UVyP&E|Ҡf_eBXi -Uu%,Ok%!2A[Ao̖i Bc*GFl8-EOʫyPaHalL#`:N9Zƾ+cMhA wAD{E+jE )v5q] ;?]i}NE%$ynAo]^)(ike=SoK4{A=#$gi1egkdvAkkF-*Uc`A8j$UxqjCRԌ3m)ր^Sb&-YSkA]b?EEaQ bt[/s1'$GՇ E%ʀfW;,:)DMՐ[QYOϦMJ;pJfWqiYj>99^]H2EC i:z\КjDF#XCۋI7>V46o9ӆǺ$HM PЗN@у%'GחU gGyRNEj\1(mFyESڇ+RB\x~e'ߤE8c*TN75BmQGIə$ %fԎ`b^7p䥍^ ,2n܍Mv'ۆ%Qױ$ ["DTO*Zc}+l>z KR|ZG- p%?: [`%xc)jHb5+q۪6o^Ġ+^f\k Og*Gu O5QMB%Cj- ց  W)Ma8&ݗce !jNw2n? :W/CF%cvlLof/'*z$,Ĭ((XeDr`섙YS pFԠdi5šQЈ7A0a|dŖW͹DdzUwȺŐ@юYpKVbcT\>YRjհˡ+gu$3K^SKsU5"nӠ? B#\R9e=;>Pw<gTXg55^*UV+L,M|ͲRYgyߎ}Bgʭ#ԸM&%s7NNi]τïbیՓoWη`c O4 =a_78ǐ^N*Ύ53,%-LY5QrəK9Z 5y4Sخ/ac5n7h!@ _b6ZZʣh`@U9#dPxN ^!@hcxue(͖I׀jа`2bF$-d{֦aE*gUCkY+XZWSp[FKőlS Y窢v, C:i FuF 3-fnӆģMTqk)<X0|c Flk"t9Ln+B$s3l`"I:a^./Rw9v#W̨g3lA&=RzafRayqpynE̴LE쑫LdBZRj#fk LКa]P51P[U $~ĮAY Il0<"8RK$k 0(/\3j4T PVcYK^U[yXbINCUΪrC wFV1ѣRn4%EzzG VjIwqj7¸Rs䚖g%?o8藅׆-2Mxa>-J'D|;Cqsqx#](1bS6/+J.23z $ FPI@Y5$J4s`6d.?-]s^mimQרrH-@IQ[̃3hnX̝FX|lfÕCgzD!X1²2{]K1[[d lj 65  SN'ɦjr6큱̅O{2 o YԗB? vW(wTf~NfUiRL\/ƶ;A4K;EQc'6V ҪwK+Aށq\R,@檜)s]γWs (b7^aI]+6Z)ߘT.m\faL:% ZI69{Q< bsV5B3Z;b!KauyZuQRZraɁO_",8欪JVVU!X0qe*)~VI(&s;"jr cעMs9YrK-.U;$'q*j*l P +! rEQ`]Ψ m;IÚ ";tNEձj^w Z3b4ʒqe{ʆT\ RJӼ2ZF5X*/9Kom UCCaםMe 3{EeYms r X*2g~@4`||oH7&HV_þ!¦LNxk9a!DwheIuoN{i$"r)@˔jCBB϶{VGx~+l5R(ey?Jaϋڟ?T&^~sr0 Y[KU!UbT[ ڼ%|~rȠ>D'i)fȴ608Jsga*kk(dqtHձgoEfe`YlE-qՎ 720-V0!̣ffR1{MEz&F!BFBm 4.r4XJ;X:PyTh<ƞ:0em7ޗI3vDj"Qݼ/1::h1@2>=$jVzRsٮnLO:C$ao1Ͱy#JAmƙ*А2ZrFwٓ`%- -rr5'hI6nAGkcK a<48)(iZg^뚕HOKD&#TR"_-C{9ED%Ҫfq4ΫGv+ıg,KeD~TL^v#_ZtJT*VNJQWJڋ*&pBBU*OfKB 2sd:1zS?lbkJO\T*jd,f)-Țb+ʒ@ewM=͉;U^5l3@RgW~Fl׀Sn&~bzUkF|=Y!cYtMT _Wa Ad)4&Bu1s22j +fB?6mbL͆,M<ʢ&%)n CHMo'_4t7b5ӄ0oԚXF{)}WlDΐF YS)X)zS,"C4PxF1_.BwXKoBq;'PQjuS['>vz8[pM)H `;[-f|vh!tblC&|.BsD!#YuN(TmWq+Z\h+ "C5 =Uz=Ƞh^V`[(EjO004.NXK M1Hľtph4vƠ7:UġβW51:(]^)QѠC 0T6aNn-}q+)<<$N|%R=NV;Ii[)jԜv6pIf(7YiI 0V"[NRf ik??yz%>2}Re~+.|uJtK  ̮=%abQ) t?,@n")Xgmy/v: iB}E7D~Z~ڙ[wFYݟ)L8\Mz Ʋ v.Պ0F/ݥ^,GK2; a!CŪ9l|nƣj%L.~VrPAgǜDhkv}JD1a(f<N4MjHy`t_J}[bfdOcEhIo#r`OƑ]%@S]d (96RP}a,a֢.gU,]M+5I R:+ =T_+[(X? ?Cj}kdG4cZ_RMNTL"ܱ(ˣ>:)GWIuT}*MJMg' q r2{io%یY5Y&Зh6Ul)R2)i*9sds摬S~ȧ\fHV,j$0Z40%5WVBxLna1DֻU6^cWiwdj5,f pҌ`ҭ~ÒUXE,?\L:h;_'_56ӪLX}HEcUX۟X:;*IS ?[ӑcg%N6I;hVäl4ʆ-/K*.-%[Y#'fY}H{GdҌ١q(m6͉kY9{mʘLdhuFWKPiv&^?fBBZRĊck{fKjLxJ֌v5H`BgF񢛜$J5MA%Kx-]# ɻM?" . }Vd,u)! OI% }[͵jc|nS].G4I YdJavԹ8_uB H N+R Dc'/M17齓\_rرb'z$Pg7W<=Z>={.BWū\1 %6=Q֩:_ -6DHG2࿌ $oUMR󵇜Mԙ}5\ygxCl?riߚFҬQt8 %;±+[]Lf 9 ʪ'lRi-Z1QI5avB]І"إ\DKo@Sַz, `Ew͢ݛt^.-mm\$i3 %# ) [~ĥӥ+JLgvLmHƥilán,QHNr;h>CC K5JSoSGJ%҆Sd2H&p)۔g4브=\tJ=ױLt" txn1`"0:t4M8RH}=M|H̜층/8ibEt[Y|6ԫ` mF n-ljN˿^§Hj:Sq,LԣR9jw?+\/-=C99a^3*-ft\3N?J'Pk S qi|Ԓ Qʸsa.VfX1T_NTz MQp^Pʨ \!H3N2d3 ϝN'j/`2ΐ$d~9k/W(1 CY0Td 4sYJywdX .,K -L*].@|UBlb\\߰' w,`i 42JqTe均h4ńꕵ/sKI1_c {\:bt:IXn[?o YB8F~qKh*gZ\T"vB, <!!q`J-4@]qCH9ՑW5hs-uWPiazN\+ZMl@B'{+y0dXg3!7Tʟz~$&p)ޱh#̟33!{aģ`o"k 3m&g9`;x'/Ψi[HI '3O+36w:euI[5gTg1Pl9NK (*6 :EeSp -mqhAjY̵r &fuP6<%"C];d켪B[ %l:Ow%Ži@fd䶅iƔߙ1SjAZK] LZT+’K,FW^?R˨+I큒uI CPZ80F@kyzP4B~Z-MF3#0wE]鸯YCh82u@OGfjEU"3RXFUuoV %s(q=`G( ]DB4EHtW{@:y|#6`$K"BSFvrTS|j$S)dl#ѳ[ic*6G"B[NAGYyM,)w 芋3Ȯ雀BۙKQ 7v'OX&Gnd[a'+dL>SxMnAƌu˶ͯ`_ Ĵv怀@Kfi;#DF:dKM}hUtwS~Ei(Q%w Eyg^*9Gk9bZ8ĕ+U^KjyHw1۟.UJyQ[a$'YKa_ں |lyj juN]7 Хi{LxP7Xl>Ŭ~ fׂUn+%Ӥ#^=6W5cۧ k͐|\=Qщڢ:!4l맇\%8ƘYR񼻸?s֩;gkf"I9av:g0&  C+kf$ vPFuʅ0CK]>J- ٘TOP(+dg퍤5Iu%J'Dz^0HY̆ݙW-k*;:O9ަzp+ /6O>R=d4le %bUHI-6X)#+7+H:MMWո@i}H:^?NDXetf6Ɗi-3OtNһ b< dp4TaּoQvV0Z.cm-lg?^5xdlsqv8T('Vn YOOjČX_Yk̝>r7*Ӑ^3jB3Ai:4ߛI4v$¹a$ꍢɳ!(,qw@m}\NC 6 }ٓ.b= L&v#+z|54_ˬHj2V/M+Vɵ 3 ֒2W=)+ȬX%BHS"6G: 89kM]AʰV)HH9*dű1}TWiZ624cz psf9olѣ>fpgo s05$E΁ZٽRmŒx#H,8N12AH21*3ƌ(NXzc#+ͧxA䧬v &U8o} vֻ sB*FzCM1wﶅLed rz,oC aMvl\Z#.'0&\v蓑O6PiܸfZN\+ yg̝GMԕ EU1s4 VH2$yMzg W_R cku,{PG)i,S4;S΂8j R,lن^Z(w{G~TNu'q@J= ufiU#!CۓL,S!4[ʂ?0p/N^w_by|W8A|Ay0v+KS _rj;ygu þTV,J[D)S$Tdg."?[,yh3`9m84T@>ZOZߧ'~n¤\F^DfR2M0BT%}hWr?x[qBK5Rss{w$9Z_s=n sLVҔ"sAIa !%#[MTɬUݳa8H<}d^2 me5 )O2h]O,մoodLnHVShFm%d&U'NrP]Ѱ"48]~t_F2ƶ=N}zS*b4%n q+RHD=]Xݯ -R4#řf,XN:طP1AkX-IYa ~Hѵ|4]Y Kel;Yfb[>!yCgK̵Zr1գVF]$.b֕uЮ3g$-yO:A6NXr~y(œylK'V)ĵH$3CeT:q'[p)ԕ!k}4>ܛֱpRzsL4ѧ<+ ||fd.+Ma#xJ&. B M͢9?;!$ײgtnפ%TqhnSEJc Ts3x_S6lL= 6SU2:a7Ei.sY 44-`+odU{P=U˪uhhزUԻBJ׽B'9d*ـpfNItk =36$akǐxydސN[(l)i:Ik^ CYĊʸ-3$S/雱|3 ţѺfd&T(y#bgֻ#rKD1BqZbш5f)kvX]K=2Pa]'#R}1O*bABڒ*FP{kVs"=ʧBs+}A*='O*g+=;h+wϔ?3x9Ki#-sQnVP*87%.17^tlc},CXg= )2$XZ6^u\Pov8hv3ScrVKkD49$ BR2F$]iJ`teݲm*zp߱C?j9ȖڷޛN9XETvUyrqxS\OBuޠj<9JNfo^$|{cۇv+4p*1LpNLD3eh\0Y1閩 cd0 1eյ?\ᛮX>o^ UN>ّcJ2_׻N{ӛbE7bѝZδQl&_mR/{kz.~{,>˱.i/%Tکi:kynªCpJ2\;^=Pe\RmN(G֏W^ oaG{XĩHPK1,|=ST.ц]d_i^{ǒ2mo]#a*ٽ=t Jy/3x] Qh"ZTo=3㖙J NBim%-'n]/U!3>MZFw+,ҕ[ Sͫs+x;`Z1JJmp>^z6 2z+Eol?{R6Gl`} @)?XcRP芩3h7 ڟMNL0/B.5}x-k'{bouk/ ru͓;;e  )ʡHZnA 7}*-eKCCo m̼Ig>Z_i<_ * C߀;M~|ee1`*r#nX 2A^UƱ/MK݉:.d8{FH†&wd90utEp3x[s}Iy $K::77;׾rģ;sמg?|>o?q {Wvg}ӕ6ldb)GUk_u2UT f/Nm% rz¡;FݖR04`L((`5=jzm(%}ȎVd0\X&lxD ctS bZљXBpcTZ)L@rU9;a$X^&k]DCqByݚqʥH ߮#`F fᅀl߼>/~su3#īypv;.?uO|蓟w}'Oǥ+GHw!ZH1(zv``ɀGf|ΩB |5%2p 0gضzXjSrUfN0%lG9M)/D[ :}(8+1 hwo$l);|Goa5YĀͮ L![VN/ݮ;/Zwx[ʛ_wtC͏1Ā =7>~ԇ?Ɲ{P~p*(xI5Au@Z#32 V [ƀ!NCT5)"VQ_ 9rާ~t623^KX_ӀU^[ÀЗ" xM .% 1!p,E>#,L׿!3^uaQ)(H :AR)օؑ/,cM$/T ~rN,-n$ev(//(uf?O~3?[oPʴK0ƵxOKD~vojL.ΈK,mfy  Nu 3M$! ~caIC;4(bb'k8T4=j%ΡXDہ:$ҪI"Y C ܼz߸٥7Z$iwt_TE֊Rt p:ƇyZl8+sE"]sxo6I5a5']'-m)ױ:枆CVxL7+ra},G)hœS羕ɨN5&N7MJE"(ں1*ݕ ~YRAD|ǕEZ(t!egp}zKdl0TE&3iWc TijsQh(IV.niN"cI{+to/ņ.%Jb0A^HDNޑ;MhC? <'`5}sϼP>9NK163OWȚyQ~ pY:ԭ BHBioN9GavVDv #G=f.x (͓-d2Q)#HRXlXUgBnq UV_ ٮTDŽN=GxbG?W 8as{:1A.?Fb#Ow^)v۪\GVCD"ڻg/}dnM!Y}rKC]fFŊBR!FC{Ҵσ/}DuUpoR1L` &QaR&4L8Ji0@`s=6ԟ)Dp4 :DT `-:+V\:]%@4߷SYd%,nfa!x.~~;ƹ%owCyg[t,8ntb#{K_G `w1BxcjK&Jbd פG^j{?ޮtЈf[?"]h:Q! g,/'A,X="s,3+pq`Any$nL(Anjui6;|3]6SBv5ͪ Sd#g69tp[Koȴ0 s8[!:DDXiLͿ[vZELnOG.2ٜ'+猊/W53+h**%d 4DTU2K\J*MQ8mQ%h8E*Oǝml;XY?S>ke 0}͎jy5v7Tk/ H5aZ3 \Du_$&F$5휓{ӰLnaYv4D0:^5l$/҉_΋( . o^Qzl6{Е͙)U-eS䞒?6q'qϼ%]sa 9VjjcCZ}i:,JIΈ Ih o[h7[vww^tkWvaڹnݺ}w޹s!I+XJEɉH~c˼9f޹_S~ӧ4P,Z~,LܦH<˚.j/$IuX V`HꄲUP+8;2N굣wCYuAj{1IDÂ2@@9ya?@"JĪ@.&B ώ[h2"ҫ^Wm$hx͊)#⾓:7.jy6c]ݸg;t: .S0VIb[Ns|槎ᰱG{C??흿sk׿믿I%5dB _/NcP'2yQN秪}IpgLe?s%0A7&IV|L d?R7a<@aUOPBPÄ́a@n0< O c#`<Nn.h,J._74-r oAI `%i`t';o@cz}ҥ}~~?@vw߾qs jb.hgD*2"pʟ~3'C, ze`"+t !K.ʟ@Nkk{۱`q_A^a@OquDb+ɨHȝt1rSu7;:GYD)B(afR8 _63Xm. ٠ IDAT<( òLqp_ʒ@1ROBI+۠jNڮͯ~3C^Lx!snVn]< +x < pvf 9^uଭ干BK7p l_zwN>X . mXST~.c,.Nk)j+aL+O+Uwgm4ܩ@}6#[[ɧ)=kÈQlu GĂxu &z@awl6m;kb6JS^fVѥuxNR84d!3N0MIVXVZU؍Oƭ?sMŵrk88xp;Ê= ^7 "뽽/ptmI> Q]ȍl|W?6'jB6K0h|D !H؋ ,= qMiO 9oK",?jPwY*ۨy Կ! [bޫM9'*iF6Jf[6ceеCi`5qWޮ63ET6B[hb2NF>e~]y[{Y1] f`]wA"2;;;.\xǯ^pB2'NwKOrH _ΧzjwwwZY8:.=C[G6ăq.}O~G??SԕǮkq D*6nIJ"|p@:gSɚT"O2mV~),C&$ V@ YE/h^WJ&кh:N#h" >.,v?J h;11N#66⿈Kݳ#ۦF1A@@X6x3jwTFN Uyq~zԢUlKWw)*bIN=|uX5'+ v1D@zgooܹs{{{;;;GG7wVe8DBX'>{;;Rm`epHZM$^|N[SkeHv;fl1ux\$PauH8 <R3]Z[jc1Xɤ%$6ʆiG647?tIGV0 ) ۭx j%Kw8vc/PG~Cf{: . Jaגm [.Ú#fͼAB *'R,Dz! f}!SZ\a7n~l //yDs.YVupvv.#w>vOWΟ?c,RX׿ O])`Tɕ˙=S&-~ɮ:*M9WʷKvGcU_ԛGnx !E==d:V12uL KWM)aԢ*{]2 6V乥i)\_ilfIOsF0K>g;S(u'%&(&4l/uY55]߸N!fÝj n`?xoޫ_ ]}ҵ>Vp#Đ+5ߤ캵9['/=?\ن"BX,"P[WҰ.n#߬f\̍X$_ =1*QbT3aEofoa\td X-5mXe`{̈́6hzFKu9R,&4K$2$)0k 4S<6.UWCSgBu_߮SdQo]֌ y&G֢JA D*9}0gP4QJM7=_Lm9&夬Cs1bj9#ڃE>w&5mwX\:6ɮTMꣵ0(G 7wR =sU_|JL^dAbP*oMd5?o}_u HiPjZ'6\W/;|ۏ|z͍WOog?O;ܿ_*MY3A݃;=&.h`9EVV@vJ"!dsu%*1,g6] zE.1HKf.+Dsf6&a_j0'AVڗ_M%DX7Ѧ!a"1ψ8r\u@#SvrT ,bM1p5NU &|njδRڵϿ--56$@nCDh=Uk##ZƛЉ8IsX ޵STl H_g6tsz;s F`]x_oZ^Ǿ{_O\Ûo#x\^|_x>AKBPVX42Л7k&rN[F'U>7rPщV"\T8}ׇ|sp6 =z〚ד-1c[f\<Հ)Qɞ+˽9Tg.,Ǩ5!ʉ6$ ~iR:lI\4VB]JAA$ CiLR1l1sX"QO}?/<~_&zZ,u6p.]aїbmhrjX'/`&5RCDAX"eQẻ턍ըn:–^4\ǠF9jfcI4iwۮ vu,ןڤ%+&y1is›A14muXeÜeDM 'PSӏ66piF6,Ղ&'dmAyd 4,?1~nܿ__~77߿xa׫x}Bpݿݱp/}K?|M8.&)V ,]g̞ -:H ߍqUje-@J* i9I{F 5iH u4zfb)+C4 "n)!>FO':vv<ʹ1ɶDL|xx`[?w|>я}O( %R#ɵx!U$kMt=b/ҁUͥxI#U=2Z.$0Ql\ ٩J$LqqtՑϤӽj*0CJr8+S4 qІq`^KKʋa^ ]@Z vW+_$?fIrhDSu(?IkeVXr~آY>˟jk~c՚߿W> Vt.ظoݺSOп?kk\9pxn?ݟ___?c?sϽKA ǂHqY 7}7^6k0zg H.MQ['-k[ b9TRj[+āLO1ڬN <,%(f-T!\(WDޙ޸V`+l 6F1 C\hL1x> {FQ=N6PJ*"SY?JbOo2n  7tċA4eeBڌrF2'-/'謓8ZnéFgڶ0% ?I׋~=n~qOx;޹g? WEG ocHffēOۿW_[cuH0qo?'zMj?YA*DE.G_| >KňʅPlZbPKT<׃5Y69/Qث!W^mҫʞ|ċyD"a޻c9ІF"Bu -rJ"/4Ӌ/+# 2ӄ"s\Y ـCKY++cjw[$XD"Qq4"~#fUv@|Z},r"-t4M, ӤWu,X'jh[4T%EX38lV;F*Dkp4<0 Vi/eo{`gwguno  0^o0+oW._Ώ}sl<8?ȷ?v<+7j'?{[7߽}lQPf.]C'|9f㋌P:}կϽ[oAKϏHA*s2VPu\Kk): " SVmR#MUX<lSqFW(x0[_"X7q^4TM PUkKS"5* FQ g&cy#pj.4uZ68q, m?]Qzq۳/[,^$c $LK7bVSppfQ'7Wnu;M%ihܼ }wis @%/po ^ | :˗sמxҭVX>o໮GʵǮ9(@?O?h*\>,~g'/cp{_ysgzvx[B5y/az;ϽUЯi}E߅7+!;||D6.`"UY2)ʖD҉Y]ȟ-(6EYd-4hzg8}=Jj-ޙ K]qE54-*WmB+(j3"ued6Z"W3_]:dÔL] %l9=iY%cb˥x0m 33ŝU|'c֞׳L܍Z :MJ)7U]*}l`h3ET%@lQ$%ivNʭvwjr]xqoɏ|joP8~{̳W|>mW._>`ɧ>p㻰{ =^'.=[ځ[^~|Ohǟ =6M\yb|DG_'o^8Wh^a} *tE]4lYKQmq`BL!VGn(j)uB9$BYl|utp6-6Y J \ʊ6QI9I2a'#•Qxs|ݷ`9x q!حV_3sV5p{W~7_gy76j?xy'*76o}v~ /=~գGO?4 l{NI?,6=);\v6_q QKjPGkK@&6eMbc7 #%qHݼ2fFdh'=y-$ l)#8RSqFhpx=S+ 'pvhIpb9|LYR\hʱVp8Dj̚F@CZ npDԡ m5W+ ުVƣ$V`)7I8ET,oޯd\CN+Fa g*_ٓ[KĔBLQ6RP ]jh9(}+P5D\.]ηq!"γOm RC|'BXjzg ߠ ?B$k%ڰ7nJ@ t MZf= Dē @+YPn0KM <SrYN5dc8w<ˠ`~Rõz^C-tE"xϦqxAk_[V}Sν@p7g>88wWy8{<ƀD7遇ᅝ ;D'CeI6O$VGWMـàN,jbV|kn^dk^Zo|-`gJre&WH}ҢEG|LzBPZI0cu” U" h|V JԤ F06 f!tZM,MXn$.3uDŽ@%qi:kN)Zڶ4p1Z9r>i  Zzј>ed"ˇW?CΧrbu m$V+zpGb*>C{-jy9vo`54ۜ_Cԋ{>!Ol\=wk~VNǛQ]VhBO^Ñ/ԋ\Bޕ~OHo0{zفKk)q^D QSGN+7!D Fm۞& ƮIFHEF7BR"߂@k F'9F]Hp-+ ׵WfF)IX,*0TyR]r-9ڲ /خ.=ӓ U}dAfT}KF#UqBZ ܹ}g>$D+]zޝ#j|ן䟼@9j^G!<f?h?a[ё?7r`൷j C+EW?G˹L8edJ]Na peL>pC&JE96urMs AtT`2NJBCNI]+vgX q80V1|2R5P{J5-XqJOpn:IªF̑$#39_SYj≮Ձg = `_ZʑEcʶ 헀H61 :Tmd8Ay䠆Z H$ZsgE9է9"iw{Wxu?qnܝ{rCĽwnm` ?ēaV=מ{~/ݸjgggZAݪѶ$ (o{pg^wN[2?\Uܜt0pyT_[J݊{wkt !y MZ.*M5+uQ%EzW`=sVyܢ|o)t1w^W/1\Fu͔:"/[H1VF;)&Vţʃ9z~Qfh%`[T $OaYj`~YipeuU{@۝L MB*"u 2ob\VnuţD:;sM$:{ &|o? vvv׫ѝ6hsDDLD1߽wܺ3ps띝[2 5(TYݼ{Kh{A RMf/jҕ5p2fšUAZzI@&Q }|սh{.`;2+8VC@퍍eH4)!Zi Q)Z^I"!0;jYܗPc_gEg֚bGYA2!xb ] ڮ^5HN^lu1 BRSzydsCTFoeGTK궦f[ZP{IX j9<~֭azOgȟ;r?;!*~%j1jN[Z3q2ɌbhѸݼl]S#kS̋30t[qAoj#UlaҡFY0@'(`5"к C*3ݟ`D>أPFs/-t6:B Q_i21$k@ C!q&e{) OIն* ʁJu%O2= GrMܔTdZRH"15gC*0I?nof": URl+C$f$y&!\xf/ݹ_nN.XfoooyP GH8Hq~Rp zGp!U = }r04ͤ$Өu"*}o)eR! ,c(IJ.@IÐC@v$j?A$E:E(Ԫ(L1GbP3˙&G\M ZBؤrb2;9 LIy:n[ŶLH8u7]p _&糜иXxq8zbn،` x%2($}ڰ[~VK\\IðI@UQO1K7{ nOp$na S"xpp_^G.? =9v7vְܸNΝ?wzyΡ`p~WK+{:"r8ΨPZP[Yк6e ԙ'yV@(雁2#PsBc~e18\ S" ?plA$ƒ,nj+hG_d>ˢz #l +J9jF@22a=p>2 cRYD|e $e5fvRo2Ke<{7I-uL&(A!1 ]=HF[&bQ;} m^xE~]G}ᡠɤ 'DDy7ҋ]uݛ?={n1o>sͷ hwoŋR1%#1(pg߾yݓ_j9(TZ8h$ rkw9aAmR-BJ=kM RoA56]j2HH*ReRpI޲Z0֜Z(<>ۂDRdr4E R#-JyxUqҩbQL3Wmj e{;bPZCl#¢6BHMf)D%j \Ր9&XLb K,rmDNvK*?a|llt"4MT*kf6$-Sm=Ƌf[{񃃐 R!mH }>Q_'zw>_ogܿ_p!Xs3@r[57B¾捷7ǫX}GZ;ubmW$wE.JC,yVD'6^sS0Nrњ'0 '8bkHS&UZ "NOʜOuT>>~w?߽y;Ͽwߺzv?~pppx(kĨ0wֻ6dMJ6h۾\@R[oOe_K~1]V)$5D<6l1<-K!@lʜY0+Lx:u6 Psb>f,g0DzȨʴVIh+F,8 MQqY.PVrPVN!''$2 )(RMJ{#D&>Ic|"]d ek;;))K=A$A1?8,cu'#ά+',R_ԼV7_%g3m|F6vXI;KI?dyB3o$ظbK٤+A1H3>fc[R0XJĨv1:BeĆ+_@'h#kf8YEJ9 jĠBGgavE2~TiB\KL ᛷʫ_˿ƍ<6BpNJ o3" tz6tWì1:YmOqg9tCL'N)1 %ު~ism12oIqInZF dfT=Kc2s,DzfkP 7d7V*u@WJVE5UNښsJyJ6[gDj&3X`E|DY,m׈d 0Ips)P: ΡY<>K &5TOəyf2ÌaL u[]bż{>ҒxkK g:C@f1wؓeIBIQI'?V),+s/ԟ5xёABEBɥ'//{/_=*7'_F$1x(ܑZ_[6^F1`aKr"$BP`v&A%wEH,*OɶP-Eb گSU`٧Z AUځR&B:/3 (H0iE"M+ 6|H4垖V IF D)SLZ,FY4l,yFDuJR(xn 30ђg_DH=Yn\jxFZzs"HdY/ e#$ªZ>QWAe,cU|;d<$Rxf lVGڙjJJi&>pٶxۿ~߹~Oj0|obӍ &쓩+n><:,&2x"C@\㥝/go2#71Sn>i=i[du4Y)]O_]H[!:3 (4 yQpa $]`(o Du=[N7UhJN& P־D[(p|A*)9q݉^n2t!gyEo"H[IT,I2\2~kTᨼ)/GEP3 ~C2&Sj&HNP+`u0\2ݿi礤bzZٯꉜ3k:}岦r@,K4̸FMLW+Ңl5GYIEASbRZob"TH6x o`~ΫfCbK1'%)lpxA <`dއEx{|)q/!$66" q2?c&M /1E케x|7Ya%żWY1* +[j8V$Arhn-1ED.ɿc5V0F!=ɭjHШDTM xP`F.(+sٙxynXJP/i%+1'; 2-N&V F P2ACVg5]3ʴb]ZxI\Փ)~I,T9v0 ĄZVPcOܡ0ʦ$1*YHGScIu/8q5w]pA7 ~u_dj(IRP~ms?wBf9:V+":<( DdC]^mǃķZhX-6ԩvyۀ[ Ē'@ $R|j qzW曫j"?^uSr,1KD!.[[9nN9Y:JrMg7~!Jz1b9.U卖[ps%zu7T+brIX/|"Q5I;Q>GKŬ>^ KJOX$zR31 R4TUhu|SRLDtʑfϲJc)QҁV̩RvzE ._o6ڈ:r T=qp|pG${)JW TI]oRa]9eyam;,unRjȇÞJ4Կ2VP)u+ͪ-->p[oR5/ŕ fU#'"Mչ42M [.Pk$S6BiZ :W yie.0#=??O +ytu}"#4^)G_h 5;&RNi*/bc 'cE&1MA, #N+BƚxΝ]~p{GG<´Q0c6<3xamV8{ucLDͻDNb95<*kWuWo6A[foօ3SE pw$X$)%ULofÚ!4A"Q*䈭ے d֨($! b,ܨ57CQYQjN\RiN֛#h]/RcSyAb,RN.3|W )W)@P8LX^0:%e H/f3HlΝĄ mOߑ?>׿xCsݝ":::DnйK@i`.bl#}0qYBړebywX Ol 76pMP]^8 i͢$Y-;~)볠ZQ!%YJgOǗkZ5#dD k #xHIߟTR"-VHYDbdF+|mijoU'd +ԣ1q4=TnE9M!XUye=c2Js+`$d:ILbQ0 )_H ZV,{"@m @'PPV GҝЫ>-&oݹ[@.^x9XVVzp9~׮=Z.]tƍ  Bؼq Vvwߺso|/o"C^v"y}٠!e1Ts#.~wwH7n˱#g]=*4ʇeΔݒ*CIqm 8gysCANˇ;qІcr>ۖυmZς81r;uj{(W&fa8|SBzP,Buc\>^@FYͦiAb#!<^72 5BecpQr.P; 3r@ɫ%h/[/v>Z&bhM{EZ{E9t !=jvi .FַLZ@)(:k֒a#Qy.hmTyH{텻G1\[cD9z|޹[9r>7ti9;ݻr \|͛`|9.\*wڵ'׫O+)pcxs 9\B !#\$0:0ܱ|ў3۟Myas:Yj}\&ת;|Xh'#j:woaQ$zD.{.~Ho–Iبc$DV,|7/⧿S/dOKu3l.~{+-_AhYM!('C>̚$<5$UA-B*V az*+sCFEy 7`OQJ{- y!L>(r`oLbH k01pi}@vwvrڵVu pZ'q/}'NW"fl6BY“p{fB;]@_z寿  pawwggl</] v#=N[5}y,;/T H2g"ܸNzOsW]ut:Uq\t9{ҥׯ ,%#ʱ.֋W{;W-qaYΟ?~A"!aJw d NMOw) / ~Ѥ!qbr$C1k//5}YL''TlQK29R3/߂5F eQ4 hBZXS+'EAE]Ps[ dgBD5$a3iy*UF>LRJwRyMV l|/ywF|&Ig_:qdI!z` C*BC@c1%DB 8R[.q\bNLgͤ]&f ~ALr(5<%!Tt.jIDiwPLAfZvvV?[ŋD1ht^xʕZoS`sIpw;>>> '-BEչs;;;&R/8KpHPy[h/?ܹs:y'_pԀho޻xߜcʈeM1NBˤhF@UޣO4ЋIT-ʝg֒M@?O![ P3 17JׂJQ: .bDAu41Q&Yl 5O|Q0+@@{#h 4R 2+ NʚKÜ Vt&tَG$^CuUZ)pEqbQ>$f ZyA3^YP >/F)xL邷Qm 89SGHGp6VG[ԥYV$OΫ ,3W2RGiӷNq_A7DeaWdڜYLOD5V +K&_Q77[gĉ DDd^98Vwe*IlR ,ɍï) q~i+,ExlIC4$Lj$$;|8$z3 یKabj2ګX>a A(h 8:dyFvy~˽P i+0͖@9a+$ nDúq "8ѝ=YSf#!0`tdP` .zNGb)$\x;to"EH'݉kιzNj8%o#?'>G1'_JآCI&c*ux%%(O~%Bz!#̬2Nd{"Y^{"+UryT=%ؔs.;ش-kB:h,q2k]KWf/6boE󪜲[`fZNd6&ϖ̯/![( p^ʽwփ/hG7$`KBkH t\|pNIUl>{|pѾ@00e,[u\ ->nE(!/oz39wGa<Ve#t"݌;88n`h z p %aZ]vmwg{2qoRa :rdOv#ݽ .s`Dt2ڿ[osp%[?49UpeSi)5Fcb*##iĦ1[9cdJ|#LUd֔UM A GIU) xلь+[-@T:է*ӥ֑E{Y"PKjI:#jn0 Šfk-P*لVӸl kjAN]9DǙЗISV*I>"bQ+islUW924}]%1ՀzpYկ#'2PpC~Rf$%"uI:ϗQJ Z`W[;Ѷ ѥ'@t9//\Ѝ?H%},`[!"Cvwwwι7|s`v d&sno/ D<;Dفͳ'^>_ѿb-]}P wX,*1-ys\pZUոr` k\ו:IPy8%؄M 2'@{46q#-P^92'Jܔijrf9%2k#Եh e!.:ZYk HI`LaUfBJ1b7nUJF&e6NڜDifDIsbfqaZTVFR byQɱY7v-:yrX !#IIO"XY4xseሓ 䔓r .TD}z|=v%1&2e l;Ƴe(Ji[H vWH'mm?4^!$Zg^V/\l9yymΪLu9c:&H&It?j~߽{w7)e,' \+u.C.;oXs;qI\"ǡfC>7o~c#Z|1J7$\B׬#CORqMOB4df0ɤ=fm|My2ɥ+uK OfLe|f![6R&,'шDc6RV'(T*CM-o*V F_(ڧr*vj '5Ub1,PeX.-`lگV@4=jRڰᩄ]*AOd-6+hT,9W]Rb $Ns$,]!|^# \i6#%lBȟ ˯?5у}tnwwwoo/ $;@c& ̍Vk{P'M931R;;W^ݹqwo8qHܟ˖]ط9'3߫yXHH3HIvnZr+np8:?mE-e)4Ԣ(RI fPsիzp,>qjc; jd>TW*hOtD$rCm60D_Ozv5A?BܮAa`UE oO`#޴2@z1YlV9إJ*sRI-UU+q}Ê)@X%ڹ^M9OSOlz&p֍p=Z& ?i^+{89Në{o推y1{]k%c9k6SPvUۺ'(zW3zxxBlL%pO:YT4 ]vxmW'>_ b/?"Pjmmh~xtp|tu<"ΚRi(L;_?3/_o2/L0LDEv ɜ9K ԇMmۍ@\*)7 ]‘ߊC_\AULQV*Ζj y4-5/ b"nKܝ)A jʱWJ6Ǝ:4U`=Q;b*ƨf":}Į.=rR _XAr'H8B>8J筐ZIiј B$l^+aWhMCL5qWj_UH~K:-6Uķ/?{(IÃL)ͦ3Rk%r:xUs>,@FaK9- T!MDD.u={<_7Q&JH씨!=pYs`W^p{zO ycRZY Jփ|d.SncCsopI h_?v*7H_- - G;*GxTs]!z"J55P#kFIjSe̵{UuQ8 ɈF1Ϥ b=k[+Jb;:]i`q[Qw_++Xјt_^ou#*Mee$ i}Wn]d3QYmqrnL i9(& y 9NZc. jJ\4i6 wExqΩI??_G= uD鑋?؛"Rj2DI]԰fw=T<8uU %2o.E >Z~W@k{jfiq6xE1%É,<u0d5ΆI^C&}94"e_ F;K=^ڌzb ŭy×T§ftw9#աj|9Ҁz Ws^AUI/ *H8Xw5Wuy/rlT}:6ba6!E>Y;t`՞*-vq믢m&iҽ{@JDD H`pxXro]h؄Fcy\˜&5M'J ?'+?7l]&l6+vшK(%lel _y՟ϺYo܌te# huE1ITK|U˾f6ʣk_~">2F~#NL1YQ2 ب#Y2!'42 cČu_U:c^̉_q߯ϕ$692+OUlNđ^G(૑w"nWW˭K`I_'eM#lWv^%-Yb#L#J+&M\H6!PC(7^;yuݤھy3SJm z>L`K^}յ>b98iɨ#PmG^lm'+Xf+R;љ3gy^M p,{|Vm꭫y~MjbݭIIZ+kU9Ts_Jwg)e4H2{D֮q[ͯW?>f+Eqm*E.cF\_E]j)Fzw|s[hPn**xe+oSq-QF|*a]A\vԀz#kÚ<ʏEbSk:VȑO{5ښSiKhSQ(N'pW?izy1꾫Lns~|dF\yxIsYX< ?SaJiyp{~o2&d}R+gD)k9*r?B/!!^uyR/3rA&qSNć>W?>yiuk荻;(Hf3Aۉx: K|O^~cQqQ)p_ 6CR9Is~I*EU8o3_::j۶mw<۷s&+1˅ ȩ0LDkau, 9lKn!7 ]xw}#O?1@-m|=㗿K{3WrsiyȜ 31x{|gzSIZWec ])4 >_NuC:4w~|ς@tQҙI}}JCA? Aq Q/Z u΄njuG T*|RWçv5:dORX]'@,uSO8iRM^3+׈VsAc)ea<diNzNSx'ki;4TQUhd<ٳ{8}VP}s-1ϣۮ-&]7LxkYBB5 w ";iooW^9TâjXnCGkGȢf/=g~ŭ'4,WzBg.|{^*whR"{"@̥֦Jwy߇S+5խPۅo銼ѿQc>Cd@Z͕#E,ËYe wq8t] S,.Oő.O2.`BMt'^Y"ѬrG~U?5+I,+avBC9;bbĥHl˸FjVYj~<]MY?ŎĘS ߂BkqHe qbUc4"l1Ї",a=+qɼWUNgf$M߉A.xOc],_uf`XDFo:iJ%U]m+֦D t +pQ;;,QWg;vB[}7j:nʗJ25yLu;"Dnznw777*VIȱ&W/޻wı}oaI`$CgOOʬf@9G_[72ڤX/n7 s \C |xڛ?ɟ6Ztr"Қx G#_^y@//hXdA4[53@Z|U`o8mOd W폽( ou>9DT nVi:R\'tZiy5AfW 'L~kf`-5K>Eu_uWF+ uUٴO89 ߍ &:I`*Q8#҄Y2.+ \-(UYWWp[_Ǿ]SgBK͂9)%ܜfSC{{YJ k(yw&f3k;N9xiȷwQkt?i^YG`_R( E3 _߸uE3RD,' Ce>vƙS{Qضc]Yf]F[5  >:::::gιx8Sja1^㼆Tͷa}ҕ(=|t/]7_rmWfdR3ke?@sM朘Q$J0iS̹ӳS̔gT+^goy+FiH%deSmCm:_53Zk3 ,@ʱb9o q}gٝKlqA=Ylj1Q6n/H_X}%%6db7i H &,R^oMA EHb6;X6*zkSk?Z0haȲa4&hW2>b J%bCBkf<*By@Apy kG)^ZlbFBwRh|k/A_N_>&?mL7k=RZL0kVZu&bX,e9zi6sybsΜs nݺu굠$ ڵ;;? _} ^>{셟lw8~WΚ%&ҙU%& Nǔ[L)%FM-C.3s&JY+s~;L^H-,"%ONqfv"RlPvp0WkՓukY 4_:.Q NʔQ)d?(zZDʹ߁|TM n6 if?ZlPW^o ɤDsVW*PVWo=)DhA} VRF}bEtp ]U, t4{\/S Z9$eUhw]8dhj|eRI^nYQWeX!3>ԵW|&]~ʔ:ˌ`՞=iy5vrkxX,b~CΙ9[S/rWez}Gu5_svn\KmCS?wwisΣJ7Z3OK4V232#3qw;Tp)@AUۚ3#i,תb?U6=~_M )"mTYm Sj\E*\ʋ #Z}9y?ێ7bE 3U҈(cb#mK-ZVjzCm|$i'9U1?O1 Mպ ᔲ(TH~]#KLP[^' ɸs'b.6Olӷk=xS dn\MLzȡ=\OK=2JS_OQUYZkU=eF r%2?քA7'18cCԦvNn>-rCbyf`x^z%f$n9\ҷ,īǞzPəҙg-eȄ/(3rgdOݿo/.y&4Rȩ `=d9;7}}|ܥJv;񪿅7uzU6m AB3%=aBFklN0Fߤ`:r*Hi=A3"q"XBead[kV,YKO$qe`'%_ikE9psƤ%ڟ ߊD0cW5w(n&jtk}F aT\$ʺ4"%(9!4rBh95|+1Rmj\׈:_/~[-JĔq*7`w+zk&`~WCܚnۑ2<9߸7_)S2˧F4j[₱޸3j1ˑAX? vs~3*7j.J1;rD;8@@&U\TrZ,:F0pjQ;{h1ۣDNbFfN5$%QNL $ ,k\"ȇ?aSf7Z4WYa!FrdG]Qb< 4(?Yc>1y4hYcH>=0& V[M )j֠_;KpSШTZ@ P1/Uk%0Ta:hU @2Jv}be}Nr`6oGNa$D JÃjIDATys^PlkͶ^7t3:K^\nqrcaN^ })/>19S\6WFIzMkamyaF ֗}y3Pfc=K[ ;͋鏮j#9h8R8"0k-JN{?Ϟ;ΩtֶmO>{vczSg7hO'M_?ԟ?>rm_L;ŸՃ^=/scF!31aMs&JjTqN8gn&뺾ڶfH91\N-)_s=YjU10tbԜ9h.Ɯ@-:PdCZ]jB.Iz*);(2b v P&4L#b ۓB2`KfguL 9z1S[(]UlUz W C1#6p\~Qj3Ÿ&fktDZ׏s H)FӁrlEAbbwTT raX]עX%1c;.##R6Pa'bE?"Ksq/t'XRfEf` ]:Is9̿|o\c?>Lmat cGg]jG8<< 'ZA {]vOAJ ;;ۧ.t HNL041\U4 rnۖniJ^p9}?]] %% !CΚayJ+$Z>~i&jt}2sETGn^ RQLi ,̕0,c,b0ka+GUKUg 2V`-JKrjcS`hfB Z7߲7(X%&`Au ^>dj,44Qyj>^0(^T*$P^GԄqiZET[zvJQCkX#uhrlL1zH%h#vú3i{V'F:ّ?%'ՈVVK)5յ9AaѢVyIܕzkR*۳__ئS`BhYr%$&J[[/_~j@uʄMg|?ھw|z@E_m-ȓvxu 4 !7p)/M9m!< / D_$ 7 JМ8**%U z̏+JpJ0ؤ^% GiGYH&#ClPޛXiw"yrhPEUO /`{i;'S\qI_5`Lᑑ|JUw5hTt̓پL* JL5\ '5pđbèHkɢIZ CXV`U./?᷾ϿK[8!5ME rQz~ݢUzXg[4 JKE\C|H7pQLLX?| 3DvePH6IirvmR 4'{f:^VWWDoYr_0$:\reà2*DvW'DB:)錡RtIbhSqb8 ϒqw3 -T"WԎq&nLѥ0߱QZA9CʲW ] ruIDz ZsXhFp/>~iI5M23?Г?C?=a‚ _u2ΐC컮zⳟ^{=D+)g>3y{x≝oGFι~a1/eyEp9,b>,< rxȜ?0CbA3?^Վ ~Mlիu??bc2MݤƜ.܀[(IͣFO>o32n,U+mP"*D(YYeY%lPMK43jZH$J,T9"ҪP(%ga"x!dfNB`mVh.M'i3 __P0!t@2X%{S(XR'|'ws=o޽{g(MDsܹ .DT ;/>G'c+iUUD$¯_XptM|tu c-aq3ݷ e1k+W͡,R$.zD= R]<;iK|ZX-F&CNzpڠ%UO(`xـ &EF%)o(TMTblr㣥(P(ZOZ>K"YdrFvz$+#0h h;tѐޗ(,լǷ: L1Rb>G_?`mx(#_zA?-2 ay8Zb<^ =o][ BP{U ckR+’pDQeF254| 8F86}6}%I~4m,"-ݻ_;x/`Dn9t.jijpoXc5Ts(9\I2WƩ +`m58 '嬰l$Bd4IU.6S(g3a0>1}uN 5fEs}fʼnL¦}6ƳZ׶0b+c8shD+(24';sxK%g &|ѨA"'!MZu3(fTM$@u>Jd&ǨZn\Wq` `>0uew%At@Ҧ }z2 *]Hjs.R)n0`&AUW˂ӭp&C |uʫ ǡLYcƐs?,_y~'76fl:miDM4392Cen|4/R'W( 3S?_M7麚ܰ\,o" ^.}tVYP,w>K?NolHA+ƛku WAW+n1(~Rq"MvA`l^ј<3b"$Qu+D%Ńe,:h"ʞ=ƛMUMa:VǑ1e^ SU0oOg^ T/2yieuʰ&JkPI-*^Ǥt8!(\JSon޲:uJq|_uҲ}˺|FC5^1TMfTJTqW&k; uvh5;W]*ģ*F>qFd RC!0 ˾a@{z`ΐk?яIs!D#|3kץs<@f]{OVa1×$ort1M$}}_hEqpʔNo޸O}TuE֮*rMAݠu-GvCL9XzmnMU uɚ6g% + F(Y=i(>fOOM+y\ bd M|OMtY%^(6*s^.ðyaa`ֲå^!{ cD9oF`y"-UpAAѵΤA)iс3oD}_L\ Lb0X.yv@y]¡!1 9G7@c\Yp}Q*"1b=zkToݩk&Dz3yVlGqp2fK *TܐR"2c6RTg_` kcնads,[+l_rx@jDB ըXL Ag&cBvsqŇ p)3$ qcq @@No Z:Q*KQhNuhcI@)(*pTt)?+!xz+A?U$7uh+t!>R+Ӽbh՞#>j0_C? σ 9ՎC쇚b]tAm[ZՑ6@RXآv깑m2jpt!yNhXVTTJ]q 1XFsr‹F_C-,yaɚT". Uk/?̻F/fOjy?8oI]-EH{v(0FZ!MPr Ɵg* hĬM/1U fof}m8 J[4c;8\Kj]R}%sR F5Cr`5šjZ!J~eBMUN yE6@%}j-buX15\cea5{7/@b_*btyT#^<xC<~-7{e 4BV n$ƸiEݬsښ'f6s~W#ltrur`: w:t5|,~-F ڶ]uP,Q[|?v4֌# 6 #ߵ F 7zļ} #Nˣ +b7s(HMʜIfq⏵P҆ɒK.dKݤ:U2)'hr9fg','v}UtIo0@o L^mu'&Q>` ^2m$La ]uYn/Z[BySYմy@6Nhc纇RPl7p(hEx]4Xr Tb۹]Sc71 _mr}YY'DeM)z9ܨ$6B׭"ky|O5N 5?% b+7)a 6p2}Q[<+f֪V>G d4~1mJs,DQZ.y~S?GƆz2͡IqkoY^/,4}߆ƉlJ@63iAl!S`MuD\rpLS+銢f\U)^a'# 3Z Yܺf:4[Mj.-)2Grm[T<8CJSfIMZv6QX`DhZ+Ȭ 2CmO_\TъXdCRFKRM[n=Ctכ`nug#>{cXa1quLhH ֓ ﵕ9G`0`iѻ|,땩UޓR4}>&HI( }BD'\6rX+7AOROp0IS@%0sي"AVUAW+2XR cJ)M& s4^EptN?>1Lö߬7<,:Cj"Óhg_hd>(${V݉rkҬ>]e& zP|Yڄضf+Frtg˗1Bf#mY`F9XTeIʅjnVҮ`RY"u ʬQvYz)mv3(!8m!l" e0j5";'VRlb+HZJP+ן@:!k?E(TQd>Hv`};z}ǻ溜/ItpCpN薍o0,CLeː:Z$aGz0&(#L;{XmEJWx+utI52S왙!ALZZtZA*) j1UN[ЋWm1(3Q.oE88] Z)XKM5CPm(W"«͕IB lW 4~kmn*h֚8y@2o\:LU*|N]`l(ڌI:u?A $e:í]8ڝ޼}k{iz>:}sKfN^bLk^9r֧ZL³JRP ov]:J2rK_{xw> :_R?(1kQo%ZO&]* 0 %`8>>*`-!2Ic%-?:/{N+M8tձFk(DOH`[Y4o۬TmjWl #`Zr̶@5 }kJJ qӄ16Wk33%-Qzn 6hTz]W [ b^`F=e&"L"- Lؒύ;uQZ  Y[7ķt7CT%E?Bu l g/C!I5BRwRut v~lK*l =c5p bzWaSB}fFr%z1\֠FS)])v,LX=ٍYs7&"NO^K/zCwjzbNѫ&zOr!*B4(;L^ܦSWT,Z̯r?rٳg?C!"x;OJ AY@(^U5ZȚA (# ><O~#ͰԴ S< 9{*Ek(B1 Q_,Y­cO T:]Ekc]Y<aE&xn:541,Y Q. *?`2::=G;`Ġ~0C0u'c2~&P&ͺ(sT)F*AҞIpTm)ӝޗ2 pxJ#89!neVw *%Kog^b¸dH~i:BQʦvWmvCdҮвr-2l@*Cݭ,``b11LKov[6I'iunJ>q:Ujd9U=XB:3u^as@!gy6 *gSR፬zqK;]R+x(J K3 hUvZӒĻV T4DXL,ZM {$d6jɃ^F3CQJok!#dqTҍ9ZGxu3_0y*ڱ9 MNDמF{Jl`2q8l6sn͟EުFаYl0e˜ߢ vJ֕ 4I͹uژł_N)U{2C: 6mzƦ3G٬|A_!2}t]RfMĐRӤ6QQ" tg>ُ~Ct?]0VO׍z]S^4WZ[YᕛBCeKQcag&15ץBRNIgREjs%TBd8}M AUexłk]YIZHv a6z=Z ).79?6݇%. CLV֑W 4"p'WBجŗ-}*=%[يu4NtMj1bPy!cTa2*˕Vw3dj ҅g-#F+\ٕ Ⱥ.BlG*Ϟʌuum۲GBl}on1k~RC5.21@_s'(P՗{=|6'3;j{CC`(a[[[A ;IFl(-eʉ{0H( 5w q 7f=Zt:Ql9M3|qCh1{th!*&|?_ HZT%C̡>ڿNs!"t*Qw"mq:zz"3g$UumHpXDɫ3ʐ-Y+G)hIL2619ёko:8,9QnxLy􉖜_/r7Ky7]F`{z捄eJs߾sNsg7'>F7' 5nOh{J޾y?󎆖ƶ&MĐyggLә3MNX8|xxuf:Rv%DM  ?si=ouB0\~u[\7x]@qFv0rFm N.W%CHWJVEuIMr*_DFS2Єj+H/aoXM#*kҭ$AT?аH ^74/$"z,YaJz*ȅC8j {G7aa @QMV+6 2[docbÉ/q۽1{!@,oXA K;o~+׈2@.8J-W af9ux;&rA8 <-m_:??ٿaP]:tk -Bg:SR{? yfgv<>Ӌ/j~ɍP&]~ݗ6mJ]޽0Ԕ`e#VmʐW 1<ۦNZWOagmRU"#A G')/=./#I#O֪hD.>N"0dUZwYIo4`Kd~7BozǪ2TĹS`Q`xmKQXn"j>LpWHK&P.fZe0։p8CTp¤o7V@yZnW޲@CRV~]Y!ᔉTAdt4 f}j4r0(#AL.Ƣ]B24,nVK1Ȅw]hgd6G.n-W4,1+t||Y' -ljhξ=wn>s;Yܤ}W^֘}yk}ի4m㏜N4آxn6mŸy'?9iP/@)lҀ3poŋZ5MmC h҅Id-R2RQQM/|S?&IՈn?s"L#e -p=7,V^Ha*7F4Җy1+ݡw |ĥrTO$d5Pf|zէjE@ Ҥ/rNJ#&Vd_hZ6m581?PC]*# 4T?@ؽ,J9k-iǽUAQ$7&V8r?[ ʯ_zư(+%NŢt`R@b\Z$ܮ4(=Ѱ7-Z, g_N0fղ5f%RDưr0 ج-JΡjحeBbR-k KϿwonl4Qbe H IWR2ƪe8#ߝw|VwOo;Ok}ESB[ʳ/rЂ[BTnQO5^n/ޡ̩ f~9I t?7?4?{ٚ;Ϝn/߾rNC< % ڱ"/}NJgu6.137o>6μ|}*yd:JQbff)tm۶'^ I3d=*I߸yvbd(‡g9n u[c h }S^'E~jUE$l%<ΐ4[w,*&aGt*1i,2 })Ȗ ͱ%~*&u0 ]կQqժno%t LZbv`C%`W*05ջWOtɏYȪgdd5[)b&WlYLL5%4PTl6'K#0JvPp 2ښy 6Ga;jhq|3Νp^xGI!fy~3KčPze߽ӭmz^ko Xӗ^?Phxܹ\, .$=X8 T0GGRJ9瀃)g$w\[(G %i2wςV%kg7O+ayD C a*9{3<ʩ4 @_dt@, 7CQ{/kдެd !8yl< ZZjT%8-0$yI*"4QGGII1GQNfrWORٍ=gݟ__OPl(&a4ffsu۾RTbx#byIk&&wښc{ΓSvI9T'iSZj0".Jo 6^O@nw(?\3`E⣃~޽w||S8VE#DUe%/d1E/甎OMIsd^9n{N)IZʐ>7kgΜ:gE@bN>4x|F/k 9O[{ۢx`'E2blb0w͂+ z!moogn\;|Ӷqg X,2]yhd,%?LYEA_pw?/s;miF90dhMu-9^sYȷrlmżZR<,܉Gtpru<5+"X6^z0ߕm(m5UΓ׹E*Z{y5zNN]=x#rf>S,7d) fBPbωo2E"wP<@qǥB(M|f-㚭+0,upUok,E Zv!`^SM+/}Ħbqfat9ѹtMtxeJVO@76^wdTC6/AeoeQnKvJ:۬rZm殰LtH=ja1@/ҍ7{KY'#/K'J|VR2)/)QT $$4LDܙ]&-$5/}W?GyMJ~eF{Wo^7L>mE>7neSm4@ɚ[uc1]uUj[ ==0IF[cZu Dr?*)C( OmOfS::v RXÀ13̼)#K%n7[2cЃ9} TIuӎ#gEyWsG%le^xW_{;o×uF<>2"{1gڳ29s lJu0+*Ϫk4"WDD?X _<`p%OMce7j d+] o@١芫&܀FU> 92:uRJ=ɪKP?v%+ԃ1w#EuuD{xH>+'c`h&c׼ | AI@(bUŊ1cnY rHpJhTjacz U Qx5ԏrtrMoPIn0HLM 6sr6'UvP`TZwR$9=H'"?mڶ}//& )r}ۊn9L>ǒ"|χDÀ!WӴ5-/`:)t0aP2dpÐ["99cGGJ) K[ QSFDz.!3tg5VT tbxsPRLjjؖ4B1cs51Ҁ??mZKgsi!K<ֺUd0Vȣ`/2Aj}_oZA25Vp| B>fa Tf"j@@9ގ nݭe^UB*AR*j6ǫ8Pj^D*fV[\s]jg.c̱!.Bpآ֓Uŗ͋*k ]ciC$ `^,$8^k&"& zWWx޵ U'm\Ҧ T ډOL  GLPdL(>8)IC$q*&NQ@b&^X.yu`g;I1dWcڎ8:e\0dZźmhX2|92},5ț2PN +o6l c+_C\ ǚOPDeJL#VZzi ˌzod*CӼɝysrcr6yrt6Ā\6=dj8%tk2g[TڙT\0<)6yԦy0g׏>/o]xx[}.~`GKG SI;F? L'sR zN=b\F$>/RlQʩV@~Jq`؈I#$IVVO9LI _Gon2;ZBJBbW\1d#ʠͲ@:C%Z5; ق2߉)=|7j8?FU10`SJU*n8E#M!>4ziٝ_kMiQj%&pD()%֣PjY{{F~5)&m/_lntmR -ͦ-r1.0z.ׁyAx fWrYj#1 fF!SF_o.B1i,z-[)H l̺6מ~쩤ux"gN0(n>Wqs(u(`77ڔ0dn?5ٟ=+)3RNgm%x{(.dbZ$0 鈊N#x0_~+*)IFPy~zRt|!^smC#toF\x!(@ºӭI0r؆ܱ1R5.zV/7xXTŁ0vL Ǜ1>{ʭ řD&37^EЈ1܆IcI+=ZӥPI/PqP2أb8Eql$ͬ 5ٓz8-g ˎT=X"M9r+3\O~"*}px3DY\*4ܭQKJro)wՋFeYh1y&as{x:tmpbXP2%p 46pj 7󍳛q ;A@i|ѫ0f]"nRjAׂZ]'di)#` oLKy 4l0֦/ٙZ,j[M)s7n>9mϴJ˞DDW.m[[; ̦M{9= m&0MTdFa;KD_3'IHc/޵7-<ۺ!4@X,wVև)w+_tӦ= ,6^Tq׺mUz7roRIB9;u=qsQ^i*TɢTַZxbڮeRX`?Adց[L[3WK(W)"/1b:\P-4\hijtgm`dQQY@(xwZ9VUzttFF"_3o(C ")t$Cjq-%ڢbZpM.vuFo:RY 1hANۏԵRV Ȓ5 nnK<^t u$ ìKQec9HOg'WYqIK5Q6i/7?fĠ{g8_:u}.̛_+^]8e0i-@LӦibm(5JtR%}@J ͍i"dFC.~ayn2m0_ܰ;K&]!cIC iw卦t)kDX]|.olnhAӮmRj}iskLLX.K/w7onSs3ΜO& 0FÌSze{NfD)Cjv6RJsCșڳӆS 8ruڭ7n^z|x4]8GlMWasra@ ,Ҿ 퀦чrNe3[us[M֓]4erPLmu-Fy`X8'A,6G;LuWt.Iݶ&L 1ty$E WaNcŸ D'`l`&;E3&:MBXIx|Zru4WvQbX#2Iy<[}K9\Ѷd!̡T@Kf<@b?OߔtY¤C}TC%,UdTmV)teEΆε` PN6ָ;JB$ș$Zk d4ܾqkŗ|{)?'Rleed)TrsfN0xZb!i:&.&~sL667%}>8;ӧO {ݤ{rn_@^9]n޼upXCmۮnഷ<l NS]ypbG{y;% zٳ玏2[Mpel=JD/s.˛;B9綛{WoNZVĪG C8ΙE>vR"R9Q:{lMeJE`'b[_Ok4'^N.WyZ(Y:e).Yl"MݰMFP bZTM˻/KM@QJl#Hn )Ebg|^Ndp` rp-y£e[ 0ţ)V5(!;KD0l*n뚒RMP35j KB Z8d,; yp}0lb0~G&Jɔr.()=̱fgL88;ܼ_{sWlc#ѹhD/Ko4=u=r i˗y {wo,22%l@HÐNhc13EO-54a0%tnE fN):4Jz/j [[[E'7+{Fbahhx߻k޼ȹ{mD,nDjsBmvM;|1ݽ\C眑5Fļ"$dXׯ/f Sc@jvZWZnBYK Zm[Q2F$HVK!2әox*񫔂1D,̡Zmj+.]6"܂j0ϰ8۔lc*OԴ$6WR&-G5&J4;6[>VkQg!BJGE`a]TB*S:ۢth~=\KłB{3آzIn.CHgjdNV%DrX^ùġkYƭ-WY5@OB;q6tr DˬVrrRݥV@t4͎"k(YeT|߃#D9 :s?Zd&@33mdJU8 N^4e\od(5I7 C_:{ІBGKksI4Ͷ6\!3ֹ.٤Iv0'ZDBgn[˞١dgR9bww75x\..GG,ȭ7w1x_W1Yu|(c2."|չ;U٦T V/ `7dBF[D')s*Vs*GK*eܩ ++Nr&+"J X"1.tP%W H1T+`\VK0K88=s͒E,0Sj=Zrd5MQTEpa1ɏ'w~OzQjk /EpE_ॢZZ3RZ,Qꤚ,ZF/~`e)b>x`RDe4lљ5Ыr-ڬCD+Vv49Ω;3 J̺(ё]w_qfH8T*H|4Es>c`>w9 6{Ϝ=<stLo^;fgg,#XtM'fnF yܗ:8@%30kR/(D$U bQJ6@<mEYQR}x+Wqn#?w>5 f٩8Qr{gTbMHN $][Wy3gϔ5mCr/C?dSk}Vhphh WQLa\ *0UR՝3>' u#lLϱv:9Ҕ(b i\uE$CJJAzMpVjY=srFxmB9Xx̸8K%VOټΨB8-!b\@)'{ +ڀꎁQ"XdT]%05Ei>q ;F'TvjV{!*LWN)vŔUUt${ "" X1f&UAM (o%"Kѳ=&^gͭ!N}YǫrrX,0X8FKELS}t{7t`W5äɓ'f)Q3LX*{R :_߀|kTנYg^|cwwg37M33NG"/+)0H)s)Q ].uz89SNK `f>w|>~jGʻgΜ;8Om<~J0yz}BO{BTaRVVNwͧ~ l6#Jm޻wGc{uUarofL_lnD,֨>pQMu=g>g!E`Zm -Hi]--/R gGA3ϠzV2 ֳN*&,<'Tp^'>Ҙ N҈V ACDQ! ' DKS]D27qXҔqpsR9%`̱?Qrwd p⪪I4ʤCKrO^28IBz3NrKOіejj_@[10I^01Z5㸶,ƨL`Vd#[xpO| 2I(W#Rr2gmcOmr{tjkoԤDg|l裏j%*ڕUF*Rj $EH)X# )"s2wܴ-aSVa(zan߾}Ro >#M>md1_9RÙp}._ig~C -̩{L=wo\]x/_|l6XQmryt|0G3: !c2bμX.r elWh^uo3V7 /JNlĚ ZXvW6)Qi4."\>ݯALF ĦtTE7e I0+fFXS*l Ki#$3HJQ""z!R6ĺe^r⦔섓R=̦Ppr#*Qjx|:E sc޴+7&KCjqsPU Cƪ_Y /˪^&̦6A A!6 m \:fP]7zrI0뼬UM;;gac:K KXeܡMKL)-88Y.Ǘt!7-߸{6mvmRL rrs,Ξ;coll-Z|QpsMy x9@j\6 d1oiۦ--Ƞi|wwڵkGGG&ы1LΟ;wܹi1lmm%22Wom$3?xcg+&Rp>νWo~uΓ?%7zzl:HrI\'`b a1Fl=(ǰp`3N?wגiH \UL4jFjk8=r&b8'#!ٹffR bErMlОqa*Ab"a2<,`bET!rG5QHʌi61 iz4,4\:KJĠO&Apn9+8_xdжMpmll\tV0RJmGd2eunrӴLi~a?nܹs1hMAܵ?sqR=rdmgl6kV,rtC.^"u)A R[}? ׆a 'f g21mdn,bd 惃~  SftQ`o%ΙȊ=E 16L۴!+ z;RC Q 0L [p9yZ $F79Ӣ{Au˗'˗m4"p0KSNa5N8IDugWJissssss=?)E-H)h#T/#Stӭ8;Xu6!ݤ㜳VdQ>ɴ&%\Ɛ~X + 1BuN?샭$) *h0(*2Kqh;Uiz* 3BWrum[M92_!.QBT,U\&kHYuY)vOiE lw ['8aY*wT5@X462ޕ@I ֒Z7rfdaSpS6O Fj.k#"U–.GYMUg<`e1PD-Ъ>W#/ @r?ŨH#B7a9g0vijCEx#>EGfPKZأ,K4ʀ8wK뺵UqX#]w+R{ڍk<ֵbCu <#ߏ2'V]l#;Ȇ`L3W:Gn5IonMgS ^ܻꗥ~:ESUFMPuv &Vo^0(qlȖQ+% +"Qߤ}[!x4JR(>0Zy}J;TdJhZ4&}6~̪'Y0Q䦾ԩ^ZK0*(2"4~BUCSm >-sC ASYƽ2n?|#vX+ۦ +S:$jB)u}HԨһY>.t"rhЀ9䞛\T%u/ xG, Lc}ui2< 4bAy6[4@iޏp wKx<Ȝ8ma8O xVg=L.||c SPM.q˘(7a:N'ӣӀN>u"15*0Ҳ-xcu?O$9ԦJ *ceRA@Ĺj.7666V{Xs9s]dh kW%sw-K#(mIDAT4N;}G֘2 V l&&9cEtidZX1xAnK5(7`/IM"(E*lPs]JQ+ "UdEԎJ&+XS,WvS17ZZIpGR@%4g"h9V@%tf[ߡ ֡TBD%mjAPtaPIPL$,D;K#%B StCAZ-:C~P(j ym`N}5%1 aNǎ8(9ǒDSL^9R܌y']ev0j&=x̔ZPhCM\pW_ Rܧ҅ KeFA\[+0B1K-l0v }%롇z饗JIݶo/\P~U5RJyFu*]Ëe Kpsز-_@sӔ6s$.mB˝T* ;h!%@#5y0yh#E']֤<EVo 'w=smq +SXL(™bU !d%"?k!9~]wƂ!ѦA*³^ xX0Fכ oMZИw$klB(S0ԚI$8bX,E ,=H➎Ԗ_6`dh J)DS5YbjuNSbdw{i'8ŘD u[_XYjf4}T!kwwX 4ϟљd6QM4X תXdxɖ)N|k1YT#= Ƣ"yG\X,Vm8c=vM[u/!MD*Ρ$Q1_6RRr*5 ̑} *Eڪ  VFvyƬ>A9Y dj2Qn5FŪgIY=,H0d+A]4f Wg*U+i)|+:ߧp2*Uf X|*6a2I uj*Ѭi |+#7s|A,4dZ*Vv!*+a'[H>8~1t!U&cA$(3HKv\}|[ʈ1Z `8nەхG#[BJRP1kWȂ]tEF;Gd0^-_tԩSw=<< CMlllZa@Xw4v+,E6Qڑ¸\L)k.+h#\V֑3۷oۛ0lmӧO:e|&mWPv^eUi3|O9ͻ 4B_fQ 3~*rD)$ji i)kOu.~# ҭ (Y -UW;P#A& -" GeOHjJ֏_@@"=] Q9q`q!،HbE,h@p߶Zz'5h丼6*+vUtqӴm(B)k7R C&OﳥǤγAciAU+Òs96DH!J*-ks'L!Yhy6ҏ5>far}@xF,W8[d$Em^p^)rĊ]m2Q<,l5w7mzdzO}?|=׃-G[aK%C=g'~"V"06_̂r230ah祉ѷbkI4$7a؀ >@E'tɮ(\C-5nT ; vCU`Smy$rP>nK#.V'"쒏̲ Xn1X9(\޹-+ĄW/AY؉^S#iM9 _md1M* c9VCVsgE O&ͧRE l0sn/%iyHZ `R["(SHVVu(EۊRy I Vv ܀&iUYkmb5DCrƔZ5,KdJTj4B&t;|?jqY\o+@&ߣd1Vs-~.ZШ3M(N pΪ1,^,Զmː} ㉨IEɐyM$0peuURstcȓ}RBm)=#`VE)E[mK82{ϐpXrZDÃfpj'R NmT#vY)Dn-?y|e(;/Ql{GS & uĸ_5Y1{5Ov4J@WN}ĶDŽJǪ a]S N.lZ*1rxexT܊  ci \iO~*U@DDHX!UpM,8Lu]&,5)w(]ȣgXK8"J G:&q$#0 QQ=4NcI|Nb(FYCMdF{* Z+0se)SjYe Ze4T}*HV޵Ѐ@2 t^mM +Կڴ*HjDI)QBAԩH*:oP#֩p{ҕs.IYG.ұ ~H9]^uJC8`" kDԲ}fR4 6|U2@%Ib2tX .Knʠʹw5EU:W'VxYs*ӗ4PJcpRIh)B^%.s,!Dh'3,|d Ư4*VL*?91 Cte*cW{НDQeV`)Df1m H ev &MZ%+f:-8f'F[\M\l4<"q2\r ?ɶMO,B ȪUaXw1k'8(~ݯ}:G*ʼn4cOY/?-K V/ݪ?}iN1oR4~Fk/?F1XK&1OkjAUO,9 <8`2&.Jai[H9^Ū7t˒A[j25I9ᬚTӔ]~u}ׂ tLP4 y3$$M):q+Uq:9ky2;ўP~ b)|"RRVUwk݀s#QWp͞(14`n=ƶkR׍)# =CA%* zޗ( "beUuwɁgpH ^Df3FhyV٦K&tKh ΰQ lZ +K *@hFwnB\/B`n#9S ]c R̀mGw*J%5TUq.9=?-X\pIکչM&Jae-SNRD1I`6&s&6?ZiUcT f*_IֹMڜHKv-@'?5]7% d3r(V{-cU C(̼\.Wu\^1oR9{l܇]ʜK)3h$Y] e,g!:.=`C R,]ۯ$}XUr.aKnJidruWZ  yq :hpڇ>2âϢhc#_ӈ.i) r1#W |=E=AFVc@T+偖sOLM3lmNv6im& 5=|eFPi}\eD ʊd8IsJd3 iܿ>ۖeyasyyo*+nBBȎP%!$+o(  , miu*73k9?s}Qxu}^ks9}ݜ F"(:?jo tSK4gC<+ kc7*i&R+̋RdT{[̄kz5TYԓgGgP'}r6UXAa.< ՞P ɂלX vr 7cuOWtRcI+HRA"ah2e-4G !5u@ SeV\xXJ--UoR1RIpoT%˨U 'WKx',xQ$ҩiz s )GwX(3N<]2v5,Ej̋?n (XpLgN~$ʈD3QetZ~(@;F8뷎_u򍣻'paտ G$"H}O]Z_dvt16SVpzǰ]*sOYdYYjsx ַxA C̋%1 0=N~Żl@ubY6b; 2te=)vp_\ؘg(> P!YܒeV.Q!y~Ib ey_+ڢHn]5Z6!Z|<-,!,Mxkٷb(R҉a @43*WPQQ½y\lI ݁Y_Aۭ1tDr&tڱf2i^Lɓ( (ldT-@ÞeEHK Wr2nUAMfŊ>ܪyl>;&8%(~m¦iSo b;&L&8U[C'A,%G1R`q_.P: 3Hq4 eʔ9R(^ yFoia,wam[2'jNj@ `ᖻb;}ꗾtk7_>D8@Xx::8<ѭ.Ui}҃m>O0"D }g/e JUuҙqL^s%6JH0 ڳj*J90cs-׃7CˎEih%jF=1Xm9`2 Nv(lAviXSцq=a w+ -vfjWJْI< GzVMK 3^O1 o3bE#px:3bƭZWU!Wt[+S 5ZHWؒ߄~mija%h b(%k)\ιëlID7rX/l#>7ED% ;\#0HđmVCνIDXȦ:(MNh/WC6٘df=0V8$H-^bkYurn,_Ì嗶)~6zfHA|iF C1e_BR<4#U}WЊi5c2{bgNm?Mn.4@<0.Z )0:#s)E^;/;"YW2 1+Xk"vA"lZ%eEDz#h@g722xѧ<{|ﵰXB/D;;3 !8z@A9Q)>_ï%b$Ew{vaq3;_O=~x KL$|+#2Exí_Tj`1'bP3djC/fETCl(]I;(|rPiZO_P?1:zxD#v4,ƴ ](l8GrFtJϡ3eN|IE(ajܳTtqW5a]wV¥`Tti6^=p! OuYJ|8p@SlAk=8@dSh$PM,HEdI?yZn'~u4` @4\Oc.GbX-q7 ?ggp *XK87?l{D?zon -PO~yz #Nn[}駛>?aKվ &`)rxv!<sAԲgTO@Kȳ3ڮov1xf!j|q*"-ŧ|JK s&8XSnW?"KUU419 tڂUr0>ʤP<h6a e$.UE-(8.LOZ+XEE0v0ՃHI$8Cg-֢S.>I:}d=G*`yȰR Y UiΊMfj,Y@C:eX[:+qVv)*˲Ӎljb*ψT-~,= &?8O6Ь'NtKɦ0(dZpu$O j.7gWŜXIc$XI%&D 09f9 Aդ+[`8;@RN ( ,#.}ѻo|3tbw2=Hĵ} ?d?C$*SLJz ,?9A Nd")2,""PVc&D7m6Lg.m U!B`ǫm 44QDs%\.S |oMf C8 R%)؁DЙ(!f# ~31)`3YQmY\=BkԧY3Ij9PW3!XhRP72wfBuVgS5Dp^lZ^G*8`C֐%%Jt6 ;D͵P_(C%Їlw[pn Eo(4]fQ"^f3d #J ~Bs =mڄrxA*,eSLMP/ĩ2>0K+Lu b#lSQ˘ ö31(<]8XuWk~?:WdDq| R /|gE\frJ$a$(h :""nt^r~rG?3T$RJf` v!PZ7 7œO=y nndE%fMnu7?F#3Ag$N1b`D%2]e?3KZ 2 2MXt`tUgջ4++UD{u ||re Q7>8|3y$u3p8K `O+Ï7oB= 7 $EZ7*C"@B(&']mb ]/ԍ/|ǿc.zøœGT~ (n` n/uw?cC6ybzxyG{!-3GtppoR "d $QyV XJq{S tP8~s|04.0.R] O>|spx˓%+_(0yx[ YDSG pru?~x>vuI@T 2^rQffd9D.3EGw(&!ܖ:Aj v:( QDGUεWpǒXb-O5|otQF;Y3ݪI؝l^LWd 9)vuʞ @GP' 1Hb[4:SJ(sqޚ޸Mj=c;l(ʆiSQd> U #NIЉ!]d/@ EVt.qTڑj,h&{4c/ .QWsxYɼ Ċ@nJPl]@Ͽ8( R gn3PL@yrv;RXWӣ7,Sw?]cxke `DH! &u#`ȈV6`"P9]i_r)D.2\;c:Mw+ߤEH}_|3My0~~qcHcYBxė C~C OL D G O9;Im>7nX2|SU(/vVA Qyp'z\P%Wqh+Wӌֻb\"캸Z棃x`{WWf(wއAΝ;%*CHBȐ$: 0vQ o}H>Fbya"z}LJİ5P@^9o_<{|o.sH_q_CJwCN Ɣ1# ) =cX.hmRݚz\ u]P5hKu0穗XM}:+ av%VU o‚e%?TiY]gl?}P*a =?) ZNwP9%TQS>U Fd DEEX,j^vg;YBg $`j@M5)J}h JdT!a5)ʆ)Qʏg01%> QIYaSw:fЉ DG`73R)[p&94 +_)%|yzU jClPυ Z!!8@""NyFOq{0s?Ҳ |#QF 1o 2f ZUwr0>~x?z}z5}lx̓S !BA`P@ gǎbY,}쒘Gݯi̐3RƔsvWpzó?{owG׉s&|ݓmJnvyH9DL)ј)g>! ,D>;cHϷE҇}2M'ɳuŝPBSJ0&(ܵ towGCKTXDB\^=4'>i?)Ri2*wRdDWHϠ@Wx/ є@!٩JUQ CJ#M\Ģ=$-FD9^0e^zlMvꮬ8?;@DcRvb[ ds>}ULž!sՏ$5䩏COMʼnN3~v̳MWgƍf%ҩ2YC >R [H lTU(g3e׻]E9 FȹbL5y &7LUKX/È_~}F")oiLt}g~$D1)l{ZDb1MBX| G*~;;_B *gO=9sJI߹sR!RP o:zT ݢDdVp"w}W İəR1eҢ KF2>]?=^ªl|zqק6톼R9giL3)DcLR!)#2W dnq j|g)$<@IX-γ%(7 ܻ;AE VׅPEsr'HkQ/jاc"nQ E!7a@VιT?ΏWP# 3,[WH!hkP,}+"D/Z%e ɨeZh6;&xL&GK> Bhjd WӐ7bI~lH9P&21bʰb FRsL!)X( BXtx ;}KwO~ÏV{ ֭[1ĜsJ)1D-8#ITe qX&w s%FUU&_҇!nH>LW] x W:@$+$"|tPDhѓi]TcL Wmr %p9 2Phݚ*B=9okNye "vf9ۜrBD)rYbLr8P;%i;& iمS_ppWŧ|/ hzwمa^,R8%!x ,A9B P ߳KF *qmV/]jtr_ZQBA :STZո;Uj% uCN(+؍04 s:ۂ=V†G=+u j[But aR^7'4Dr++lYT`)TTR T^ O&Y5*+b+NcY7qwÔ-(r0%n!@ oYk@ۦ33$pLY @8 iB1*(=bX.2wʛo{w,`x{׮]/ SN1hLLn8[* @(4E !C%BB@ nn*&e͙:&#B/|` yM? R)A"b19!8ަJ%)CNWP* cb.#*㈗E;2 N/R4o=3yBzU7Ǩ/Ӥ(lWb'/[JyxA+:"oꔍQI'd)^4C}WU\uT7Vf$G Z7(o,E+nL}hyfN eqALghZM꼛tUڙeh6[JeJn!U.)<)V5#tN1جs|mݴ1>SpemTϨ_zo۩u &PeRr05l9Vn:J#!Ă+VWV|ʣ8B!'ʈ)PyHq;łH,"xNOg_}p~/?!Ʈ~9`„`GC" )c brk/:CZp¸1RmN^N٘q(.۔ ؇ABHicׅ!aC@LcDcXlJT)gH|C-9 К ePI|jW"CY>fKm>2L cM0p.~I vn3) I@ ʎlKy.R3vd̓,p\+ba0CbZ#`Aq& y XebSO\Ck(YX1, LfSy'o"1T R0Bq䒇]Bv!d 1C*7 `X-NϪ䊪n΀3$@0>|/FwCGJD)Ә!ƃ:fw!lbZtqh\rRrDD*/rP!!vaمE\Y&+uljbCO[x~+\mu RW-)oX* ^x #; ,7e-U/><qD{ cUY" =PS ˓%/*(F^i'"e)b[[zVL߸Y"pu,$HX-#xQLh7j H,OlMqtQkc+0T'E拐כ $ہN3S"QOӚ%F(M)WN߫QQEY^Oéj@ǀc8ӛa  WL4K2Z,0.8|0mDD La2cSXd 1HpJ1wpfwzƯ_ [t]b# Ry&?YI8e9)D@B!F٢s e1@Ba¥f Wv"B"< 4n%h9eHbyFd!QJ1੢d&ʙ0 dX\Pb90 8]bDnLPXVM82A "1JĚ5 J2Z!6Ҕp|9r9P5!A͜Tlsb6Fٸ6. k;dX&} ia :WMAMHZp&ebX*2Ta؅+S qO0,s & hH=+5 c` TxkXM<3J:1"baj䠻FX}Njn]X?]ЧDZ~Hؙ)4R;Z>\XAWВ"@J4cH_ږP)%&Z*fNg7@_@"%3ۻ*(XtE jH;,ȑAa*s!c+&{TyكDїy\&ci4,ڨ2QjOŬ*QE:ЂXҁEf!j ='HT02**!T3L>e(9J&JDc+]*(jB4,C>C4HKUB;䘣"*xiJ6R_ԅXE0jUw$N^0f >xlˠ&}2 yT@5w ʳ/G $Q tP]Z3;i*Ơ 6acMlc,Z s8`J[G Tc8<]<+j0iqHtʄAp܅Er F"`mO~񗈰]! Pzųrrp9L FSD0`$VR?+@ 7F`Jv1}KNǛh('Q;Jrl{,0){HE5He"`ʱWu Z)~_G[ӧ9AI'% +C^ʹ,,U@'Er3Wq#KUVBʐˡLU.;+j6,p: @lROT2ttylv}< h(|db] ϱpؼeκ8 UE bNS>G,$T)yu~(rGSpP F$ WgeMž y1]?F~di uẘؐ% C=EmJ/$`TN4H% D u*,͛s<*;0L =8U4TYV~"ƭV:vfE.ۇ ɐP9)c iхBa8w1,",2^9wE\.CDnS_t"}s9@DTs!cz{>~ &zjz$dɟtg`LyLE"BX(R4Vr!}MF/1jR1 5U4<%l=~ɕcIf`C/zt6QLo›,K,yjII1s*)NS' <ޔX8BW'[b#E?TjzsbY 5IrNi]!(6٬ND]Qz|QP1\Py 6bkAߎRъr =)A^W1뾭ZATZ]VIɚ1A&ѰG$lҩ!ၮ h3/Mw5s@V+2QA.G)9/Sd%Hn1oi_4sknb ߪR/Eutye-Nv;d /³Y 0دbC ޸ģrT gJѿCʋ1@rE8ZśWVg-cB)轟ws&Q%#Q1G!BR,Yf(),87*<#ER:l{R|JqʤmjP@aTQ_&e5Vu>bxxM)AQ\L)Iؚ3qz$X~ ew&0S;-Ӱ\P-2Knq{d=E*(R{sJ@0!(ye]S/!>#ԫ"N4D T&w!`o)J'UO>e:z'<_,++c*TBp,n =hB *PMװfyV!y̺dBko#(<+fZEk鄏(+{VJ{:,UڒN)|U?Y0Xtżi"*Ml"oIBz3j?[tJ"T9g-8AȱBLZYUB(yVĔ,pzFKA7eH}r`)1snH],C1`i"pxqx<b,1"Bu轘ar8ss!Bр/D\ʾ eU eՂ`R@1LcN4fH"Ĭ ozM=̫(Z ᨺ`@8Xuǫ,LHs.v-V^ia*mRW]A8_m[fY²@O)U=,X$ng ehܠ"ra+Mpփ9g<`9eU*7IP"D-(bĄmRPOk,ӽC0} 9o~griǦtb[L^vIݹT4S$k"̝NQΐD˙ʛCKөi#ɒگz {FB% +[Z%0*cU[[bZRJ d̢4zm`V(V;Ivɞ6^TN䄴H8V BVS>b>`gG8 Pj˶i\ LREL S)Os+6Y2j(x] u4FIƏ f(DhJ yTK=>3Dqsr&${y)@!*/̽i-AԢ,! AmTiz׼B7׏Ѵ CfHD(Ch0nˎ1@HB. E'.6iLSK䮢.-z b8zbBfU ~w| Zn2e6w4䆀#(v̰cuf %5:%A #؞tǸl+Rݘq_1 ܷ(ѦBY\!OTxc}6W mYY836ϫh7ܭAXhL,m Jg"ILqC>*Z9([)(!4mq?H4qﴮ V趠4f1he\0=EH c|xڂ敆78wߛu فA`Qp@E!yz%o\EGeN[aE/ڭ[O?-;IR[,1a1.B(b\,`ezOq1E b]]d)]W ͪ@b!bKmdVh8h.4e*CB;,y+}L6׌, |VңB>浣~Lm7;ڍ\^œ҉d:::8>:R2dߍKAAz2R)}W6Yp, r Jdcy\V=Z@-%'z3H(;ҼK r:^-HeXj&SyQ~^&1ƚX`n^WT{P/ yEUTrhm1\b_mN[9ˌ ԑT"S PYꡰXtyQh) @MBĒ19TC;4f4_/L"+nLd$c~S 8n-eq{ysrP)^\tx|ǴX ߼}|+˓ٍ?m 礯gŕ-qB7-W u>#9:TPc,<b46KPp6ơ_C *]%TXˣ]%ڽ K9\NblYԻ۝kdQǔ!؊]Bڄy J}C((GI)_%IL8:+4zM -S~㺁x!=EoKCTJ2CO N*>3 ⠸\wsp̸)iZ{ZUAy2UIYc=K0s9i,<Pk+i%\!dHJzoDfJEXD p #.a9U<'*2mo}#')ykm+C X C@$Ĕ31#bV _؊9#>#B⠙VmM\;0L:9?[uhL!`.eNzk,!H1:%.p[oH\ ZILTw5wnblMGHY-SL ɱ_ߵIq5Z 725dܨo3˔hNx9QDV)^gXD2!n&椚qaLKOQP VJ4lL $ymƆ(aߋALp/ "Nf:e#r"*WE՗0r!֏/t@Pх(J45MQ{􃎅-Ӳh,#q%AHOoT0a x UQLA..Xu5]V/WԟJ}˿dIĔbE eQ( 9bXvyՅUz/>G c__}e\6B"ԭ SF #L %1 .ĤZZd "ԏc`YH1,pf ӫ)XFV]r1*ј()ԧ@_y^'gN{Fp;\șsZ%BTκ4ji A_ vΪp6GG1yqb(Vn&{j<+]DTݳm@<`^c+D迗&kq~~=hg5N_ga* PU c)Ic1cFy@:f98".:\vhmHBؤrܼu4o'OX&M7ӔVS.7O& q=1!iV[y"O)Q)ʗ%GN{}/P'&r}VGI_D cEי^Kс[ ?va` }U`('HڡI)_Ǡ_XұuU } 3ֽr8Rn׶N;)*e=h Z)qzN#V0WskhMmh{yN?tĕrj_QU=/oߜ=E|_ Mbc%1%F y]x- /x|-/vcVG@Ez[|돜^?}f!kB"Q6@Dk D P,nsv GܫY.+b`HЧSaB C^]Ĥ"Un\===Q*WCŨ7H!簉yqnfs~00 csǔsNio.%b~we, vE" ? T"`EҺ`YXx=@>pMnK26P Sgd9қ<*CU=˕yz7+♨g4h I;1V#ϙ :Š Ed7E!z>"'Wu!OD/Y]jf8˦n>Qb2aHHI4r|c~g94'A-*Ƣԏi7vc! Kv=B]<_])XtХԧT.̷a |](hGQvNI#ջV{McXj>UZ Zgjӕ蘢=?KL!g``=AƜRqC@B+FST{w_~rRKpdOcς $>faVx:j*IT+3!vn\/fnS1]Q Itl `ajܠC>;\fkdAHIի\kH8MI p<U8AOe獑DXv Lq<kC(!D |m(MY0l1H!W䶁L 9]ϑrm".ԫހE16ʘR9T6h( R jWP[gb_b~iA;#:ο¢K{J lX/ZCyJ&gcibD#`+>*`U2H܏yхr:C1Daø8ߍv:R~o:,a5CιX+`}JJ9 8a@ {YcGqDu 搠m s URYjlTqSA"!W Hrv)qi12WFxCNv}!DR'jEkرrrQJ9qm7f~R֔c.?YzI@RhM:2i1^FMZ*B\(^j;rV %>eUPÁވbZMO"67k[!c`)bv59 h &*B]ɬ5,nD`&t$+ тXHP+^դRX)Bɸ,?ԫǡo/&ř/iBՖkoUJb}٧i,EeWd 3"ϻe^-2D 9(3P uai>b؍_'7W]cǡGu57RT́SZ<oYbγ :1?Dg)J:=eHgcmQMfQjԫEhT&a)F8JF0iI>]#r_W`#R?%}L4b#1qvv]E^\\\n7cJI8l{N s/(;NWwCߦS'GJ|i/cr ;bIP*&0`C%9sZBmC3l¦=nWJ9.uK̰|"բv\iK)ffCu*$6)S "9+S3m޸w8zDϨgJ.W#/F7{ij9+傼(-5i+ּ=0`9֕RN -!nH1,J* b`a|zm<(\<<_B8V88؇@c,ȩnBf[XIx~ XEoR_~ӑA.!GEr<6j^IX,!Xv asK)H29l^.#cuEha8o`( =fh+QJyv٬/|nwn}J)'"WIP#tRjh=*^\ُ, `Q9؟XGkZmeu3PXHJ(˘fZ;cW8塮g3PkJlB:A&*GTWbsS}ߜ焘hp(W- _?66zv lCP$ӓƕ~M$z KwU#vf"=~4X4BhA"U܀Ǜ  S /_\Esvǀb\ .|\,$@ g[9O RM6}"qan6z}~~~~~^mZn,>Q&QטY>leKNNPGC аh}9`( 7-giX",i:΄8BZ z ul*Ujq"!{n6peogΩe~o&U! v@?&;(uR@B1;@G~՜:$@gHdOazz2CgS77oslg/+,^G̬ њĆ6aTCx~mAT'W:bg7ƊsZѝ `lUtq $~V^vZI"XR'4İ"Aj4!ѶO]:\eBQ8 B,p+kly_89:z G8aRJ*G>H>SJEs|*, =B. HepRRrLx z Pٰl}W|;@NB9Sb'#[z3BD^޼}7^ A2嗔8f^\\?{v; Gxy0,uxm]-?Tgޞ| ʁƠ[d3a 0Aͭ~]t1:9+ӵr'D#sQO-B+xYFj{_PUG5ꃺ܂Ps'6#UuofZC&Ks{Ma]UӤfg?Á<;&r:Y! $VFqyoSm7s Wo=^HCfܾEX{ͶCpE\-0P!.xz\laB!%"?Oqoa@Z `!g,GLA;U <.(4K4pt%&V1S0RQ,ҪLBbf"zoZϙ6&<]gwN}RObܛf똏YXf0S~EIsc KQXEB{g 9Z:,O,8Y]m25FsJ&eT'VJg.Qe". )EqSA3HZA9kC\# J[@O-s/SVzD@]jV, #}+P)vX*Tk' >/uWE菜eS]VّΜ7ޘ:L@"TFh #RTmk;lL 4Y5jV~ц|WbHrq^Q (^J32AAd3av8\E!@ Q)pO$lEWj\!dGF@ !J]0T1Yڦ_A#JErH,BFq (-0oDKE{H' H9-Z 1JZU.:!h+`u f٬a2Asi4O zUxb`oCq2U~gwfٓLK=5ut[i0Zr9lh6$\VX)fd tAn[c\JXִbBS7jHz1G5Z0~X/]xe46 H4TZzSL(;ݭ܋F5ՒxL21ZDOB{,;m͂)`P4]"ma _$‘QZ&6zi NMo`H\=e+Qm+U䀓Ns6$Z..."b9HOBDˈGy T&??+|ewo[OcB^>YK$^[9,8L(^v|7JfGFQΓ٨TZc.X9DWJM}^'L)CJ>z^| o$T}?8Zǟ~zA0_9avȪCeC@QmuL&oYqdŜtPLJp B3lekO3S&npᄛyq#*e 9]2B*,e`5ovhMj:fvLu2vO;p8tJ_4x3*})To)ҝ귷˚C5(UJTru];6id/[EdG~4zQ'mz5&o+nFnkWotxm ܘ*YN@N!9<!_la!B9R'#.^Q&")q079݌XvK34bd;ĜJ(4!+&y!)HEHi93XYJ&T:4& Yg[R՘r&S4gg;,MX,"w?zG[?A=*CV@De\NF$P3[[.ˆ&!ЭaX=<e_}B#CWdYbyHCƔDc1qmO>]l2s2\v@B=VU!Ȥ \ŰZ U}Qg3ae3O SHY|gC]UHY/N^Bza֥.bK}nɢu`p6ptxQyY{TAG`.'n9Z8]nvmTډJZMQ;{B4QQ /U|}Ƹ/ڢ["*qu\Y(od4?DI'fZh hh&#HeqTe+AmKM0!ܦCcp7j[;Z=M3Q( fmڶO~mW>7_҃Ͼ2bN;um,L$J٢R]O`]0A!#E8\nz(O#pAIDAT9W+7_q,]Jk, fJPOI,:Rsur\->ȔP`%2k+{_rBzY1d!B,Z|SmhEhL4$>]l!(POptrhy!rE.r ѳ(5}!0 MK2*((0N#9%,=cJV!; ifE*Z#P9A*'G<9u@-ZUݳ & EضDKaB-p"֪0L:X:W;4c~z2ՂmKih,@7|ϗ-I!A@H bF, *jvdӮl0~!$ 'A]9JP"t0'ynYQhLl2"w ~nhfؤd!j@i1'K;CO'۔Rfü: 0ioyP64 6TCriCora"J=\ƪN-U(z캂6g+Z_/rtskR.,(AzvA[E-$htn3H\=8lj&gK*<͸Ntmn&e׶&/񭚳dBUv5: G{0"@\v@rPd1iY'#ަxeH Eģe9e ʀEw?[+IJ~-#2,viB$#DVÓUynTn?%'P'G⏕,ZP9Y ܧIF9gLmUvSsig#/,a.哷P<:w?{1d uCf#U`u K1/8yۏЭ:Qj`-pơ(Pĵ _yt(lBlqt*~48eaLAol>i/Ms@^玦;/;~)ŕ=k{ﯳ)%o|\rET n¡^PjɛTEg& cU"`f&.&O?Ǐ~)UE !jVGN=jQ*Or.mv)9ETY".,V%I:BĜ|GK_җܹX,c\.''WOvWKgLL5i1(<0SFqThŗh,_„CJcfaaӧusNUtb]ue5Eފ)I^dBBXg+9:9n fW~:4q@m8]]O䃺L+Z =_fYۢk%:\آ +EL5yN3biFrCJ?{^y+WPLA ç/}`p)Fu񵓫W'pzqqD1(EjNxdytQ|#͜ʗ|l&l**\qq1Si7ҳ~C7@FQ\qeu4?LR#B6j|C]z?MZϾ˿NK٬#^(('jUGb!4$ь{L$WgwO6L(:+|oaetb.Y47tPk5&wTgɑb%_w/@K.ũZ%Ji nZv1!2"l3_ed3ʫSJ{|||Ν7o^v0.bzٶAg@ bqtttz{?|ۿ?x̤3橼oν_s9gRc>pK!'_DaeQݛ(rZ" Z+u]GssW;oB1!뉯-ZIzLM6DZ̀ufЊ\bAma9JG) K6w:9h' (kk@bVXq{pE:N\x׳LIˑ/ԟwgY9`!⭩Nc DÐcs5J;%'ZD\uM#ؒTN"'9gϞ+׮^vrc#!l^W]{O:qp,sTMB>KrN+F!wDc1AJӋa XB*ܺscyG__5Yr{BRÙ?}N#y$>kfhU?A8#i'Iʹn=!uhF;c.ei7d׎XV~%X/'dw-*LuՎ3!ʀmE6XEA&=fCPrA_`߀;9P֌;s萢 B pB;J Z,]PDpDX:z4u# Rygſ8_rWkAKU*p}HR/1u"'gҊ,ƖHDiMѓ?#buӓãŢKN0 ?8A)y#|3w$/̢  V1ӐҘJmb8ێ!e.DZAJn߻w+J3ُ{JZn̕g҃ 5q>ˆ[8y1k29-<^>yZ ފ0Ҡ%Bc*9ulE-YV3Z/u/PË<^:_(N(Kp!ETzFB6`shӵcyWb~g@7g!!ULfI5P8q mA|%6S@q U(WD0p~vv~@DC"b @I1B0x@<#zumYsW7?u33ZbLCZvcL0|Mga| q8}r;w%)9jgUR,53®~kIU=pJ>SҞ]`_6?\/P$]YhXy+ڞ2bl״P֦yjKՈ 5Ɯ3#{j S{sL#jg_]GZjƀAyTJ=,Jъ*Ttn0ٶ355%sk/ۛro2Ř5'c 2븛4ImK68Ũ;Oڟ{c""8^ŀK%1]2?3R3Bh7Kz"H}C"H!⮩hq"O Q6]4A!!%ԅX!M/9GD LͱJ C32`siUh]F6!rM5%ͫo]㝕}2QZ]K^bRUVRw 6E-:Q 5*b ӂ-γ 4|vkiqg!_3ʘU$U5y qpkN?;.(ZI<jy[v5ȻzPo~|̦Sd_}W]qţ=+x7LTX0`:Ud9i"I\ގDe {8ZЫP7Jqc(GɪT_|K2&y:4˯|'g~?MDb@m%*"}3nwc@{^S~HC*@?~)RS+qRC-y/P.!) ā,a߄H\9QĮDBOuP;Eժiܭ'qu  81b߉\ D>:\] /$S1fZ6(]*Ɇ)K%5ˢ5$$ 0mI0TvS"E"m"_*fsܬk '/]f0ZzWGC)$ Mdݓ48ʸOGH(7חVx+`Ҍ_Z,r6sAztbfވ${l͹YIa`>q9lWE.I$ݬ]{9=@ $:7ҥCYS{3)S-<swS_W~LUXtQxha6 D-"#c i3)Sʴr1/ >sA}CU@ A bEW%W<ۄZ eT {nd7;Uɬ˰mivP'(sR1!؟Ű/i M؅׿ ^-C x H*%hiYǼ ŰZĺ8{xܢXi%AX ߟ{^bOhlCVּm=]oiYxL^2?銪mTnrr`cԟ.@NrOSB+itq7ExUq63|?}] ji_RC3^3}dY., W'q4_W]% 5A\ @׎{ڕkOw`s O_̨L! 9S!~m74 )dL);MBЏb|BBrNvT 3ȱ:B9>$zC]-}4SJrD1g>o<|MGZ"{SO\5,/td4>fҾaJ5Z N)GJr ښ!cgźDigU`{THv,$ͬ8Jr2*PtULgh2ԄOPڜv0,o_hthq/&Z_~?칹{83iͼk`K[ IՉބ2Y G˓_߸y`w W"t_IeT0.Ɣr (KAG@1 I]|]"pY" ZkeC|iifg9 J Ucaamzr_lqdF ef̈́sw,WyTK=qƛg%\G.mYt3k*HD]̓>۠3bk#mRQ -'\kf{7`Îk} RrM OX"&߼'cg\EII3Yft+R'/R<#:+Q%V芪uO2Zոӏ3j^ :ݭJI;lZ^B98QX6%ʀCG/>vՇ? ue0/EdF#ooDŽB lyT! I¥ۍd8gl{f4"d@DEa˹53:]PTysNAtg>C#01Sr]zrޟo0R9q4&zY4B[oK40ٙC|;aVO-jk:+6((cq)-bb)iR-s&K ͷ#عC~w5Zp,\8[ĉ"";ΰ ' R_oߟ "`r[N!#3vK씉čɈ!ٌ-T ؝x?(W 3Il3o7=1Y$ BgauF8,/3Ha1NVb^ٞ܎4Jӗ4  g\g= 4>^?|GO/D#v'kKXvAƒX8DMc&@""FdKD!x0Ĝ")jtC8. s JR9ȴs huRJV5(I20<윗4'˴?jD96Yj|65MU) "4́_fMc Jhψ iuV%NFy:ԎI']}_S ~|:DJNUٱEH'fpp` =X&ktDhe^V۽BD)V xe8'r/}{K_n"a<ʗGO^~t5' S""Sb0q7iӏ])DL"MII&uTTY~晱z,GE#8wNf)ħG`RlDGrjJ:R= tf$D\jcHi76=>۝m/$N-D#ʳxrBae% o=Sµh.n-34&(uH4 3dOܭ i5딨Jۄ}!Q)|k.CiL_l$@Fiǻf[1B:f*GZ0:)U}^ZE7U}H֬2dTQva}ncJ ͵m6 G{qv jI<"#ZoT PsIV_\!bU7+t^[Mh,rM- DAXz6_Fwn͍~qGխVY2-oG~2uN-׈PDLyLD7çvga71׽ƧkM7dtEvoHub)IUCbM F1LY4?jIp` {P:*c ӦO]~lb ys ^y{B (7- xB$)O Rb%̊aaf{;$пcb6  ™QbD"K'5vR@DU᳜XWAHtw wrWn>7Uku[އŋS E.QuʟpLUֱ=ĦŴT=Q?蟭Y_cȩH@^}wog$PrG̜ E"˲D!2#Q'H MM*3g*fSS(+) 缏PZqI/DgmC(hlUP:PVN0C6x/WgyPUiA v6֭5c)N(hw%؇Ӷ%_K.Wd*0+U݆]+ ZqMkNVk{^hw}S7=LbOZjEOo*ڴԼo/&㣦vغ { J m4o(܃n~KNj|gO2&Q50+>xrFX}kE4n$(0f臼٥l=yלTzLPDG}F5" א.5DЄ\q5:0SId_*5"b9c0nnț]~r><>׻,KfyJAEGo~卓#՟PbѯBƺ*GVkau_'f ѣ˜ =g 2{~UQ g!iY~B ;0D~[9ܤ/oHڱ}QB[^b+<טmݿQkԼJ1oIW+QHt<=̤31OQ7O4Ù^q/e/l ן7sO7/=%޻[{/yxY}nȿ=So~lнTlq=샓Et eJ |$C> .Ƴ|8 YSk9`Lc'W̶I{TOSoN#_ŦGSi Rs^oRgAo/LN\b;nmOgYަr b}Z]7_yR@: THQJv:p~4UrJ&詽XI%Gz՘~.zjoʫ\\\o֛q,/RA _`]*9G权n<:Bg8rѥoۓ\b{t)6 Øzz||>\l,þoV<W+ݻ}&HE=`/J yBشg]xs00E at*IB~r3PȆ1~ j *Dy4TR 0'0"xSE2iߝC1wk+yXU2>[Z%gP7BimA"Q].^i—hdI9w)_drr~wx81m"83&J'KDP MATȐ]<8{`${BϞ<>;9 4&K6-^lgóx^ 8<<# ]4a~}Ҙa(/M9!@N1sI-G$d0"¿};vǜr ٝ{^='}a-$ @,җ6z\]ηYed:NF.1^ƛ'\^pw^Zc,?{}&/XJDeE N.yCPqOQ{FV1թUpU[{m`dKUnD4w/KCZfb<41,T|I ۑg>dw'y< k2s4.O=k˓6oAnss̰6acj) ֵG/ʨ-ni]ry]wn~~,rgM*쓒ۄ2ɧKv~@K;ߵ贇k3e7JȉJ`ק>].oǧzXA {{/tr`fs][謐>Z͒p&٧7<\M$;lf/Ͼd} p}hȦBލѻ=SƱ苳GWV#"Aʴݥ~Ő2`u{/߽r bI9 3QLrZ9anw~~q~v~qNitXTY ?/m0&PC^/] `n036zxNyM9OÓ+캺=]"Prs}DyxK1/NT2?E M$ze64P|R;jpӤrXMjkfSq2z5>O3^6| _Y ?\^Y"ü\N?NVvMڢK[P;?'BY?}Ggŧ9R~C)i3ëW޾sʕ+b6`&hN}D4V$כӳ~9-#/W؏JhE${PSZ 1!eƼަz|] ۑ2'(X.{+/kL[՗`ZT1C N(ڞ^dA)ѽzxӵ/' QyuupvOsZ3rP*+sv%Fio{Ȟ*to~aۧ] uy \/(z"Üyzۋ g:s'~Wy{@y "[d_d/$4>8'v=yǏo۔r&Wׯ_q$v]Z‰w bHZc'+vrI 5^!qnϞ<{z3onCƱr-+Wr>358Ʀ $sz7bxtoz:e"ON''Zj[V$ھ.pr}=7ZW6d5r* DZEFIq'(Y% XX&Z& Y>N[)wgHr>_*6W6R\t^(Bj5reQ֫VjuHq6ȕky>犫IERwְ}uwxir,\ƪ/l%"8mi9wqMzASgUCf_D3鞆 eu?y|>E.4C9_(t11A ]5_i8dL"'Xsv=wXQqJ4 ggoZK߼8&v1 BpӗdN=AӑaH4|]grIr_18ҫnf$٫z+J2nfoU:O.u.(lvΎ^M UBw,Gn|3:6`v[~P_spJ@hyg+ˁÉyͷeV>]rCTst^ߘF{\b |r[c'FkII8= 9Ͷ ?;dhr S3gn.2_q!Ee}!C>/޽_}{ۼnK=O?фJ!4''h CT͖ͳrɨ sq[7C1愁K~/_q1_lG㣳çNȂ ov6yulΕNosC 5ȌCU;r>UmhM[f:.;wqx +R}Я.DrْE5-|$^RW~_]d',lv-j,={{~UJVK_=mJ@ܞF[NZ ^>K~kV8U>W~p bKh#ϴ5'4ĥM'{r$cލyHt==x?:7D\{h;r-*57L0x39I}l,%cAX#U&.?7$ήn\/}͛)o_o6o YgWm ZJYFyjl m/[VE||?>;9G"^z7_;9=ZZnu_8Xoenz7DirL`G_Wۯ '_;{jBѷuIE[c~f6YU-]YFzsWx~!uzkKdt_֕/rMI鲞\r57CK&Oڽolv>W$ J V@>,jo;8ێZ>g?g۳>[0mex #EX^#?/8Aǜ4lv맏}g={lbwяcS\5Dn'a3%uUeyN;]tLH_<] "}&=ƀǯC0f%hXڛګM5Ԋ.j.UZN_ 㣓׾koc~4ʮQ~N(\mE h@pw}^ZV;6h}'|̀\\ 6;0>}K7$cf`2K&EjF=8/nn_<עn\Ovcv%gy}ӰiͮNPU[>!y8ߝ=8?᳇OoCFDy>&Ԝ0d@)<)vm=We,d&R|xz1l+޽{o\_,C.ZX#Muu{}/P30mgT4x7᫯Wko^9αb[o{]8`77k1[EM(Uct`ϙbO(m~cL\yzӮξ^LT??O][}nAmg[~dK㥿ڟvUߣ=ghӁL@ZW)Ch ~ԯˀa8XEkYU7I jRȐvit㇟|Ň?O8۝y(I{⁩o@GxLb #B=QϘ~ ޽6yŃeIE +wtz4Ơ^f< iWv]xm `\\ɿ3XdE7bP"OVZn厡;9>ݷy4`p8\_5ܣ8ld@ 9W yD>$xUaO.m{ɃK~u'nIS2,Noz0;#mN ^S f EɵO!htKl |9&!.-=J(pڲިG-=6+m%}{&3 DX,aoJ[Ysv]O?ۧGx=b;l2e@  AL!a@HRҫ$W*[f NN}L9#]lgBɭ7_~pxUaU WϓlFDt^!𝑙jtҠ)x\錊ZC讜^}7Ɨ_ĩiG]G::yq{xl=7]~8zam*/i,Zܻ_] Fz\xD2q3# ;<8sk7rr5[$eZÒ$<;;[d:;pb"&j>HOqF> n$*ňՆ#}7>KTQZeھ=gPNx6?}{:OΫ/&w^" oJPɜ { VwR k4)&MYĨ in|VN \0dl:qҩbzV ɹ(<˗o}o?~g>8{#NZɌu]C(%C(eD\YX$MY(f"@PLf<~!ؽ_w{\z'=L7}#ѧO;K/ nbf_D`a}C#hg"tׯ]+_~KwܽvzBTT 4te9<~zugC*#׹SV ;\`4O g{ ͌\Op,}l)炚M[')I`>c(y˰9-_=5&ɠKig`EzB՟F2-Ot՘OfG1O |-YH˱6# gG~Ͼx~ jyt0|q0gH k!9][ 2C؎_d bUEb/`P*wvrK/wܽq PșL1Tמh;MUFV0{F{B5M#{M7Uh鮟硟~b鯞wvi빂v_ɔ#ߏE/֫f2 s[iSRQF"=y OoKoxRr |=_ӊhՆ鯸wK/5C HʐηϞ?Wb729gC@,1&E`L)ӶOۏl^|׮]uG`*ɣIܨ? )#@&:dW"EN [O:SLDTl4$I ȭ/֗oܺvsX/.}=u-tTl+>?+~S)J݄5.E ^f7p/=;&|]KBugfqdyjkKJqM' ۓ1Q`I3oP /idߟS=C[aϔ=m_Wgs;a0S#!%J-\6>/tRE tU #.뱙07LERژ~c[:;̦B ] m@C[b1ha8ⵃŵ_}o_Φ?: AX\JgW #lLݥ6O17Ne3+%oj/oC QƊqc^]Q/tS05=TJtqrGf1aS9_u+WW˃Qa5pin?Hh0oq,rv|eRT~o G}NQ55)U{ݹO3zؼs:)GnZ jṂJXs(۟7//*,խLBx+q|μ F}Bϟ:D${QrC_kwG55ͭW@koT%&z뫯o11FBy-5 Qv@@" L!?=xl3o\;_?::z:PI c9 F8}ZTW'! 3@X-dpQtJbIXea‹.TmBVu,ɃO~!`xxpt՗nݹs;7o_k[zeI"Ι{}pș%W /6J-aH6lK܉E6%$[a~WТ*3#3#g8;Y>e<2ã|1kfC&F/zݏbzHك&|4@qߋo(Q̚PeE)Kdq85h]j#CI6mc2} euoQv3jدu].K_['&v?!%'ݙYdɳfO<ƂS?Ȕ+RDǿo{|w7 IADpHj&8fA\u퓗˧V~{_/ĞJj/:HEwxJ~_ĉ ?U(''%!H;/#}0Q3 R{v/|w:uν;'w=:x/j/˖?9"gK @LEz}`PwV-̊ uI.,XnS,6~$TuĢ]0{kw JӨ( .W߈: =ʒʿCM熶tBL*;\)&YRŌMǿb;9ܛ,y` AK@]G]G|||ڸ|ٯ}g6im3m4ga8nt>ȅi@wOnܽ}ޝ{'7Oo/ ࢕sݏ'wԅQ%@$yU*Ubs5K==rG&HD?Y޴#644l,ނ U1fJzͤ-@rbL=m7.QWN<#m`&_2wfg>WKJ`v]^ursl77{r$벉HtA RP$^|TN& /E OC--+oY{7ܺsܻy|h>s_?誑苬$ub4i*HkOt+0 6(& rde0@x=MIY男jpmI%CRدV*H $ev?٣w{s刜]庻j/[''w *揊O4# yO4"ddȻ^7gl4Gψh@p#zfg㓛'έ۷n޺qiُ~nW$[taCdYcV |lh%L5|bp!hWP6J[T׎4C'7 ]EmQq0Ee-!뫉:O߿'tf>k3u49tuZ[]ǟ|Xap5w2IَP;,bk&\.сGZX'~\؊;QȀNñp?l؅߆C< 7;U/W Y<>9uٳm]59>W4t0>KG9?Fнj^i(\|J&?(e6 7>"='SpW*Qlg>%$OlE B 󳙴Qڕxgesuέ7vsf۷oa>,Grctbw ^ǐ1#b19*MkM7ӏOG]2d-;dl8`-JnAV_Jez^%O>j-mI7h(RZ\vN:f0F`As-H_RE-GG&3&ո:Z:.VNŃ|Ŧ[w8⌓8抵;\ Pʗ`i?;?zWv(ffL-Ġ [^[Sk9Hl+3Dr줎^7iպVę~B#V0ՁlJYPUJF᭮ȞT$grip/'&#bMX]xW_xq|ujWtb1  uoUIQEy_0&ܠ!N[,|!AD7h}x[w?{w>:9>Y,g=|'^~\-;膛B{nnAU!%~Pb|;qv5_NN䂖6;9zQYDM_k.% (B0Vn0jIj$Y*jPۀCPym3%]n.Ϯ^z}ūӋr}\_۫M׶sԑs\;nPL>3Fh:'r7&|ƽQ#ĥIO7oOwɷwwvϗ^={/}哗//VkOA>a@C$ IJփO14p Ek7Q( ID8#x:z6klWGeDLR W[+ uFyxUrp;w%uG/qDM8GsݦljZmr\//ˋ\,Vr,7nk#rȅ 廡BgI> B/qҐw1s" ݱC_jsth75fs<}郧>=1((CjzN׸'t0MH?Ȣa4d;5 4s6%ZXo0dz῕ȍR2'`0|;PAOZ*2+{dU'|tq'.הAۤ] if3Ōfq$Ṓ8usnݮ;rrݶWjnM\]6ruګfչm7Z:G:G}xHn}A3B86BŘaO<| N4Ƈ'f1߹{V96bqpo~in^_>~/?׫%G{5?g&4Ƙ4^XlyvgbY,vwvwvn8?@[R*s&r65YlC&1k=!q4S" X?/L 8V è]&+13LA'ұzԑsD\ZGusݺ[]n]6..ۮZ]{pX-Vsnn:s}D<]nARJ0gooߝq!knzyɫ'J4`0|؊A|.cI,ǭyFt`cH}UKp ]-J@`FbJ4õ(v>_Ub2]>E^*OCkmGOt=;Yз$_]֋͛td0vhzBMfUW uqVFr_+]ˬGA [ͤd{2z u>y1tL]i+o~(0qpJ߁T"(^]V.=INmȞ~aljZ3`0鵝o~RS ˚W=hS)U>,H' ;qP$B Ä(L wS*gv$fY.nU7bNj &F.,/ MGE\Vr=d޿ qҭi=k}'3ѕˊK@\fsTEm@'~0SsyĦ;X8[ i6 šy97En"1`0]tا1b%|^) hwFHA-x=4+Yrk `JS E<%Zy _P1I0-e1^,־qҷ%fѹPޯF`06hZhUΨ0{=Fv,C:gvb>qE,A*.IOPnv".By;`ĥCVzrBtEz&>BtR.e`xfTpP* pls ~M3+ɠʣIBnb >TҶ 2 1fj5m_`:•DN˄66 :J,Mծ{|&8sT+rE&V"ŻŔ.UR<:&h|DKCY$ǜҨ?b*suW#M3`x0j --0zb?[\2"ebFY&/%xK>NwT9v!q>$I)O7s(1Jv!`xPşIWeI.O1Džcr *͏.Jg颤HϕWAOa[ L (}[dhrQ*b{2=bPmV 46 rndKE@I}5M(ے\xU7kGφ($W94?T( 2_tgN9KMT$u4\q^ɬٔ ]U{a=!kw{`04Q3OvYs%Gfthϥ `ϰ¬2itJPM\bn8 )u\ߣRo>n80w9`N%(nNQ2 I 3n%I5?Lr2q}\ "Qf riqf2ut1Z]͋zDiiS({)R(:iz;`0(UZn gJ ![ľ\{Gc݆\HdeB7R28ZdkR<|ˬUtגnFErUR'Mɨ+F_[t4JEr`0^KbХCИ~/gbVZjzjR=x#lgxͪa<]IpU&BzPis2 _SݩKzcB2Hi5z빚&Py#ZH FX3;#``>2Q cęuotqUUȋ/YA4B<K#7B}X|FˀRH|9WԀ gbӔ[U^##_QbQ>;`IZ h˟gtnl0 _HN(C=& 4\o% 1ִT sI6H׉ =pQR_)ۇlMq0FheNX%"RYG6|Vo7bfnmmOIDsM8j x#X|EFc+.2̓oq^EKpEY&i%%\P4? ))YWSL}ㆌ3l& +B.4/-rOi+4<[ SM4T2\S; @^׉I à$q#qF$?*P+b-'YGcgRL!yQ9[$z5#&T9%4;3s`0\5A6 vUB.*(nKaG&dB'dVG{p1=rI̽Xd=8`0~5\EfjU %ݬֿ Y:[YxeÊ^9 ȤrBXٞ wJ2F},4T66 _5HDJ2ĽYy%qo4jmg՜](yBg>{[/9)32+Yp1Ǖ ׂzU3K>…H qBO>S H4S |?.KJq֢PSD!!x~16 [UUbJCvUJJi4\+ KJIh;%Sa5Q5b' C0,#``:;U;(SxMP.M&]WJkKQ/r63seV@4X|A%HlF`oH^K_$36JiUڞ&U,Cze'8״<97T={76 V(ͲBْ 4[UDa(N2AP34!&Yu=0{;՜FƁ$ z4i-DTI!'eR%8Tr@Hۺj'OQ3S-#ǟ `l0 o*pE# VCOS" SX[NQhi˩;xQ#d.Izn. ÛrUFdVlrUEPON7\[3PlNѧ0VB'NɱN_bnFVЌu4â &[u7U9x̿X^T/,My}c7 o"^)s36 750dMjtӄW,hRz&"F,p,qbS&Pƈ`j+I9+6O'*#``xc!@OIim`(hZnJ@OiT7E[v쉎RhԘ2N2`0xT}`xOf7khdQw[qfeI{%يݐ"{sUG mAH4 `S" 0pVZvϊ'^e)}B-NchmIąNgk -* S&(ѦSԍ28B :e9LE.҇hF֡~CInR 4z›]atX U G>%Jp}EHUi8T-\r9=:va8 [˒Gmkg o[@NS5,ê;aӓ&"iHmJ/(  [\Eqa&Jm QUS h نIBԏ }-OFck NNP%I)\:ث+kIk [Qs|td,ʯS\p=%5&bXNý^z)j^W3W1ʅj~$``xGp&<;F閷*So)mG6) H+̷ekA?& &.p`xP16-Ҋj,Uxa7AZ(pS*Ow}=OFsi8k ]5պUUS+qZm=0Bf` @ J/M=_aR"&ShBƛIi|=+;sIdIENDB`grml2usb-0.14.2/grub/splash.xpm.gz0000644000000000000000000002467311153000035013617 0ustar Isplash.xpm]y0V3saf A/@/ E&Z hrQwII]P}<;I~?n}7o}W_Ϸw7?;zAn᧟/_~7fGo~o/~&7͟~~#7?͟$7|폿#7'r?~fOn~˗_3o_J~"7?/!3OAHl-BGJ1_ Zl)`epAWJ'F$:6bZ)vX1tl-W,Cd#:Hʶ{۞%:X bo۳xr*q6)`F Bm{žDH1If;Xv0x:&i O CR]A0 QY#;d?0N Im1@nY 1W%^-FW>b29y>-!)f& `n(;[b0&0?BpM``L멃.yD8&#u`ߎlgl m0jh `pj7^`D@AHШ{`6 ",F0"u-358`x $o`=1̅ j&s2pϕ#+lY3 5XHg֛:C3ϒ5/pkF(X rQbP#( Bq}V#Ir3 C: 8< š]i_`@+!|` .K(ԮD`6k|Ԓ23cz ^eu~B D:72AC_O|WgP }/YZbyC+D4XҢIׯލ! BdLttfnUdP1qAERIMo2F?`9F!lZ [N8*׊ep`C1lZjp̳Kn0fa3X@Ycpf XB%Okak+ X%+4PKɶjq"#C9(28ð<{b< VT/wnfdf|WC9 V{PJmu5&`!eF)^է*}| 3[ib|?/ ņ_4ƭ?x!r;>f9\WU[<.>uP#k\%6+o؋ ]tca3x~g;NE z!ds–ŴN 1&F- t.>^WhAP98og#5qϐNGH,aI%Oo =\ݣf ٳ^؞fK?^s B ,ĠKO&Rԯ?xzPJ3g5ic9QIos+gpt3x!IgB|U ,U@]HfjhW±Dlʎ* 1Xx=h5Y?bg? T!;4,ͣDU`IalW:vtSlxr8R p}֙a-3\ =:x&JL۵"H_ b-=v$bw؏:!0meQC^at@Uwu]?@vTb_,!&_6np+q]b|)B P nk.. Eg!UXd'1Hp1bPkapq`ueA% b+ qڪzR7-d 1 Vڶ߀@p18~Ni]{zR;F AZ&W(?_ OeCh1HV!ksGN}a-Ch3\ ﹇țFd}r8eI:N~|u:vu  $~f% Z`u=B}Av컩C^CXJ-Eb4PaCg!Pޖ#o3x_ NI2h'xBl{<#_D6;(amPoB(\ n~Gfн6ur]~ 0XB؋|zEx.tox \!bG碸T=NvnH> 0Ü[yZBAXt%%*e*K0_KE@l`ܯK7wjCDh^EGEt:d_AZxa;oz<I~aw4KY\oL۹zWVJ/T|ݦ7e4 {-q[wS;4nX)3X/s0:ܑ$ AJ^-oKAh N]e H^Q;1'6$ 0!<7rD9ư7L[G|Z#й!0®Dɔkn Ch8'Ta)krf)8o-AZ?I6apxnP먫3Rm^Ï4?j!#;6ow>0P CX:w֖%5X;C:%8>>! {j_}_kkU#Kg"hgpCLը (md.6]Q Ch;ۈ4R54R3c R7͠ R`sad?YZ/PM9AqVWdAI[r 0A n][b3$I4?ݳ@BXհ 7<>]o~`@/Xl N8x A<YܜcE7ju掵010`Uܙˠts£vpRA"3 01.38 mexlՎ@A038{gPMyePɂm^o+4np4J3A{oy as: 譾VB)ܵvoFB[ &HBZh؎?`ap*pˠXt A7j;}L7($ iSPA9DrڼIc@Z?F _Ba%){oA9: *z|>`fPix%bnP +zD`7MM2(٦.fPI6.A6h#eE;|ShASȠ rJ7"{Szy2v~1C[3} J3%g3mrD5AC $A:A M478=^n,<<ֺ5[f2lKHLܭ [Z 5( &oL!lݻY sP 84;j"qfy'k\N4LH}nAq^fpOogPF4!Tsf0}DyAqH~p48 *;AJ<+AѠӏl2t3(K39J'! b J;ɠL}`KE4&hf*!)M|s}{ot#mڻCQ(EX>0bA0Cbxq6h ^3P gc05f,V =C3xH VOOa0f**݅!`n?( Xld"wy0˷J<4HUn9&7P*A\ qSAЎ|96AnшYvhBW|Ե`9&p! ^iKj65 ?xg#[o<)ݻhc w_"}YؿwAr1=Km$gsƠpʆikc_' [2ݹy{f0>r:7mb&Oy4nGf;vy٫{ED s@iclgkߺ`p AAo9U4 \5™#h;"8z!|1짌e08w^KG<)$1V dP򮻏b:saP 7\Y>>,=BOAxSh!HK 0ˊm꪿*jp'"$ - 5H_\zaD1,Pe^}ZB[g @T;6hK>uj33 zz1Og4o7P|ܲ֫WG諰l&H_qrZf(bʅ)Fi Ki" E11lA%|Z8'\^G:{vJPAmjpkY>}c Wuk~H,JOFGCO!Tmp&CNk~]})~S ЇaS I 1 3H6vvn$6Ŧv,Mܗˠ~v,^:q8 j aG .?eо!c! 8] G dp0;BخF\^g",Sٴ7xߍ9[xB f2Ȼi%0YOa(45lkt<09vB4MAWE_o߄n0s(C}U|WjZ߷yۏn73N_cnl,hP3$MLICr0xͿ3t|A(%dmr@mqOwK7J^_"ePؚe}+M y({r bBNquĆ v=J .NŠ!} Ne{k'-: CB &5O sSH;h6xDxWB:0#u } V4%O_+o`I|Px"6hb{]p "DDL+δ6 1Ipoyt7B8  `QH)U#~oЎp6J#喹 OFDm ׭`xA b# 6M+1g`.=XN 4wx$A,hɃRiwcXLb0;@gѽ,6%c@t`$!ASniRN14ܒ` Ep7ا7g猣: *IdPw F< A433) O, BlOs4:pB0Bb Wy_7zc%, Uq[qAK7x]Ɲu<"+)}sf}B4#hc5o)e?}UySbh}iS${b|$ HOn0u_/S ޶:o  `ɑ##d͖<,FLk>{qLp5'sLyGnzu} }cgyW!ϒ J4A &oߩ1`|˒f]DX@PEHĒ3G'5xIu>KrgJJrXЗ $ɰlR-Qz'c9ŭ APe=<`g1 N&B/G h]huIj`TH!*3fPH@B;7Bv _8\V1H>bT O$ěmwfW/(FP)5Q Ml9(8揟7Oޡ#掖8$_3SZ~1f%yb$z6߄TU'Ρb]6|AsP)8 bo &|r*h<5X bok',D\馤 @!,?R=bco%Xz@pIq=yv)ᆱӈs gN*I&(%[#f։x[<^;ܤge|fl V9!V%eNt@{S&4KbhZۘr)g('6L  ݅9G}&0$08lϞ`Gd //@DW]luj,$-r3XO@&T HW0]56vZcV%d u3x@VCv$] IX /$.S0т^ x> }'z-kz#l/U0fE CgT¯7Y %&[3 ^.]lق̰l%g'7Mi[ T6Nx Tc?6-Ő `ψBS*l[֠f%a ``~Q`f?Хl$afER h:6i[BŰl1%`0fŒ8 K" B_`5 :ؒ&qC6-V Џa3h> 9Y7-~W D#t0l[] d)`KHrTf%( 0hB &9f%0qkX6-9P u E D%ùlJOcgrml2usb-0.14.2/grml2usb0000755000000000000000000017135012234405045011712 0ustar #!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable-msg=C0302 """ grml2usb ~~~~~~~~ This script installs a grml system (either a running system or ISO[s]) to a USB device :copyright: (c) 2009, 2010, 2011 by Michael Prokop :license: GPL v2 or any later version :bugreports: http://grml.org/bugs/ """ from optparse import OptionParser from inspect import isroutine, isclass import datetime import fileinput import glob import logging import os import os.path import re import struct import subprocess import sys import tempfile import time import uuid # The line following this line is patched by debian/rules and tarball.sh. PROG_VERSION = '***UNRELEASED***' # global variables MOUNTED = set() # register mountpoints TMPFILES = set() # register tmpfiles DATESTAMP = time.mktime(datetime.datetime.now().timetuple()) # unique identifier for syslinux.cfg GRML_FLAVOURS = set() # which flavours are being installed? GRML_DEFAULT = None UUID = None SYSLINUX_LIBS = "/usr/lib/syslinux/" GPT_HEADER = "\x55\xaa\x45\x46\x49\x20\x50\x41\x52\x54" # original GPT header RE_PARTITION = re.compile(r'([a-z/]*?)(\d+)$') RE_P_PARTITION = re.compile(r'(.*?\d+)p(\d+)$') RE_LOOP_DEVICE = re.compile(r'/dev/loop\d+$') def syslinux_warning(option, opt, value, opt_parser): """A helper function for printing a warning about deprecated option """ # pylint: disable-msg=W0613 sys.stderr.write("Note: the --syslinux option is deprecated as syslinux " "is grml2usb's default. Continuing anyway.\n") setattr(opt_parser.values, option.dest, True) # if grub option is set, unset syslinux option def grub_option(option, opt, value, opt_parser): """A helper function adjusting other option values """ # pylint: disable-msg=W0613 setattr(opt_parser.values, option.dest, True) setattr(opt_parser.values, 'syslinux', False) # cmdline parsing USAGE = "Usage: %prog [options] <[ISO[s] | /lib/live/mount/medium]> \n\ \n\ %prog installs Grml ISO[s] to an USB device to be able to boot from it.\n\ Make sure you have at least one Grml ISO or a running Grml system (/lib/live/mount/medium),\n\ grub or syslinux and root access.\n\ \n\ Run %prog --help for usage hints, further information via: man grml2usb" # pylint: disable-msg=C0103 # pylint: disable-msg=W0603 parser = OptionParser(usage=USAGE) parser.add_option("--bootoptions", dest="bootoptions", action="append", type="string", help="use specified bootoptions as default") parser.add_option("--bootloader-only", dest="bootloaderonly", action="store_true", help="do not copy files but just install a bootloader") parser.add_option("--copy-only", dest="copyonly", action="store_true", help="copy files only but do not install bootloader") parser.add_option("--dry-run", dest="dryrun", action="store_true", help="avoid executing commands") parser.add_option("--fat16", dest="fat16", action="store_true", help="format specified partition with FAT16") parser.add_option("--force", dest="force", action="store_true", help="force any actions requiring manual interaction") parser.add_option("--grub", dest="grub", action="callback", callback=grub_option, help="install grub bootloader instead of (default) syslinux") parser.add_option("--grub-mbr", dest="grubmbr", action="store_true", help="install grub into MBR instead of (default) PBR") parser.add_option("--mbr-menu", dest="mbrmenu", action="store_true", help="enable interactive boot menu in MBR") parser.add_option("--quiet", dest="quiet", action="store_true", help="do not output anything but just errors on console") parser.add_option("--remove-bootoption", dest="removeoption", action="append", help="regex for removing existing bootoptions") parser.add_option("--skip-addons", dest="skipaddons", action="store_true", help="do not install /boot/addons/ files") parser.add_option("--skip-grub-config", dest="skipgrubconfig", action="store_true", help="skip generation of grub configuration files") parser.add_option("--skip-mbr", dest="skipmbr", action="store_true", help="do not install a master boot record (MBR) on the device") parser.add_option("--skip-syslinux-config", dest="skipsyslinuxconfig", action="store_true", help="skip generation of syslinux configuration files") parser.add_option("--syslinux", dest="syslinux", action="callback", default=True, callback=syslinux_warning, help="install syslinux bootloader (deprecated as it's the default)") parser.add_option("--syslinux-mbr", dest="syslinuxmbr", action="store_true", help="install syslinux master boot record (MBR) instead of default") parser.add_option("--tmpdir", dest="tmpdir", default="/tmp", help="directory to be used for temporary files") parser.add_option("--verbose", dest="verbose", action="store_true", help="enable verbose mode") parser.add_option("-v", "--version", dest="version", action="store_true", help="display version and exit") (options, args) = parser.parse_args() GRML2USB_BASE = '/usr/share/grml2usb' if not os.path.isdir(GRML2USB_BASE): GRML2USB_BASE = os.path.dirname(os.path.realpath(__file__)) class CriticalException(Exception): """Throw critical exception if the exact error is not known but fatal. @Exception: message""" pass class VerifyException(Exception): """Throw critical exception if there is an fatal error when verifying something. @Exception: message""" pass # The following two functions help to operate on strings as # array (list) of bytes (octets). In Python 3000, the bytes # datatype will need to be used. This is intended for using # with manipulation of files on the octet level, like shell # arrays, e.g. in MBR creation. def array2string(*a): """Convert a list of integers [0;255] to a string.""" return struct.pack("%sB" % len(a), *a) def string2array(s): """Convert a (bytes) string into a list of integers.""" return struct.unpack("%sB" % len(s), s) def cleanup(): """Cleanup function to make sure there aren't any mounted devices left behind. """ logging.info("Cleaning up before exiting...") proc = subprocess.Popen(["sync"]) proc.wait() try: for device in MOUNTED: unmount(device, "") for tmpfile in TMPFILES: os.unlink(tmpfile) # ignore: RuntimeError: Set changed size during iteration except RuntimeError: logging.debug('caught exception RuntimeError, ignoring') def register_tmpfile(path): """ register tmpfile """ TMPFILES.add(path) def unregister_tmpfile(path): """ remove registered tmpfile """ try: TMPFILES.remove(path) except KeyError: pass def register_mountpoint(target): """register specified target in a set() for handling clean exiting @target: destination target of mountpoint """ MOUNTED.add(target) def unregister_mountpoint(target): """unregister specified target in a set() for handling clean exiting @target: destination target of mountpoint """ if target in MOUNTED: MOUNTED.remove(target) def get_function_name(obj): """Helper function for use in execute() to retrive name of a function @obj: the function object """ if not (isroutine(obj) or isclass(obj)): obj = type(obj) return obj.__module__ + '.' + obj.__name__ def execute(f, *exec_arguments): """Wrapper for executing a command. Either really executes the command (default) or when using --dry-run commandline option just displays what would be executed.""" # usage: execute(subprocess.Popen, (["ls", "-la"])) if options.dryrun: # pylint: disable-msg=W0141 logging.debug('dry-run only: %s(%s)', get_function_name(f), ', '.join(map(repr, exec_arguments))) else: # pylint: disable-msg=W0142 return f(*exec_arguments) def is_exe(fpath): """Check whether a given file can be executed @fpath: full path to file @return:""" return os.path.exists(fpath) and os.access(fpath, os.X_OK) def which(program): """Check whether a given program is available in PATH @program: name of executable""" fpath = os.path.split(program)[0] if fpath: if is_exe(program): return program else: for path in os.environ["PATH"].split(os.pathsep): exe_file = os.path.join(path, program) if is_exe(exe_file): return exe_file return None def get_defaults_file(iso_mount, flavour, name): """get the default file for syslinux """ bootloader_dirs = ['/boot/isolinux/', '/boot/syslinux/'] for directory in bootloader_dirs: for name in name, \ "%s_%s" % (get_flavour_filename(flavour), name): if os.path.isfile(iso_mount + directory + name): return (directory, name) return ('', '') def search_file(filename, search_path='/bin' + os.pathsep + '/usr/bin', lst_return=False): """Given a search path, find file @filename: name of file to search for @search_path: path where searching for the specified filename @lst_return: return list of matching files instead one file""" paths = search_path.split(os.pathsep) current_dir = '' # make pylint happy :) retval = [] def match_file(cwd): """Helper function ffor testing if specified file exists in cwd @cwd: current working directory """ return os.path.exists(os.path.join(cwd, filename)) for path in paths: current_dir = path if match_file(current_dir): retval.append(os.path.abspath(os.path.join(current_dir, filename))) if not lst_return: break # pylint: disable-msg=W0612 for current_dir, directories, files in os.walk(path): if match_file(current_dir): retval.append(os.path.abspath(os.path.join(current_dir, filename))) if not lst_return: break if lst_return: return retval elif retval: return retval[0] else: return None def check_uid_root(): """Check for root permissions""" if not os.geteuid() == 0: raise CriticalException("please run this script with uid 0 (root).") def check_boot_flag(device): boot_dev, x = get_device_from_partition(device) with open(boot_dev, 'r') as image: data = image.read(520) bootcode = data[440:] gpt_data = bootcode[70:80] if gpt_data == GPT_HEADER: logging.info("GPT detected, skipping bootflag check") elif bootcode[6] == '\x80': logging.debug("bootflag is enabled") else: logging.debug("bootflag is NOT enabled") raise VerifyException("Device %s does not have the bootflag set. " "Please enable it to be able to boot." % boot_dev) def mkfs_fat16(device): """Format specified device with VFAT/FAT16 filesystem. @device: partition that should be formated""" if options.dryrun: logging.info("Would execute mkfs.vfat -F 16 %s now.", device) return 0 logging.info("Formating partition with fat16 filesystem") logging.debug("mkfs.vfat -F 16 %s", device) proc = subprocess.Popen(["mkfs.vfat", "-F", "16", device]) proc.wait() if proc.returncode != 0: raise CriticalException("error executing mkfs.vfat") def generate_isolinux_splash(grml_flavour): """Generate bootsplash for isolinux/syslinux @grml_flavour: name of grml flavour the configuration should be generated for""" grml_name = grml_flavour return("""\ 17 /boot/syslinux/logo.16 Some information and boot options available via keys F2 - F10. http://grml.org/ %(grml_name)s """ % {'grml_name': grml_name}) def generate_main_syslinux_config(*arg): """Generate main configuration for use in syslinux.cfg @*arg: just for backward compatibility""" # pylint: disable-msg=W0613 # remove warning about unused arg return("""\ label - menu label Default boot modes: menu disable include defaults.cfg menu end menu separator # flavours: label - menu label Additional boot entries for: menu disable include additional.cfg menu separator include options.cfg include addons.cfg label help include promptname.cfg config prompt.cfg text help Jump to old style isolinux prompt featuring further information regarding available boot options. endtext include hiddens.cfg """) def generate_flavour_specific_syslinux_config(grml_flavour): """Generate flavour specific configuration for use in syslinux.cfg @grml_flavour: name of grml flavour the configuration should be generated for""" return("""\ menu begin grml %(grml_flavour)s menu title %(display_name)s label mainmenu menu label ^Back to main menu... menu exit menu separator # include config for boot parameters from disk include %(grml_flavour)s_grml.cfg menu hide menu end """ % {'grml_flavour': grml_flavour, 'display_name': get_flavour_filename(grml_flavour)}) def install_grub(device): """Install grub on specified device. @mntpoint: mountpoint of device where grub should install its files to @device: partition where grub should be installed to""" if options.dryrun: logging.info("Would execute grub-install [--root-directory=mount_point] %s now.", device) else: device_mountpoint = tempfile.mkdtemp(prefix="grml2usb") register_tmpfile(device_mountpoint) try: try: mount(device, device_mountpoint, "") # If using --grub-mbr then make sure we install grub in MBR instead of PBR if options.grubmbr: logging.debug("Using option --grub-mbr ...") grub_device, x = get_device_from_partition(device) else: grub_device = device logging.info("Installing grub as bootloader") for opt in ["", "--force"]: logging.debug("grub-install --recheck %s --no-floppy --root-directory=%s %s", opt, device_mountpoint, grub_device) proc = subprocess.Popen(["grub-install", "--recheck", opt, "--no-floppy", "--root-directory=%s" % device_mountpoint, grub_device], stdout=file(os.devnull, "r+")) proc.wait() if proc.returncode == 0: break if proc.returncode != 0: # raise Exception("error executing grub-install") logging.critical("Fatal: error executing grub-install " + "(please check the grml2usb FAQ or drop the --grub option)") logging.critical("Note: if using grub2 consider using " + "the --grub-mbr option as grub considers PBR problematic.") cleanup() sys.exit(1) except CriticalException, error: logging.critical("Fatal: %s", error) cleanup() sys.exit(1) finally: unmount(device_mountpoint, "") os.rmdir(device_mountpoint) unregister_tmpfile(device_mountpoint) def install_syslinux(device): """Install syslinux on specified device. @device: partition where syslinux should be installed to""" if options.dryrun: logging.info("Would install syslinux as bootloader on %s", device) return 0 # syslinux -d boot/isolinux /dev/sdb1 logging.info("Installing syslinux as bootloader") logging.debug("syslinux -d boot/syslinux %s", device) proc = subprocess.Popen(["syslinux", "-d", "boot/syslinux", device]) proc.wait() if proc.returncode != 0: raise CriticalException("Error executing syslinux (either try --fat16 or use grub?)") def install_bootloader(device): """Install bootloader on specified device. @device: partition where bootloader should be installed to""" # by default we use grub, so install syslinux only on request if options.grub: try: install_grub(device) except CriticalException, error: logging.critical("Fatal: %s", error) cleanup() sys.exit(1) else: try: install_syslinux(device) except CriticalException, error: logging.critical("Fatal: %s", error) cleanup() sys.exit(1) def install_mbr(mbrtemplate, device, partition, ismirbsdmbr=True): """install 'mbr' master boot record (MBR) on a device Retrieve the partition table from "device", install an MBR from the "mbrtemplate" file, set the "partition" (0..3) active, and install the result back to "device". @mbrtemplate: default MBR file @device: name of a file assumed to be a hard disc (or USB stick) image, or something like "/dev/sdb" @partition: must be a number between 0 and 3, inclusive @mbrtemplate: must be a valid MBR file of at least 440 (or 439 if ismirbsdmbr) bytes. @ismirbsdmbr: if true then ignore the active flag, set the mirbsdmbr specific flag to 0/1/2/3 and set the MBR's default value accordingly. If false then leave the mirbsdmbr specific flag set to FFh, set all active flags to 0 and set the active flag of the partition to 80h. Note: behaviour of mirbsdmbr: if flag = 0/1/2/3 then use it, otherwise search for the active flag.""" logging.info("Installing default MBR") if not os.path.isfile(mbrtemplate): logging.error('Error installing MBR (either try --syslinux-mbr or ' 'install missing file "%s"?)', mbrtemplate) raise CriticalException("%s can not be read." % mbrtemplate) if partition is not None and ((partition < 0) or (partition > 3)): logging.warn("Cannot activate partition %d", partition) partition = None if ismirbsdmbr: nmbrbytes = 439 else: nmbrbytes = 440 tmpf = tempfile.NamedTemporaryFile() logging.debug("executing: dd if='%s' of='%s' bs=512 count=1", device, tmpf.name) proc = subprocess.Popen(["dd", "if=%s" % device, "of=%s" % tmpf.name, "bs=512", "count=1"], stderr=file(os.devnull, "r+")) proc.wait() if proc.returncode != 0: raise Exception("error executing dd (first run)") logging.debug("executing: dd if=%s of=%s bs=%s count=1 conv=notrunc", mbrtemplate, tmpf.name, nmbrbytes) proc = subprocess.Popen(["dd", "if=%s" % mbrtemplate, "of=%s" % tmpf.name, "bs=%s" % nmbrbytes, "count=1", "conv=notrunc"], stderr=file(os.devnull, "r+")) proc.wait() if proc.returncode != 0: raise Exception("error executing dd (second run)") mbrcode = tmpf.file.read(512) if len(mbrcode) < 512: raise EOFError("MBR size (%d) < 512" % len(mbrcode)) if partition is not None: if ismirbsdmbr: mbrcode = mbrcode[0:439] + chr(partition) + \ mbrcode[440:510] + "\x55\xAA" else: actives = ["\x00", "\x00", "\x00", "\x00"] actives[partition] = "\x80" mbrcode = mbrcode[0:446] + actives[0] + \ mbrcode[447:462] + actives[1] + \ mbrcode[463:478] + actives[2] + \ mbrcode[479:494] + actives[3] + \ mbrcode[495:510] + "\x55\xAA" tmpf.file.seek(0) tmpf.file.truncate() tmpf.file.write(mbrcode) tmpf.file.close() logging.debug("executing: dd if='%s' of='%s' bs=512 count=1 conv=notrunc", tmpf.name, device) proc = subprocess.Popen(["dd", "if=%s" % tmpf.name, "of=%s" % device, "bs=512", "count=1", "conv=notrunc"], stderr=file(os.devnull, "r+")) proc.wait() if proc.returncode != 0: raise Exception("error executing dd (third run)") del tmpf def is_writeable(device): """Check if the device is writeable for the current user @device: partition where bootloader should be installed to""" if not device: return False #raise Exception("no device for checking write permissions") if not os.path.exists(device): return False return os.access(device, os.W_OK) and os.access(device, os.R_OK) def mount(source, target, mount_options): """Mount specified source on given target @source: name of device/ISO that should be mounted @target: directory where the ISO should be mounted to @options: mount specific options""" # note: options.dryrun does not work here, as we have to # locate files and identify the grml flavour for x in file('/proc/mounts').readlines(): if x.startswith(source): raise CriticalException("Error executing mount: %s already mounted - " % source + "please unmount before invoking grml2usb") if os.path.isdir(source): logging.debug("Source %s is not a device, therefore not mounting.", source) return 0 logging.debug("mount %s %s %s", mount_options, source, target) proc = subprocess.Popen(["mount"] + list(mount_options) + [source, target]) proc.wait() if proc.returncode != 0: raise CriticalException("Error executing mount (no filesystem on the partition?)") else: logging.debug("register_mountpoint(%s)", target) register_mountpoint(target) def unmount(target, unmount_options): """Unmount specified target @target: target where something is mounted on and which should be unmounted @options: options for umount command""" # make sure we unmount only already mounted targets target_unmount = False mounts = open('/proc/mounts').readlines() mountstring = re.compile(".*%s.*" % re.escape(os.path.realpath(target))) for line in mounts: if re.match(mountstring, line): target_unmount = True if not target_unmount: logging.debug("%s not mounted anymore", target) else: logging.debug("umount %s %s", list(unmount_options), target) proc = subprocess.Popen(["umount"] + list(unmount_options) + [target]) proc.wait() if proc.returncode != 0: raise Exception("Error executing umount") else: logging.debug("unregister_mountpoint(%s)", target) unregister_mountpoint(target) def check_for_usbdevice(device): """Check whether the specified device is a removable USB device @device: device name, like /dev/sda1 or /dev/sda """ usbdevice = re.match(r'/dev/(.*?)\d*$', device).group(1) # newer systems: usbdev = os.path.realpath('/sys/class/block/' + usbdevice + '/removable') if not os.path.isfile(usbdev): # Ubuntu with kernel 2.6.24 for example: usbdev = os.path.realpath('/sys/block/' + usbdevice + '/removable') if os.path.isfile(usbdev): is_usb = open(usbdev).readline() if is_usb.find("1"): return 0 return 1 def check_for_fat(partition): """Check whether specified partition is a valid VFAT/FAT16 filesystem @partition: device name of partition""" if not os.access(partition, os.R_OK): raise CriticalException("Failed to read device %s" " (wrong UID/permissions or device/directory not present?)" % partition) try: udev_info = subprocess.Popen(["/sbin/blkid", "-s", "TYPE", "-o", "value", partition], stdout=subprocess.PIPE, stderr=subprocess.PIPE) filesystem = udev_info.communicate()[0].rstrip() if filesystem != "vfat": raise CriticalException( "Partition %s does not contain a FAT16 filesystem. " "(Use --fat16 or run mkfs.vfat %s)" % (partition, partition)) except OSError: raise CriticalException("Sorry, /sbin/blkid not available (install e2fsprogs?)") def mkdir(directory): """Simple wrapper around os.makedirs to get shell mkdir -p behaviour""" # just silently pass as it's just fine it the directory exists if not os.path.isdir(directory): try: os.makedirs(directory) # pylint: disable-msg=W0704 except OSError: pass def exec_rsync(source, target): """Simple wrapper around rsync to install files @source: source file/directory @target: target file/directory""" logging.debug("Source: %s / Target: %s", source, target) proc = subprocess.Popen(["rsync", "-rlptDH", "--inplace", source, target]) proc.wait() if proc.returncode == 12: logging.critical("Fatal: No space left on device") cleanup() sys.exit(1) if proc.returncode != 0: logging.critical("Fatal: could not install %s", source) cleanup() sys.exit(1) def write_uuid(target_file): """Generates an returns uuid and write it to the specified file @target_file: filename to write the uuid to """ fileh = open(target_file, 'w') uid = str(uuid.uuid4()) fileh.write(uid) fileh.close() return uid def get_uuid(target): """Get the uuid of the specified target. Will generate an uuid if none exist. @target: directory/mountpoint containing the grml layout """ conf_target = target + "/conf/" uuid_file_name = conf_target + "/bootid.txt" if os.path.isdir(conf_target): if os.path.isfile(uuid_file_name): uuid_file = open(uuid_file_name, 'r') uid = uuid_file.readline().strip() uuid_file.close() return uid else: return write_uuid(uuid_file_name) else: execute(mkdir, conf_target) return write_uuid(uuid_file_name) def get_shortname(grml_flavour): """Get shortname based from grml_flavour name. The rules applied are the same as in grml-live @grml_flavour: flavour name which shold be translated to shortname""" return re.sub(r'[,._-]', '', grml_flavour) def copy_system_files(grml_flavour, iso_mount, target): """copy grml's main files (like squashfs, kernel and initrd) to a given target @grml_flavour: name of grml flavour the configuration should be generated for @iso_mount: path where a grml ISO is mounted on @target: path where grml's main files should be copied to""" squashfs = search_file(grml_flavour + '.squashfs', iso_mount) if squashfs is None: logging.error("error locating squashfs file") raise CriticalException("squashfs file not found, please check that your iso is not corrupt") else: squashfs_target = target + '/live/' + grml_flavour + '/' execute(mkdir, squashfs_target) exec_rsync(squashfs, squashfs_target + grml_flavour + '.squashfs') for prefix in grml_flavour + "/", "": filesystem_module = search_file(prefix + 'filesystem.module', iso_mount) if filesystem_module: break if filesystem_module is None: logging.error("error locating filesystem.module file") raise CriticalException("filesystem.module not found") else: exec_rsync(filesystem_module, squashfs_target + 'filesystem.module') shortname = get_shortname(grml_flavour) if os.path.isdir(iso_mount + '/boot/' + shortname): exec_rsync(iso_mount + '/boot/' + shortname, target + '/boot') else: kernel = search_file('vmlinuz', iso_mount) if kernel is None: # compat for releases < 2011.12 kernel = search_file('linux26', iso_mount) if kernel is None: logging.error("error locating kernel file") raise CriticalException("Kernel not found") source = os.path.dirname(kernel) + '/' dest = target + '/' + os.path.dirname(kernel).replace(iso_mount, '') + '/' execute(mkdir, dest) exec_rsync(source, dest) def update_grml_versions(iso_mount, target): """Update the grml version file on a cd Returns true if version was updated successfully, False if grml-version does not exist yet on the mountpoint @iso_mount: string of the iso mount point @target: path of the target mount point """ grml_target = target + '/grml/' target_grml_version_file = search_file('grml-version', grml_target) if target_grml_version_file: iso_grml_version_file = search_file('grml-version', iso_mount) if not iso_grml_version_file: logging.warn("Warning: %s could not be found - can not install it", iso_grml_version_file) return False try: # read the flavours from the iso image iso_versions = {} iso_file = open(iso_grml_version_file, 'r') for line in iso_file: iso_versions[get_flavour(line)] = line.strip() # update the existing flavours on the target for line in fileinput.input([target_grml_version_file], inplace=1): flavour = get_flavour(line) if flavour in iso_versions.keys(): print iso_versions.pop(flavour) else: print line.strip() fileinput.close() target_file = open(target_grml_version_file, 'a') # add the new flavours from the current iso for flavour in iso_versions: target_file.write("%s\n" % iso_versions[flavour]) except IOError: logging.warn("Warning: Could not write file") finally: iso_file.close() target_file.close() return True else: return False def copy_grml_files(grml_flavour, iso_mount, target): """copy some minor grml files to a given target @grml_flavour: the current grml_flavour @iso_mount: path where a grml ISO is mounted on @target: path where grml's main files should be copied to""" grml_target = target + '/grml/' execute(mkdir, grml_target) grml_prefixe = ["GRML", "grml"] for prefix in grml_prefixe: filename = "{0}/{1}/{2}".format(iso_mount, prefix, grml_flavour) if os.path.exists(filename): exec_rsync(filename, grml_target) break else: logging.warn("Warning: could not find flavour directory for %s ", grml_flavour) def handle_addon_copy(filename, dst, iso_mount, ignore_errors=False): """handle copy of optional addons @filename: filename of the addon @dst: destination directory @iso_mount: location of the iso mount @ignore_errors: don't report missing files """ file_location = search_file(filename, iso_mount) if file_location is None: if not ignore_errors: logging.warn("Warning: %s not found (that's fine if you don't need it)", filename) else: exec_rsync(file_location, dst) def copy_addons(iso_mount, target): """copy grml's addons files (like allinoneimg, bsd4grml,..) to a given target @iso_mount: path where a grml ISO is mounted on @target: path where grml's main files should be copied to""" addons = target + '/boot/addons/' execute(mkdir, addons) # grub all-in-one image handle_addon_copy('allinone.img', addons, iso_mount) # bsd image handle_addon_copy('bsd4grml', addons, iso_mount) # DOS image handle_addon_copy('balder10.imz', addons, iso_mount) # syslinux + pci.ids for hdt for expr in '*.c32', 'pci.ids': glob_and_copy(iso_mount + '/boot/addons/' + expr, addons) # memdisk image handle_addon_copy('memdisk', addons, iso_mount) # memtest86+ image handle_addon_copy('memtest', addons, iso_mount) # gpxe.lkrn: got replaced by ipxe handle_addon_copy('gpxe.lkrn', addons, iso_mount, ignore_errors=True) # ipxe.lkrn handle_addon_copy('ipxe.lkrn', addons, iso_mount) def build_loopbackcfg(target): """Generate GRUB's loopback.cfg based on existing config files. @target: target directory """ grub_dir = '/boot/grub/' mkdir(os.path.join(target, grub_dir)) f = open(target + grub_dir + 'loopback.cfg', 'w') f.write("# grml2usb generated grub2 configuration file\n") f.write("source /boot/grub/header.cfg\n") for defaults in glob.glob(target + os.path.sep + grub_dir + os.path.sep + "*_default.cfg"): sourcefile = defaults.split(target + os.path.sep)[1] logging.debug("Found source file" + sourcefile) os.path.isfile(defaults) and f.write("source " + sourcefile + "\n") for ops in glob.glob(target + os.path.sep + grub_dir + os.path.sep + "*_options.cfg"): sourcefile = ops.split(target + os.path.sep)[1] logging.debug("Found source file" + sourcefile) os.path.isfile(ops) and f.write("source " + sourcefile + "\n") f.write("source /boot/grub/addons.cfg\n") f.write("source /boot/grub/footer.cfg\n") f.close() def glob_and_copy(filepattern, dst): """Glob on specified filepattern and copy the result to dst @filepattern: globbing pattern @dst: target directory """ for name in glob.glob(filepattern): copy_if_exist(name, dst) def search_and_copy(filename, search_path, dst): """Search for the specified filename at searchpath and copy it to dst @filename: filename to look for @search_path: base search file @dst: destionation to copy the file to """ file_location = search_file(filename, search_path) copy_if_exist(file_location, dst) def copy_if_exist(filename, dst): """Copy filename to dst if filename is set. @filename: a filename @dst: dst file """ if filename and (os.path.isfile(filename) or os.path.isdir(filename)): exec_rsync(filename, dst) def copy_bootloader_files(iso_mount, target, grml_flavour): """Copy grml's bootloader files to a given target @iso_mount: path where a grml ISO is mounted on @target: path where grml's main files should be copied to @grml_flavour: name of the current processed grml_flavour """ syslinux_target = target + '/boot/syslinux/' execute(mkdir, syslinux_target) grub_target = target + '/boot/grub/' execute(mkdir, grub_target) logo = search_file('logo.16', iso_mount) exec_rsync(logo, syslinux_target + 'logo.16') bootx64_efi = search_file('bootx64.efi', iso_mount) if bootx64_efi: mkdir(target + '/efi/boot/') exec_rsync(bootx64_efi, target + '/efi/boot/bootx64.efi') efi_img = search_file('efi.img', iso_mount) if efi_img: mkdir(target + '/boot/') exec_rsync(efi_img, target + '/boot/efi.img') for ffile in ['f%d' % number for number in range(1, 11)]: search_and_copy(ffile, iso_mount, syslinux_target + ffile) # avoid the "file is read only, overwrite anyway (y/n) ?" question # of mtools by syslinux ("mmove -D o -D O s:/ldlinux.sys $target_file") if os.path.isfile(syslinux_target + 'ldlinux.sys'): os.unlink(syslinux_target + 'ldlinux.sys') (source_dir, name) = get_defaults_file(iso_mount, grml_flavour, "default.cfg") (source_dir, defaults_file) = get_defaults_file(iso_mount, grml_flavour, "grml.cfg") if not source_dir: raise CriticalException( "file default.cfg could not be found.\n" "Note: this grml2usb version requires an ISO generated by grml-live >=0.9.24 ...\n" " ... either use grml releases >=2009.10 or switch to an older grml2usb version.") if not os.path.exists(iso_mount + '/boot/grub/footer.cfg'): logging.warning("Warning: Grml releases older than 2011.12 support only one flavour in grub.") for expr in name, 'distri.cfg', \ defaults_file, 'grml.png', 'hd.cfg', 'isolinux.cfg', 'isolinux.bin', \ 'isoprompt.cfg', 'options.cfg', \ 'prompt.cfg', 'vesamenu.cfg', 'grml.png', '*.c32': glob_and_copy(iso_mount + source_dir + expr, syslinux_target) for filename in glob.glob1(syslinux_target, "*.c32"): copy_if_exist(os.path.join(SYSLINUX_LIBS, filename), syslinux_target) # copy the addons_*.cfg file to the new syslinux directory glob_and_copy(iso_mount + source_dir + 'addon*.cfg', syslinux_target) search_and_copy('hidden.cfg', iso_mount + source_dir, syslinux_target + "new_" + 'hidden.cfg') # copy all grub files from ISO glob_and_copy(iso_mount + '/boot/grub/*', grub_target) # finally (after all GRUB files have been been installed) build static loopback.cfg build_loopbackcfg(target) def install_iso_files(grml_flavour, iso_mount, device, target): """Copy files from ISO to given target @grml_flavour: name of grml flavour the configuration should be generated for @iso_mount: path where a grml ISO is mounted on @device: device/partition where bootloader should be installed to @target: path where grml's main files should be copied to""" global GRML_DEFAULT GRML_DEFAULT = GRML_DEFAULT or grml_flavour if options.dryrun: return 0 elif not options.bootloaderonly: logging.info("Copying files. This might take a while....") try: copy_system_files(grml_flavour, iso_mount, target) copy_grml_files(grml_flavour, iso_mount, target) except CriticalException, error: logging.critical("Execution failed: %s", error) sys.exit(1) if not options.skipaddons: if not search_file('addons', iso_mount): logging.info("Could not find addons, therefore not installing.") else: copy_addons(iso_mount, target) if not options.copyonly: copy_bootloader_files(iso_mount, target, grml_flavour) if not options.dryrun: handle_bootloader_config(grml_flavour, device, target) # make sure we sync filesystems before returning proc = subprocess.Popen(["sync"]) proc.wait() def get_device_from_partition(partition): device = partition partition_number = None if partition[-1].isdigit() and not RE_LOOP_DEVICE.match(partition): m = RE_P_PARTITION.match(partition) if not m: m = RE_PARTITION.match(partition) if m: device = m.group(1) partition_number = int(m.group(2)) - 1 return (device, partition_number) def get_flavour(flavour_str): """Returns the flavour of a grml version string """ return re.match(r'[\w-]*', flavour_str).group() def identify_grml_flavour(mountpath): """Get name of grml flavour @mountpath: path where the grml ISO is mounted to @return: name of grml-flavour""" version_files = search_file('grml-version', mountpath, lst_return=True) if not version_files: if mountpath.startswith("/lib/live/mount/medium"): logging.critical("Error: could not find grml-version file.") logging.critical("Looks like your system is running from RAM but required files are not available.") logging.critical("Please either boot without toram=... or use boot option toram instead of toram=...") cleanup() sys.exit(1) else: logging.critical("Error: could not find grml-version file.") cleanup() sys.exit(1) flavours = [] logging.debug("version_files = %s", version_files) for version_file in version_files: tmpfile = None try: tmpfile = open(version_file, 'r') for line in tmpfile.readlines(): flavours.append(get_flavour(line)) except TypeError, e: raise except Exception, e: raise finally: if tmpfile: tmpfile.close() return flavours def get_bootoptions(grml_flavour): """Returns bootoptions for specific flavour @grml_flavour: name of the grml_flavour """ # do NOT write "None" in kernel cmdline if not options.bootoptions: bootopt = "" else: bootopt = " ".join(options.bootoptions) bootopt = bootopt.replace("%flavour", grml_flavour) return bootopt def handle_grub_config(grml_flavour, device, target): """Main handler for generating grub (v1 and v2) configuration @grml_flavour: name of grml flavour the configuration should be generated for @device: device/partition where grub should be installed to @target: path of grub's configuration files""" global UUID logging.debug("Updating grub configuration") grub_target = target + '/boot/grub/' bootid_re = re.compile("bootid=[\w_-]+") live_media_path_re = re.compile("live-media-path=[\w_/-]+") bootopt = get_bootoptions(grml_flavour) remove_regexes = [] option_re = re.compile(r'(.*/boot/.*(linux26|vmlinuz).*)') if options.removeoption: for regex in options.removeoption: remove_regexes.append(re.compile(regex)) shortname = get_shortname(grml_flavour) for filename in glob.glob(grub_target + '*.cfg'): for line in fileinput.input(filename, inplace=1): line = line.rstrip("\r\n") if option_re.search(line): line = bootid_re.sub('', line) if shortname in filename: line = live_media_path_re.sub('', line) line = line.rstrip() + ' live-media-path=/live/%s/ ' % (grml_flavour) line = line.rstrip() + r' bootid=%s %s ' % (UUID, bootopt) for regex in remove_regexes: line = regex.sub(' ', line) print line fileinput.close() def initial_syslinux_config(target): """Generates intial syslinux configuration @target path of syslinux's configuration files""" target = target + "/" filename = target + "grmlmain.cfg" if os.path.isfile(target + "grmlmain.cfg"): return data = open(filename, "w") data.write(generate_main_syslinux_config()) data.close() filename = target + "hiddens.cfg" data = open(filename, "w") data.write("include hidden.cfg\n") data.close() def add_entry_if_not_present(filename, entry): """Write entry into filename if entry is not already in the file @filanme: name of the file @entry: data to write to the file """ data = open(filename, "a+") for line in data: if line == entry: break else: data.write(entry) data.close() def get_flavour_filename(flavour): """Generate a iso9960 save filename out of the specified flavour @flavour: grml flavour """ return flavour.replace('-', '_') def adjust_syslinux_bootoptions(src, flavour): """Adjust existing bootoptions of specified syslinux config to grml2usb specific ones, e.g. change the location of the kernel... @src: config file to alter @flavour: grml flavour """ append_re = re.compile("^(\s*append.*/boot/.*)$", re.I) # flavour_re = re.compile("(label.*)(grml\w+)") default_re = re.compile("(default.cfg)") bootid_re = re.compile("bootid=[\w_-]+") live_media_path_re = re.compile("live-media-path=[\w_/-]+") bootopt = get_bootoptions(flavour) regexe = [] option_re = None if options.removeoption: option_re = re.compile(r'/boot/.*/(initrd.gz|initrd.img)') for regex in options.removeoption: regexe.append(re.compile(r'%s' % regex)) for line in fileinput.input(src, inplace=1): # line = flavour_re.sub(r'\1 %s-\2' % flavour, line) line = default_re.sub(r'%s-\1' % flavour, line) line = bootid_re.sub('', line) line = live_media_path_re.sub('', line) line = append_re.sub(r'\1 live-media-path=/live/%s/ ' % flavour, line) line = append_re.sub(r'\1 boot=live %s ' % bootopt, line) line = append_re.sub(r'\1 %s=%s ' % ("bootid", UUID), line) if option_re and option_re.search(line): for regex in regexe: line = regex.sub(' ', line) sys.stdout.write(line) fileinput.close() def adjust_labels(src, replacement): """Adjust the specified labels in the syslinux config file src with specified replacement """ label_re = re.compile("^(\s*label\s*) ([a-zA-Z0-9_-]+)", re.I) for line in fileinput.input(src, inplace=1): line = label_re.sub(replacement, line) sys.stdout.write(line) fileinput.close() def add_syslinux_entry(filename, grml_flavour): """Add includes for a specific grml_flavour to the specified filename @filename: syslinux config file @grml_flavour: grml flavour to add """ entry_filename = "option_%s.cfg" % grml_flavour entry = "include %s\n" % entry_filename add_entry_if_not_present(filename, entry) path = os.path.dirname(filename) data = open(path + "/" + entry_filename, "w") data.write(generate_flavour_specific_syslinux_config(grml_flavour)) data.close() def modify_filenames(grml_flavour, target, filenames): """Replace the standard filenames with the new ones @grml_flavour: grml-flavour strin @target: directory where the files are located @filenames: list of filenames to alter """ grml_filename = get_flavour_filename(grml_flavour) for filename in filenames: old_filename = "%s/%s" % (target, filename) new_filename = "%s/%s_%s" % (target, grml_filename, filename) os.rename(old_filename, new_filename) def remove_default_entry(filename): """Remove the default entry from specified syslinux file @filename: syslinux config file """ default_re = re.compile("^(\s*menu\s*default\s*)$", re.I) for line in fileinput.input(filename, inplace=1): if default_re.match(line): continue sys.stdout.write(line) fileinput.close() def handle_syslinux_config(grml_flavour, target): """Main handler for generating syslinux configuration @grml_flavour: name of grml flavour the configuration should be generated for @target: path of syslinux's configuration files""" logging.debug("Generating syslinux configuration") syslinux_target = target + '/boot/syslinux/' # should be present via copy_bootloader_files(), but make sure it exits: execute(mkdir, syslinux_target) syslinux_cfg = syslinux_target + 'syslinux.cfg' # install main configuration only *once*, no matter how many ISOs we have: syslinux_config_file = open(syslinux_cfg, 'w') syslinux_config_file.write("timeout 300\n") syslinux_config_file.write("include vesamenu.cfg\n") syslinux_config_file.close() prompt_name = open(syslinux_target + 'promptname.cfg', 'w') prompt_name.write('menu label S^yslinux prompt\n') prompt_name.close() initial_syslinux_config(syslinux_target) flavour_filename = get_flavour_filename(grml_flavour) if search_file('default.cfg', syslinux_target): modify_filenames(grml_flavour, syslinux_target, ['grml.cfg', 'default.cfg']) filename = search_file("new_hidden.cfg", syslinux_target) # process hidden file if not search_file("hidden.cfg", syslinux_target): new_hidden = syslinux_target + "hidden.cfg" os.rename(filename, new_hidden) adjust_syslinux_bootoptions(new_hidden, grml_flavour) else: new_hidden_file = "%s/%s_hidden.cfg" % (syslinux_target, flavour_filename) os.rename(filename, new_hidden_file) adjust_labels(new_hidden_file, r'\1 %s-\2' % grml_flavour) adjust_syslinux_bootoptions(new_hidden_file, grml_flavour) entry = 'include %s_hidden.cfg\n' % flavour_filename add_entry_if_not_present("%s/hiddens.cfg" % syslinux_target, entry) new_default = "%s_default.cfg" % (flavour_filename) entry = 'include %s\n' % new_default defaults_file = '%s/defaults.cfg' % syslinux_target new_default_with_path = "%s/%s" % (syslinux_target, new_default) new_grml_cfg = "%s/%s_grml.cfg" % (syslinux_target, flavour_filename) if os.path.isfile(defaults_file): # remove default menu entry in menu remove_default_entry(new_default_with_path) # adjust all labels for additional isos adjust_labels(new_default_with_path, r'\1 %s' % grml_flavour) adjust_labels(new_grml_cfg, r'\1 %s-\2' % grml_flavour) # always adjust bootoptions adjust_syslinux_bootoptions(new_default_with_path, grml_flavour) adjust_syslinux_bootoptions(new_grml_cfg, grml_flavour) add_entry_if_not_present("%s/defaults.cfg" % syslinux_target, entry) add_syslinux_entry("%s/additional.cfg" % syslinux_target, flavour_filename) def handle_bootloader_config(grml_flavour, device, target): """Main handler for generating bootloader's configuration @grml_flavour: name of grml flavour the configuration should be generated for @device: device/partition where bootloader should be installed to @target: path of bootloader's configuration files""" global UUID UUID = get_uuid(target) if options.skipsyslinuxconfig: logging.info("Skipping generation of syslinux configuration as requested.") else: try: handle_syslinux_config(grml_flavour, target) except CriticalException, error: logging.critical("Fatal: %s", error) sys.exit(1) if options.skipgrubconfig: logging.info("Skipping generation of grub configuration as requested.") else: try: handle_grub_config(grml_flavour, device, target) except CriticalException, error: logging.critical("Fatal: %s", error) sys.exit(1) def install(image, device): """Install a grml image to the specified device @image: directory or is file @device: partition or directory to install the device """ iso_mountpoint = image remove_image_mountpoint = False if os.path.isdir(image): logging.info("Using %s as install base", image) else: logging.info("Using ISO %s", image) iso_mountpoint = tempfile.mkdtemp(prefix="grml2usb", dir=os.path.abspath(options.tmpdir)) register_tmpfile(iso_mountpoint) remove_image_mountpoint = True try: mount(image, iso_mountpoint, ["-o", "loop,ro", "-t", "iso9660"]) except CriticalException, error: logging.critical("Fatal: %s", error) sys.exit(1) try: install_grml(iso_mountpoint, device) finally: if remove_image_mountpoint: try: remove_mountpoint(iso_mountpoint) except CriticalException, error: cleanup() raise def install_grml(mountpoint, device): """Main logic for copying files of the currently running grml system. @mountpoint: directory where currently running live system resides (usually /lib/live/mount/medium) @device: partition where the specified ISO should be installed to""" device_mountpoint = device if os.path.isdir(device): logging.info("Specified device is a directory, therefore not mounting.") remove_device_mountpoint = False else: device_mountpoint = tempfile.mkdtemp(prefix="grml2usb") register_tmpfile(device_mountpoint) remove_device_mountpoint = True try: check_for_fat(device) check_boot_flag(device) mount(device, device_mountpoint, ['-o', 'utf8,iocharset=iso8859-1']) except VerifyException, error: raise except CriticalException, error: mount(device, device_mountpoint, "") try: grml_flavours = identify_grml_flavour(mountpoint) for flavour in set(grml_flavours): if not flavour: logging.warning("No valid flavour found, please check your iso") logging.info("Identified grml flavour \"%s\".", flavour) install_iso_files(flavour, mountpoint, device, device_mountpoint) GRML_FLAVOURS.add(flavour) finally: if remove_device_mountpoint: remove_mountpoint(device_mountpoint) def remove_mountpoint(mountpoint): """remove a registered mountpoint """ try: unmount(mountpoint, "") if os.path.isdir(mountpoint): os.rmdir(mountpoint) unregister_tmpfile(mountpoint) except CriticalException, error: cleanup() raise def handle_mbr(device): """Main handler for installing master boot record (MBR) @device: device where the MBR should be installed to""" if options.dryrun: logging.info("Would install MBR") return 0 mbr_device, partition_number = get_device_from_partition(device) if partition_number is None: logging.warn("Could not detect partition number, not activating partition") # if we get e.g. /dev/loop1 as device we don't want to put the MBR # into /dev/loop of course, therefore use /dev/loop1 as mbr_device if mbr_device == "/dev/loop": mbr_device = device logging.info("Detected loop device - using %s as MBR device therefore", mbr_device) mbrcode = GRML2USB_BASE + '/mbr/mbrldr' if options.syslinuxmbr: mbrcode = "" mbr_locations = ('/usr/lib/syslinux/mbr.bin', '/usr/share/syslinux/mbr.bin') for mbrpath in mbr_locations: if os.path.isfile(mbrpath): mbrcode = mbrpath break if mbrcode is "": str_locations = " or ".join(['"%s"' % l for l in mbr_locations]) logging.error('Cannot find syslinux MBR, install it at %s)', str_locations) raise CriticalException("syslinux MBR can not be found at %s." % str_locations) elif options.mbrmenu: mbrcode = GRML2USB_BASE + '/mbr/mbrldr' try: install_mbr(mbrcode, mbr_device, partition_number, True) except IOError, error: logging.critical("Execution failed: %s", error) sys.exit(1) except Exception, error: logging.critical("Execution failed: %s", error) sys.exit(1) def handle_vfat(device): """Check for FAT specific settings and options @device: device that should checked / formated""" # make sure we have mkfs.vfat available if options.fat16: if not which("mkfs.vfat") and not options.copyonly and not options.dryrun: logging.critical('Sorry, mkfs.vfat not available. Exiting.') logging.critical('Please make sure to install dosfstools.') sys.exit(1) if options.force: print "Forcing mkfs.fat16 on %s as requested via option --force." % device else: # make sure the user is aware of what he is doing f = raw_input("Are you sure you want to format the specified partition with fat16? y/N ") if f == "y" or f == "Y": logging.info("Note: you can skip this question using the option --force") else: sys.exit(1) try: mkfs_fat16(device) except CriticalException, error: logging.critical("Execution failed: %s", error) sys.exit(1) # check for vfat filesystem if device is not None and not os.path.isdir(device) and options.syslinux: try: check_for_fat(device) except CriticalException, error: logging.critical("Execution failed: %s", error) sys.exit(1) if not os.path.isdir(device) and not check_for_usbdevice(device) and not options.force: print "Warning: the specified device %s does not look like a removable usb device." % device f = raw_input("Do you really want to continue? y/N ") if f == "y" or f == "Y": pass else: sys.exit(1) def handle_compat_warning(device): """Backwards compatible checks @device: device that should be checked""" # make sure we can replace old grml2usb script and warn user when using old way of life: if device.startswith("/mnt/external") or device.startswith("/mnt/usb") and not options.force: print "Warning: the semantics of grml2usb has changed." print "Instead of using grml2usb /path/to/iso %s you might" % device print "want to use grml2usb /path/to/iso /dev/... instead." print "Please check out the grml2usb manpage for details." f = raw_input("Do you really want to continue? y/N ") if f == "y" or f == "Y": pass else: sys.exit(1) def handle_logging(): """Log handling and configuration""" if options.verbose and options.quiet: parser.error("please use either verbose (--verbose) or quiet (--quiet) option") FORMAT = "%(message)s" if options.verbose: FORMAT = "%(asctime)-15s %(message)s" logging.basicConfig(level=logging.DEBUG, format=FORMAT) elif options.quiet: logging.basicConfig(level=logging.CRITICAL, format=FORMAT) else: logging.basicConfig(level=logging.INFO, format=FORMAT) def handle_bootloader(device): """wrapper for installing bootloader @device: device where bootloader should be installed to""" # Install bootloader only if not using the --copy-only option if options.copyonly: logging.info("Not installing bootloader and its files as requested via option copyonly.") elif os.path.isdir(device): logging.info("Not installing bootloader as %s is a directory.", device) else: install_bootloader(device) def check_options(opts): """Check compability of provided user opts @opts option dict from OptionParser """ if opts.grubmbr and not opts.grub: raise CriticalException("--grub-mbr requires --grub option.") def check_programs(): """check if all needed programs are installed""" if options.grub: if not which("grub-install"): logging.critical("Fatal: grub-install not available (please install the " + "grub package or drop the --grub option)") sys.exit(1) if options.syslinux: if not which("syslinux"): logging.critical("Fatal: syslinux not available (please install the " + "syslinux package or use the --grub option)") sys.exit(1) if not which("rsync"): logging.critical("Fatal: rsync not available, can not continue - sorry.") sys.exit(1) def load_loop(): """Runs modprobe loop and throws away it's output""" if not which("modprobe"): logging.critical("Fatal: modprobe not available, can not continue - sorry.") logging.critical("Hint: is /sbin missing in PATH?") sys.exit(1) proc = subprocess.Popen(["modprobe", "loop"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) proc.wait() def main(): """Main function [make pylint happy :)]""" try: if options.version: print os.path.basename(sys.argv[0]) + " " + PROG_VERSION sys.exit(0) if len(args) < 2: parser.error("invalid usage") # log handling handle_logging() # make sure we have the appropriate permissions check_uid_root() check_options(options) load_loop() logging.info("Executing grml2usb version %s", PROG_VERSION) if options.dryrun: logging.info("Running in simulation mode as requested via option dry-run.") check_programs() # specified arguments device = os.path.realpath(args[len(args) - 1]) isos = args[0:len(args) - 1] if not os.path.isdir(device): if device[-1:].isdigit(): if int(device[-1:]) > 4 or device[-2:].isdigit(): logging.critical("Fatal: installation on partition number >4 not supported. (BIOS won't support it.)") sys.exit(1) # provide upgrade path handle_compat_warning(device) # check for vfat partition handle_vfat(device) # main operation (like installing files) for iso in isos: install(iso, device) # install mbr is_superfloppy = not device[-1:].isdigit() if is_superfloppy: logging.info("Detected superfloppy format - not installing MBR") if not options.skipmbr and not os.path.isdir(device) and not is_superfloppy: handle_mbr(device) handle_bootloader(device) logging.info("Note: grml flavour %s was installed as the default booting system.", GRML_DEFAULT) for flavour in GRML_FLAVOURS: logging.info("Note: you can boot flavour %s using '%s' on the commandline.", flavour, flavour) # finally be politely :) logging.info("Finished execution of grml2usb (%s). Have fun with your grml system.", PROG_VERSION) except Exception, error: logging.critical("Fatal: %s", str(error)) sys.exit(1) if __name__ == "__main__": try: main() except KeyboardInterrupt: logging.info("Received KeyboardInterrupt") cleanup() ## END OF FILE ################################################################# # vim:foldmethod=indent expandtab ai ft=python tw=120 fileencoding=utf-8 grml2usb-0.14.2/grml2iso.8.txt0000644000000000000000000000721511746010600012666 0ustar grml2iso(8) ========== Name ---- grml2iso - create a multiboot grml ISO using grml2usb Synopsis -------- grml2iso -o ******************************************************************************* Important! The grml team does not take responsibility for loss of any data! ******************************************************************************* Introduction ------------ grml2iso allows you to create a multiboot grml ISO. You can specify two or more grml ISOs and will get one single multiboot ISO as a result. grml2iso requires and uses grml2usb for this task and installs grub2 as bootmanager on the multiboot ISO. Options ------- grml2iso supports the environment variables GRML2USB and WRKDIR. GRML2USB specifies the path to the grml2usb script you'd like to use. WRKDIR specifies the work directory for creating the filesystem. The work directory needs at least as much free disk space as the sum of all specified ISOs. *-o *:: This option is mandatory and specifies where the resulting multiboot grml ISO should be placed. Note that (to avoid any possible data loss) grml2iso will exit if the specified target.iso exists already. *-c *:: The content of the specified directory will be copied to the resulting multiboot grml ISO. *-b *:: Use specified default bootoptions as default. *-f*:: Force the program to run and overwrite an existing iso image. *-r *:: Remove specified boot parameter from existing command line. Could be specified multiple times. *-p *:: Execute grml2usb with the specified parameters. For a list of valid parameters have a look at the link:http://grml.org/grml2usb/[grml2usb webpage] or the grml2usb manpage *-s *:: Generate a small iso file which downloads the squashfs file from the specified URI. Due to current limitations in busyboxs wget and DNS resolution, an URL can not contain a hostname but an IP only. This is useful if you want to boot systems which support booting iso image from your local system. Besides the iso image this command also copies the squashfs file to the output directory. Usage examples -------------- # grml2iso -o /tmp/grml.iso grml_2009.05.iso grml64_2009.05.iso Create multiboot ISO /tmp/grml.iso with grml_2009.05.iso and grml64_2009.05.iso. # grml2iso -b 'lang=de ssh=passwd' -c /tmp/grml-content -o /srv/grml.iso /srv/grml/grml_2009.10.iso Create a new iso with additional boot parameters and copy the content from /tmp/grml-content to the generated iso image. # grml2iso -r quiet -r vga=791 -o /srv/grml.iso /srv/grml-small_2009.10.iso Create a new iso and remove existing boot parameters quiet and vga=791. # GRML2USB=/srv/git/grml2usb grml2iso -o /srv/grml.iso /srv/grml/grml_2009.05.iso /srv/grml/grml64-medium_2009.05.iso Create multiboot ISO /srv/grml.iso with grml_2009.05.iso and grml64-medium_2009.05.iso using /srv/git/grml2usb as grml2usb script. # WRKDIR=/mnt/test/grml-tmp grml2iso -o /mnt/test/grml.iso grml_2009.05.iso grml64_2009.05.iso Use /mnt/test/grml-tmp as working directory for creating the multiboot ISO /mnt/test/grml.iso with grml_2009.05.iso and grml64_2009.05.iso. # grml2iso -p --skip-addons -o /srv/grml.iso /srv/grml-small_2009.10.iso /srv/grml64-small_2009.10.iso Don't copy the addons from the specified iso images Online Ressources ----------------- Check out the link:http://grml.org/grml2usb/[grml2usb webpage] and the link:http://git.grml.org/?p=grml2usb.git[grml2usb git repository]. Bugs ---- Please report feedback, bugreports and wishes <>. [[X7]] Authors ------- Michael Prokop and Thorsten Glaser grml2usb-0.14.2/tarball.sh0000755000000000000000000001003711746267740012220 0ustar #!/bin/sh # Filename: tarball.sh # Purpose: generate tarball for using grml2usb on non-Debian systems # Authors: grml-team (grml.org), (c) Michael Prokop # Bug-Reports: see http://grml.org/bugs/ # License: This file is licensed under the GPL v2 or any later version. ################################################################################ set -e VERSION=$(dpkg-parsechangelog | awk '/Version: / { print $2 }') DIR="grml2usb-${VERSION}" [ -d "$DIR" ] || mkdir "$DIR" cat > "${DIR}"/README << EOF README ------ grml2usb installs grml ISO(s) on usb device for booting. This tarball provides all the necessary files for running grml2usb. Execute the script install.sh with root permissions to install the files provided by the tarball in the filesystem. Updating is possible via downloading the most recent tarball and executing install.sh again. If you want to remove grml2usb from your system just execute the provided uninstall.sh script with root permissions. Note: If you are using Debian (or a Debian based system like grml, Ubuntu,...) consider using the provided grml2usb Debian package: http://deb.grml.org/ => http://deb.grml.org/pool/main/g/grml2usb/ Please report bugs and feedback to Michael Prokop . EOF cat > "${DIR}"/install.sh << EOF #!/bin/sh set -e if [ \$(id -u) != 0 ] ; then echo "Error: become root before starting \$0" >& 2 exit 1 fi BASE="\$(dirname \$0)" printf "Installing files:\n" printf " - /usr/sbin/grml2usb\n" install -m 755 \${BASE}/grml2usb /usr/sbin/grml2usb printf " - /usr/sbin/grml2iso\n" install -m 755 \${BASE}/grml2iso /usr/sbin/grml2iso [ -d /usr/share/grml2usb/grub ] || mkdir -p /usr/share/grml2usb/grub printf " - /usr/share/grml2usb/grub/splash.xpm.gz\n" install -m 644 \${BASE}/splash.xpm.gz /usr/share/grml2usb/grub/splash.xpm.gz printf " - /usr/share/grml2usb/grub/grml.png\n" install -m 644 \${BASE}/grml.png /usr/share/grml2usb/grub/grml.png [ -d /usr/share/grml2usb/mbr ] || mkdir -p /usr/share/grml2usb/mbr printf " - /usr/share/grml2usb/mbr/mbrmgr\n" install -m 644 \${BASE}/mbrmgr /usr/share/grml2usb/mbr/mbrmgr printf " - /usr/share/grml2usb/mbr/mbrldr\n" install -m 644 \${BASE}/mbrldr /usr/share/grml2usb/mbr/mbrldr [ -d /usr/share/man/man8/ ] || mkdir -p /usr/share/man/man8 printf " - /usr/share/man/man8/grml2usb.8.gz\n" install -m 644 \${BASE}/grml2usb.8.gz /usr/share/man/man8/grml2usb.8.gz printf "Finished installation.\n" EOF chmod 755 "${DIR}"/install.sh cat > "${DIR}"/uninstall.sh << EOF #!/bin/sh set -e if [ \$(id -u) != 0 ] ; then echo "Error: become root before starting \$0" >& 2 exit 1 fi for file in \\ /usr/sbin/grml2usb \\ /usr/sbin/grml2iso \\ /usr/share/grml2usb/grub/splash.xpm.gz \\ /usr/share/grml2usb/grub/grml.png \\ /usr/share/grml2usb/mbr/mbrmgr \\ /usr/share/grml2usb/mbr/mbrldr \\ /usr/share/man/man8/grml2usb.8.gz \\ ; do printf "Removing \$file: " rm -f \$file && printf "done\n" || printf "failed\n" done EOF chmod 755 "${DIR}"/uninstall.sh fakeroot debian/rules build # manpage cp grml2usb.8.txt grml2usb-$VERSION/ cp grml2iso.8.txt grml2usb-$VERSION/ gzip -9 --to-stdout grml2usb-$VERSION/grml2usb.8.txt > grml2usb-$VERSION/grml2usb.8.gz gzip -9 --to-stdout grml2usb-$VERSION/grml2iso.8.txt > grml2usb-$VERSION/grml2iso.8.gz rm grml2usb-$VERSION/grml2usb.8.txt rm grml2usb-$VERSION/grml2iso.8.txt # binaries, grub cp grml2usb grml2iso mbr/mbrldr mbr/mbrmgr grub/* grml2usb-$VERSION/ sed -i -e "s/PROG_VERSION='\*\*\*UNRELEASED\*\*\*'/PROG_VERSION='${VERSION}'/" grml2usb-$VERSION/grml2usb tar zcf grml2usb.tgz "${DIR}" rm -rf "${DIR}" md5sum grml2usb.tgz > grml2usb.tgz.md5 case "$1" in --no-gpg) echo "Not signing grml2usb.tgz.md5 as requested via --no-gpg." echo "Do not forget to run gpg --clearsign grml2usb.tgz.md5 before uploading." ;; *) gpg --clearsign grml2usb.tgz.md5 rm grml2usb.tgz.md5 echo "Generated grml2usb.tgz and grml2usb.tgz.md5.asc of grml2usb $VERSION" ;; esac ## END OF FILE ################################################################# grml2usb-0.14.2/grml2usb.8.txt0000644000000000000000000005644212073535125012703 0ustar grml2usb(8) ========== Name ---- grml2usb - install grml ISO(s) on usb device for booting Synopsis -------- grml2usb [ options ] ******************************************************************************* Important! The grml team does not take responsibility for loss of any data! ******************************************************************************* [[introduction]] Introduction ------------ grml2usb installs grml on a given partition of your usb device and makes it bootable. It provides multi-iso support, meaning you can specify several grml ISOs on the command line at once and select the grml flavour you would like to boot on the bootprompt then. Note that the *first* ISO specified on the grml2usb command line will become the default one (that's the one that will boot when just pressing enter on the bootprompt or wait until the boot timeout matches). [IMPORTANT] By default a compatible master boot record (MBR) is installed on the device (being for example /dev/sdX when executing 'grml2usb grml.iso /dev/sdX1') and syslinux is being used as default bootloader. Avoid installation of the default MBR using the '--skip-mbr' option or if you encounter any problems with the default MBR consider using '--syslinux-mbr' instead. [[options]] Options ------- The ISO[s] should be the path to one or multiple grml-ISOs and/or the path to the currently running live-system (being /lib/live/mount/medium). The device either might be a device name like /dev/sdX1 or a directory. When specifying a device name the device is mounted automatically. When specifying a directory grml2usb is assuming that you did set up a bootloader on your own (or don't need one) and a bootloader won't be installed automatically. The following options are supported: *\--bootoptions=...*:: Use specified bootoptions as default. To use flavour name as a argument for a boot parameter use %flavour which will be expanded to the flavour name. To add multiple bootoptions you can specify the option multiple time. *\--bootloader-only*:: Do *not* copy files but instead just install a bootloader. Note that the boot addons are copied to /boot/addons at this stage as well. If you want to skip copying the boot addons consider using the --skip-addons option. *\--copy-only*:: Copy files only but do *not* install a bootloader. *\--dry-run*:: Avoid executing commands, instead show what would be executed. Warning: please notice that the ISO has to be mounted anyway, otherwise identifying the grml flavour would not be possible. *\--fat16*:: Format specified partition with FAT16. **Important:** this will destroy any existing data on the specified partition! *\--force*:: Force any (possible dangerous) actions requiring manual interaction (like --fat16). *\--grub*:: Install grub bootloader instead of (default) syslinux. *\--grub-mbr*:: Install grub into MBR (Master Boot Record) instead of PBR (Partition Boot Record). Check out <> for further details. *\--help*:: Display usage information and exit. ////////////////////////////////////////////////////////////////////////// *\--initrd=...*:: Install specified initrd instead of the default. You might want to specify option *--kernel* as well. (Be aware when using multiboot setup.) [Notice: not implemented yet.] ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// *\--kernel=...*:: Install specified kernel instead of the default. You might want to specify option *--initrd* as well. (Be aware when using multiboot setup.) [Notice: not implemented yet.] ////////////////////////////////////////////////////////////////////////// *\--mbr-menu*:: Install master boot record (MBR) with integrated boot menu: interactively choose the partition to boot from, with a timeout to load the default partition, or boot from floppy. When NOT using the --mbr-menu option a MBR with LBA and large disc support but without an integrated boot menu is installed (so it's not visible at all but instead directly jumps to the bootloader - being grub or syslinux). Note: This options is available only when using the default MBR and won't have any effect if you're using the '--syslinux-mbr' option. *\--quiet*:: Do not output anything but just errors on console. *\--skip-addons*:: Do not install /boot/addons/ files (like dos, grub, memdisk,...). *\--remove-bootoption=...*:: Remove specified bootoption (could be a regex) from existing boot options. Use multiple entries for removing different bootoptions at once. *\--skip-grub-config*:: Skip generation of grub configuration files. By default the configuration files for syslinux *and* grub will be written so you've a working configuration file no matter whether you're using grub or syslinux as bootloader. *\--skip-mbr*:: Do not touch/install the master boot record (MBR). *\--skip-syslinux-config*:: Skip generation of syslinux configuration files. By default the configuration files for syslinux *and* grub will be written so you've a working configuration file no matter whether you're using grub or syslinux as bootloader. *\--syslinux*:: This option is deprecated and is being left only for backwards compatibility reasons. Syslinux is the default bootloader of grml2usb and therefore the '--syslinux' option doesn't have any effects. If you do not want to use syslinux as bootloader consider using the '--grub' option. *\--syslinux-mbr*:: Install syslinux' master boot record (MBR, which is booting from the partition with the "active" flag set) instead of the default one. If you encounter any problems with the default MBR you can try using the syslinux MBR instead. If that works for you please <> so we can adjust our default MBR accordingly. ////////////////////////////////////////////////////////////////////////// *\--squashfs=*:: Install specified squashfs file instead of the default. [Notice: not implemented yet.] ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// *\--uninstall*:: Uninstall grml ISO files. [Notice: not implemented yet.] ////////////////////////////////////////////////////////////////////////// *-v*, *\--version*:: Return version and exit. *\--verbose*:: Enable verbose mode. Developers Corner ----------------- [[directory-layout]] Directory layout on usb device ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ boot/ -> |-- addons/ | |-- allinone.img [grub - all in one image] | |-- bsd4grml/ [MirBSD] | |-- balder10.imz [FreeDOS] | |-- memdisk [chainloading helper] | |-- memtest [memtest86+] |-- release/ | |-- grml/ | | |-- linux26 [Kernel] | | |-- initrd.gz [initramfs] | |-- grml64 | | |-- linux26 [Kernel] | | |-- initrd.gz [initramfs] | |-- grml-medium | | |-- linux26 [...] | | |-- initrd.gz | |-- grml64-medium | | |-- linux26 | | |-- initrd.gz | |-- grml-small | | |-- linux26 | | |-- initrd.gz | `-- grml64-small | |-- linux26 | |-- initrd.gz |-- grub/ | |-- grml.png [graphical bootsplash background image for grub2] | |-- grub.cfg [configuration file for grub2] | |-- menu.lst [configuration file for grub1] | |-- splash.xpm.gz [splash screen for grub1] `-- syslinux/ |-- grml.png [graphical bootsplash background image for syslinux] |-- syslinux.cfg [main configuration file for syslinux] `-- [....] [several further config files for syslinux] grml/ |-- grml2usb.txt [not yet implemented] |-- grml-cheatcodes.txt [list of bootoptions for grml] |-- grml-version.txt [file containing information about grml-version] |-- LICENSE.txt [license information] |-- md5sums [md5sums of original ISO] |-- README.txt [informational text] `-- web/ [browser related files] |-- index.html |-- style.css `-- images/ |-- button.png |-- favicon.png |-- linux.jpg `-- logo.png live/ |-- grml/ | |-- filesystem.module [module specifying which squashfs should be used for grml] | `-- grml.squashfs [squashfs file for grml] |-- grml-medium/ | |-- filesystem.module [module specifying which squashfs should be used for grml-medium] | `-- grml-medium.squashfs [squashfs file for grml-medium] |-- grml-small/ | |-- filesystem.module [module specifying which squashfs should be used for grml-medium] | `-- grml-small.squashfs [squashfs file for grml-small] `-- ... [[source]] Grabbing the source ~~~~~~~~~~~~~~~~~~~ % git clone git://git.grml.org/grml2usb.git [[debugging]] Developers Debugging Hints ~~~~~~~~~~~~~~~~~~~~~~~~~~ To play with grml2usb you can avoid using a real device via a loopback file setup, like: # dd if=/dev/zero of=~/loopback bs=1M count=100 # adjust size to your needs # losetup /dev/loop1 ~/loopback Then create according partitions either running for example: # echo -en "n\np\n1\n\n\nt\n6\na\n1\n w\n" | fdisk /dev/loop1 or: # parted /dev/loop1 -s "mkpart primary fat16 0 -1s mkfs 1 fat16" Finally create a filesystem and execute grml2usb as needed: # mkfs.vfat /dev/loop1 # grml2usb --bootloader-only /grml/isos/grml-small_2013.01.iso /dev/loop1 [[performance-tracing]] Performance tracing ~~~~~~~~~~~~~~~~~~~ # blktrace -d /dev/sdX -o - | blkparse -i - # grml2usb grml_2013.01.iso /dev/sdX1 [[troubleshooting]] Troubleshooting and Pitfalls when booting ----------------------------------------- Here is a list of common error messages from BIOS/bootloader when trying to boot from USB. /////////////////////////////////////////////////////////// TODO: better list type for the error message / reason part? See http://www.methods.co.nz/asciidoc/userguide.html /////////////////////////////////////////////////////////// [horizontal] *Error message*:: ran out of input data. System halted *Reason*:: Everything OK, except for the filesystem used on your usb device. So instead of fat16 you are using for example fat32. Fix: use the appropriate filesystem (fat16 for usb pens usually). The Bootsplash might be displayed, the kernel loads but you very soon get the error message. *Error message*:: Invalid operating system *Reason*:: the partition layout is not ok. Very probably there's no primary partition (/dev/sdX{1..4}) or none has the flag 'bootable' set. *Error message*:: Boot error. *Reason*:: Some BIOSses offer different modes for USB booting. The proper mode to boot a USB stick is USB-HDD. If that doesn’t work or is not supported by your system, you need to format your USB-Stick as USB-ZIP. To do this, syslinux contains an utility called mkdiskimage, which you can use to re-format your USB stick in USB-ZIP format running 'mkdiskimage -4 /dev/sdX 1 64 32'. Please be aware that this procedure will erase all data on your stick. After executing mkdiskimage just continue installing as usual (grml2usb ... /dev/sdX4). Note that this is not going to work for any device larger than 8 GB, since mkdiskimage only supports 1024c 256h 63s. For a more detailed explanation, refer to /usr/share/doc/syslinux-common/usbkey.txt. *Error message*:: No operating system found. *Reason*:: you forgot to set the boot-flag on the partition. Or there really isn't any operating system at all. :) *Error message*:: kernel-panic: unable to mount root-fs... *Reason*:: Kernel boots but fails to find the root filesystem. The root= argument in your kernel commandline is pointing to the wrong device. Adjust root=..., consider using root=UUID=.... *Error message*:: Could not find kernel image: ... *Reason*:: either a broken isolinux/syslinux version or a broken BIOS. Check out whether the vendor provides a BIOS update or if using bootloader grub instead of isolinux/syslinux fixes the problem. [[faq]] Frequently Asked Questions (FAQ) -------------------------------- [[download]] Where can I get grml2usb? ~~~~~~~~~~~~~~~~~~~~~~~~~ grml2usb is available as Debian package via link:http://deb.grml.org/[the grml-testing Debian repository]. If you do not want to (or can't) use the grml2usb Debian package you can either use the grml2usb git tree running: git clone git://git.grml.org/grml2usb.git cd grml2usb make -C mbr sudo ./grml2usb ... or download the provided link:http://grml.org/grml2usb/grml2usb.tgz[http://grml.org/grml2usb/grml2usb.tgz] (link:http://grml.org/grml2usb/grml2usb.tgz.md5.asc[gpg signed md5 hash]). Download and extract the tarball and execute the provided script 'install.sh'. [NOTE] It is *NOT* enough to have just the grml2usb script itself without the according files provided either via the Debian package, the git tree or the file grml2usb.tgz. [[dd]] Why can't I just dd the ISO to a USB device? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Well, you can. :) Starting with grml 2009.10 the ISOs are dd-able straight out-of-the-box. [IMPORTANT] Note that ANY existing data on your USB device will be destroyed when using the dd approach. /////////////////////////////////////////////////////////////////////////////////////////////////// Grab a recent grml ISO and use link:http://syslinux.zytor.com/wiki/index.php/Doc/isolinux#HYBRID_CD-ROM.2FHARD_DISK_MODE[isohybrid from the syslinux project]: % isohybrid grml_2009.10.iso /////////////////////////////////////////////////////////////////////////////////////////////////// This allows you to dd the Grml ISO to your USB device (use for example link:http://www.chrysocome.net/rawwrite[rawwrite] if you've just a Windows system available) running: % dd if=grml_2013.01.iso of=/dev/sdX where /dev/sdX is your USB device. Of course this doesn't provide such a flexible system like with grml2usb (no multi-ISO setup, no additional default bootoptions,...) but it's a nice way to get a working USB boot setup if you don't have grml2usb available. [[grml2usb-vs-dd]] What's the difference between grml2usb and just using dd? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ grml2usb does not remove any data from your USB device and does not alter the partition table at all. grml2usb provides multi-ISO support, support for adding default bootoptions and selecting the bootloader (syslinux vs. grub) without having to manually touch the ISO at all. [[grml2iso]] What's grml2iso? ~~~~~~~~~~~~~~~~ grml2iso is a script which uses grml2usb to generate a multiboot ISO out of several grml ISOs. See 'man grml2iso' for further details. [[menu-lst]] Why is there a menu.lst and a grub.cfg inside /boot/grub/? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ grml2usb supports grub version 1 (grub1) as well as grub version 2 (grub2). Whereas grub1 uses menu.lst the new version grub2 needs grub.cfg. Providing both files allows grml2usb to install grub on the target device no matter which grub version is available on the host where grml2usb is executed on. [[stage1]] grub-install fails with 'The file ../boot/grub/stage1 not read correctly"?! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Check whether the partition has the right partition type. For example do NOT use FAT16 (partition type 6) when using a ext3 filesystem on the partition but instead use the correct partition type ('83' - Linux) then. [[grub-install-xfs_freeze]] grub-install complains about /sbin/grub-install and/or xfs_freeze?! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following message: You shouldn't call /sbin/grub-install. Please call /usr/sbin/grub-install instead! xfs_freeze: specified file ["/tmp/tmpqaBK6z/boot/grub"] is not on an XFS filesystem This is "normal". grub-install sends those messages to stderr. To avoid hiding any possible real error messages grml2usb doesn't ignore those messages. [[device-map]] grub-install complains about /boot/grub/device.map?! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following message: grub-probe: error: Cannot open `/boot/grub/device.map' This is "normal" (at least with grub1). This isn't a problem, because the device.map file will be generated on the target device anyway. [[unary-operator]] grub-install complains about a unary operator?! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following message: '/usr/sbin/grub-install: line 374: [: =: unary operator expected' This is "normal". Just ignore it. (It usually doesn't appear on the second invocation on the same device.) [[unknown-filesystem]] grub-install fails with grub-probe: error: unknown filesystem?! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following message: grub-probe: error: unknown filesystem Auto-detection of a filesystem module failed. Please specify the module with the option `--modules' explicitly. usually means that the device partition table says something else than the filesystem on the device. For example using FAT16 as filesystem type and using FAT32 as filesystem on the partition will not work. Either set filesystem type to FAT32 or format the partition using FAT16. It is essential that device partition table and filesystem use the same filesystem type. [[mbr-vs-pbr]] grub-setup fails after Attempting to install GRUB to a partition instead of the MBR?! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following message: grub-setup: warn: Attempting to install GRUB to a partition instead of the MBR. This is a BAD idea. grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists. However, blocklists are UNRELIABLE and its use is discouraged. grub-setup: error: Cannot read `/grub/core.img' correctly appears when using grub2 versions older than 1.98 as those version introduced a regression which avoids that grub is being installed into a partition (PBR, Partition Boot Record) instead of MBR (Master Boot Record). To work around this issue you can either 1) upgrade to grub versions >=1.98, 2) install grub into the MBR (Master Boot Record) using the '--grub-mbr' option of grml2usb or 3) switch to syslinux as bootmanager (just drop the '--grub' option). [[splash-xpm]] I'm getting something like "Error: /usr/share/grml2usb/grub/splash.xpm.gz can not be read"!? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Looks like you've only the grml2usb script itself available. Please make sure you've the grml2usb Debian package installed. The most resent stable version is available via link:http://deb.grml.org/[the grml-testing Debian repository]. If you do not have a Debian system please see section <> in this FAQ. [[fat16]] Why do I have to use a FAT16/FAT32 filesystem? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Syslinux (currently) does not support any other filesystems besides FAT16/FAT32 (though that's a sane default if you want to share your files with other (operating) systems). If you want to use a different filesystem (like ext2/3) use the bootloader grub instead using grml2usb's '--grub' option. [NOTE] FAT32 is supported since syslinux version 3.0. [[hdt-hangs]] Addons -> Hardware Detection Tool freezes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This usually means that the machine you ran grml2usb on had syslinux 3.x installed. The version of hdt (Hardware detection tool) shipping with Grml 2010.12 and newer requires syslinux 4.x. [[cool-idea]] I think I've got a really cool idea! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Great! Please check out link:http://git.grml.org/?p=grml2usb.git;a=blob;f=TODO;hb=HEAD[the TODO file]. Feel free to <>. Patches highly appreciated. [[booting-from-usb]] I've problems with booting from USB. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Check out <>. [[found-a-bug]] I've found a bug! ~~~~~~~~~~~~~~~~~ Please <>. Please provide usage examples and output of your grml2usb commandline (consider using the "\--verbose" option). [[usage-examples]] Usage examples -------------- # grml2usb /home/grml/grml_2013.01.iso /dev/sdX1 Install specified ISO on device /dev/sdX1. # grml2usb /home/grml/grml_2013.01.iso /home/grml/grml_small_2013.01.iso /dev/sdX1 Install specified ISOs on device /dev/sdX1 for multibooting ISOs. # grml2usb /lib/live/mount/medium /dev/sdX1 Install currently running Grml live system on device /dev/sdX1. # grml2usb /lib/live/mount/medium /home/grml/grml_2013.01.iso /dev/sdX1 Install currently running Grml live system and the specified ISO on device /dev/sdX1 for multibooting. # grml2usb --fat16 /home/grml/grml_2013.01.iso /dev/sdX1 Install specified ISO on device /dev/sdX1 and format partition /dev/sdX1 with FAT16 filesystem. # grml2usb --grub --grub-mbr /home/grml/grml_2013.01.iso /dev/sdX1 Install specified ISO on device /dev/sdX1 and use grub as bootloader (instead of syslinux being the default) and install a master boot record (MBR) to the MBR of /dev/sdX. /////////////////////////////////////////////////////////////////////////////////////// # grml2usb --kernel=/boot/vmlinuz-2.6.28-grml --initrd=/boot/initrd.img-2.6.28-grml \ /home/grml/grml_2013.01.iso /dev/sdX1 Install specified ISO on device /dev/sdX1 but use given kernel and initrd instead of the ones provided by the ISO. # grml2usb --squashfs=/grml/grml-live/grml_cd/live/grml.squashfs \ /home/grml/grml_2013.01.iso /dev/sdX1 Install specified ISO on device /dev/sdX1 but use given squashfs file instead of the one provided by the ISO. /////////////////////////////////////////////////////////////////////////////////////// # grml2usb --bootoptions="lang=de ssh=mysecret" grml_2013.01.iso /dev/sdX1 # grml2usb --bootoptions="lang=de" --bootoptions="ssh=mysecret" grml_2013.01.iso /dev/sdX1 Install specified ISO on device /dev/sdX1 and use "lang=de ssh=mysecret" as default bootoptions. # grml2usb --remove-bootoption="vga=791" --remove-bootoption="nomce" grml_2013.01.iso /dev/sdX1 Install specified ISO on device /dev/sdX1 remove vga=791 and nomce from existing bootoptions. # grml2usb --bootoptions="persistent-path=%flavour_name" grml64_2010.04.iso grml_2010.04.iso /dev/sdX1 Install specified Isos on device /dev/sdx and add parameter persisten-path to every menu entry. %flavour_name will be expanded to the flavour of the specific iso, e.g. grml64 and grml. [[ressources]] Online Ressources ----------------- Check out the link:http://grml.org/grml2usb/[grml2usb webpage] and the link:http://git.grml.org/?p=grml2usb.git[grml2usb git repository]. [[bugs]] Bugs ---- Please report feedback, bugreports and wishes <>. [[author]] Author ------ Michael Prokop ///////////////////////////////////////////////////////////////// http://wiki.grml.org/doku.php?id=tips#multiboot_usb_pen http://www.startx.ro/sugar/isotostick.sh https://help.ubuntu.com/community/Installation/FromUSBStick http://unetbootin.sourceforge.net/ http://www.tux.org/pub/people/kent-robotti/looplinux/rip/mkusb.sh https://fedorahosted.org/liveusb-creator/ ///////////////////////////////////////////////////////////////// grml2usb-0.14.2/debian/0000755000000000000000000000000012234405211011435 5ustar grml2usb-0.14.2/debian/dirs0000644000000000000000000000001111101301312012276 0ustar usr/sbin grml2usb-0.14.2/debian/copyright0000644000000000000000000000445112220557061013402 0ustar This package was debianized by Michael Prokop on Sun, 14 Aug 2005 15:31:04 +0200. It was downloaded from http://grml.org/ Upstream Author: Michael Prokop Copyright: grml2usb: This software is Copyright (c) 2006-2011 by Michael Prokop and others. This package 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; version 2 dated June, 1991. This package 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 package; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. grub/splash.xpm.gz and grub/grml.png: Copyright by Martin Ahammer / grml-team images/icons/: Copyright 2008 by Stuart Rackham (Taken from AsciiDoc.) AsciiDoc is free software and is licenced under the terms of the GNU General Public License version 2. mbr/mbr.S: Copyright (c) 2009 Thorsten Glaser Provided that these terms and disclaimer and all copyright notices are retained or reproduced in an accompanying document, permission is granted to deal in this work without restriction, including un- limited rights to use, publicly perform, distribute, sell, modify, merge, give away, or sublicence. This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to the utmost extent permitted by applicable law, neither express nor implied; without malicious intent or gross negligence. In no event may a licensor, author or contributor be held liable for indirect, direct, other damage, loss, or other issues arising in any way out of dealing in the work, even if advised of the possibility of such damage or existence of a defect, except proven that it results out of said person's immediate fault when using the work as intended. On Debian GNU/Linux systems, the complete text of the GNU General Public License can be found in `/usr/share/common-licenses/GPL-2'. grml2usb-0.14.2/debian/NEWS0000644000000000000000000000257711723651702012161 0ustar grml2usb (0.9.35) unstable; urgency=low Starting with this release, grml2usb-compat is no longer included. If you still need to install grml ISOs older than 2009.10, please use an older version of grml2usb. The dependency on lilo has been dropped, from now on only primary partitions will be flagged bootable. -- Christian Hofstaedtler Mon, 3 Oct 2011 22:56:35 +0200 grml2usb (0.9.13) unstable; urgency=low This release makes syslinux the default bootloader again. Grub fails just too often. Therefore the --syslinux options is deprecated and option --grub was introduced instead. This release provides decent support for multi-ISO within the new vesamenu bootsplash, providing a menu based system. We had to break backward compatibility (otherwise the isolinux/syslinux code would be unmaintainable). Therefore support for older ISOs (everything before grml release 2009.10) had to be dropped. If you still need an old version of Grml on your usb device just use an older version of grml2usb (the old grml2usb versions support recent ISOs too, they just don't use/support the new vesamenu bootsplash then). The grml team supports old grml2usb versions through the grml2usb-compat script. Further details are available in the FAQ at http://grml.org/grml2usb/#grml2usb-compat -- Michael Prokop Wed, 21 Oct 2009 23:32:08 +0200 grml2usb-0.14.2/debian/compat0000644000000000000000000000000211645615675012661 0ustar 7 grml2usb-0.14.2/debian/changelog0000644000000000000000000007614112234405211013320 0ustar grml2usb (0.14.2) unstable; urgency=low [ Michael Prokop ] * [bb87234] pep8 cleanups * [1d2aba6] Fix typo in /boot/grub/addons.cfg filename. Thanks to Michael Schierl for the hint [ Christian Hofstaedtler ] * [be8270f] Remove Recommends: isolinux, as the package is gone -- Michael Prokop Thu, 31 Oct 2013 08:45:06 +0100 grml2usb (0.14.1) unstable; urgency=low [ Till Maas ] * [d26c252] Support also /usr/share/syslinux/ to look for mbr.bin -- Michael Prokop Wed, 14 Aug 2013 13:04:40 +0200 grml2usb (0.14.0) unstable; urgency=low * [360c9e5] Use lowercase 'timeout' command in syslinux configuration [Closes: issue1262] Thanks to Martin Šlouf for reporting this bug including a workaround * grml2iso related changes: - [20752e3] skip --uefi option of isohybrid if ISO doesn't ship /boot/efi.img - [f3370b9] extend error message of required ISO generation tools with xorriso - [8e0bdf8] mention isolinux in 'isohybrid executable not found' message, add isolinux to recommends - [37fa9f8] disable UEFI mode by default, only enable for xorriso under according prerequisites - [86c00b8] make sure we have the sbin directories in our PATH -- Michael Prokop Wed, 26 Jun 2013 17:27:18 +0200 grml2usb (0.13.8) unstable; urgency=low * [de40a5f] Skip check for bootflag if a GPT header is present -- Michael Prokop Wed, 15 May 2013 14:54:21 +0200 grml2usb (0.13.7) unstable; urgency=low The "towards jessie" release [ Christian Hofstaedtler ] * [87143a6] Remove obsolete DM-Upload-Allowed flag [ Evgeni Golov ] * [3fb00de] "if not" also triggers when value is 0, use "if is None" instead [ Lukas Prokop ] * [7b409af] Fix typo. * Rework error handling to avoid unnecessary backtraces, commmits [26cf633] [7cef744] [6990c85] [5276a23] [cdb4aa4] [a06f95e] and [fafa0d8] -- Michael Prokop Tue, 14 May 2013 19:04:50 +0200 grml2usb (0.13.6) experimental; urgency=low * [9e7a48d] grml2iso: make sure to exit properly if provided argument to -c option does not exist * [a22cf21] Make sure modprobe executable can be accessed * [62acdab] grml2iso: provide more user-friendly error message if grml2usb executable is not available * [0ab2a72] Normalize temporary working directory to not fail with relative directory path -- Michael Prokop Tue, 23 Apr 2013 22:32:36 +0200 grml2usb (0.13.5) experimental; urgency=low [ Evgeni Golov ] * [a17807b] fix detection of strange (xxxNpM) structures when finding the device for a partition [Closes: issue1244] -- Michael Prokop Mon, 18 Mar 2013 15:12:10 +0100 grml2usb (0.13.4) experimental; urgency=low * [aff3fa9] Add realpath to Depends as it's required by grml2iso * [14e017c] Do not use partition for bootflag check but disk itself * [0deeae3] Mention /lib/live/mount/medium for new live path + adjust ISO versions -- Michael Prokop Thu, 10 Jan 2013 14:08:09 +0100 grml2usb (0.13.3) experimental; urgency=low * [7705455] grml2iso: use absolute path for working directory to not fail when user specified relative path * [3f80e5a] Verify that the bootflag is enabled * [922c039] Bump Standards-Version to 3.9.4 -- Michael Prokop Mon, 17 Dec 2012 13:21:39 +0100 grml2usb (0.13.2) unstable; urgency=low [ Michael Prokop ] * [7e6faf1] Fix logging message if operating on a directory * [cf525c6] Exit with better error message if running with toram=... and invoking with /live/image [ Lukas Prokop ] * [5251ce1] Fix error message. -- Michael Prokop Tue, 11 Sep 2012 18:28:31 +0200 grml2usb (0.13.1) unstable; urgency=low * [720b859] grml2iso: make ISOs dd-able through isohybrid -- Michael Prokop Tue, 11 Sep 2012 12:16:04 +0200 grml2usb (0.13.0) unstable; urgency=low [ Michael Prokop ] * [927e586] grml2iso: fix typo + improve wording * [178cb6a] grml2iso: support -t to set temporary working directory [ Lukas Prokop ] * [752b503] grml2usb: introduce option --tmpdir -- Michael Prokop Mon, 10 Sep 2012 09:13:25 +0200 grml2usb (0.12.2) unstable; urgency=low * [f3a85ac] copy_addons: install all *.c32 addons in /boot/addons/ (fixing broken addon entries in grml96 ISOs) -- Michael Prokop Mon, 28 May 2012 17:16:40 +0200 grml2usb (0.12.1) unstable; urgency=low * [7c076d1] Support multiple flavours inside one ISO. Thanks to Ulrich Dangel for the patch (Closes: issue1172) -- Michael Prokop Sun, 27 May 2012 22:23:07 +0200 grml2usb (0.12.0) unstable; urgency=low [ Michael Prokop ] * [f1cfc39] grml2iso: use shell for calculation instead of using bc * [2223843] Rebuild loopback.cfg with present configuration files * [5df5aeb] Bump Standards-Version to 3.9.3 * [09149d7] Drop oudated tarball-online make target and support prepare-release instead * [607fd41] pep8 cleanups * [c2d87f6] Adjust PROG_VERSION code in debian/rules for pep8 cleanup [ Evgeni Golov ] * [3505897] fix manpage markup -- Michael Prokop Wed, 09 May 2012 12:58:46 +0200 grml2usb (0.11.6) unstable; urgency=low The "custom bootsplash without remastering ☕☕☕" release [ Ulrich Dangel ] * [f956c82] grml2iso: Canonicalize overlay directory * [7494e3f] grml2iso: Support template parameters in overlay directory. For now only GRML_NAME, VERSION, RELEASENAME, DATE, SHORT_NAME, RELEASE_INFO and BOOTID are supported. -- Michael Prokop Fri, 27 Jan 2012 12:29:21 +0100 grml2usb (0.11.5) unstable; urgency=low The "grml96 support ♫♫♫" release [ Ulrich Dangel ] * [eb087c0] Support multiple flavours on a cd * [4608131] Modify grub config files for the specified flavour instead of all grub config files * [c6af951] Streamline grml_flavour modification * [c421fb3] Only modify live-media-path for current flavour -- Michael Prokop Wed, 11 Jan 2012 16:10:51 +0100 grml2usb (0.11.4) unstable; urgency=low [ Ulrich Dangel ] * [35feaad] Copy complete Grml flavour directory instead of explicit specifying files [ Michael Prokop ] * [7c0195d] Make sure we don't fail in device check when using /dev/disk-by-label/* - Thanks to Bernhard Tittelbach -- Michael Prokop Mon, 09 Jan 2012 16:37:18 +0100 grml2usb (0.11.3) unstable; urgency=low [ Christian Hofstaedtler ] * [894eef9] Use grub splash image from ISO * [fdc186c] Remove hardcoded version from grml2usb * [bd89fc4] Cleanup grub.cfg install logic * [569dfb3] Add support for new kernel/initrd filenames * [5818eec] Fix add/remove bootoptions with new kernel/initrd names * [6817350] Fix typo * [b82aaee] Mimic /boot/%SHORT_NAME% like on the ISO * [100193b] Use grub config from ISO instead of writing a new one * [feca364] Warn that older versions can't do multi-flavour grub * [6b93ccd] Load loop kernel module [Closes: issue1097] -- Michael Prokop Thu, 22 Dec 2011 23:55:08 +0100 grml2usb (0.11.2) unstable; urgency=low [ Christian Hofstaedtler ] * [bd2f924] Remove 'quiet' from standard boot options * [4f47c04] Remove failsafe boot menu entry [ Michael Prokop ] * [a1ca17b] Add UEFI boot support to grml2iso -- Michael Prokop Thu, 15 Dec 2011 14:35:58 +0100 grml2usb (0.11.1) unstable; urgency=low [ Christian Hofstaedtler ] * [2534968] Add nokms option to grub menu * [e9f7cff] sync grub.cfg menu entries with grml-live templates -- Michael Prokop Sun, 11 Dec 2011 21:28:12 +0100 grml2usb (0.11.0) unstable; urgency=low * [b1bf09c] Install boot files required for [U]EFI boot -- Michael Prokop Thu, 08 Dec 2011 15:00:04 +0100 grml2usb (0.10.2) unstable; urgency=low [ Christian Hofstaedtler ] * [8483753] Remove mention of grml2hd * [49672e8] Disable validation of autogenerated docbook xml -- Michael Prokop Sat, 26 Nov 2011 20:30:20 +0100 grml2usb (0.10.1) unstable; urgency=low Packaging fixes: * [05f4996] Fix FTBFS on i386: must build arch package in binary-arch * [ba108d8] Reword/reformat some text in debian/copyright -- Christian Hofstaedtler Tue, 04 Oct 2011 10:07:42 +0200 grml2usb (0.10.0) unstable; urgency=low Target Debian unstable: * Build only on i386 and amd64. * Remove Grml Origin and Bugs entries -- Christian Hofstaedtler Mon, 03 Oct 2011 23:27:14 +0200 grml2usb (0.9.35) unstable; urgency=low * [19b2fe7] Support USB keys with superfloppy format * [e8fb17b] grml2iso: fix check for grml2usb * [e1ad166] Loop-mount ISO with read-only option * [e5ae97f] Remove grml2usb-compat * [5d028a0] Remove grub1 support * [7874f97] Remove static lilo binaries and lilo support Packaging changes: * [ecfce70] Use dh_prep, bump debhelper compat level to 7 * [1b22f2a] Set debian/source/format to 3.0 (native) * [7a142d9] Fix debian-rules-missing-recommended-target lintian warning * [c26aae4] No longer mention mkisofs in debian/control * [fdb81b1] Add debian/control headers Origin, Bugs * [154f7d7] Switch section to admin, from grml * [7e48792] Update Maintainer/Uploaders to Team -- Christian Hofstaedtler Mon, 03 Oct 2011 23:06:42 +0200 grml2usb (0.9.34) unstable; urgency=low * [def6424] Fix warning message for missing files. -- Michael Prokop Fri, 22 Jul 2011 09:41:24 +0200 grml2usb (0.9.33) unstable; urgency=low * [c021230] Don't nag users about gpxe.lkrn -- Christian Hofstaedtler Mon, 16 May 2011 00:49:34 +0200 grml2usb (0.9.32) unstable; urgency=low [ Michael Prokop ] * [b2a896e] Support iPXE as new alternative for gPXE. * [a364513] Add pyflakes to codecheck. [ Christian Hofstaedtler ] * [c479a12] add an FAQ regarding to HDT hangs [Closes: issue976] * [39d0e12] Bump Standards-Version to 3.9.2 * [af2a36f] Update debian/overrides for newer lintian versions -- Christian Hofstaedtler Tue, 10 May 2011 22:45:27 +0200 grml2usb (0.9.31) unstable; urgency=low [ Ulrich Dangel ] * [f5e949b] Support mkisofs or genisoimage in grml2iso. Updated debian/control accordingly. * [a9ab0bf] Print warning if grml2usb is not found in grml2iso. * [d85b3e3] Support arbitrary grml2usb options in grml2iso. * [cc12ab6] Allow multiple --bootoptions for grml2usb. This makes scripting a lot easier. * [161f2d5] Support generating small iso images with grml2iso. [ Michael Prokop ] * [1980861] Typo fixes and minor formating corrections. -- Michael Prokop Mon, 14 Feb 2011 10:39:07 +0100 grml2usb (0.9.30) unstable; urgency=low * [35b606b] fix broken grub command terminal_output (should be "terminal_output gfxterm" instead of terminal_output.gfxterm) - thanks to Bert Schulze -- Michael Prokop Sat, 08 Jan 2011 23:11:15 +0100 grml2usb (0.9.29) unstable; urgency=low [ Thorsten Glaser ] * [601cc84] correct a pasto (it's 'grub.cfg') * [dc6a084] There is no /bin/bash on most operating systems. * [eb1a910] fix bsd4grml boot (loopback and regular) [ Ulrich Dangel ] * [3cec649] Append new flavours to grml-version, do not only update existing versions * [35d64cf] Update version * [ff5be86] Improve logging message [ Michael Prokop ] * [e32e549] Re-add mtools to Depends as they are just suggests of syslinux package - thanks to Michael Gissing for the bugreport. [Closes: issue905] -- Michael Prokop Thu, 25 Nov 2010 11:15:10 +0100 grml2usb (0.9.28) unstable; urgency=low [ Ulrich Dangel ] * [7b4fa5c] Some code cleanup. * [2a93d92] Copy bootloader files from /usr/lib/syslinux/ [Closes: issue894] * [c0fd54e] Run grub-install without and with --force option. * [1a5a6cd] bsd4grml was not copied correctly to the target device. [ Christian Hofstaedtler ] * [875b62b] Rename variables in update_grml_versions to be less confusing. * [791485b] Properly update grml-versions when updating a grml flavour. [ Michael Prokop ] * [91529cc] Bump Standards-Version to 3.9.1. -- Michael Prokop Tue, 28 Sep 2010 23:57:16 +0200 grml2usb (0.9.27) unstable; urgency=low [ Michael Prokop ] * [3836a71] Check for precense of grub/syslinux at startup time. Thanks to Eduard Bloch for reporting. [Closes: issue855] * [bde7012] Mention --force switch of grub-install in debug log. * [1c1c18c] Doc: fix documentation regarding default bootmanager. (thanks Martin Krafft). * [bae5bfb] Bump Standards-Version to 3.9.0. [ Ulrich Dangel ] * [b79a4cc] Fix error message for unintialized partition. [Closes: issue857] * [cd204ee] Fix user feedback about default flavour and installed flavours. -- Michael Prokop Wed, 30 Jun 2010 13:10:09 +0200 grml2usb (0.9.26) unstable; urgency=low [ Ulrich Dangel ] * Code cleanup. * Support expanding bootoptions variables. * Fix string concatenation and string formatting error. [ Michael Prokop ] * Document grub option in manpage (thanks Andrey Rahmatulli). -- Michael Prokop Fri, 28 May 2010 01:16:35 +0200 grml2usb (0.9.25) unstable; urgency=low * Fix typo in option handling. -- Michael Prokop Thu, 22 Apr 2010 18:10:35 +0200 grml2usb (0.9.24) unstable; urgency=low [ Ulrich Dangel ] * Add support for isos containing multiple grml flavours. * Copy all {sys,iso}linux *.c32 files, like ifcpu64.c32. [ Michael Prokop ] * Use --force option for grub-install to support installation to PBR again. Grub2 starting with version 1.98 supports installation to PBR again iff using the --force option. * Update documentation regarding grub and PBR vs. MBR. -- Michael Prokop Wed, 21 Apr 2010 13:54:51 +0200 grml2usb (0.9.23) unstable; urgency=low [ Ulrich Dangel ] * Only ask questions if options.force is not set. [Closes: issue833] -- Michael Prokop Fri, 02 Apr 2010 18:32:25 +0200 grml2usb (0.9.22) unstable; urgency=low [ Ulrich Dangel ] * Use GRML_{FLAVOURS,DEFAULT}, PROG_VERSION from global scope. grml2usb was aborted when using --bootloader-only --skip-grub-config as parameters. This fixes the behaviour and declares correctly the correct scope for these variables. Thanks to Daniel Tiefnig for reporting the bug. [ Michael Prokop ] * grml2usb-compat: drop duplicated boot=live bootoptions. * Bump Standards-Version to 3.8.4 (no further changes). * Add syslinux additionally to recommends so people should have syslinux by available by default though don't explicitly require it. -- Michael Prokop Sun, 21 Feb 2010 16:52:23 +0100 grml2usb (0.9.21) unstable; urgency=low [ Michael Prokop ] * Document the Boot error issue regarding USB-ZIP. [ Ulrich Dangel ] * Support bootid bootoption. -- Michael Prokop Thu, 04 Feb 2010 00:56:56 +0100 grml2usb (0.9.20) unstable; urgency=low * tarball.sh: do not use $UID but use $(id -u) instead so it proberly works with dash and make sure to escape "$0". Thanks to Stefan Weiss! -- Michael Prokop Wed, 25 Nov 2009 00:47:36 +0100 grml2usb (0.9.19) unstable; urgency=low [ Ulrich Dangel ] * check_for_fat always check for fat device. * Unset option.syslinux if grub option is set. * Mount vfat devices with explicit iocharset option. [Closes: issue735] -- Michael Prokop Wed, 11 Nov 2009 18:34:56 +0100 grml2usb (0.9.18) unstable; urgency=low [ Ulrich Dangel ] * Also set GRML_DEFAULT when running with --dry-run. Thanks to Moritz Augsburger for the bug report. * Make sure that --grub-mbr requires --grub. Thanks to Moritz Augsburger and mika for the bug report. -- Michael Prokop Wed, 04 Nov 2009 20:51:24 +0100 grml2usb (0.9.17) unstable; urgency=low [ Michael Prokop ] * Depend on rsync (thanks for the bugreport, Andras Korn). [ Ulrich Dangel ] * Adjust labels in {grml,default}.cfg if necessary. * Always copy grub files. -- Michael Prokop Thu, 29 Oct 2009 01:06:12 +0100 grml2usb (0.9.16) unstable; urgency=low * Dynamic check for addons as grml-small is nowadays shipped with addons. * Copy gpxe.lkrn from addons. * Modified grml2usb to be able to run on a generated grml2usb iso/directory. -- Ulrich Dangel Tue, 27 Oct 2009 21:41:07 +0100 grml2usb (0.9.15) unstable; urgency=low * Support new addon menu file layout from grml-live. -- Ulrich Dangel Mon, 26 Oct 2009 12:32:27 +0100 grml2usb (0.9.14) unstable; urgency=low [ Ulrich Dangel ] * Do not use '-' in the directory name for the linux kernel to allow creating iso image from generated directory layout. * Introduced --remove-bootoption in grml2usb to delete existing default boot entries. * Added -c option to grml2iso for copying the contents of specified directory to the generated iso image. * Added -b option to grml2iso for specifying additional default boot entries. [ Michael Prokop ] * Sync and add grml2usb-compat to grml2usb package. This simplifies installation as well as use for developers and users. * Drop unnecessary header line from grml2usb script. -- Michael Prokop Sat, 24 Oct 2009 14:29:46 +0200 grml2usb (0.9.13) unstable; urgency=low [ Ulrich Dangel ] * Modified syslinux configuration handling to generate new vesa menu entries. * Support adding additional isos to existing grml2usb installation. * grml2iso supports new grml2usb using syslinux now. [ Michael Prokop ] * Update documentation regarding syslinux and FAT32 (thanks to Stefan Traby for the hint). * Changes with regards to Ulrich's work: - Add a check to identify old ISOs which do not ship a default.cfg file and abort then. We have to break backward compatibility, otherwise the isolinux/syslinux code would become worse than it's already nowadays. - Search for isolinux files in /boot/isolinux/ so the correct grml.png is used. - Support setting bootoptions in syslinux.cfg * Drop duplicated boot=live references in kernel cmdline. * Apply patch from Thorsten Glaser which prepares code for his future[tm] work. * Raise CriticalException if filesystem.module, kernel or initrd are not present. * Avoid the "file is read only, overwrite anyway (y/n) ?" question of mtools by syslinux. * Inform user when using grub as bootloader. * Make syslinux the default bootloader (drop --syslinux, add --grub instead). Grub fails just too often. -- Michael Prokop Wed, 21 Oct 2009 22:25:57 +0200 grml2usb (0.9.12) unstable; urgency=low * Replace 'logging.*("%s" % foo)' with 'logging.*("%s", foo)' so the logging works with python2.6 as well. -- Michael Prokop Thu, 10 Sep 2009 16:21:06 +0200 grml2usb (0.9.11) unstable; urgency=low * Improve handling the 'No space left on device' situation through using an according rsync handler function. -- Michael Prokop Mon, 07 Sep 2009 23:05:30 +0200 grml2usb (0.9.10) unstable; urgency=low * Support the directory where the grml2usb script resides as base directory so /usr/share/grml2usb isn't necessarily needed. Thanks for the patch to Alexander 'Leo' Bergolth ! * Make sure grub.conf isn't a symlink but a plain file instead, otherwise it will break on FAT16 filesystems. This works around grub-install of (at least) Fedora 10. Thanks for the patch to Alexander 'Leo' Bergolth ! * Use 'pci=nomsi' in failsafe bootoption. Thanks to Marc 'HE' Brockschmidt. * Mention the --syslinux option if grub-install fails. * Fix usage of --force in combination with --fat16. Thanks to Johannes Endres and Reiko Kaps for the bugreport. * Replace hint to '--grub' with 'grub'. * New option --grub-mbr which allows installation of grub in MBR instead of installation into a partition (PBR) which is necessary when using grub2. -- Michael Prokop Mon, 07 Sep 2009 17:12:54 +0200 grml2usb (0.9.9) unstable; urgency=low * Use ascii.pf2 as grub2 font, since grub2 (1.96+20090307-1) the old ascii.pff isn't available anymore. * Use terminal_output if available, otherwise fallback to old older 'terminal'-command (thanks to Felix Zielcke for helping). * Document the 'grub-setup fails after Attempting to install GRUB to a partition instead of the MBR' issue. * Use "set gfxpayload=1024x768x16,1024x768" instead of vga=791 in grub2 configuration. This requires a recent version of the linux loader as the new linux loader loads the kernel at 32bit entry point and not at 16 bit anymore so it has to be translated for the Linux kernel (as the kernel parses vga= in 16 bit code). In the long run we don't seem to have another option, so let's change it. Thanks to Felix Zielcke and Robert Millan for first hand information. * Increase timeout from 5 to 10 seconds in grub2 configuration. * Load memtest86+ binary via 'linux16' in grub2 (otherwise it fails). * Drop the serial boot entry from grub2 (I assume users with usb pens don't need that option). * Change the way MirOS bsd4grml is loaded (use the fallback method as default). * Improve descriptions of grml's grub2 entries. * Bump Standards-Version to 3.8.3 (no further changes). * Fix creation and installation of grub1's configuration file (menu.lst). Thanks to Mario 'BitKoenig' Holbe. -- Michael Prokop Tue, 25 Aug 2009 23:53:51 +0200 grml2usb (0.9.8) unstable; urgency=low * Support installation on /dev/loop*-devices. * Generate configuration for syslinux and grub by default, no matter which bootloader the users chooses. * Added options --skip-syslinux-config and --skip-grub-config if someone wants to skip the generation of any bootloader configuration files. * Make sure grub-install is available before executing it. * Display information about default grml flavour and the other available grml flavours at the end of the grml2usb run. * Use /sbin/blkid (e2fsprogs) instead of vol_id as vol_id is going to be removed from udev. Thanks for the patch to Andras Korn! * Use rsync instead of cp. Thanks for the patch to Andras Korn! [Closes: issue683] * Use 'forensic' and 'readonly' in the forensic bootoption itself. * Spelling fixes (thanks to Thorsten Glaser ). * Write GRUB2 config even if the target is a directory (thanks, Thorsten) * All these "set root=" are not needed for GRUB2 (thanks, Thorsten) * Switch order of check whether the specified device is a directory and check for usb device (as the usb device check will fail if it's a directory). * Add grml2iso for creating a bootable DVD: - thanks once more to Thorsten Glaser for helping and patches - thanks to Ernesto Domato for reporting the issue regarding i386<->amd64 with grub-mkimage * Move syslinux check to install_syslinux_mbr() * Drop the reference to --grub option (thanks for the bugreport to Peter Palfrader) * Update documentation: - mention the dd approach - mention grml2iso - improve section link names for the online version - add 'grub-probe: error: unknown filesystem' * Support use with python version 2.4. * Bump Standard Version to 3.8.2 (no further changes). * Depend on debhelper >=5 (using compat version 5). -- Michael Prokop Tue, 21 Jul 2009 18:01:50 +0200 grml2usb (0.9.7) unstable; urgency=low * Fix typo in manpage of grml2usb (thanks to Wernfried Haas). * Fix bootoption toram: it should be toram=$FLAVOUR.squashfs instead of toram=$FLAVOUR. Thanks to Wernfried Haas and Frank Prochnow for the bugreport and debugging! [Closes: issue680] -- Michael Prokop Tue, 02 Jun 2009 23:32:13 +0200 grml2usb (0.9.6) unstable; urgency=low * Support installation of the currently running grml live system ("grml2usb /live/image /dev/sdx1"). * Add "persistent" entry to grub/syslinux menu. [Closes: issue669] -- Michael Prokop Wed, 20 May 2009 19:32:02 +0200 grml2usb (0.9.5) unstable; urgency=low * Fix dashes of options in manpage (thanks for the bugreport, Thorsten Glaser). * Display program version during execution. * Apply fix by Peter Daum , making sure to use the normalized path for unmounting. Thanks! * Use 'multiboot' for booting MirOS BSD when using grub2. * Catch exception if copying files fails. * Make sure to exit if installing grub fails. * Integrate hdt (Hardware Detection Tool) in bootsplash (but only if using syslinux as grub isn't supported). -- Michael Prokop Mon, 04 May 2009 22:31:30 +0200 grml2usb (0.9.4) unstable; urgency=low * Bugfix: move kernel commandline from initrd to kernel option in generate_flavour_specific_grub2_config(). -- Michael Prokop Thu, 09 Apr 2009 00:04:56 +0200 grml2usb (0.9.3) unstable; urgency=low * Drop some leftover 'lang=us' references. * Update mbr.S (thanks, Thorsten Glaser). * Rename --mbr-manager into --mbr-menu (people seem to be confused what this option does). Improve the according documentation. * Update failsafe bootoption. * Fix comments section in manpage (thanks for reporting, Alexander Steinböck). * Mention the Debian package in the error message (thanks to Lothar Speil for the bugreport). * Mention grml-repository in the docs. * Support older kernel versions in check for removable usb device. (Thanks to Ralf Gross for the report and relevant information.) * Also add specified bootoptions to default entry in configuration file of grub version 1. (Thanks to Ralf Gross for the bugreport.) * Make sure that options "--quiet" and "--verbose" aren't accepted at the same time in the command line. Thanks for bugreport and code example, Karl Voit! * Bump Standard Version to 3.8.1 (no further changes). * Set debhelper's compat version from 4 to 5. -- Michael Prokop Wed, 08 Apr 2009 00:09:46 +0200 grml2usb (0.9.2) unstable; urgency=low * Rewrote grml2usb from scratch (in python). New features: - you no longer need to setup the device via /etc/fstab, just directly invoke "grml2usb /path/to/iso /dev/sdb1" - initial multi-iso / multi-boot support [Closes: issue501] [Closes: issue584] - provide *several* new options like --bootloader-only, --bootoptions=... check out the manpage for all the details - get rid of "polution" of root directory on usb-pen [Closes: issue466] - always write a default MBR (thanks a lot to the work and help of Thorsten Glaser!) [Closes: issue295] - use grub by default (but support for syslinux is present as well of course) - fix regressions for temporary mountpoints / wrong directories [Closes: issue603] [Closes: issue602] * Update debian stuff: - Bump Standard Version to 3.8.0 (no further changes) - Change XS-Vcs-* to Vcs-* headers and replace mercurial with grml's nowadays git repository URLs - drop mtools from depends - slightly improve long description - add asciidoc, xsltproc and docbook-xsl to Build-Depends - either depend on syslinux | grub2 | grub -- Michael Prokop Mon, 02 Mar 2009 16:40:55 +0100 grml2usb (0.9.1) unstable; urgency=low * Fix problem with comment chars in /etc/fstab. Thanks for debugging and the patch to Robert Euhus! * Some minor cleanups in Debian packaging. -- Michael Prokop Sun, 25 May 2008 01:29:30 +0200 grml2usb (0.9.0) unstable; urgency=low * Support new directory layout of different grml-flavours * Fix uninstall option (really clean up usb device) -- Michael Prokop Sat, 23 Feb 2008 23:43:57 +0100 grml2usb (0.8.0) unstable; urgency=low * Fix the "mv: cannot move `/mnt/usb-sdb1/boot/grub' to a subdirectory of itself, `/mnt/usb-sdb1/grub'" issue. -- Michael Prokop Sat, 19 Jan 2008 16:57:08 +0100 grml2usb (0.7.8) unstable; urgency=low * Adjust grml2usb for a present grub directory. -- Michael Prokop Fri, 16 Nov 2007 08:29:20 +0100 grml2usb (0.7.7) unstable; urgency=low * Improve error handling for execution of syslinux. -- Michael Prokop Thu, 13 Sep 2007 01:38:31 +0200 grml2usb (0.7.6) unstable; urgency=low * The "reworked grml2usb for JUXLALA"-release. * Added fs check via vol_id. * Improved error handling. * Fixed some code parts regarding use of $TMPMNT. -- Michael Prokop Fri, 08 Jun 2007 18:07:09 +0200 grml2usb (0.7.5) unstable; urgency=low * supporting directories and direct blockdevices as source for the iso. -- Michael Gebetsroither Tue, 03 Apr 2007 23:28:19 +0200 grml2usb (0.7.4) unstable; urgency=low * Get rid of bashism, thanks for reporting - Paul Weaver! * Change version schema from x.y-z to x.y.z. -- Michael Prokop Fri, 16 Mar 2007 14:43:49 +0100 grml2usb (0.7-3) unstable; urgency=low * The manpage was just a template, added the missing documentation now. Thanks for reporting, Jens Heidrich! -- Michael Prokop Sat, 3 Feb 2007 11:08:30 +0100 grml2usb (0.7-2) unstable; urgency=low * Use 'Architecture: all' in debian/control so we can use the package on non-x86 as well. * Bumb Standard Version to 3.7.2 (no further changes). -- Michael Prokop Sat, 11 Nov 2006 12:46:35 +0100 grml2usb (0.7-1) unstable; urgency=low * Use different exit codes for different code parts, and quote $ISO, thanks - Richard Hartmann! * Remove unused configure lines in debian/rules. -- Michael Prokop Mon, 6 Nov 2006 23:48:46 +0100 grml2usb (0.6-1) unstable; urgency=low * Allow overwriting of $TMPMNT. -- Michael Prokop Wed, 4 Oct 2006 22:50:58 +0200 grml2usb (0.5-1) unstable; urgency=low * bailout if mounting of target device failes. -- Michael Prokop Mon, 11 Sep 2006 23:47:01 +0200 grml2usb (0.4-1) unstable; urgency=low * Check for existence of syslinux before running the script. * Updated copyright file (new fsfs address). -- Michael Prokop Sat, 3 Jun 2006 21:02:53 +0200 grml2usb (0.3-1) unstable; urgency=low * Added uninstall option. * Improved error handling and its output. * Added colors to improve manual text parsing. -- Michael Prokop Fri, 10 Mar 2006 20:19:28 +0100 grml2usb (0.2-1) unstable; urgency=low * Improved usage information. -- Michael Prokop Tue, 10 Jan 2006 09:35:20 +0100 grml2usb (0.1-3) unstable; urgency=low * Changed 'cp -a' to 'cp -dR --preserve=mode,timestamps' so we don't get the ownership-permission-warnings. -- Michael Prokop Fri, 2 Sep 2005 18:02:22 +0200 grml2usb (0.1-2) unstable; urgency=low * Fixed small typo (SYSDEV/TMPDEV) [thanks for hint, tklauser!]. -- Michael Prokop Wed, 17 Aug 2005 21:50:32 +0200 grml2usb (0.1-1) unstable; urgency=low * Initial release. -- Michael Prokop Sun, 14 Aug 2005 15:31:04 +0200 grml2usb-0.14.2/debian/control0000644000000000000000000000157512224471456013065 0ustar Source: grml2usb Section: admin Priority: optional Maintainer: Grml Team Uploaders: Michael Prokop , Alexander Wirt , Christian Hofstaedtler , Ulrich Dangel Build-Depends: debhelper (>= 7), asciidoc, xsltproc, docbook-xsl Standards-Version: 3.9.4 Homepage: http://grml.org/grml2usb/ Vcs-git: git://git.grml.org/grml2usb.git Vcs-Browser: http://git.grml.org/?p=grml2usb.git Package: grml2usb Architecture: i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends}, syslinux | grub-pc, python, rsync, mtools, realpath Recommends: syslinux, xorriso | genisoimage Description: install Grml system / ISO to usb device This script installs a Grml ISO to an USB device to be able to boot from it. Make sure you have at least one Grml ISO or a running Grml system (/lib/live/mount/medium) available. grml2usb-0.14.2/debian/rules0000755000000000000000000000410511752446713012535 0ustar #!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 VERSION:=$(shell dpkg-parsechangelog | awk '/Version: / { print $$2 }') build: build-arch build-indep build-arch: build-stamp build-indep: build-stamp build-stamp: dh_testdir egrep -q "PROG_VERSION = '\*\*\*UNRELEASED\*\*\*'" grml2usb || (echo "PROG_VERSION in grml2usb wrong." && exit 2) $(MAKE) cd mbr && $(MAKE) && cd .. touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp # Add here commands to clean up after the build process. $(MAKE) clean cd mbr && $(MAKE) clean && cd .. dh_clean install: build dh_testdir dh_testroot dh_prep dh_installdirs usr/share/grml2usb/grub usr/share/grml2usb/mbr # Add here commands to install the package into debian/grml2usb. install -m 755 grml2usb debian/grml2usb/usr/sbin/grml2usb sed -i -e "s/PROG_VERSION = '\*\*\*UNRELEASED\*\*\*'/PROG_VERSION = '$(VERSION)'/" debian/grml2usb/usr/sbin/grml2usb install -m 755 grml2iso debian/grml2usb/usr/sbin/grml2iso install -m 644 mbr/mbrmgr debian/grml2usb/usr/share/grml2usb/mbr/mbrmgr install -m 644 mbr/mbrldr debian/grml2usb/usr/share/grml2usb/mbr/mbrldr cp -a grub/ debian/grml2usb/usr/share/grml2usb/ # Build architecture-dependent files here. binary-arch: build-arch install dh_testdir dh_testroot dh_installchangelogs dh_installdocs TODO dh_installman grml2usb.8 grml2iso.8 dh_strip dh_compress dh_fixperms dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb # Build architecture-independent files here. binary-indep: build-indep install # Nothing to do. binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install grml2usb-0.14.2/debian/source/0000755000000000000000000000000011645615675012763 5ustar grml2usb-0.14.2/debian/source/format0000644000000000000000000000001511645615675014172 0ustar 3.0 (native) grml2usb-0.14.2/foobar/0000755000000000000000000000000012117625367011503 5ustar grml2usb-0.14.2/Makefile0000644000000000000000000000440312204377115011664 0ustar all: doc doc: doc_man doc_html doc_html: html-stamp html-stamp: grml2usb.8.txt grml2iso.8.txt asciidoc -b xhtml11 -a icons -a toc -a numbered grml2usb.8.txt asciidoc -b xhtml11 -a icons -a toc -a numbered grml2iso.8.txt touch html-stamp doc_man: man-stamp man-stamp: grml2usb.8.txt grml2iso.8.txt # grml2usb: asciidoc -d manpage -b docbook grml2usb.8.txt sed -i 's///' grml2usb.8.xml xsltproc --novalid --nonet /usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl grml2usb.8.xml # ugly hack to avoid duplicate empty lines in manpage # notice: docbook-xsl 1.71.0.dfsg.1-1 is broken! make sure you use 1.68.1.dfsg.1-0.2! cp grml2usb.8 grml2usb.8.tmp uniq grml2usb.8.tmp > grml2usb.8 # ugly hack to avoid '.sp' at the end of a sentence or paragraph: sed -i 's/\.sp//' grml2usb.8 rm grml2usb.8.tmp # grml2iso: asciidoc -d manpage -b docbook grml2iso.8.txt sed -i 's///' grml2iso.8.xml xsltproc --novalid --nonet /usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl grml2iso.8.xml # ugly hack to avoid duplicate empty lines in manpage # notice: docbook-xsl 1.71.0.dfsg.1-1 is broken! make sure you use 1.68.1.dfsg.1-0.2! cp grml2iso.8 grml2iso.8.tmp uniq grml2iso.8.tmp > grml2iso.8 # ugly hack to avoid '.sp' at the end of a sentence or paragraph: sed -i 's/\.sp//' grml2iso.8 rm grml2iso.8.tmp # we're done touch man-stamp online: all scp grml2usb.8.html grml:/var/www/grml/grml2usb/index.html scp images/icons/* grml:/var/www/grml/grml2usb/images/icons/ scp images/screenshot.png grml:/var/www/grml/grml2usb/images/ tarball: all ./tarball.sh prepare-release: ./tarball.sh --no-gpg clean: rm -rf grml2usb.8.html grml2usb.8.xml grml2usb.8 rm -rf grml2iso.8.html grml2iso.8.xml grml2iso.8 rm -rf html-stamp man-stamp grml2usb.tar.gz grml2usb.tgz grml2usb.tgz.md5.asc codecheck: pyflakes grml2usb pylint --include-ids=y --max-line-length=120 grml2usb # pylint --include-ids=y --disable-msg-cat=C0301 --disable-msg-cat=W0511 grml2usb # pylint --reports=n --include-ids=y --disable-msg-cat=C0301 grml2usb pep8 --repeat --ignore E125,E126,E127,E128,E501 grml2usb # graph: # sudo pycallgraph grml2usb /grml/isos/grml-small_2008.11.iso /dev/sdb1 grml2usb-0.14.2/mbr/0000755000000000000000000000000012202663560011003 5ustar grml2usb-0.14.2/mbr/mbr.S0000644000000000000000000001556011153456304011716 0ustar /* $MirOS: src/sys/arch/i386/stand/mbr/mbr.S,v 1.13 2009/03/04 10:50:28 tg Exp $ */ /*- * Copyright (c) 2009 * Thorsten Glaser * * Provided that these terms and disclaimer and all copyright notices * are retained or reproduced in an accompanying document, permission * is granted to deal in this work without restriction, including un- * limited rights to use, publicly perform, distribute, sell, modify, * merge, give away, or sublicence. * * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to * the utmost extent permitted by applicable law, neither express nor * implied; without malicious intent or gross negligence. In no event * may a licensor, author or contributor be held liable for indirect, * direct, other damage, loss, or other issues arising in any way out * of dealing in the work, even if advised of the possibility of such * damage or existence of a defect, except proven that it results out * of said person's immediate fault when using the work as intended. *- * Compile commands: * $ gcc -D_ASM_SOURCE -DBOOTMANAGER -D__BOOT_VER=\"0AA6\" -c mbr.S * $ ld -nostdlib -Ttext 0x0600 -N -Bstatic -e _start -o mbrmgr.elf mbr.o * $ objcopy -O binary mbrmgr.elf mbrmgr * $ gcc -D_ASM_SOURCE -DBOOT_QUIET -D__BOOT_VER=\"0AA6\" -c mbr.S * $ ld -nostdlib -Ttext 0x0600 -N -Bstatic -e _start -o mbrldr.elf mbr.o * $ objcopy -O binary mbrldr.elf mbrldr */ .intel_syntax noprefix .code16 .text .globl _start _start: xor eax,eax mov ss,ax mov sp,offset Lstack push eax popfd mov ds,ax mov es,ax mov si,offset Lbadr mov di,offset _start mov cx,0x0200 /* size of one sector */ push si /* load / return address */ push ax push offset Lmain rep movsb lret /* entry message */ Lemsg: .ascii "Mir-" .ascii __BOOT_VER #ifdef BOOTMANAGER /* Lem are patch points */ .ascii ": 0=" Lem00: .ascii "00 1=" Lem01: .ascii "00 2=" Lem02: .ascii "00 3=" Lem03: .ascii "00 4=hd0 5=fd0 Enter=default (timeout)\r\n" #endif .asciz ">" /* failure message */ Lfmsg: .asciz "bad magic\r\n" #if 1 /* okay boot message */ Lbmsg: .asciz " OK\r" #endif /* output NUL-terminated string from ds:si */ Lotxt0: mov ah,0x0E mov bx,7 int 0x10 Lotxt: lodsb or al,al jnz Lotxt0 ret Lmain: sti #ifdef BOOTMANAGER /* patch the partition type values into the message */ mov di,offset Lem00 mov al,ds:[Lptab + 0x04] call LpBY mov di,offset Lem01 mov al,ds:[Lptab + 0x14] call LpBY mov di,offset Lem02 mov al,ds:[Lptab + 0x24] call LpBY mov di,offset Lem03 mov al,ds:[Lptab + 0x34] call LpBY #endif #if !defined(BOOT_QUIET) || defined(BOOTMANAGER) mov si,offset Lemsg call Lotxt #endif /* fake invalid partition entry for MBR/FDD boot */ mov di,offset Lptab + 0x40 xor eax,eax stosw inc ax stosw dec ax stosd stosd /* force bad magic if sector load fails */ mov ds:[Lbmag],al #ifdef BOOTMANAGER #if 0 /* see above, eax is already zero here */ xor ax,ax /* read CMOS clock ticks since midnight */ #endif int 0x1A /* 32-bit result in cx:dx */ mov di,cx /* save it in edi for later */ shl edi,16 mov di,dx add edi,183 /* 10 seconds, rounded up one tick */ Lptmo = . - 4 /* offset of the "183" above */ /* input loop with timeout */ Lwkey: mov ah,1 int 0x16 /* check if a key was pressed */ jnz Lgkey /* yeap */ /* delay loop */ xor ax,ax int 0x1A shl ecx,16 mov cx,dx or al,al /* past midnight? */ jz Lsday /* no */ add ecx,1573040 /* should be 1572480, but according to RBIL… */ Lsday: cmp ecx,edi /* time is over? */ mov al,13 ja Lfkey /* yep, fake a return keypress */ jmp Lwkey /* input loop without timeout */ Lgkey: mov ah,1 int 0x16 /* check if a key was pressed */ jz Lgkey mov ah,0 int 0x16 #endif /* BOOTMANAGER */ Lfkey: mov bx,offset Lptab mov dl,0x80 /* drive to load from */ #ifndef BOOTMANAGER jmp Lscan #else sub al,13 je Lscan /* CR / Return / Enter */ jb Lgkey /* invalid input */ sub al,('0' - 13) jb Lgkey /* invalid input */ cmp al,5 /* floppy */ ja Lgkey /* invalid input */ jb LdoHD /* hard disc */ mov dl,0 /* drive to load from */ dec ax /* 5 -> 4 */ #endif LdoHD: shl al,4 /* 0..4 where 4 is virtual partition */ add bl,al /* we boot this one */ jmp Lboot /* scan the partition table for an active partition */ Lscan: mov al,[dpart] /* try hard-coded by fdisk(8) 'fdef' first */ cmp al,3 jbe LdoHD Lspar: cmp byte ptr [bx],0x80 je Lboot /* found an active partition */ add bl,0x10 cmp bl,0xFE /* BX = 0x07FE = Lptab + 0x40 */ jb Lspar /* boot the virtual partition #4 (MBR) */ Lboot: /* try to boot, first LBA (we're on a HDD) then CHS */ mov [bx],dl /* drive (0x80 or 0x00) */ mov si,offset Lpblk /* LBA parameter block */ mov di,si mov ax,0x0010 stosw /* size of LBA parameter block */ mov al,1 stosw /* number of sectors to load */ pop ax push ax push bx stosw /* load address offset */ xor ax,ax stosw /* load address segment */ mov eax,[bx+8] stosd /* LBA offset of start sector (low 32 bit) */ xor ax,ax stosw /* high 32 bit */ stosw /* high 32 bit */ mov ah,0x42 /* LBA extended read */ call Lload /* try to boot that */ pop si /* edited partition table entry */ pop bx /* load offset (ES=CS=SS=DS=0000h) */ push bx push si mov ax,0x0201 /* CHS read 0x01 sectors */ mov cx,[si+2] /* cylinder; sector number */ mov dx,[si] /* head; drive number */ call Lload mov si,offset Lfmsg call Lotxt #if 0 Lfail: jmp Lfail #else xor ax,ax int 0x16 ljmp 0xF000,0xFFF0 #endif Lload: mov bp,4 /* number of tries */ Lldlp: pusha int 0x13 popa jc Lldre /* error, try again */ cmp word ptr ds:[Lbmag],0xAA55 jne Lldre /* bad magic, try again */ #if 0 mov ax,0x0E0D /* output a carriage return */ xor bx,bx int 0x10 #else mov si,offset Lbmsg call Lotxt #endif pop si /* Lload return address */ pop si /* partition table entry */ mov dl,[si] /* DS:SI point to partition table entry, DL is set */ cli /* be nice :) */ ret /* jump to 0000:7C00h */ Lldre: pusha xor ax,ax /* reset drive */ int 0x13 popa dec bp /* another try left? */ jnz Lldlp ret #ifdef BOOTMANAGER LpBY: mov ah,al shr al,4 and ah,0x0F add ax,0x3030 cmp al,0x39 jbe LpBY1 add al,7 LpBY1: cmp ah,0x39 jbe LpBY2 add ah,7 LpBY2: stosw ret #endif . = _start + 0x01B7 .globl dpart .size dpart,1 dpart: .byte 0xFF /* default partition [0..3] or none */ . = _start + 0x01B8 Lntid: .long 0 /* Microsoft® NT® volume identifier */ Lpad1: .byte 0, 0 . = _start + 0x01BE /* partition table */ Lptab: .long 0, 0, 0, 0 /* partition entry #0 */ .long 0, 0, 0, 0 /* partition entry #1 */ .long 0, 0, 0, 0 /* partition entry #2 */ /* partition entry #3 + pre-installation hint */ .word 0, 0, 0, 0, 0 . = _start + 0x01F8 .size Lhint,2 #ifdef BOOTMANAGER Lhint: .word (Lptmo - _start) #else Lhint: .word 0xFFFF #endif Lpad2: .word 0, 0 . = _start + 0x01FE Lpmag: .word 0xAA55 /* BIOS boot magic */ Lstack = 0x4000 Lpblk = 0x5000 Lbadr = 0x7C00 Lbmag = Lbadr + 0x01FE grml2usb-0.14.2/mbr/Makefile0000644000000000000000000000105211153462570012443 0ustar # https://www.mirbsd.org/cvs.cgi/~checkout~/src/sys/arch/i386/stand/mbr/mbr.S all: mbrmgr mbrldr clean: rm -f mbrmgr mbrldr mbrmgr.elf mbr.o mbrmgr: $(CC) -D_ASM_SOURCE -DBOOTMANAGER -D__BOOT_VER=\"0AA6\" -c mbr.S ld -nostdlib -Ttext 0x0600 -N -Bstatic -e _start -o mbrmgr.elf mbr.o objcopy -O binary mbrmgr.elf mbrmgr # bootloader, without a bootmenu mbrldr: $(CC) -D_ASM_SOURCE -UBOOTMANAGER -DBOOT_QUIET -D__BOOT_VER=\"0AA6\" -c mbr.S ld -nostdlib -Ttext 0x0600 -N -Bstatic -e _start -o mbrmgr.elf mbr.o objcopy -O binary mbrmgr.elf mbrldr grml2usb-0.14.2/grml2iso0000755000000000000000000002506012162604060011705 0ustar #!/usr/bin/env bash # Filename: grml2iso # Purpose: create a multiboot grml ISO using grml2usb # Authors: Michael Prokop , # Thorsten Glaser # Bug-Reports: see http://grml.org/bugs/ # License: This file is licensed under the GPL v2 or any later version. ################################################################################ # make sure we have the sbin directories in our PATH to find grml2usb ootb PATH="${PATH}:/sbin:/usr/local/sbin:/usr/sbin" # define function getfilesize before "set -e" {{{ if stat --help >/dev/null 2>&1; then getfilesize='stat -c %s' # GNU stat else getfilesize='stat -f %z' # BSD stat fi # }}} # adjust variables if necessary through environment {{{ # path to the grml2usb script you'd like to use [ -n "$GRML2USB" ] || GRML2USB='grml2usb' # work directory for creating the filesystem [ -n "$TMPDIR" ] && WRKDIR="${TMPDIR}/grml2iso.tmp" [ -n "$WRKDIR" ] || WRKDIR='/tmp/grml2iso.tmp' # support mkisofs as well as genisoimage if which xorriso >/dev/null 2>&1 ; then MKISOFS='xorriso -as mkisofs' elif which mkisofs >/dev/null 2>&1; then MKISOFS='mkisofs' elif which genisoimage >/dev/null 2>&1; then MKISOFS='genisoimage' else echo "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." >&2 exit 1 fi if ! which isohybrid >/dev/null 2>&1 ; then echo "Error: isohybrid executable not found (install syslinux/isolinux?)." >&2 exit 1 fi # }}} # helper stuff {{{ set -e usage() { echo >&2 "Usage: $0 [OPTIONS] -o target.iso source1.iso [source2.iso ...]" echo >&2 " Options: -b Boot Params Additional boot parameters passed to grml2usb -c Directory Copy files from directory to generated ISO -f Force overwrite of existing target.iso -r BootParam Remove specified boot params. Can be specified multiple times. -p Add the specified parameter to the grml2usb commandline. For a list of valid parameters have a look at the grml2usb manpage. Can be specified multiple times. -s URI Generate a small ISO file which downloads the squashfs file from the specified URI. Please note that due to restrictions in the bootprocess only IPs are allowed. Supported protocols are: http and ftp -t Directory Directory that should be used for temporary files during build. Defaults to /tmp/grml2iso.tmp if unset. Examples: $0 -s http://192.168.23.42:8000/grml/ -o small.iso grml64_2010.12.iso Will generate a file small.iso which tries to download the squashfs file from http://192.168.23.42:8000/grml/ - the squashfs file is placed in the same output directory as the ISO file. " [ -n "$1" ] && exit $1 || exit 1 } # }}} # command line handling {{{ [[ $# -gt 2 ]] || usage 1 ISOFILE='' DIR='' ADD_OPTS='' FORCE='' URI='' typeset -a GRML2USB_OPTS while getopts fb:c:o:r:p:s:t: name; do case $name in o) ISOFILE="$OPTARG";; b) GRML2USB_OPTS+=(--bootoptions="$OPTARG");; c) DIR="$(readlink -f "$OPTARG")"; [ -n "$DIR" ] || { echo "Could not read $OPTARG - exiting" >&2 ; exit 1 ; } ;; f) FORCE='true';; r) GRML2USB_OPTS+=(--remove-bootoption="$OPTARG");; p) GRML2USB_OPTS+=("$OPTARG");; s) URI="$OPTARG";; t) WRKDIR="$(readlink -f "$OPTARG")";; ?) usage 2;; esac done # test for specified URI if [ -n "$URI" ] ; then GRML2USB_OPTS+=(--bootoptions="fetch=$URI") fi if [ -n "$WRKDIR" ] ; then GRML2USB_OPTS+=(--tmpdir="$WRKDIR") fi # make sure -o is specified [ -n "$ISOFILE" ] || usage 1 # we don't to override any files by accident if [ -e "$ISOFILE" -a ! -n "$FORCE" ]; then echo "Error: target file $ISOFILE exists already." >&2 exit 1 fi if [ ! -z "$DIR" -a ! -d "$DIR" ] ; then echo "Error: specified parameter for -c is not a directory" >&2 exit 1 fi # }}} # we need root permissions for executing grml2usb {{{ if [[ $(id -u) != 0 ]]; then echo >&2 "Error: please run $0 as root." exit 1 fi # }}} # check for grml2usb {{{ if [ ! -x "$(which $GRML2USB)" ] && [ ! -x "$GRML2USB" ] ; then echo "Error: Could not find grml2usb executable. Is /usr/sbin missing in PATH?" >&2 echo "Tip: run GRML2USB=/usr/sbin/grml2usb grml2iso ... as workaround" >&2 if [ -x "./$GRML2USB" ] ; then echo >&2 "If you executed grml2iso from the grml2usb repository use" echo >&2 "GRML2USB=./grml2usb $0 $*" fi exit 1 fi # }}} # variables {{{ ORIG_DIR="$(pwd)" # normalise path case $ISOFILE in /*) ;; *) ISOFILE=$ORIG_DIR/$ISOFILE ;; esac # }}} # create necessary stuff under WRKDIR {{{ [ -d "$WRKDIR" ] && WRKDIR_EXISTED='true' || WRKDIR_EXISTED='false' rm -rf "$WRKDIR/cddir" "$WRKDIR/grub_tmp" mkdir -p "$WRKDIR/cddir" # }}}} # execute grml2usb with all ISOs you'd like to install {{{ # remove all parameters shift $(($OPTIND - 1)) $GRML2USB "${GRML2USB_OPTS[@]}" "$@" "$WRKDIR/cddir" # }}} # move syslinux to isolinux {{{ mv "$WRKDIR"/cddir/boot/syslinux "$WRKDIR"/cddir/boot/isolinux echo "menu label ^Isolinux prompt" > "$WRKDIR"/cddir/boot/isolinux/promptname.cfg echo "include hd.cfg" >> "$WRKDIR"/cddir/boot/isolinux/grmlmain.cfg # }}} # change to $WRKDIR {{{ # make sure $WRKDIR is an absolute path, otherwise accessing files # in it will fail later in the code path if user provided a # relative directory WRKDIR=$(realpath $WRKDIR) cd "$WRKDIR/cddir" # }}} # efi boot {{{ # default, independent of UEFI support BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat" UEFI_ENABLE=false case "$MKISOFS" in xorriso*) echo "Using xorriso for ISO generation." if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then echo "Disabling (U)EFI boot support since xorriso version is not recent enough." else echo "xorriso with -eltorito-alt-boot support present" UEFI_ENABLE=true if ! [ -r "${WRKDIR}/cddir/boot/efi.img" ] ; then echo "Warning: File /boot/efi.img not found, not extending boot arguments for (U)EFI boot." UEFI_ENABLE=false else echo "/boot/efi.img found, extending boot arguments for (U)EFI boot." BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot" fi fi ;; *) echo "Using $MKISOFS for ISO generation (lacking UEFI option), disabling (U)EFI boot support." ;; esac # }}} # adjust ISO for small output if necessary {{{ if [ -n "$URI" ] ; then bootloader_files=$(find . -name "*.cfg" -type f) bootloader_files+=" " bootloader_files+=$(find . -name "*.lst" -type f) output_dir=$(dirname "$ISOFILE") for squashfs in $(find . -name *.squashfs) ; do media_path="$(dirname "$squashfs")" filename="$(basename "$squashfs")" target="$output_dir/$filename" if [ -f "$target" ] && [ ! -n "$FORCE" ] ; then echo >&2 "Warning: $target already exists, and -force not specified, not overwriting" else mv $squashfs $target OUTPUT_FILES+=("$target") fi sed -i -e "s#^\(^.*$media_path.*\)\($URI\)\(.*$\)#\1$URI/$filename\3#g" $bootloader_files done fi # }}} # copy specified directory to cd {{{ if [ -n "$DIR" ] ; then echo >&2 "Copying ${DIR} to generated ISO" for param in GRML_NAME VERSION RELEASENAME DATE SHORT_NAME \ VERSION BOOTID RELEASE_INFO ; do EXCLUDE_PARAM="$EXCLUDE_PARAM --exclude **%${param}%**" done rsync -a ${DIR}/ $EXCLUDE_PARAM . fi # adjust files from overlay directory for GRML_VERSION_FILE in $(find . -name grml-version) ; do GRML_NAME=$(awk '{print $1}' "$GRML_VERSION_FILE") VERSION=$(awk '{print $2}' "$GRML_VERSION_FILE") RELEASENAME=$(sed 's/.*- \(.*\).*\[.*/\1/' "$GRML_VERSION_FILE") DATE=$(sed 's/.*\[\(.*\)].*/\1/' "$GRML_VERSION_FILE") SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')" RELEASE_INFO="$GRML_NAME $VERSION - $RELEASENAME" BOOTID=$(cat conf/bootid.txt) for param in GRML_NAME VERSION RELEASENAME DATE SHORT_NAME \ RELEASE_INFO BOOTID ; do value="$(eval echo '$'"$param")" # copy parameterized files from the overlay directory for file in $(find ${DIR} -name "*%$param%*") ; do file=${file##$DIR/} target_dir="$(dirname ${file})" mkdir -p "$target_dir" || true cp -r ${DIR}/${file} ./${target_dir}/"$(basename ${file/\%${param}\%/$value})" done # adjust config files for file in ./boot/isolinux/*.cfg ./boot/isolinux/*.msg \ ./boot/grub/*.cfg ; do sed -i "s/%$param%/$value/g" ${file} 2>/dev/null || true done done done # }}} # generate the CD/DVD ISO {{{ $MKISOFS -V 'grml-multiboot' -l -r -J -no-pad $BOOT_ARGS \ -o "$ISOFILE" . # }}} # pad the output ISO to multiples of 256 KiB for partition table support {{{ siz=$($getfilesize "$ISOFILE") cyls=$(($siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32 ofs=$(($cyls * 16 * 32 * 512 - 1)) # padding offset (size - 1) dd if=/dev/zero bs=1 count=1 seek=$ofs of="$ISOFILE" 2>/dev/null # }}} # make ISO dd-able {{{ if ! $UEFI_ENABLE ; then echo "Skipping check for --uefi option in isohybrid since prerequisites are not fulfilled." else if ! isohybrid --help | grep -q -- --uefi ; then echo "isohybrid version does NOT support --uefi option, disabling" else echo "isohybrid version supports --uefi option" ISOHYBRID_OPTIONS=--uefi fi echo "Creating dd-able ISO using isohybrid" isohybrid $ISOHYBRID_OPTIONS "$ISOFILE" fi # }}} # cleanup {{{ cd "$ORIG_DIR" sync rm -rf "$WRKDIR/cddir" "$WRKDIR/grub_tmp" [[ $WRKDIR_EXISTED = 'false' ]] && rmdir "$WRKDIR" echo "Generated $ISOFILE" if [ -n "$URI" ] ; then echo " Information: ============== You requested to generate a small ISO image. Your generated ISO image $ISOFILE does _not_ contain the squashfs files from the source ISO images. You have to provide the extracted squashfs files under $URI. ISO image: $ISOFILE Squashfs files: ${OUTPUT_FILES[@]} URI: $URI " fi # }}} ## EOF ######################################################################### # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2 grml2usb-0.14.2/zsh/0000755000000000000000000000000012073535134011030 5ustar grml2usb-0.14.2/zsh/_grml2usb0000644000000000000000000000347612073535134012661 0ustar #compdef grml2usb # Filename: /etc/zsh/completion.d/_grml2usb # Purpose: completion of command grml2usb for zsh (z shell) # Authors: grml-team (grml.org), (c) Michael Prokop # Bug-Reports: see http://grml.org/bugs/ # License: This file is licensed under the GPL v2. ################################################################################ local arguments dev local -a devices devices=() for dev in /dev/sd* /dev/hd* ; do if [[ $(cat /sys/block/${dev#*dev/}/removable 2>/dev/null) == '1' ]] ; then part=$(ls /dev/${dev#*dev/}[0-9]) devices+=$part fi done # TODO: # * handling of --bootoptions=BOOTOPTIONS # * $devices should also list directories as valid target # * as output before :device:.... ISO files and/or /lib/live/mount/medium should be suggested arguments=( '--help[display help message and exit]:' '--bootoptions=[use specified bootoptions as default]:' '--bootloader-only[do not copy files but just install a bootloader]' '--copy-only[copy files only but do not install bootloader]' '--dry-run[avoid executing commands]' '--fat16[format specified partition with FAT16]' '--force[force any actions requiring manual interaction]' '--mbr-manager[enable interactive boot manager menu in MBR]' '--quiet[do not output anything but just errors on console]' '--skip-addons[do not install /boot/addons/ files]' '--skip-mbr[do not install a master boot record (MBR) on the device]' '--syslinux[install syslinux bootloader instead of grub]' '--syslinux-mbr[install syslinux master boot record (MBR) instead of default]' '--verbose[enable verbose mode]' '--version[display program version and exit]' ':device:($devices)' ) _arguments -s $arguments ## END OF FILE ################################################################# # vim:foldmethod=marker