From 36be65ed23ff7bfa23211c7b04aeb6f97c440cee Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 14 Feb 2012 01:23:42 +0000 Subject: [PATCH] [iso] add support for isolinux/syslinux ISO images * use a modified syslinux that can use isolinux config files * update syslinux to git version * remove embedding of chain.c32 for the time being --- res/syslinux/ldlinux.bss | Bin 512 -> 512 bytes res/syslinux/ldlinux.sys | Bin 31205 -> 36160 bytes res/syslinux/readme.txt | 8 +- res/syslinux/syslinux.diff | 29 +++++ src/format.c | 71 ++++++----- src/iso.c | 29 +++-- src/rufus.c | 29 +++-- src/rufus.h | 4 +- src/rufus.rc | 14 +-- src/syslinux.c | 3 +- .../libinstaller/.msvc/libinstaller.vcxproj | 6 +- .../.msvc/libinstaller.vcxproj.filters | 10 +- .../libinstaller/.msvc/libinstaller_sources | 2 +- src/syslinux/libinstaller/Makefile.am | 2 +- src/syslinux/libinstaller/Makefile.in | 12 +- src/syslinux/libinstaller/{fat.c => fs.c} | 118 ++++++++++++------ src/syslinux/libinstaller/setadv.c | 3 + src/syslinux/libinstaller/syslinux.h | 5 +- src/syslinux/libinstaller/syslxcom.h | 6 + src/syslinux/libinstaller/syslxfs.h | 26 ++++ src/syslinux/libinstaller/syslxint.h | 70 +++++++++-- src/syslinux/libinstaller/syslxmod.c | 2 +- 22 files changed, 323 insertions(+), 126 deletions(-) create mode 100644 res/syslinux/syslinux.diff rename src/syslinux/libinstaller/{fat.c => fs.c} (52%) create mode 100644 src/syslinux/libinstaller/syslxcom.h create mode 100644 src/syslinux/libinstaller/syslxfs.h diff --git a/res/syslinux/ldlinux.bss b/res/syslinux/ldlinux.bss index 884c5a8e5cebb8ea1558f89479e7684b05194637..62142e2f53c398333171f6e8a0fa21ddf9243c3e 100644 GIT binary patch delta 16 XcmZo*X<*r)&&aZCc6Z@qW5%-pEh`1m delta 16 XcmZo*X<*r)&&Xn&7EmzRnDHzCCK&|U diff --git a/res/syslinux/ldlinux.sys b/res/syslinux/ldlinux.sys index cee0f82ffadde50dacf85f68532a10d6fe309470..e5ddced50fd4791030e8364bdb76610aa91966a0 100644 GIT binary patch delta 24352 zcmZU)2~-nT`#3yzW|B-cCP2i1sF@_}i$oDY(1s-t5HKu(u;Z4Zf+8e>3I+_c3`4AK zwAEJYR$FVe)t0hYMGysT)uLEyYZt4vofx%Pt%3{r4}IVFobPwO9GK@W&z-wJ``md1 zdf$a-2zgm~S*gkCI=wVJG%P|233*-+^BadhpMU&4YRyFYe?K#H?bwV&E_Uq;I%Twn z-({=kdPxVp3}rVDLlB+dX_!}Mf*`#41A3CL-e#7<}PY1(@Y+}M8>S0nPE7EUWOn;Sw774z1^0^_Y~Af$#ME) zX|ZFFe%n^X*Tq!}jUjZjly1Zw;@qCWFX$L46#<3Ov!%=u&@-ex%wPhfCAkAEsE6rc znzY3J*|=r??@YIDJ@zkXq146|O!2xsz0nEv8Hd7p4>4$`Vv=(VWf2^v+mCGX1;ph4 zjj81S3~9A(tso8Tx1AAa5}@N*Oe;g#Lmt!Un@I(D^AX5Eaj1wrkp>bSNI)S=Kic?Q ze0=Tql*`pj;yly6ww=B_ttTd#{$^Uw=N`v#}W_DCa#0Xrj2zvj`ud-hRYh3=nt3N0*lo)+-dOmEY!=Rp+1#}?PbF7_KK*h}4nSSVV zZU%B%ZzN}Wf6rg-^f}K7oYS5YThPpY!u~c=iZ^}X*>5Ow@|hJ`C+gvL(EDvwZrSXA zm&nt0!7T>F*tqVqIa}Sjc~DQCP3`VyroSw!wmB4U(Vt6>O6et%x9Ez(4mLI%*hXt2&`Alc47>3}p{om@Y$c+SBbee`2Mx zB;+MJUE;h=pK_;{K@(4|WVF9EQA~sX!l&41Kb-GId zXWis)pHE}sd+>vX(id$PH~+l(EP016aJ7v3RKdz#8@S}SX6 zX19q6Fo>w3?2UtF>Yu{6t|_zm;qJVW=|5kcXg17;=RY2r)2Mm4(w*DZ;!2T zk~etMwr*0Wxd3iUX9h328a3MgZ%P6&a}z-jv&g`Gw4X{8+u!r}56+)oGP4Fu4YM6F z82)d6g=ks>@-LYc&Z=B9Sjlxp;H8f_5ksX5=;YIyDA9Q?G+v-5R8sDz$-F$s> z@Bi<*(O&M(+y9})cysb&d&NUTsj^pj<)S;yenx-bW>{obuzRAr=)c_>=6_Q!G4g01 zG?n&qx#;N_r=>0zC64j`ZsuODaatBN?P!O^A!>a7``jv5lF5*Bl)YpU+>*pr75tB$ z)Nqx(1^rn$xom3wQQIQV7K8i61J9)Z z9JXamsb|IQ>}M$BcT>W_mo}bvILNoX;yu}Q)6P?EsSaX*eK(pj$o@Tgz3o-+sYEx= zF^!67O&vg?p0?Ceo74Ww*=DfmO)re6=uq1MZy#P)2XVtVRom)&(stE*F6gr1Q@tX4 zI_^ntM&87?^^Tu=Zdla+oUY`zyI%A#B~a7;ZSdFL@R(=O?3pnpZ)+~=-a%meDQ@CE zEt(ny1HNt7RMMxb!*Y6}#)RhUcYVXo?Sf`*?hU2p&x{GBJi0pW9SWUjuwYu!l&)RO z@%zNmi`^PK)eE|@|7DoIY)7W;H+vsHbtaRcw~q`5PQ}E8^^TuCG~RpbxnVEEo%ct^ z^fMeX6W^4I?EgLU6ndW4K4*9o)PD-QO{8mb&cBk$WF2$_lf@k5{HvJ^eWWv? z8vGP?gO*N|-XP}>O&|@^t`pf|ixW0+8|GufAtu|m)45=t?T6_K^S?LwYq(!ayF4qd z!VO)Y1bSRCJiToI!v@luDSkRuTm}D|+5=9-r2Kcqx5NKEEpNakpl8r5|DVbYFnwus zqS(p4mDx{!Ifie#3S}84F5HO@+B#OHq>W?r`(srB26+~}ajXiXmyOYHj4?#;M#GY`djW*W(>pixa6~U;dLi384&AwGBz*BTjTY_@m*EhJzR* z%q@J`F#q=s$mlx2X268}H28c%aO!*BKgjOtfFNd+%}@z50b4RL2SnH!iF6nmvt1@8 zfj@135>vrU8%q}dYHtU9jN4CFL-e7i#`3DM7`gFphMpV}NDX+$b^7loRk@5{z@NzX z^|QkI9rx≺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 F^nb!c)4>1$ delta 19390 zcmZU)d0Z1m|2V$0yGb?|2@o_WN;U~MB2iROwBZT?0|ZDQ+^CqQii(gRDjG1*vMjN- z(N?XtTD7$vRUehZDuO7e)fUC8wYAh*yD_%Kqly>#Eq$KPAK%xH7uolmJF_$MzTeZe z75@DRn9S#7=VfbB()9*OR7B)73B>1&gXq5z_&;-|8nqRp>Hqt)Laj$8tJqlUQ7Uz~ zbAOv-4SSsA&^V*1>i`5%;l9S%Ck+rJXnga8x`$IA`%sZ=3U#!xCxA+AqHGTrf- zjn858gb=k)Y@BzxZOvilzIJ3w$nbun=^~RZc8JXg_0d?WbK-vhRqFqn&uOUp$!as12)RlPb&J(jq(Q-cy`nVSmna~8XMnR}vv z%VnGMQx;^omrJ~;cS7CNX^D}X9@T1`H9b1EdP=78GPI@w)l9JqB2GmK9 zz?76Y4~^L7+@pu}>O6Cl`p4hF=8Yfst$)26>NfXBcI~5^osLb(F`6(IJ?#6AIXryq z|IMl7|Cv&*qneinNXJ>8I&nuwHr>l;`i?_)I_gs(XgmlRNftSMN3@YZdlON})`Ql+ zI@VErlk~Wjg?A4OzezJp^i@MOmB5s99n)vQt~lp0+;&Bm+~3!p5D+#nFW?G z%6GhB7PFzv{HM|Fu{qkzqQSOk%P)DZvb~}wDdDKb))#~Ws$Aac zth+lBSU+b3==TX4Z;s@Ub8cjHQpY;D(39Px^Zm&;us6vqp)O+N^v|QI%f6?f;lO4_ zvZTwrHda#oG^6v$F+nTuw=ubnUp#x&c+l(kL4Zqc zi;D4QX8t!jHXCi{-6s%;x+^jgbK0ZZA>sP2&Su9r;S5xdb+#PU3q=4u#B?5VEb;V5 zHyv|Mb8PT@i}mj|4GSGNJmd5KUHwBsV~IH+r*rKwDiZ39olAv6oy0Lp4i(dHr^lfV zdl`v|UC}K6p3c5w)M4MzHv4=>x1gN)jQM@EM9}bwZ;#OgjiSOlVdt;MDbi8trDOiP zM8I*$D;9_xZ0~8TTCWZc)TwhMc?Vg$j+?3+F8PPlR`Fp8HCOy0_33CLUTh?WsU2c! zf!O)SvzMltX2pd9#k2Ky*7q6({|P*N*x1MXsTHd8fnL2fnjU!2Lyi$p!0R{e=t|EL z6W>wO#qQszFTJUS(CG8g*x{aLm56fw58lCsd#F^%f4FD8Dv+!e1s;f%n;F!%V_p9Y z_tecfbsVxF)Jx345lym=X1u9an54^sH3gnLKEgb8yh-KPvx820oI37$^6E8}Df*s% zmW}=X)kLOXhhVR<^mWVS^*^saNBmADc-n>oDq%&J1Kf6hTzTBtJMyBZPvsW?^{K=R zv`-~cKrQLQmSTCI3jOM6p9(tAM$fBQPF4#k^;qlwrRft(UGX+eZgGA)VtP$F&y7$^ zyhcBOZipI9ja+&a9`KEX%8y7F6V>RyHN`@@l1vvHO+lka^&-CtRy?CCjdYuyfBXHr zVgKO|_w=g#6gxVznpEN)=G9FqQA@g%o=}Bjnvcj^*Gi~FJ9Fr#c&DKi8*C2DcNF^g zff~n3p9pIz+>%aDUU)5LxaZ%L7^1&T2to8BJLxHsDv{GR=D%%DAE&<>&^7dS#A1T? z)5Z8HbhfZZ}WR5R0IZuaEh8bmwtr-E&eUv<(YZjQd>OMy~{!BO*LB8e&Yk zW-mtXa;{*w=S9zs>1{M3@^?fzD#sMj#JzuvFYM+!Tw|oxcRi_rSH{y2GzKyniWOJC z*}Iv#%r|!aTW}hpKhxO3pcxAF8Q)kx2NJfAXf9jE)y+YLxW(JJGdfn$W!&{stMMC% zZtMK$-y`~osPpx4YLm#xd&2w|XGf_8Sb@r|0T7@%Q(*&!0f!;Mm_PWoAd1&v6({!pj5EOWnb3_ zm56&>7Q06Nx09c<%@ec9iJDfMOIZKv-poo*g3b^#6kS9z+?32z7W^MEsbMR+3VO10 za+%~DjboK>%70191jhwmsh_5mobf-R^EYPe5stp3xS%IDn{IoQHLeT*wWECe8b-*r zp3Zc~U*n@drbFfz6%x0thpHT@9NXaGnq@{Y=7U)-VIT9}tarAZZqc~#Ub=uanxE&W z^P7O5;J7A|)0;KDDAd`aIlVsZe~d1YNv(TrK21$_bovEwbglSp^8{^kV4mYoznRf= z_NrOBGb;AwEasG0%UIhP#>2h9EQqI(r}d#^FnUn1scYo?E91PLSJZOuG0)3mEQ#bq zoug#JIFRpHH6aFpxf>kEClEmAcx$2`rfYq;FJct)7EDYAI~@Bb`qCBWChoGH>^OZk zizcd1jC)SU#zuCHoZC0jb@!EVC(VL)MaTBcV&2OVtkWR7?q!`uFHjk;XhsC}oW_2m z5?|H-&Hjy;b2W?3x~OS%7IP7Eu4U0gkjjEq2u@?SDgV*Z+r*sy(MAK5a5Ot$bHf&P z-5hLSl7#~++{7GopofZeJo1-w|HavhaF3SaJ0y}Zafk zRAN-w3u^rfnw;IP`$N$62ii0zzqRR?`ro)i#6*LmO(OBkY1P`?$O`6_Kgd%MO3cwY zC`rO}L+fAn>+aX>#b~iC<4xV1x>m^S*~_HCs3g?;YE%U3dezg%)U`qoJ?BQKgr2cu z9zFwLjxBh)*gZ@mW^oTqtQ1`xDCfyOYAICpin{M`;}ZbKF+rMOEo`NZuzRQ~i2CZe zxxDg4tjzqFrWE^l5~HB?7WL>^WiHL~xuf~+9!6x3>mgPCoE8bGRnN_{D+8#K=be)F zj!4LO&=}KW4m2LT`%hd+V#Napag0c zL+eKozkmJUdWx>zaaeJcZXh2SZIJF*Ad|&p9)uw0TDP$@qL-=Exam){ERApn-fxZQ zW8QClZ&y2zZ@cWXohpDVIkddn2w5`zt=Z~0EtAXcx1Qg1??WCeAG!ZwCN2Mtfh@wi zFY+QrJd_&Cr=3)*^QMC--vkmJ+vJ9sl0!66b-giy?~UNQo^Ng(av~!}y^)OA8*MZV zkIHD@y)hP5fSyi9oAa9|&aS8Q8h4-&b-)o35UjR6t-L@HPw6FVniJK=?0_QIchgjy z_@Ubg)0o2QWlnDc&zS1A*Yrskpi^|#tY)5~+nqZFLCtih$lG+i2c7HNsAe~{+Oa-7z{(G`gwlubhNx zAB^(F%VOu>{r^?-7C}1GDDQPo+jSIzOu`fN7=vo zh0zeyagh1nG~Kepv3)e%^DHR@HiK7geT4Cw`=7fcG>05qKZO!N{fC49i!_HZ0d$KD zpyg7CpxnQ`d`4oJX7@a5E9j{xj=IOXQV>u*7{ zg8Tn!yi+0-ib;wolOkgr)YSb)H%2J|nCG}Y?R`X36 zLl|`o&iKN5ai{r{S@eW+BUx(Ulw^^zE2lC;z3aC?6{qe zN8y~foli#LTX8#|jzVSJ&VNQ>T-?rQqcA>h=krmR5Vv!96eh;)d@%}>;&uu@1yHOi zZs*Wwo`#;I`Q*5rUZYS=zwgcv3PCqNi&!w5`!^K)LeghQap4H}$)5e~`*%aoelq!Kz)cScL?k~o?l*q3dAIXp1J{Ag%C`14 zd1*wnBz%69-0dN{ZNDNMa3oCduXx(LAx|sXdeh;lmm!q z8%C-p?7X*B2sL(@neP6^E{liJHe0Jk7?2rxvZ3c`Pa=R|eQr*+?IDje@JKC2R!I61 z<=CoV+xLj?IVX{91eLezRGQnTiX=x zcJb}2M(p*_pxbRE;z#Vc?s6{LlyGPYF3oo@(*}yU+!+sb2r?!kVFNKxDuwu2(^UJCV68aMwmw!WO4qIA_#-3AVl$u zmahLKYY(8V(7IYVGTGuoJjuW&C_7D|?3n&4?_Mz3#aAkxWdK%lp+N%s#x?sl#ew8P zG?DvllI;y_Io){GjPwF%NRr5h{D_;xMRFQ1UkH&NWS(E+Z8JBEctM;YhTH=#?+#wB z5UP7?vKg_b%X6uDX^w-l#a1nVl^8hRk-H3X?ou*9PImpnDnRt?+|1<&$y7<>1v8uY z(S5~Px(p$1QH3a!o>sGpG0CV-=LiICUG@t1;%B`2UP`CskSfep!$ZwHVu(7DT4X!V zsLeRc21*H4p9m+RZsr8iXBkYyONvlJ2e$|j;>R#zkQ!eotYb25U2@YVy%4hNLr<(i zs7;(N+)UR8S(1*1CHXR};rD#*-MyCR3t{ z#tAVW7ESNnSDyE8slRIi2+`j|y#jUyv>X4->qKk{0@|;|qzKojg@O~%Fio{Ud^6n8 zW%i;)wtw=*_^5e#(1}9iq<8QydF><(qYtf+Tx!LhU!^rp{EQx;0OqAF z;ngl*7%EH*4Pqli972{ua5R}LRObTG^Zr~&?EFN>m zodq0Q>~1{useuV%hO4|zC)>`*ld|?LX5S%(staj~%|vh5<8%~9Ri;nL z6f^%6_azlU8&%9~7l$;U)H7C1UJ=4AN=((REJ*&NphwRl%`__@g~Tm)mZ+n2D!rMv z3Y?uZpUS2d0LZPCf0iONeVnbM-b_YVh7(rhn#hD3zWoFPE?{``w=n?Qohgp-@Niz& z1gIw#a*JRIpX8ld%x5A)>A@BntP`{)u=#^|%xpO0j6Lm3ZPD6XIIJ(Pss*y}lNQa$ zW*hqw=8h#+OEy|lxLJwgrxk!PqA(>jMau3fC{4TgY z64D5Y&+)Rkn3060{R)f!^vPy;^_*o}8psCr2a3E}>}#Xw)GDTJP3|qB?HtqdjY*pa zEPp%8%bU@Q?#4d_4P_NXN0T1F9QIRQ$|`S<{q8GlKBmw3)3VjAg;-?1#GQcA2OV1T z4vGW`8Xg;9>++?drCY=0rSsvs=*bqZoRpv6{PI3&@G~&;a!>;#aDn9Jv2`yen}>5wPuv40tvzPCnE0AETm;$?hvW~7zLunG!AfHoi= z&gpjkCmsdEdpyM0EP;En8SRB8EA6!XnMPGAJ$mjsq!;>hJ+(HGnLnrcHDflB9_Fko zd5b7UkFzE)6e#f9xTGoPvea6LEaTsCG4dhB?GLdSbbGL(0)s7BUlLmVW&NM!Dv$0r z@H>C*-?wj{)vgDEwyQ2>VeD2!aU1JRjQz>uU?#8Z_-n-`aCCF>|T-)4Wr7Ms) zVJI za}H`hJiHnek|w`q?F9APEH30sd{MoO+NO(#wd7 z(@thp)c@{YkuYzUun0T@Qvmm^K88pGN+E`8YU49Yh~la`na_pTNA$Jz5{fwkMI` z#jd>>;yy;Ldi(0_eTny=A5F|qJfci}X=p)1M*1YYAOd9KZI-o^X=#=XsFmgFcJh%OUWLRXhO5@|0 zmo(8jiTJ_xE6>imTr-ws`|Y*uTR<4lzIS8DJjNme8&dO4aST!o!*L?$QzlA$Yx@nE zYnhqPC+=Y05O>HP8yR!c5@!2#2t2a=CSdXrp$_$ zW0N#G1hY{>XS^~iei^B?GQ6*Z;P73Z57$pfW@0XHvJ#E?u}YZ8=YShALzNOT3yZmE zaq>9HzY}Vnl9QT4#N%F(&VLLWwdGh&w&FH%r~5vmzPFN1stlM;$3iR|TQp)}P~Ta$ zC^1jwkj0r`dj(qtG|aDqi5^@Wrtkbb$G`h7UvS3yp=XbOdJq{8!s?exE6`BL`yboy zLoq*BR@$>AG1n_Kc9EE@!EE<=w(mg5&+Na5O0*A#4lr_Inh9x`Mt@=z6XfztV|5`K zd19DSo(?iaRwH@csA>yjC!Q*B|x$A zhf=>N2u{kduK>+O?z&f!71v|B&6Aol-K7s9m}Sp%$J{bcwC9b)+_G@%R*pniRDVa9 znaT$dJm3LVpeZVs^?SPtxEQoV7pG3W{@k$9N2lXph`0A#lvJVx&dni#t0OR4-Pr&e zgmZ~P&4$|lu%m3lz+7${h6N4lG(K5_jh~jecmr2lV1P{H5qAduQn+RL4B|2V$25xC zk>)qc0N56PL93tG)(dPmp$kZ3Dk5mrm;h!4JudCn5b7r;ZUwjn5cCX{1G9#>)lH$U zBrbL3E}4YkwOlapKye|3m1<(aZK&84Sb%ijg(KELp+yMEW(BN5T`;sTJZ7d?Di4#M zk4#7;Gvv5-W+Br!AtM<7Ba+M&r6H*10F05@!uGOhjDbOWBJ3WpQbn*(b79Hz7%o>} zV`L*_LMew`)~vzUf`k1751w^P%qY>%KX(pg3QS~n`K)mHib=C*eWEgG1#?ycx6(gM z4~59dc}&jNOpFbUNbJQ7iQjS(h# zT?2heYoG>M%N~&9LzA+Zf<0%@NhdkDPc)L`;hpHgClV5gY&ESc5D8jEmrMLJ#xKHD zNy`MeAs}1J5hcyS_sJ`N?H7R3zJ#)M&nftAcu;XQcs4Ncz022xi95rH-vbuR=pn9v zA2DfJfCufZNP0-ZBJEyZl9e*C;TS!&Lac3qW_DM3+2eq1%@Aa%ot5;^_bT4+ zsv?u_k$NgD>EU?&5Rr6`&{MW9V7m$tNk0+#K~fb?BwgD==x>qwpYSte(x5Eq7Q5ff zh-bTIe9a&z8yYx1@H%2tFLgyE>~_T*W1BS&0_|gGkatH5y=^R%mDR z5(D-u(7`DYQTrosI5^vby?`U@oJxJN9r$@5V>*gXL&cvE5vLc{KMYo{*0ORE$mqF? z$PAux(MA=-#K^g&w$){j1&ujh#UT?6ZUh*zRP#ZPhS6n6 zWFu%ufA=uM;@Rs#J4mvjvF=kzW$wTYv)RNDaffgbZ-_qU@43uoW&>^yTbKWF?C*Tg zQwB3~xOFcDf<`zEG^v&7UZvF>(yZdo1!L>VxX4>|wFU8l_cj+G9UQo92Wn50i>c2h z0Au@iN{n;zNFzcpQS5AfW1L3 zQ?tvFq%ai6(|P5-h>_&j&cJ0bQ_%W@J!*SYfv|vYjIr|G1r`Pt%7k4$#+Vkbip&Dw zVN_$3SMhA{b&Sx|+KCoiNW^(Aw2K$O7l%Z7;bN*UU7l zT)>Zlf|Lk|yy{|qOB2Ip4!7=wV4wI|0)8!&!4|Y$XeKJOIX;+D$Kqj@!MfF$#2nHK zMJP{TrE7vaAmQW=h|A{o>UcZFA=2zbp3As!4v?OWBi?dr=c2Y=i7gqGpwFc#(L&4L zE7)J<2zIfk>C&M{2)SalsY-z@rwk%gCL*Vtea5_+w3KP^#woJe!rX&4C*#)K6{)VH zWZZ^0{CT*j`!4<;Rl+!kA0H$nI6W$K*%w4S%A;^e7&9Idv?g$EgTl-UzVMy9D5DZx zz%UY8VCnjMG8Gv%cfAUg#BDaos4&g@;|eC| z;&t%rh8WKu*@i`e_X87Hw)4s&oi}?6zf1~Yb#o#t0nI8v>yVt-2--EcmX@ML_LFkS za?WG?&Gcd=n;$al$|D{tx|%uhbuT8H)3PF})d+~Nj1?^HZ9vNz42jY<%v$@n-MVUu z>*ihsBZJn|U;J)iqGw_F2&1W`j!}rhoVBekkC0y=&f3S3#X9?UgIbaiS^;hXYjr-HgQ=~%-YH5)W1abr`=10QfK>;H_t$U_!g zf8Hk@qcVqM*y3u>&bM-a6(3>I%Xa2RX$Ka3!^0VpG>)Hf(K9+N&2n~eZo0dPk9hI9 z-4=^kXF-OD2h_!vvMqDG@=II>{_l~Q2UF2o%xC6EL2FE0{U6dM88FT|_SXF6W^p6P zP6i$>OWrtMib_<&XE$E8oUMz2Tx=tW*|0c^J`H}fL}~?Ha@5O}LHlm!H0PKlLHqd{ zA1Le~|3TUkPuShTeW&Vyrra1#6&rl2FqM{00=KAXFO;R~ zRP_=3P6_)jygVoqaY~=P)!`R#b1rr8p;Q;mw1`Z%Xj6lU%7!Sf332=v$tbD!%T(e9nI$39{Rp+rcEL>>U08)P7n~r}LJcYnj^XF? z2(^hYloM(LVJLKEghv9_4dQ0E+n@c?!c{-RPs}1$ffo|)(-GTEUSu4cTH<~_aR1~l z5bwF-8B!_qUL_(bOhk>foTxAmHHCs!J=bYL<14km^3XkFKg=pU9CJk z1-zdM+N0+?e|VY}-m@;)C+BYPmGMbPdp3=3nA9?JN`*Bm4aMT7Doc+nhbQMnGZPT8 z3)3gZrVNT#!l5a!Fm9HpbXE>E?f>RW+SWf2fzyl&X*sgUG+2Lv|OO_B>zz{3027VVrI45lm#`z4NfELVt3v(jb=)1ssB$(fO4VPY~SlDlTxqx^}XQ}A}h8*Mtis`OBA zo|xBiKINuc0D^79Jc$}$YZ&%o;Nn=Agu-x^$tRx2ysEXHCVZQ+11nMkGee{C@<9Gg zBB`IyU$Z9-Y2DMzi-gHJrq6@$u!U*;CydIS<>@e$kNZgqbF=&zZYIaYRm*wAnNf+s zoJOV%rF8$w*oF!~H<5Oh^dwVILVuD->mt5|PO+2DB5KUrz>E21#dxIsyDA^t5FoI= z3`;sWUf)Hgokilr-kE+b2FbB6eEOcKW1H~p2xqlC&^1j=^vHfmHp|29GNp7{A;gs^3iSv_+h4slRgCxm?d=_;m0)mS2$i-;Vlrwlz)S2arx|7~64c!b?hfsyM ztvElAR277r!%M<-^60G6N)B%2Mn+Ym1{jI5(>lI$MKQHqwnh|^2KyRN1}K-K;4jac zsYo=pfM&oel|gzS(icSqX(H>JgxMn6psV~Cd`}*bFB(H`Lzh>;NI!9r${XqWT02hP zwD6%wPxvifN!=f5n4)j0&^L7&r(G+-$0(_VTv?Wu97wR*x)$PFBeS$P1FyeYM;%CH z!GhKXd0iy5=j zk`p+N=SyDJz>xjrGCNhOAZ2-I;L15|8>N9)HMV-VTjhDORpT{A|6eY&R_tU#&j? zdi8H7a5@qh(uO+xP_!!+$rO552zzhYy11EF-Gr_xaP#z(Nm$AxUKw-J6yF5x1}osa za=WLPA*=MsTSS$P{k~z%>+{1?bW?Ck(RVUkj0ai!k+RWkR*;&HO5RR+uMPri0nZj=fd zWXoq%czj_JX7>j`L-?Caihm$Ms(Q!Fh5-I@Ml%#-fy-ko@c7x)@U55o^j6EPIIsU4 zNpCekdd-na%rZW30Jn9m(k)5SZ7Nk`ZZPEel1R`I*#^PV+r%w~-9j0BuO?-=|E^A@Q#60!|>4vo|w@cjY=b;!Nevvth_&Opr}aVjQ~>2X*{QB;(Y zg*4u_u&4_t6S&yaoP+3$(lka)qFi4&X$3pcAC1w;GpnT?<$?qjyIq;=MSV1W%Rpvc zpuXazE(pI|jBtA7?y{INX^;)IX3@0$usn@B8Mhl3)z+}-ptE*JLfxR;?p@``fo04- z;?9#jeGKy=`R#=+tDWti74}ge@q^3}NS*j6pf(Vg3&=@pk@`0#Ca~~LCzc!`wF7*E zOG!K+{_g&R;qm~_K`+UBvL_YwmA*GQc`ydwv0;(GdKX{6WzfptT?z4klZXwRz~zOQ zRQNU*CbQ6(ffc@$9x>f3ypsS|_B2a6G04RZe(i1lsvG|xs>Z}rqs-?k=2j-g^sGoq z0;mV5jNXPaoAa^gJZ#0Z_L@X~WdxZ=yNLK?Je$no$6U$ec_lHulL505OJkx%Tuv!J zc!Q5M@)O`+DbHm3{=gH5ZUr8`g{(SQc5L#{v3}b-$AhJnC0em&^|bedWCAKZFNwS_ zi2LW9^`xDdJLz|UJ0B@3N|@$j-zZ09!<14pQTpY&E{jILov4Hp&_qzVj$o?zgbHs9 zYmpzT(#P?Qcz86O=R-YokV{K&vVQ8e#eDpjM_9$ zSl*Utn|(={fej%(TxoH%hjB_05}fq}ae=+qZ4tzLMOcVsxKcu6)(u)lVGnv{xYw@@Emd19++d>V57Aad*=(ry-h!J`Tc&ogV3w00AqT!oY>WBS+lB_Alw$*#C; z{vuU8^J(R4=gh+CKa9115kOgFYpfQq{#PYZ2Inxoe*WpW2Clunf6tVj;K}3aW?x$R zqoCoZaAP_HnsS4^t#5bw`G}Ak>~9}mPv2%|X7dX-*du7Nct41Evc`txrH5S~FZ*Zw zIP-WDE7*n%QF+A-LqR6{v#@uWAHV)+eCUbNF)0)G8#5M-weA))d?$}pEa$SXa%*=5 z*Pw5+shrne#eP`JHp$I!F`s-^3j_0dSM97fNW)M5Ef-Guo4^|XM-e9{gug}%vi!F) z!Iro5c~)pwbtU1mqO$&M`}?f813gc~z0ACEd-N7T{+Uw?9zw;dKfBleN>ObF--?Q6fv~_a$043o`o>w>Z(%Ee#CU z)gtc6sefA-yd(zgfzHXwHq9=AOl2YYFZ{INo=?E*Jt>bR@|Sx?u0g?#z!*0pcrnr< zm#h|CY?tM~N68XHt$5O$XMh!%3o9+$tZ_ltrCqD=pS68R%8bTm^8C+j=KxZK8zp9@ zblu0U`?4B!sqgE3aArKw-6`9-%11u*HO#1+IoTYz@oPqWx_vEZ&UZ@>d@XHU^%MTy zDzCbgP!!+7vuCWT7wcdyN6?ziwC7;TiZ7LKbpo*^0hsRTe*GYDyTAhm0&N?Bf6ho>~PY@+vk+0!mt0N&Z zGvvx)FfbSx8_b%OAhJZ;vvtIyxZe|0JXeG|1C5ebBV?>Rl|upSbrFWLrl$flhDw#`y zdH4jAdLhb78Iuh?z;r@Ds!%!>@KZMP)$a`4U(pSmac7D>vQc>)V`>qa$v$xAI9j7a z*<=nTIJ8J?_Y3ZbT{7)uUifxhiu9-LT(gEmtj2DNM+X}aD&CeCLI%JXz>fiV3?R=P zL#QMSAi`7klL^SrDiMi)s8@yK;btbGinP<}qe}NNhnnnZ*;5>{nITo=h!(9R;Q-{Y zh}vU86QyOJ;Uyhz=f`s2882j)le!Jn=GC&@^KeF#v$8WRb(s~7>6Te7htPnH5hV=N zMqwfG3gg3ZJ3T-lbQdhV~$*?(hyOIxS6`x%33e-5fF+L9aiILC~ZjVxuW zuuDu}_A(uwmyoA}@pPrLs}xT;p8igln9;}4P2JGSByJA;L97)vb?3C@h%=F3>E*yg zTy;7Dlll}H@RsBFKZOKqt?i_|!Up_TaEu!3jdy?~$=K2WuA&J%+2AyptO%S}<43fj zT+JgQ;r$RIK_s;n7>InYC~LqI**Aeg^H_GqF{Y*1v50Vpf;eP zS!WB3UuR!qGIP>ykuwO(L(+;8Ywl?+Oq&xX(x|?qp}GNR?7|`9{PSCcHEED|o*_8& zLUBRSMOuc^3CmAJ+BMR0%N6fVdq~@oCd^B-(T-yjGFOmk4+V$PC{jN(Kzl3h5kgl{ zVsWu3i+Msj@PLc`gkQujTLd`5?F z6Mc5x4Efg)m^B7!+2?wi+hwjo_J+1Z`?qan;4Ob@9j|`X);yBR=M0?W0uNOSd_a z_TPfXg0@PGu+W}>!R_<2489nmAM{SUXC;$SYE`m;fFOxGT*)=XW9B|@d zuGBtCvAu9xgeF$euaxwYBgM{fInd$@{4tMMnN*m9Ay}#VlB>8HGa|5|bYPvJEt9F9 z#7Myuw?Vh(fNWP0E9AK#dx(gJVi}67;JoLL&f7~oli6!lz)cnk5kuA$3HaB`R?J}z zI&|xplRBkB+#}?Mz1E>q+-|%e*wkZ3xhKwsFwu`KtaxxM=5bO;5!=TbUgd0BChzSY zLF;fQ#`-kH-t=ZD0^i z`~|z4m>bC0@JPVK{|><$7UKaMN&+>q`qc0uf%OK?PW(egUnqI9XIp;#UFnVn-F76n z?)NwBi>kxHT3PH|kWH<;utXUB(~^LybM0TPNwXg+5k7Uj>Dx@({-rFFmTcJ$ooInG zFlr;uw5k~da#ydcKZ};t1aChd9!YIe$nA7>zB1)BPE$Yax;a)fJD z^AN2tb>KnF^=g>7u3n7iocs(}E(~})$d1+A<+G4%S_Z4++gC@~s}eiVx(Ry`4-Q$S zwDZQqoUh~&39)?%%IXMLFsD4^N(l)0j^MJ$geX2IT5V)jGHkL)fqJFJ503dq@ZKV;DTxKsN_2vf_$%g|KA_ipO*;0= z=L3HP6$6V%;N!LkqzxCBU8gRyRnqZ`@Fk&I)6W_h$lcoDWJ^_)XFT()5I<<B7D}i-%+LDL)dmUyem_l8FZz{I`eeX zQTPudQNvSras+K|du}itphsICvCpQMZ4?OVn|J;>e(Jb~^g4bf^V$`QABG=0j$7&h ze&_&3#_fl0pDNw zH>s*&;Xj1o?_in15rE7o_c25GyZb75>SsYqiq2(MeNTP5K-3dcvw#z69w*b9G^K1o zTM|#3n?oi+REX?sIL-(Z9uAdjrfm7N@9mmq`uJLDLr6%I|B?}nLBq(9kR@_5nfKWu zT1$|}MDH*_<%a|IX6O#H=nDnA&v3d2IWfgR@SgN$QzbhF|Ge7v#xSjy_A(hTm}f7P zM+OW|ReiLPCA)CXA8&fE#6wTAav)8+bjk4mY4`zo2^~HhQUo=}c@0S0*Qk98S6N>! za=!OoFDmb>XY_7C|0GASU*nsm z>hgUhO>%`!QnVY9o-2g4uocLa?EYd{+pOi|hu%peDE#k+z9F1_?2@NAKvH$XG&Z1jCixm+};0mLuP{tAP7 zLR!M5prsh`09~<$)&2pipI}j%R+vNlRsW_xJ%!U*%Kw5H^B3>;ypRxlL&XQlXk{|- zAkI%O+xz`BB|i3R+g(A`xKJ0GW}U@TzF84x>|>ZFN~g@6kRAt&d0&Kjz-c7Xge6PH=gK#nmL44VT>3#`ZwhMtNj~;JqJcq87bm9I z!s|;8E}u!?_S;a#yQ~j+s88XZ|4Mh>scRy13*OP4lfAb<Pg`)DLP_K6}3pXj` zvA%+`s6Tr+bT=o3Gf)6wf3c5c96 z+i=Q?F{-B>sY|AIH*s*!8P-)x_~J5@U;n}ls>1|r7wmEF#`En~+Use-U2lG1g6JC<5)Pxwf-~pUe@o zUd12oEIg=wT~wTT46@dOr4V%=Ul*}!cL}49u{Rfj>b#P`u`-Z2CbOWu9Fcw&M*EBK z?3ETyyY$XJ>aW~oy^NnV2!NX=Tr)s;-lX<-1o&#b^AM+w$#Ag~1f5+}cNU`=!3*7t zM+H65Z&5k9nj8<}2J!OBgDQA;O4E5dWWI7tHeeV7_u!AFG>Oy^U$sv@58S}m6Z$;PA z0OAb3Xt-`BWEQ*(IYWm>L(QBfEWY7_8Bw~tBbodh;)dcvv&f@KgvHSjr2hoG{yw+z zy5bq1p};rqV+mSor$MTaVGA0EJ`A`tMT6D}a8A&;W^`i8B1B`I@~e<5W4>!fi-mXd z8=2WM^bA~3-{a*YV@?rimHVZ$Hwk6sVF~A<{DK35lvQQV823c7?J0)5;%I$C%_{m1 zZeV0a5hM?objt5%!221(KEC+9QyUL#FY$J{^j;`R+zC78sBx*7_swzK^fah5?d_5@ z$Uhy54FJ|(E^E6~-qA7moz+#`w?ArPs_^yALU%gHIg*RmC<*r~!F%7TLE=P&_#v#t zc4;x^*9||VV>P^k(AAJ|XbE(G(rjqxXJDgQ(D^iA%l#U4epJg#2AH#@4+x#>`hdh) z(+7ZaX(Hg+EBc8?buZW}d=}Gk5+^s?N;^8GtP_6D3s4b#OKYJ44JUh!8ZQ#n1`lR_LlAr+|(&lZVs*Aa@QiS91l8-xfl!Jqab3NDu$b zkT?EGoD&e&(qZSRQWQeV%`>gMSd%#{c9D5ptj6UPYZf#dT!>g#@xh*22wrXpbNQFg zkTKJ@GUXG8oF9~e9N0*+yVDy-(Q&4uRRE}eTIYS(6XqMrGl*W`KY4^c6$7$W3L>A31d zjgUw?>!5J*(H&|lW`|T=2i~Jl4<{hZoM@Vk7ikJw1VS;Db-#y?DHZ!CViO!WD{wwM zI7>M4wBMNxJyyp<{nKR3)=9$CTbp$Ued}lq*#(8*2W#Vzn)99)`WXY8SJW9Svxjt0V zk`cZ^AzR9l-74%F5--5gSY-fFUPVSFgy?X}uh3LPv^-ep%nd8cL^2yp9FI-nv2k}F zQWU#_RAfXAx$9E5k!2`qf{{h6!Y~Pbud!klKL(>epsvB?F4RIe;#-mnYJjZnJ|F;=!4Q)Ee_RG&*?90XITCBvRt(%tBhcnehql?n#6eM5zax!i0z zr}LDUhO#7EJh92{T-WMLmR!0(OFVcT`JyEW66YG$0O61CR+exBvHjmZOJkpdn9<36 z?Ban4=R^RP8~6kJW~u!R!q4WJuV0;-y=P}$w^nYGc$KzjBI`=pR@Rw~MC>ONFgCZt zJPo-Os4}U)r?++F(MsZeeHeAGKvz3+??hi}k9^aNdN4>_%s1NAOvHZEiU|41##!C9 zvl_v{-O_A=y{TMD?-GiORuSKaB2RmTUbKB-*8NVEVo+C|$V}{sQ}ia(CsRA^LjPn{ z)RtpQ;q&oT1tqzkN2j~K%lH+t)#nF`3$7TRsEkMV6dv8Px=O#>$@D3``u%ggXSKr} z1qMePDr{uLY?2!rNHh&&hwa^HkaNbV%r*AeEgodVH;S|iarUWxG%n-nV#r>;0FCD1 z6%#mXu>R5U{^x9RAKb!Y#Y$Nq{@j@<%|!dj&cQk3%?GrM9mv z<(0qUeJN?<9d*n$IhdOaA$tTW1UtuF4a7H|8$TUU?_Xeu-qw9s!7r~MJ|)ZgW80GF z%hU;JDWi@05zyhq2(OQ~5zKdD^Vw6)oT-8Xfw}eCyZX(%YGQbd^AW^wy{u}cU(ml6 zW2{q5)ibWqt8pVQYhE-FiMtKR?iv=m1>m^qKKxlV&+_}NTxsG8RQIznUJpv%k2Y03 zK7tafn^|h5Py-S>)$P2M*6B{E(K?-2H3K7)s;!R|qj%xGr;5@4!F&Ha ze~F-UO0|E1Ou`ke{;e}i7SoNzt|rv#M-j5G>*=CH;=V?#E(oL~)< z0gDrGnE;siM9*@9H`M0@Y1NwJ=${v!65-i$D9uy=OsUjgf@4c%$X?=4=SS{fH`H<% zQptgA?In0J{kA}NN^m+O{W;LoAnS=*>z8D<40I6}F2BG_x#L4}d|CRxV8(M0UyB;E zWMHBcEph_YiZPVLwZRR|{vKg4zo*!pDgdASedlJ#m#%R+K+(S6?Q$Vr`jequ5J@!T zsXso`JYjHv(+Au+AkJD*v8LiJ+!@+OWUKd0GfmNT2-qM-8^cls;D-YZ?Y?F_&_xGY zY24pHH{gNx_E5V;aTVL4!g&IpY(X0o`3JD{sJt~qzq^p;zYz&!oC7>xXmeY8ARNve z13*w$WUFYbVlfnCZs5n$nKi~>iM$Iql6Jt1Komq7)inj^x~BF}q^-^$2>Uh^rfnL75Pv%#kHK)A&ntyAz7$W5fPB8!pPs%Q zG)IxsVv~};1;IBDV>>e5Dqf-w<873n0k^tc%QBZ|no})8_rf6mXi55$6+v03@ell4 z_OH;LNJ~)`-7HhIi$|L2(FL`s?JcWJO+bt{_@kiMRw-I+^(zrvXEJxWS2>G(bQk0W zgAv@Ii)1pu=#*G2xhH^_0tQKCFlb!*0hMs}B2W`2QxcqDsET^7BTJ!4_e`$>;Q!At Bsy+Y! diff --git a/res/syslinux/readme.txt b/res/syslinux/readme.txt index 46216b8f..a8c60fd8 100644 --- a/res/syslinux/readme.txt +++ b/res/syslinux/readme.txt @@ -1,3 +1,5 @@ -o ldlinux.bss and ldlinux.sys were extracted from syslinux-4.05/core/ - and chain.c32 from syslinux-4.05/com32/modules: - http://www.kernel.org/pub/linux/utils/boot/syslinux/ +o ldlinux.bss and ldlinux.sys were compiled from the syslinux git tree retreived + on 2012.02.13 from git://git.kernel.org/pub/scm/boot/syslinux/syslinux.git + with the included .diff applied to be able to use unmodified isolinux config. +o chain.c32 is from syslinux-4.05/com32/modules: + http://www.kernel.org/pub/linux/utils/boot/syslinux/ \ No newline at end of file diff --git a/res/syslinux/syslinux.diff b/res/syslinux/syslinux.diff new file mode 100644 index 00000000..389d12eb --- /dev/null +++ b/res/syslinux/syslinux.diff @@ -0,0 +1,29 @@ +diff --git a/core/fs/lib/loadconfig.c b/core/fs/lib/loadconfig.c +index c9652b6..4dfe1b9 100644 +--- a/core/fs/lib/loadconfig.c ++++ b/core/fs/lib/loadconfig.c +@@ -10,6 +10,8 @@ + * This searches for extlinux.conf and syslinux.cfg in the install + * directory, followed by a set of fallback directories. If found, + * set the current working directory to match. ++ * isolinux configuration values are added for the case where ISO ++ * content has been duplicated to a disk (typically bootable USB). + */ + int generic_load_config(void) + { +@@ -17,12 +19,15 @@ int generic_load_config(void) + NULL, /* CurrentDirName */ + "/boot/syslinux", + "/syslinux", ++ "/boot/isolinux", ++ "/isolinux", + "/", + NULL + }; + static const char *filenames[] = { + "extlinux.conf", + "syslinux.cfg", ++ "isolinux.cfg", + NULL + }; + diff --git a/src/format.c b/src/format.c index 538ca0a7..0c80f7ed 100644 --- a/src/format.c +++ b/src/format.c @@ -307,7 +307,7 @@ static BOOL WriteMBR(HANDLE hPhysicalDrive) fake_fd._ptr = (char*)hPhysicalDrive; fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; - if (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)) == DT_SYSLINUX) { + if (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)) == DT_ISO_FAT) { r = write_syslinux_mbr(&fake_fd); } else { r = write_95b_mbr(&fake_fd); @@ -321,10 +321,11 @@ out: /* * Process the Partition Boot Record */ -static BOOL WritePBR(HANDLE hLogicalVolume, BOOL bFreeDOS) +static BOOL WritePBR(HANDLE hLogicalVolume) { int i; FILE fake_fd = { 0 }; + BOOL bFreeDOS = (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)) == DT_FREEDOS); fake_fd._ptr = (char*)hLogicalVolume; fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; @@ -510,10 +511,10 @@ DWORD WINAPI FormatThread(LPVOID param) UpdateProgress(OP_FIX_MBR, -1.0f); if (IsChecked(IDC_DOS)) { - switch (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType))) { - case DT_FREEDOS: + switch(ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType))) { case DT_WINME: - case DT_ISO: + case DT_FREEDOS: + case DT_ISO_NTFS: // We still have a lock, which we need to modify the volume boot record // => no need to reacquire the lock... hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, FALSE); @@ -527,32 +528,14 @@ DWORD WINAPI FormatThread(LPVOID param) // after the FS is re-mounted by Windows UnmountDrive(hLogicalVolume); PrintStatus(0, TRUE, "Writing partition boot record..."); - if (!WritePBR(hLogicalVolume, ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)) == DT_FREEDOS)) { - // Errorcode has already been set + if (!WritePBR(hLogicalVolume)) { + if (!FormatStatus) + FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; goto out; } - - // We must close and unlock the volume to write files to it - safe_unlockclose(hLogicalVolume); - UpdateProgress(OP_DOS, -1.0f); - if (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)) != DT_ISO) { - PrintStatus(0, TRUE, "Copying DOS files..."); - if (!ExtractDOS(drive_name)) { - if (!FormatStatus) - FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; - goto out; - } - } else if (iso_path != NULL) { - PrintStatus(0, TRUE, "Copying ISO files..."); - drive_name[2] = 0; - if ( (!ExtractISO(iso_path, drive_name, FALSE)) && (!FormatStatus)) { - FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; - } - drive_name[2] = '\\'; - } break; - // Syslinux requires patching of the PBR after the files have been extracted - case DT_SYSLINUX: + case DT_ISO_FAT: + PrintStatus(0, TRUE, "Installing Syslinux..."); if (!InstallSyslinux(num, drive_name)) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INSTALL_FAILURE; } @@ -560,7 +543,7 @@ DWORD WINAPI FormatThread(LPVOID param) } } - // We issue a complete remount of the filesystem at the end on account of: + // We issue a complete remount of the filesystem at on account of: // - Ensuring the file explorer properly detects that the volume was updated // - Ensuring that an NTFS system will be reparsed so that it becomes bootable // TODO: on cancellation, this can leave the drive unmounted! @@ -573,9 +556,39 @@ DWORD WINAPI FormatThread(LPVOID param) uprintf("Failed to remount %s on %s\n", drive_guid, drive_name); // This will leave the drive unaccessible and must be flagged as an error FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_REMOUNT_VOLUME); + goto out; } } else { uprintf("Could not remount %s %s\n", drive_name, WindowsErrorString()); + // Try to continue regardless + } + } + + if (IsChecked(IDC_DOS)) { + UpdateProgress(OP_DOS, -1.0f); + switch(ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType))) { + case DT_WINME: + case DT_FREEDOS: + PrintStatus(0, TRUE, "Copying DOS files..."); + if (!ExtractDOS(drive_name)) { + if (!FormatStatus) + FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; + goto out; + } + break; + case DT_ISO_NTFS: + case DT_ISO_FAT: + // TODO: ISO_FAT: ensure the ISO doesn't have ldlinux.sys as it will break the existing one + if (iso_path != NULL) { + PrintStatus(0, TRUE, "Copying ISO files..."); + drive_name[2] = 0; + if ( (!ExtractISO(iso_path, drive_name, FALSE)) && (!FormatStatus)) { + FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; + goto out; + } + // TODO: ISO_FAT: create menu and stuff + } + break; } } diff --git a/src/iso.c b/src/iso.c index 2ef64b68..cb1700dc 100644 --- a/src/iso.c +++ b/src/iso.c @@ -63,7 +63,8 @@ RUFUS_ISO_REPORT iso_report; int64_t iso_blocking_status = -1; #define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0) static const char *psz_extract_dir; -static const char *isolinux_name = "isolinux", *bootmgr_name = "bootmgr"; +static const char *bootmgr_name = "bootmgr"; +static const char *isolinux_name[] = { "isolinux.cfg", "syslinux.cfg", "extlinux.conf"}; static uint64_t total_blocks, nb_blocks; static BOOL scan_only = FALSE; @@ -126,13 +127,7 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha goto out; } if (udf_is_dir(p_udf_dirent)) { - if (!scan_only) { - _mkdir(psz_fullpath); - } else { - // Check for an "isolinux\" dir in root (psz_path = "") - if ((*psz_path == 0) && (safe_strcmp(psz_basename, isolinux_name) == 0)) - iso_report.has_isolinux = TRUE; - } + if (!scan_only) _mkdir(psz_fullpath); p_udf_dirent2 = udf_opendir(p_udf_dirent); if (p_udf_dirent2 != NULL) { if (udf_extract_files(p_udf, p_udf_dirent2, &psz_fullpath[strlen(psz_extract_dir)])) @@ -144,6 +139,11 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha // Check for a "bootmgr" file in root (psz_path = "") if ((*psz_path == 0) && (safe_strcmp(psz_basename, bootmgr_name) == 0)) iso_report.has_bootmgr = TRUE; + // Check for a syslinux config file anywhere + for (i=0; i= FOUR_GIGABYTES) iso_report.has_4GB_file = TRUE; total_blocks += i_file_length/UDF_BLOCKSIZE; @@ -242,13 +242,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) continue; iso9660_name_translate(p_statbuf->filename, psz_basename); if (p_statbuf->type == _STAT_DIR) { - if (!scan_only) { - _mkdir(psz_fullpath); - } else { - // Check for an "isolinux\" dir in root (psz_path = "") - if ((*psz_path == 0) && (safe_strcmp(psz_basename, isolinux_name) == 0)) - iso_report.has_isolinux = TRUE; - } + if (!scan_only) _mkdir(psz_fullpath); if (iso_extract_files(p_iso, psz_iso_name)) goto out; } else { @@ -257,6 +251,11 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) // Check for a "bootmgr" file in root (psz_path = "") if ((*psz_path == 0) && (safe_strcmp(psz_basename, bootmgr_name) == 0)) iso_report.has_bootmgr = TRUE; + // Check for a syslinux config file anywhere + for (i=0; i= FOUR_GIGABYTES) iso_report.has_4GB_file = TRUE; total_blocks += i_file_length/ISO_BLOCKSIZE; diff --git a/src/rufus.c b/src/rufus.c index 08348ee6..4b9cc590 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -965,9 +965,10 @@ DWORD WINAPI ISOScanThread(LPVOID param) } uprintf("ISO size: %lld bytes, 4GB:%c, bootmgr:%c, isolinux:%c\n", iso_report.projected_size, iso_report.has_4GB_file?'Y':'N', iso_report.has_bootmgr?'Y':'N', iso_report.has_isolinux?'Y':'N'); - if (!iso_report.has_bootmgr) { - MessageBoxU(hMainDialog, "This version of Rufus supports only\n" - "ISO images that rely on 'bootmgr' - sorry.", "Unsupported ISO", MB_OK|MB_ICONINFORMATION); + if ((!iso_report.has_bootmgr) && (!iso_report.has_isolinux)) { + MessageBoxU(hMainDialog, "This version of Rufus only supports bootable ISOs\n" + "based on 'bootmgr' or 'isolinux'.\n" + "This ISO image doesn't appear to use either...", "Unsupported ISO", MB_OK|MB_ICONINFORMATION); safe_free(iso_path); } else { for (i=(int)safe_strlen(iso_path); (i>0)&&(iso_path[i]!='\\'); i--); @@ -1095,7 +1096,7 @@ void InitDialog(HWND hDlg) static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DRAWITEMSTRUCT* pDI; - int nDeviceIndex, fs; + int nDeviceIndex, fs, dt; DWORD DeviceNum; char str[MAX_PATH], tmp[128]; static UINT uDOSChecked = BST_CHECKED; @@ -1218,11 +1219,10 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA if (bWithFreeDOS) IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "FreeDOS"), DT_FREEDOS)); if (bWithSyslinux) - IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "Syslinux"), DT_SYSLINUX)); + IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "ISO Image"), DT_ISO_FAT)); } if (fs == FS_NTFS) { - // Only allow ISO with NTFS for the time being - IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "ISO Image"), DT_ISO)); + IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "ISO Image"), DT_ISO_NTFS)); } IGNORE_RETVAL(ComboBox_SetCurSel(hDOSType, (bWithFreeDOS && (fs != FS_NTFS))?1:0)); if (!IsWindowEnabled(hDOS)) { @@ -1234,7 +1234,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA case IDC_DOSTYPE: if (HIWORD(wParam) != CBN_SELCHANGE) break; - if (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)) != DT_ISO) { + dt = (int)ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)); + if ((dt != DT_ISO_NTFS) && (dt != DT_ISO_FAT)) { ShowWindow(hSelectISO, SW_HIDE); break; } @@ -1272,7 +1273,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA FormatStatus = 0; nDeviceIndex = ComboBox_GetCurSel(hDeviceList); if (nDeviceIndex != CB_ERR) { - if (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)) == DT_ISO) { + dt = (int)ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)); + if ((dt == DT_ISO_NTFS) || (dt == DT_ISO_FAT)) { if (iso_path == NULL) { MessageBoxA(hMainDialog, "Please click on the disc button to select a bootable ISO,\n" "or uncheck the \"Create a bootable disk...\" checkbox.", @@ -1284,6 +1286,15 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA "for the selected target.", "ISO image too big...", MB_OK|MB_ICONERROR); break; } + if ((dt == DT_ISO_NTFS) && (!iso_report.has_bootmgr)) { + MessageBoxA(hMainDialog, "Only 'bootmgr' based ISO " + "images can be used with NTFS.", "Unsupported ISO...", MB_OK|MB_ICONERROR); + break; + } else if ((dt == DT_ISO_FAT) && (!iso_report.has_isolinux)) { + MessageBoxA(hMainDialog, "Only 'isolinux' based ISO " + "images can be used with FAT.", "Unsupported ISO...", MB_OK|MB_ICONERROR); + break; + } } GetWindowTextA(hDeviceList, tmp, sizeof(tmp)); safe_sprintf(str, sizeof(str), "WARNING: ALL DATA ON DEVICE %s\r\nWILL BE DESTROYED.\r\n" diff --git a/src/rufus.h b/src/rufus.h index 13e66006..cb88fd5b 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -125,8 +125,8 @@ enum { enum dos_type { DT_WINME = 0, DT_FREEDOS, - DT_SYSLINUX, - DT_ISO, + DT_ISO_FAT, + DT_ISO_NTFS, DT_MAX }; diff --git a/src/rufus.rc b/src/rufus.rc index 1dd4febc..004a26b6 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 278 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.1.0.131" +CAPTION "Rufus v1.1.0.132" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,236,50,14 @@ -71,7 +71,7 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP CONTROL "http://rufus.akeo.ie",IDC_ABOUT_RUFUS_URL, "SysLink",WS_TABSTOP,46,47,114,9 - LTEXT "Version 1.1.0 (Build 131)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.1.0 (Build 132)",IDC_STATIC,46,19,78,8 PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP EDITTEXT IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 @@ -171,7 +171,6 @@ BEGIN "#if defined(WITH_SYSLINUX)\r\n" "IDR_SL_LDLINUX_BSS RCDATA ""../res/syslinux/ldlinux.bss""\r\n" "IDR_SL_LDLINUX_SYS RCDATA ""../res/syslinux/ldlinux.sys""\r\n" - "IDR_SL_CHAIN_C32 RCDATA ""../res/syslinux/chain.c32""\r\n" "#endif\r\n" "\r\n" "// Must reference a manifest for visual styles and elevation\r\n" @@ -223,8 +222,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,0,131 - PRODUCTVERSION 1,1,0,131 + FILEVERSION 1,1,0,132 + PRODUCTVERSION 1,1,0,132 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -241,13 +240,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.1.0.131" + VALUE "FileVersion", "1.1.0.132" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.1.0.131" + VALUE "ProductVersion", "1.1.0.132" END END BLOCK "VarFileInfo" @@ -309,7 +308,6 @@ IDR_FD_EGA18_CPX RCDATA "../res/freedos/ega18.cpx" #if defined(WITH_SYSLINUX) IDR_SL_LDLINUX_BSS RCDATA "../res/syslinux/ldlinux.bss" IDR_SL_LDLINUX_SYS RCDATA "../res/syslinux/ldlinux.sys" -IDR_SL_CHAIN_C32 RCDATA "../res/syslinux/chain.c32" #endif // Must reference a manifest for visual styles and elevation diff --git a/src/syslinux.c b/src/syslinux.c index e46d0581..c4ff8b33 100644 --- a/src/syslinux.c +++ b/src/syslinux.c @@ -29,6 +29,7 @@ #include "resource.h" #include "syslinux.h" +#include "syslxfs.h" #include "libfat.h" #include "setadv.h" @@ -199,7 +200,7 @@ BOOL InstallSyslinux(DWORD num, const char* drive_name) } /* Make the syslinux boot sector */ - syslinux_make_bootsect(sectbuf); + syslinux_make_bootsect(sectbuf, VFAT); /* Write boot sector back */ if (SetFilePointer(d_handle, 0, NULL, FILE_BEGIN) != 0 || diff --git a/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj b/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj index d47eabe1..4d0e1a0c 100644 --- a/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj +++ b/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj @@ -1,4 +1,4 @@ - + @@ -21,10 +21,12 @@ + + - + diff --git a/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj.filters b/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj.filters index 029884f4..5cc1daa8 100644 --- a/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj.filters +++ b/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -20,9 +20,15 @@ Header Files + + Header Files + + + Header Files + - + Source Files diff --git a/src/syslinux/libinstaller/.msvc/libinstaller_sources b/src/syslinux/libinstaller/.msvc/libinstaller_sources index 10b20516..299870cf 100644 --- a/src/syslinux/libinstaller/.msvc/libinstaller_sources +++ b/src/syslinux/libinstaller/.msvc/libinstaller_sources @@ -12,6 +12,6 @@ USE_MSVCRT=1 TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ $(SDK_LIB_PATH)\user32.lib -SOURCES=fat.c \ +SOURCES=fs.c \ setadv.c \ syslxmod.c \ No newline at end of file diff --git a/src/syslinux/libinstaller/Makefile.am b/src/syslinux/libinstaller/Makefile.am index 722c167c..21249cde 100644 --- a/src/syslinux/libinstaller/Makefile.am +++ b/src/syslinux/libinstaller/Makefile.am @@ -1,4 +1,4 @@ noinst_LIBRARIES = libinstaller.a -libinstaller_a_SOURCES = fat.c setadv.c syslxmod.c +libinstaller_a_SOURCES = fs.c setadv.c syslxmod.c libinstaller_a_CFLAGS = $(AM_CFLAGS) \ No newline at end of file diff --git a/src/syslinux/libinstaller/Makefile.in b/src/syslinux/libinstaller/Makefile.in index 67b57790..703e4573 100644 --- a/src/syslinux/libinstaller/Makefile.in +++ b/src/syslinux/libinstaller/Makefile.in @@ -52,7 +52,7 @@ am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ libinstaller_a_AR = $(AR) $(ARFLAGS) libinstaller_a_LIBADD = -am_libinstaller_a_OBJECTS = libinstaller_a-fat.$(OBJEXT) \ +am_libinstaller_a_OBJECTS = libinstaller_a-fs.$(OBJEXT) \ libinstaller_a-setadv.$(OBJEXT) \ libinstaller_a-syslxmod.$(OBJEXT) libinstaller_a_OBJECTS = $(am_libinstaller_a_OBJECTS) @@ -167,7 +167,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LIBRARIES = libinstaller.a -libinstaller_a_SOURCES = fat.c setadv.c syslxmod.c +libinstaller_a_SOURCES = fs.c setadv.c syslxmod.c libinstaller_a_CFLAGS = $(AM_CFLAGS) all: all-am @@ -225,13 +225,13 @@ distclean-compile: $(AM_V_CC) @AM_BACKSLASH@ $(COMPILE) -c `$(CYGPATH_W) '$<'` -libinstaller_a-fat.o: fat.c +libinstaller_a-fs.o: fs.c $(AM_V_CC) @AM_BACKSLASH@ - $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libinstaller_a_CFLAGS) $(CFLAGS) -c -o libinstaller_a-fat.o `test -f 'fat.c' || echo '$(srcdir)/'`fat.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libinstaller_a_CFLAGS) $(CFLAGS) -c -o libinstaller_a-fs.o `test -f 'fs.c' || echo '$(srcdir)/'`fs.c -libinstaller_a-fat.obj: fat.c +libinstaller_a-fs.obj: fs.c $(AM_V_CC) @AM_BACKSLASH@ - $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libinstaller_a_CFLAGS) $(CFLAGS) -c -o libinstaller_a-fat.obj `if test -f 'fat.c'; then $(CYGPATH_W) 'fat.c'; else $(CYGPATH_W) '$(srcdir)/fat.c'; fi` + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libinstaller_a_CFLAGS) $(CFLAGS) -c -o libinstaller_a-fs.obj `if test -f 'fs.c'; then $(CYGPATH_W) 'fs.c'; else $(CYGPATH_W) '$(srcdir)/fs.c'; fi` libinstaller_a-setadv.o: setadv.c $(AM_V_CC) @AM_BACKSLASH@ diff --git a/src/syslinux/libinstaller/fat.c b/src/syslinux/libinstaller/fs.c similarity index 52% rename from src/syslinux/libinstaller/fat.c rename to src/syslinux/libinstaller/fs.c index 9cde00c2..179629e9 100644 --- a/src/syslinux/libinstaller/fat.c +++ b/src/syslinux/libinstaller/fs.c @@ -1,7 +1,8 @@ /* ----------------------------------------------------------------------- * * - * Copyright 1998-2008 H. Peter Anvin - All Rights Reserved - * Copyright 2009-2010 Intel Corporation; author H. Peter Anvin + * Copyright 1998-2011 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2011 Intel Corporation; author H. Peter Anvin + * Copyright 2011 Paulo Alcantara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -12,7 +13,7 @@ * ----------------------------------------------------------------------- */ /* - * fat.c - Initial sanity check for FAT-based installers + * fs.c - Generic sanity check for FAT/NTFS-based installers */ #define _XOPEN_SOURCE 500 /* Required on glibc 2.x */ @@ -25,45 +26,41 @@ #include "syslinux.h" #include "syslxint.h" +#include "syslxcom.h" +#include "syslxfs.h" -void syslinux_make_bootsect(void *bs) +void syslinux_make_bootsect(void *bs, int fs_type) { - struct boot_sector *bootsect = bs; - const struct boot_sector *sbs = - (const struct boot_sector *)boot_sector; + if (fs_type == VFAT) { + struct fat_boot_sector *bootsect = bs; + const struct fat_boot_sector *sbs = + (const struct fat_boot_sector *)boot_sector; - memcpy(&bootsect->bsHead, &sbs->bsHead, bsHeadLen); - memcpy(&bootsect->bsCode, &sbs->bsCode, bsCodeLen); + memcpy(&bootsect->FAT_bsHead, &sbs->FAT_bsHead, FAT_bsHeadLen); + memcpy(&bootsect->FAT_bsCode, &sbs->FAT_bsCode, FAT_bsCodeLen); + } else if (fs_type == NTFS) { + struct ntfs_boot_sector *bootsect = bs; + const struct ntfs_boot_sector *sbs = + (const struct ntfs_boot_sector *)boot_sector; + + memcpy(&bootsect->NTFS_bsHead, &sbs->NTFS_bsHead, NTFS_bsHeadLen); + memcpy(&bootsect->NTFS_bsCode, &sbs->NTFS_bsCode, NTFS_bsCodeLen); + } } -/* - * Check to see that what we got was indeed an MS-DOS boot sector/superblock; - * Return NULL if OK and otherwise an error message; - */ -const char *syslinux_check_bootsect(const void *bs) +static const char *check_fat_bootsect(const void *bs, int *fs_type) { int sectorsize; + const struct fat_boot_sector *sectbuf = bs; long long sectors, fatsectors, dsectors; long long clusters; int rootdirents, clustersize; - const struct boot_sector *sectbuf = bs; - - /* Must be 0xF0 or 0xF8..0xFF */ - if (get_8(§buf->bsMedia) != 0xF0 && get_8(§buf->bsMedia) < 0xF8) - return "invalid media signature (not a FAT filesystem?)"; sectorsize = get_16(§buf->bsBytesPerSec); - if (sectorsize == SECTOR_SIZE) - ; /* ok */ - else if (sectorsize >= 512 && sectorsize <= 4096 && - (sectorsize & (sectorsize - 1)) == 0) - return "unsupported sectors size"; - else - return "impossible sector size"; clustersize = get_8(§buf->bsSecPerClust); if (clustersize == 0 || (clustersize & (clustersize - 1))) - return "impossible cluster size"; + return "impossible cluster size on an FAT volume"; sectors = get_16(§buf->bsSectors); sectors = sectors ? sectors : get_32(§buf->bsHugeSectors); @@ -79,16 +76,19 @@ const char *syslinux_check_bootsect(const void *bs) dsectors -= (rootdirents + sectorsize / 32 - 1) / sectorsize; if (dsectors < 0) - return "negative number of data sectors"; - - if (fatsectors == 0) - return "zero FAT sectors"; + return "negative number of data sectors on an FAT volume"; clusters = dsectors / clustersize; + fatsectors = get_16(§buf->bsFATsecs); + fatsectors = fatsectors ? fatsectors : get_32(§buf->bs32.FATSz32); + fatsectors *= get_8(§buf->bsFATs); + + if (!fatsectors) + return "zero FAT sectors"; + if (clusters < 0xFFF5) { /* FAT12 or FAT16 */ - if (!get_16(§buf->bsFATsecs)) return "zero FAT sectors (FAT12/16)"; @@ -100,10 +100,10 @@ const char *syslinux_check_bootsect(const void *bs) if (clusters < 0xFF5) return "less than 4084 clusters but claims FAT16"; } else if (!memcmp(§buf->bs16.FileSysType, "FAT32 ", 8)) { - return "less than 65525 clusters but claims FAT32"; + return "less than 65525 clusters but claims FAT32"; } else if (memcmp(§buf->bs16.FileSysType, "FAT ", 8)) { - static char fserr[] = - "filesystem type \"????????\" not supported"; + static char fserr[] = "filesystem type \"????????\" not " + "supported"; memcpy(fserr + 17, §buf->bs16.FileSysType, 8); return fserr; } @@ -119,8 +119,54 @@ const char *syslinux_check_bootsect(const void *bs) memcmp(§buf->bs32.FileSysType, "FAT32 ", 8)) return "missing FAT32 signature"; } else { - return "impossibly large number of clusters"; + return "impossibly large number of clusters on an FAT volume"; } + if (fs_type) + *fs_type = VFAT; + return NULL; } + +static const char *check_ntfs_bootsect(const void *bs, int *fs_type) +{ + const struct ntfs_boot_sector *sectbuf = bs; + + if (memcmp(§buf->bsOemName, "NTFS ", 8) && + memcmp(§buf->bsOemName, "MSWIN4.0", 8) && + memcmp(§buf->bsOemName, "MSWIN4.1", 8)) + return "unknown OEM name but claims NTFS"; + + if (fs_type) + *fs_type = NTFS; + + return NULL; +} + +const char *syslinux_check_bootsect(const void *bs, int *fs_type) +{ + uint8_t media_sig; + int sectorsize; + const struct fat_boot_sector *sectbuf = bs; + const char *retval; + + media_sig = get_8(§buf->bsMedia); + /* Must be 0xF0 or 0xF8-0xFF for FAT/NTFS volumes */ + if (media_sig != 0xF0 && media_sig < 0xF8) + return "invalid media signature (not an FAT/NTFS volume?)"; + + sectorsize = get_16(§buf->bsBytesPerSec); + if (sectorsize == SECTOR_SIZE) ; /* ok */ + else if (sectorsize >= 512 && sectorsize <= 4096 && + (sectorsize & (sectorsize - 1)) == 0) + return "unsupported sectors size"; + else + return "impossible sector size"; + + if (ntfs_check_zero_fields((struct ntfs_boot_sector *)bs)) + retval = check_ntfs_bootsect(bs, fs_type); + else + retval = check_fat_bootsect(bs, fs_type); + + return retval; +} diff --git a/src/syslinux/libinstaller/setadv.c b/src/syslinux/libinstaller/setadv.c index 425fdefd..838678bd 100644 --- a/src/syslinux/libinstaller/setadv.c +++ b/src/syslinux/libinstaller/setadv.c @@ -20,6 +20,7 @@ * Return 0 on success, -1 on error, and set errno. * */ +//#define _GNU_SOURCE #include #include @@ -28,6 +29,8 @@ #include #include #include "syslxint.h" +#include "syslxcom.h" +#include "syslxfs.h" unsigned char syslinux_adv[2 * ADV_SIZE]; diff --git a/src/syslinux/libinstaller/syslinux.h b/src/syslinux/libinstaller/syslinux.h index 39564ea7..a4832b59 100644 --- a/src/syslinux/libinstaller/syslinux.h +++ b/src/syslinux/libinstaller/syslinux.h @@ -14,7 +14,6 @@ #define SYSLINUX_H #include -#include #include "advconst.h" #include "setadv.h" @@ -41,10 +40,10 @@ extern const int syslinux_mbr_mtime; #define SECTOR_SIZE (1 << SECTOR_SHIFT) /* This takes a boot sector and merges in the syslinux fields */ -void syslinux_make_bootsect(void *); +void syslinux_make_bootsect(void *bs, int fs_type); /* Check to see that what we got was indeed an MS-DOS boot sector/superblock */ -const char *syslinux_check_bootsect(const void *bs); +const char *syslinux_check_bootsect(const void *bs, int *fs_type); /* This patches the boot sector and ldlinux.sys based on a sector map */ typedef uint64_t sector_t; diff --git a/src/syslinux/libinstaller/syslxcom.h b/src/syslinux/libinstaller/syslxcom.h new file mode 100644 index 00000000..cde8ce58 --- /dev/null +++ b/src/syslinux/libinstaller/syslxcom.h @@ -0,0 +1,6 @@ +#ifndef _H_SYSLXCOM_ +#define _H_SYSLXCOM_ + +/* Rufus placeholder */ + +#endif diff --git a/src/syslinux/libinstaller/syslxfs.h b/src/syslinux/libinstaller/syslxfs.h new file mode 100644 index 00000000..40ed56da --- /dev/null +++ b/src/syslinux/libinstaller/syslxfs.h @@ -0,0 +1,26 @@ +/* + * Copyright 2011 Paulo Alcantara + * + * This program 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, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#ifndef _SYSLXFS_H_ +#define _SYSLXFS_H_ + +/* Global fs_type for handling fat, ntfs, ext2/3/4 and btrfs */ +enum filesystem { + NONE, + EXT2, + BTRFS, + VFAT, + NTFS, +}; + +//extern int fs_type; + +#endif /* _SYSLXFS_H_ */ diff --git a/src/syslinux/libinstaller/syslxint.h b/src/syslinux/libinstaller/syslxint.h index 749c74be..f6d9a4ef 100644 --- a/src/syslinux/libinstaller/syslxint.h +++ b/src/syslinux/libinstaller/syslxint.h @@ -2,6 +2,7 @@ * * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved * Copyright 2009-2011 Intel Corporation; author: H. Peter Anvin + * Copyright 2011 Paulo Alcantara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -193,7 +194,7 @@ struct syslinux_extent { }; /* FAT bootsector format, also used by other disk-based derivatives */ -struct boot_sector { +struct fat_boot_sector { uint8_t bsJump[3]; char bsOemName[8]; uint16_t bsBytesPerSec; @@ -241,15 +242,70 @@ struct boot_sector { uint16_t bsForwardPtr; uint16_t bsSignature; }; + +/* NTFS bootsector format */ +struct ntfs_boot_sector { + uint8_t bsJump[3]; + char bsOemName[8]; + uint16_t bsBytesPerSec; + uint8_t bsSecPerClust; + uint16_t bsResSectors; + uint8_t bsZeroed_0[3]; + uint16_t bsZeroed_1; + uint8_t bsMedia; + uint16_t bsZeroed_2; + uint16_t bsUnused_0; + uint16_t bsUnused_1; + uint32_t bsUnused_2; + uint32_t bsZeroed_3; + uint32_t bsUnused_3; + uint64_t bsTotalSectors; + uint64_t bsMFTLogicalClustNr; + uint64_t bsMFTMirrLogicalClustNr; + uint8_t bsClustPerMFTrecord; + uint8_t bsUnused_4[3]; + uint8_t bsClustPerIdxBuf; + uint8_t bsUnused_5[3]; + uint64_t bsVolSerialNr; + uint32_t bsUnused_6; + + uint8_t Code[420]; + + uint32_t bsMagic; + uint16_t bsForwardPtr; + uint16_t bsSignature; +}; #pragma pack(pop) -#define bsHead bsJump -#define bsHeadLen offsetof(struct boot_sector, bsBytesPerSec) -#define bsCode bs32.Code /* The common safe choice */ -#define bsCodeLen (offsetof(struct boot_sector, bsSignature) - \ - offsetof(struct boot_sector, bsCode)) +#define FAT_bsHead bsJump +#define FAT_bsHeadLen offsetof(struct fat_boot_sector, bsBytesPerSec) +#define FAT_bsCode bs32.Code /* The common safe choice */ +#define FAT_bsCodeLen (offsetof(struct fat_boot_sector, bsSignature) - \ + offsetof(struct fat_boot_sector, FAT_bsCode)) -static inline int fat_check_sb_fields(const struct boot_sector *sb) +#define NTFS_bsHead bsJump +#define NTFS_bsHeadLen offsetof(struct ntfs_boot_sector, bsOemName) +#define NTFS_bsCode Code +#define NTFS_bsCodeLen (offsetof(struct ntfs_boot_sector, bsSignature) - \ + offsetof(struct ntfs_boot_sector, NTFS_bsCode)) + +/* Check if there are specific zero fields in an NTFS boot sector */ +static inline int ntfs_check_zero_fields(const struct ntfs_boot_sector *sb) +{ + return !sb->bsResSectors && (!sb->bsZeroed_0[0] && !sb->bsZeroed_0[1] && + !sb->bsZeroed_0[2]) && !sb->bsZeroed_1 && !sb->bsZeroed_2 && + !sb->bsZeroed_3; +} + +static inline int ntfs_check_sb_fields(const struct ntfs_boot_sector *sb) +{ + return ntfs_check_zero_fields(sb) && + (!memcmp(sb->bsOemName, "NTFS ", 8) || + !memcmp(sb->bsOemName, "MSWIN4.0", 8) || + !memcmp(sb->bsOemName, "MSWIN4.1", 8)); +} + +static inline int fat_check_sb_fields(const struct fat_boot_sector *sb) { return sb->bsResSectors && sb->bsFATs && (!memcmp(sb->bs16.FileSysType, "FAT12 ", 8) || diff --git a/src/syslinux/libinstaller/syslxmod.c b/src/syslinux/libinstaller/syslxmod.c index 035fa97c..08acb075 100644 --- a/src/syslinux/libinstaller/syslxmod.c +++ b/src/syslinux/libinstaller/syslxmod.c @@ -110,7 +110,7 @@ int syslinux_patch(const sector_t *sectp, int nsectors, int nsect = ((boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT) + 2; uint32_t csum; int i, dw, nptrs; - struct boot_sector *sbs = (struct boot_sector *)boot_sector; + struct fat_boot_sector *sbs = (struct fat_boot_sector *)boot_sector; uint64_t *advptrs; if (nsectors < nsect)