From 9971e5924c81abb0fbfed072682dde8ac8056462 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 13 May 2022 16:20:04 +0200 Subject: [PATCH] Partition Wizard compiled bytecode --- tasmota/berry/modules/Partition_Manager.tapp | Bin 16837 -> 17005 bytes .../modules/Partition_Manager/partition.bec | Bin 16468 -> 16636 bytes tasmota/berry/modules/Partition_Wizard.tapp | Bin 0 -> 16175 bytes .../Partition_Wizard/partition_wizard.bec | Bin 0 -> 15732 bytes tasmota/berry/modules/Partition_wizard.tapp | Bin 31911 -> 16175 bytes tasmota/berry/modules/partition.be | 530 +++++++++++++++--- .../partition_wizard.be | 3 +- 7 files changed, 443 insertions(+), 90 deletions(-) create mode 100644 tasmota/berry/modules/Partition_Wizard.tapp create mode 100644 tasmota/berry/modules/Partition_Wizard/partition_wizard.bec rename tasmota/berry/modules/{Partition_Wizard => }/partition_wizard.be (99%) diff --git a/tasmota/berry/modules/Partition_Manager.tapp b/tasmota/berry/modules/Partition_Manager.tapp index 8e2c8b91b5dd2f8b33e4bd39089a6169fb7feb6c..013bd556ed34a419418ff93590f13532cc06a35f 100644 GIT binary patch delta 2669 zcmb_e-D@0G6hHH^^F6b>$z(H`Owvi5v}+pEY24N^hBSdHiV^a#(x{;(trhd233ZDr zjBfoNWYv_(gNW#Z0ShV=f)ISxCw&q05Aew+9|Rwz>+kN&>iUU-3(Glk&&NIIcg{Wc ze(@6b!^@nxdcPoQ#D4d^_r^7ILVnmhcj3Hw?%JulZ`*kBlloio=Rf_tM8y6kd9<^6 zxv|yQ+J0*G!ljE3)>RU|dE)sC_+R_*v{)cIb?v(kPN~E<$>aBlq(fB@+r*18x!Pf| zpnxx}lc>Zcf$>UA#2*rgSIY;Va^H=$6rN@g3@rDF*Y-)Y_64EDtYVG^8bqZPQpBsG zoUIiEyDgEoMxq_d;EA_m1ys$~7_a5L&Oxqt*gexR@^w?S6HB*~qHYJv3RRlSsFVxK ze`7QNok77%m@^wZ+Za(_9ZJ8R8Yx-7;q>Um?aP@PO#QioJY;n9*EQXMuI}_e}t_~v*>aqx6g6U0n1`ETR#|^evad}pGn_6?tvV9cKjW_ zHN?}K-SYmsX1>Jn*ZUiK7QLvFy&($@n%oCiPTXy9-LVC78>;G{T23r!P9T!o)Cx{p zXL?$Ie4V%@InoW2DQP~s9>(OY$cE<$G~Textkg=;vqc(*v4@JHwX`aXy;z1VN8W~3 z@NpObhBkwB9|3rAS%odz1Z_B=ddXlh^JSxbhVu3dIli^SvZ>@JX}&L;N?$fNJ0taB zIFT%8kHX2rk+P4h{Maq~d!uH69-Xdh1A(EIe6dJJ>!3zX6)NF4vz9S@k4J}iW@by^ z$3|MxjXye6^uXrmXhYV5pg>2Fb1s*}yACYc!1O%W3 zin{3T4ypkH4dRKM+CqTr;Y$qSAJH|17P6nrv%i4sZ&C9BrQ1GEbTfcM44=00>mYL4 zQ#mp>J7Yk_Pvnxf=M}S!5JcnH14xQxtYsPZvPZ_vDrBmfAuv_;ea!XA=B-#fqNj87 zlb)q#etL+Wp$yrn!GO~5=ls?r8x>-R8qdUPCA4{(YfN)tVpPIFqPgbrLfD>RI+cZW z8dzGN=FTQSE;fLeQVD_5T=TXrN^^DCD8^!CcT^9PBYG{tXd>gZyW0_ZGIw{>gv{*8 z##@=t4wcbjcTqGJ#{qK)m_xvvQCkQBa~A093}&D_nk+iQVCuJ(WUCh8l8TK+$R_ zS{SS8#_gjmg_hRHIg1kAixRCQWYl64B~qydiwNjIE=I7Z#V5HavD^ryo=2&>d?3?2 zN*%RB=uOetHFED=KM6n6+$wxUvBk>mL^yHtP0fu^_W9;qx9k}7PSjGYZrvl)eIY4& z5n0{3vs)m7jMW`7vnLxz*&(Y$D0_EJw7O-FkZOdoXVgaEL%qOJ_S>-`N8B_Qa{_driURgfIUWMuV%f585j7{hlAI<`h delta 2617 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 E0HZPN`Tzg` delta 2458 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

!T=n8KX7U-W0>^OyMEn|~%S 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 MLchkfxx#n<1GPsQyZ`_I literal 0 HcmV?d00001 diff --git a/tasmota/berry/modules/Partition_Wizard/partition_wizard.bec b/tasmota/berry/modules/Partition_Wizard/partition_wizard.bec new file mode 100644 index 0000000000000000000000000000000000000000..843fe128c1416ba47658cbab1637631184b24934 GIT binary patch literal 15732 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 O7GKz2__j?h`F{Y8)TQwN literal 0 HcmV?d00001 diff --git a/tasmota/berry/modules/Partition_wizard.tapp b/tasmota/berry/modules/Partition_wizard.tapp index 9c9f5cd3036d5e7d9b2a1d028a5e6d9fdf8ea0d0..f98760d4f0ca96332dc7a63395eea7115ef709b6 100644 GIT binary patch literal 16175 zcmcIr-)|e)bv_&pheL8mjwo8DWm>+`QkK?{En3!Y9j`2V9eb0_YS+q|#(Gf|6h)3C z))Yx_Mr%1C8Wl(pJqWEI477bq0Rs(?v@nW3=%HwVzVxB!V_*7D^tC{dRljp*h8$6( zchR&m=(%&}&i#3Qe&@{ECt)>C{P)%4Uzh&rXy-FB!j-4 zc$mvNk9CZ34=_HN=9#6M<21PYgPFn&%Ek zdreCGHL0oB;jqcm?S?4hU~;RZs|RY-t&4=SM;hgyf=aqklu5~UbzEa!okkP;aomH{ zWE%tJWH^7w?Ng+*`B}<)mJZ>4J&$e4cFjO}EKuh6Gv52-DD!xj>;coL8KdXcrfqe; zvO1wFRQJNWuB+%j#YhDZg=Wm)f?8fRV!DjRm-;Ves7P>Bvo5Y$7(ud z+rb9nNP5qNOU7oV-^6Ox(C$UUGNZIpvCEatwyDzdO5HJyQ?1N8Ew@)bt#5ZK%t)f$ zY4OnFdA-pPawJi2iuZ(VVfdQ8yxCd#w6a~Vin=X!z-?9&Ynm4gtMZj4YSvfvswFCo zR?`w&t&X@UcI(YO$Fi?4FSJ*%bbk$-dydm;nhCo9q*QwJS^3isKmN?DVk#IDv%WL? zyk2v5Zr@xiw)a1nU0L4r>#MCst8@FEt@qxaUHPKY;n8m|FKn)eN|onti%qN1dM>J! zrr7M%tIx!X)?UY(m^+E{Wbd?|m#cf74(}#Yqm&^wrYE0tEW7>_tGs37WMsvz+#Rdz zw8~o;rqy|2j`b)0*@r)P`02yXO2LhFT5Tp-I!|6_yOsU&R-3nNj)+-|K?Y8mS)g1Z)vlNX9dspPGrG~Ihj6A#w)^bcR5O;@Mo zr`$%xSUSybP`0>E%6vB=u2W)KdxI@J$lyP4g;TM2TTTUhxohq6kw!=!5ZGj^-mIB% z_qN=zDh=}@ZCj3afHe!xU9AJA05$YkTg7o#YN0Sj2tiR1|0o2BP3Zl3r|wv0m>R8Z zyaDdmtvKdQda|~9TU2){&25mfkW&D;`a_7VPHR^b_lt{9h0{V|1|?A6^G>VRnkhcvNT-g~bp9w3D?nY%V{@5Mm)1|hw@WGYmO=4CH%fD8m+vZx zd|{fV_Vs8UZ3}dgc9}F56-Syfhx_YbTG5Sr_mrAPU&S@jMfW5dBwYmSUzb@%{f$*;xmDK9-#|HJ{W$?%A^8fw!Kb{R(u*_xYM=k{r|57Cu;2X5Oe%I8p4Bg;q0=!2sPT762nwRM^-t)EXmJ*52l zx{=(#m|LX_#SMe9wRJKdbV*(AW-vxBSwR1VE_4d!TsXP_a?2zk`;{WbT*8>Q4w)^~ z$Q=4F9!+8_$}FSL{yIp<8q~S&UxP$1vMyAzzkyVFlV^)faV@z-B3H=JB=+(`NrUC4 zrE;&vlLGx04#5U=622l?gUtN88W9+4?&y-w3aKSsvS|F4PI2g?_#DO)m{aa(iUjN4 z?&VMpV+rWpTvx$3{7iVyxcnWj3}QK$#(yBnAy#6PAYEz|D5w;%Y4erE;zm{s7;vA_ z@>bny)NIRHS!VOGS%bZ_a;3Rxw?Fv4YvqW(mE+d4$+W!Sw{D}1pHtavSSw&7yU}uN zD5<*5gF+Re;9EXX+G{>*ww^aJF;XB0>&QOmoqk7l`Atg|Kr`b?Qe{O?L)gtqrTm| zGux?e?>Mt7n7{bszF1yxpL)AHH)Fr+RxO}+Y+R!P^AiV({j%G2EYB?XlYjeye>7r# zTi<$afqB4=g#lWIx#1f1*g-z2J=g|~R<(kCEk84BgCmYSjoFne4d;Wcj%8ihc0Twv z`xKZ9)bD~vR~hMvcyv^5RA8Aq<|4Zvr5$(^p7Q`|v4yi^37n2y*|L}rq=E0gApM98 zI_=ZEOTFMEq8QbfM67oCMxZ!CW+xQ7&M$@f&M)lfwXkZy)=lkmnKXEoWNg5OhDtTM zu(ct3Q~Qdly$OeXdmFYlJkkiOb=cZk)b#?RvD~2+&lLzVK#yo|Vvq|^(TDL^0dj0^ zo%CEc5zgT~S8f<6!(Q*wZ^mDTLhLYQA)pN?+mu79c7Ve?RHMdWBx>UDGdO$` z_LF*`MNOgNJ{mEPbZNIiiD+h*pT%(Kns?|ixc)xu0HwaF={do|KOXZA6$*|O4pDwJ z8qbRm?72h&u!F3>RML_n8=`4PON%VA9hTD$qK250XyFO(ih-k1N!IAOnrcw&S(OkhJb8TnzIfF zrU`)xGFiAG#k>vl$fGVWeviQ9`3#d1!|Fzyv#QV-_v4{hafC z6Z|)vFo|3##6Bg?#8ZF&yMvd*yw#O`>%$QXh%0nK_8fn0LR2c@%sm#BX*O{+h)pu# zg-nzHJLqAUKNJ`6fLyV5j`ABSi!_+OQ6mS=o7@kP3e#9U_)nN{5i;=1kR}|4IM8?# zJU=}k!aO%Xp@-iCDW2ASa%Q8qYxI*5s|9_X=RQ4}0vMAEfu3MwN}5pyXf61RX^!O# z)12zj9G*M=yFT4X2U_wdQ<`g4nJxg~qEAwUkEFms6l?H)#KKI4K9-y1c`!lrD3&dp z17Z~PX1J`uA&v4;>d?IVA#sX!aLB0A|psYpbp;ecj zQVIx@35#Bz$2#2i#{=yWUKv~T7HoHjq2-?6fX)8!Z8keJ9V0p)J(g0tvhN$FXD#-= zkX~go>dV%i1U{{O*u1cGVMJ{KP!{$J*ay2}^Mz~0US|;ZW5X1^=?|C(Xt&E zBb~+k08n|L>YZ5`pkVA~R_t2NPOEljwvEQK0+=m8*S*c%x&vF;a`rk+?v^ctxoK(E zNg(;b!_|kShjK>#pslSl6XZ!(D=+{>MR*3m_33v3|C&#DdD2I5fn(9E?81nbsH#0H zsz6rlJG0)i&5l)@T^Za(*pL!)MmM}P*&DQ^-|rcF5@>or^84m$M)ILMF03w&WIQvo z{mKBu>sj5vnE@qxu&=rDtq%SzC;sV>gT_|cJBTej8{E-vanhgAa=qE!a|AnOcV?S= zyPH-Ar(B2c^ZpVFm3=r%wOPR?rd#Fiy|<=W@l~a<#|~8;=k(*=ex5of9406l+wcuX zHSCO}OzIo+i-F>BNfu5kGMFeKH$;b2Rho28C}QTLFy#~}+1P~BA+<8cYRo)R;*%uJ zH<)(OfaHUjxCX@q#RR+@WmZhU*f(Ii!yiCoDUpRg0LhqPY#G?Pngv!f;Q-u#&)~L+ zqYdiz^*~)@VuB+4PHy5D?{$+2C`Q%A3{qT%AMh_URf4-AREGYbD9ONcR+Ljy6cyT= zF~;n1pGk|H3X@SMu|cT<+K8@xWtw#KpA8A%EfUYr^^_=RUOQQrDj2fu)oGd-6SBPz z|D6Zskpt#Iss~A?ZW$LY-GZi?>q@v1FyLfZK%xVpgfzZ5RyaI4L98GnajX6Oxc25! zqHuI^Y#x!dLU#&f#&#I5qKtZQ8K>H}W>C%&Fz?D<1Fnqc^Oc``zIw)6xZ-*X&6e2k z+ieImoM*_KUuOpbwyx_s1kJC-w>U?xh#vPqb-!coSGeFzwNXc?2pV_O0!j}IpP}m{ z{|`CEGLMmpBsDGPd8_lx#oyr&vB$-P9}<5RP{obadMw|6fW2reDC~azULTMYU)@A+#Z9qB54-Z3SvaR zN`&0F7peI!8=f4?QYinMIIfhsa;%RRj*Q6sQF6dSh%;|!pl7&b?81RD-hda^qWQ^} zX%EkZtG7leJWov?>+s!87`hxkV}E{(ts33scQwG

!T=n8KX7U-W0>^OyMEn|~%S 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 MLchkfxx#n<1GPsQyZ`_I literal 31911 zcmd5_TXP)8b*5uGRiPh~hdiWGtwlk*uzOr5lR`OLobs#b9?97;~|+ zH8V?)wqE>S@|66NX^z|M4^K7G#V)92Q`Prm&5FYeyq z&*oSEd31ks7qOn&mmbXb)pnT||izDrNc^T&5@2K$w}cV8yOB}$tEbDodpleE`uQnkBw z_ol`UQ;3OZnLXef@f_2A{#YnlouvU$bDm6-)3mq+T!xdRECW*`e2gipq{@aSnau`e z_NR1ko=rikkHBgCteCIy@!O-%4Bvs{leFrVrc5i7RVKmzO__{S^U=rmzkDE5Lig-E znV6%bJkP5HU@o%i%p867?CyfGl2;gOckACc7{6fBF?*bJRht&7?@Dqq5qx z7;cQS;`{;+H_wx7y6HbvZUUSBuhnwH4c9-(rk%UM2Y47vx#|%)W1RS>MVXZq8{pa4 z%=B}AoJ~i)&NvxXdGQ*gJ}r_e?W~!D15*|ARGO0#MS7mUOd%1)i?lFRZjzUIHZq*( zB+q9AS?1?yb(T#}&1sIcby4KgQ`_H-rcf4)*JxKJFH_*}M<=zi={z-*Pel?c%gl;= zm_m*|1pm=wgylP~fZli6I5Syk@N9}zosKLZlE#4=NYlZGrKJ<;V(HpfGzSG2X9tTD ziUSQn75P~)U`bgylCV`E2wsr_l*LnUj}j@^6hx57SX9Db5ZytQou@_b!>z5Yb+fr~ zi0Mqm{ZSrd$!iDz@2vrm74UhIyf!DVIeQBfVr2hvGf74xI}Kv7^0_0(!FFf;GAY(g zJX;G&eko-Bi;pDZB5AKnTv?G4(wpipDTZf*a(;p(;gQ25*Jtb-e81K2-}`|A*h$OT z?oP+z5dm<2e*a;={{wllVosp|C>+woV8ASyDyV;{^undP z?h)cTvNK;X!y?53ftI1H=OfWDAToKLn3H)`K`gO4L{7>7^K?2#{}p*+-*=mvSr@W2 z${-@xfY7!4XZjaJ+*;c?msDQut3$EuvxuC6MpQJ7YTg zoVdwG2Y@t?Va`tr5asnGJ?M_Iat5K=GbfXL_~MhUfm*;iJCF^E_;l^G54xat_i$g) zIc&~nf78C$-{f$IotT6hX5&VF%*F}{yJ3C<){jdwpC%Ka4epF&Z_t-FG89neSY!m| zJ%~mcyy(qT&r-&*sX_lw@(Mye>+_HD`;F}%g!WL7{&hbq2jwgqkAw1AF<@XeehoQ+ z%3w<)fS|?3*(5DrmsNT$fDEPEjL`(^iTmRVj3#nS+|H9%gZQ08PkWK!YVAQLq+>52 zg?$$W;Rg|#1ixlB&Gy#LJy~Uf*NYRHRx0{qr+P5GU^omE`hE>di@brX%R-E?#BSO^ z&9>&cqg1=!w(k}m@)3SP0B(}UR-Qmc%9N4>3$Nfdb8(hVP5NpE8xhmTLPe|Wd``C9 zFcwbIgqx5Ra^~$tjf8v?Ia93)I-48@Ly^AB@_88;B?2nkQQ;Cvg4Gra|Bebj$1UFCIia>(fO4`}fSRO|PfI36TAoZ1MqR9cJBWDr=y(2Dycl?s{qcz}%M) z_wVWQ^kP>ZOOW`h2v;&G&%BCc~b5#Mwo?G1!@kV@@Fo?ixNMi)?1>WD9)_a-?GBO-@ zIy-L~_R}*6oK0moG^T#h?N9j;y2xPVG)jAU;J7C)kV&F zbkbJfdneDD-1eaY6Y}1GXj-5(ia3FX!<3Bd3cEz8b>meqI}1K1DeS`3b*KIP{q7IW z-3voV+hIO(ZfN6;tgv$rMOxcc=WQ0~RX&GSHD9|ehqlV4l?pfqW}91N?HxzQ2wShV zXmjuZqP6oos`;%~ ztN05$k)38V7$&f`Zg$<6>7;bB4Fe^~5V7oF|4$3}GJ~`z@&Zsg5=pUxiZFLR0DAF` zrZVWE){N#`+cD^O!R$crO8hTk1{U0sC5(XvV_3r6EZ*AZqMW^nA#A;l*jJ)XshgZ4 zevQqWYv)$!uac;?iNqrGf!KVIZ7cL-i!qN8lY;e~6cS{h)mTAPw-I!bo)S!7XADDM z;Cb}o^WDv7yM&{#lp-Y@gE2#|@DD5w3_2k05mrey)lds;DD8^4{W0vPW3en?zK-b^ z1jvuA_(ORhu=s-RFN1A@tDppxB4M=%b@%}Y7@xdW1NdegLQqkhe$~r?rokWt?tTZB zR`LL|HrXCxS=;haT_j7c1CznO(FxeMPNnKrs_oXzwgh51v9i~F_;HsJNGpsMloL4p zeQUCYjL9sAc7k?Oi_JWGW<6jR`bB7nmOOXbC_sYg-GW9a&+?0bH60N|u^||182Jd8 zkk&r5rV&}i4Jg788;m#PqQ|Ob1jGub2(g33f^baK#+0*Un65JpE!4@U-12gR>_&zl zo5ml}H|}z1+=lA$tVik)qRZ0B2+Qhlf0CYprHHc~zCS%FXP;Oj-P2y5BHVVkzv0*sO_!)wYAa2z)5=A5fTV~YBr-(0~XVpR1t`T6!>`Ctr zoue~wP7wX#;a3lj9?I<81faddU5+M87kZd5gP2g@8Gq^jp|kc$S7VvWumB}V1REPQ z)8rhHRgF4yDH&yX(ADs$IYHRBd)Q=ZGkR*-$uW&t&eV<@99bhLLtY-(U5r-|_p_uN zxU>&qzWKaz%ZQr=4HGZc!E=R9E6)%=f6*kEMT<+T9$<-ASN%;Gu3^?Mk7qg~M>>@f z?^L6}8pB|gI;v>N z2$$3kO^Su0b`AaGHO`U&X_ff=#??Bf9n!niI<0s#1am)|&S1$^uV>Ic)A{*HT0oy> z$mQI>hd+{62i?_C7Xj{crjJxlSrfa9O>#0v&(#bX?^oZ zj7wFbSBh5;-li7SN+9{L$9j-LDayf55-HwZbsrOA2oAL~^TUIsV!%3h1-^+9W zwat$l9#Xlnec%?r)&Vv8mf4oy+x>pu;TXW#2!6cobVHZ9_;%P3M19zH4b!QPh+5^Y z>zXJT)Rw~4oUwowg#hAZo-+TcF)reb_7WHMtCj-kWsWV7z}CzJ3|%^@Ecgq8DRrnS z)nF&8$;KJ%hIrX1B`L*1MdrgvAJJo5>Lk%c;wrnU!PdYbAn{c+?+IMpH`mOkgtB!x z<-P~@2oKyq+Fe-3e-zHP-G42d?LK`O6z1B#m>!`wP}m29e*96eSD<|0#0)`-E-3Lda5ui~}!*d3X@P^T3V)V*8lvsq);Es1%(9Kz2k~fSBp6>D?W-)NfDk9=k%( zV|7lof`zk>)L_&I1QBAe+7o#X*57`~1RC}FLUpZLDuQ73=oPA)>mcfcqFEV)Y;0)t zE#cB7tsXir>=>rqJ|hmMf%5>&EjC48KtFw#YI*0~t7XbUtFEwXN>}f`(aK5m(3A{o zw0|viVzx*&Yziu3wFM@-aUgYAZ&s0PMWsDJh-Js<$Is%9vxj5Jlgta7i(FkE=22R8hbhMB`Tw81yEQc3xMRt0I{FD@)2g)&k zY>Ck9$x#}EDABZ!;;Cq}t8{;-s%Q7zs-DL3;uhodK&v*Al*~fCfQaU8=qB0vg%vkb zZ7QI|=epOv>fb%<@3pfY$atmh45GhbUiq^<^mgdp(LC<4P=kf^#X1(Z{ezlF4dzRg zRg05{>@b+5WBM=rTPQ=3_32%v_~fZ8R%WOeJlFCxKTJr1yk%-f3x zYYfD;;BSkxQCqU3Q@J>kY?j9~q#cPUPhrTYwsOlsMM;B8J@crO%e83Jv`EUdXUVp- zrIy}YZg~Q#BRb%~20CsW7>*|-GmeZO)E>hA==Bu24Z+P$c?-Kec6Lj8t^2|=3+n2k z9%Qypp{PqCF(|BnHd*pstJJC0)YQRhbrJ+y)iXrf^@$PmZ*e1 zyxI_qBnymVK{6;a!t(c)U~Mx_2oJ&!*8oD#&JNF_(`>OqP`RG zQEe12);r3gVxIzC(BwA{kKEa^F`gj+w1XnBpgX2%b&(e@LTMs8SbYSGRxv9S9rhAc z=NKw$Rz_j0il4$zem2qw(S06;l##DX8R^&{4W9*MVzx-@<%VMGzz$dE(P}_q!O(6` z{-E>XK~OC5s%QirrN~tFS}uoZrHE;;>bEF|0eQa;3!z3~-2vr1Ot1!=h6R^3?a>Ss zTE%M5*)TpTg@G~eFW052&UD)~!Yhpb+Kyqu5G%0<^jMmBxmTbq2V( zK{%b&9qYJd-ib!Ag@juEBoYXPvD>CF0yI?^zTq_$hHd{w3d4<2Q)}E}TG?ayw;+;h zHyO*nNRM-yav!-Cmna!6ZDahI3Yv%T>j?X#xa0v*bLoLgMutT; zlhhzyO9l>wvSo>rix?Z+D0oDkiFD8ac~WtZ4w%$~v&XFVfs6#JP72Qsq7h>-#+;X@ zd$6X$a1e9Jzhc;sH`J+?=C?;*e`P^pcu}u9S#?$f7dR8Z2o-7NsWl_1BE@A<K+n}{Y}0-gpB}j(osth9lQ`xSPt;fX87?@ia`Y?x=LUWRy|N`TR((&?5s4WK1K@UTnR0jSu( z4J4G2o3Cq^GHRF0hr8|;j;*H-D*)y~b3Iz0!k2pqPwS3`J{p^AB^?O9fC*WxdpLII?nBKi$F|f zL(8ePP+FyJ$(T=AQiT%iG&TE)IV;lfLAQJO%vyYQR@i2Sb6hk5`9%hLe=~6v;8fsC zfIDi0YVnrF4LcR3e9x#3w-J{rZNazr%T{65bO>)UsmC^OqN!d4(pf{<>JnUAhTnPf z;prY?crg%TUfPJp*6~k7W%tcdq2UQs)HH|$73r9th{U}&M}pyAPY)#2aZQqo_y`iq zxblW&`z@k%y`p_7#V^e{BLy>PL>n_H>oxhbO6l0ZErK~x+w;GzlIO*wvu4kW+mD#K zJyg(wT~qR~q;VF5H$nlL9J}BXEw#m+D&2g$YjA_gFg?T3zqB~$qABlz3iY%lZ%rvs zQ!AvU&|mpur{qezt&X+jMFK{=9Onhswrh{EX&lsAgJH zjl6up*pnfPtB~#9cf;E}z=^q$Cd0_2Mx+rrSxH&4Ff12?bpuaveu>geGxph&$B(o? z_m&I~TO%cvV3LY1UGnK|4G%6Ut_fGQ1#R$Fb!N-C8jjkyBUtXZ*5}PCu+nY0mk(_1 zR|%?f{kbjrj$A}E(ab(1Am9|b1hs}SK=Wb9Gn7en3v1}j;Qv*Jye+M&&Vb#uj z`eK@2;Br2q${$W%Zcwt*W;`^$%f>f^3)ho|2vXRh7Ws&vh!Bj z)m5nfo&t4|Le}j7`X(ZY>*s~g->#tR`mEc zZ~*xhk^fV*4H-;EiC~9&mEfd-i~)QU9k2(pMc-&5#$z5Z76p(`2L7%IpUJQSfOo0_ z!K1(&(0nm&o-3>tj={G2z266@+Q$#~gY`T^gP6W6ZAN>8*gR5ma!3>WaUDmnc2Y7pqm0J^PA9?EG$-F%bWRhix&~Smiw9Wpf5h|(MWZuN zO#^MCT1hA5mCqX(PsCefmDe3Qu31u8vhcZZ#!+ZF9W-uXbz0*VH>x6i6qJyc8wzC0 zvbpA>`N?bHZ8$f+HrJx<0f~NYK$j`%#mNc0HG8a9jPCG*ZlUi;@WwW5ISCc|pR- z?#F^SUWmX%N5KZ#(wUX58jLQ1oDjFihOk+p92|x*)T{F>M9C_==s>oY-u8(E^U$Bf z2EMjqxSsi~{sO=i^F@*#rsDfAh;)s?F6|!8xNfB4PTsv5U+JE9c zqSt~SEXzC@1x0P;N-env6L*a&Esb8s1GN{CyIX-}0C-!f;q8?IfFi`w`$OC04>k>A z=8KR7Jl@{Qu={j`+u7YE)*59m3D(grAj}1Tv_h|Qk!01CmnJ~;HFC<+OYT&X+?0Sp z;q@Ys=C4;~(3s4v&O);b=6N2p7P?on>=5|0J_}Eiq)itMahEz#9r@!i&_{0*=PDj zQWF>1s5;x*-PxMG!hH_=C+@jTS&Tot-#z>;DLAz~S@o>v!6|Pf%@FF9D>6=s44B~H zZeeF#pP}d>39dU+(rZiav( zmKITehXFpvYA*80Bt-@25V3oB8o1cx$+yprNZ4b45rCXGyqUoj%OvC?*p^l1?|1g z=BK!i?7#)U2;(MxS_C;MPO_>N(7~6}Q`1__cawtw3np~uRtOd3tOMz@QvgR!4{(dU#QVtSoz09r3C*Y;93(mcFvL4v7FT7xLL` z<`E~2@x2=o){bW2PCjm6L{VkFgBL*2vN+}-y#xJLY zqK~NvZH0Mwus}0LgT9T{(=l#Z={=Lmt@_0=a@a*ORj|ww)Rv;E%9813hi}t>Ho6e$ zKl0zEV`;UkSvPE_7fM(#_^O5n#`LER9+>O?t@HPfHO>X@NMBGdR4$+g^@C$P7sPwX}!@92x;QH{y#G8Kqjh{=PX|zGp zT9t24p#vQ4)RC9yHGf^9be?Oj2A0A(zWi$B;`2nDWJzBQ(^+NueS_PRSQ=*$adTO4 z%7GIY7VthF!pg{Ys9;@)D#kvz~NSY z^O1CWqmaZxu$b@L2PN7dH}BB9gYOKahOW6J%&axfi%9=vDx$DZ3GJ}jQ)w>s_F0$VvB9@oMmx*#h9joncKry1ipF7?W< z=~-h4wWw|`AW4Yc^0u3j`>MA1rYsj4^(O-b7hLUh^zexZH?^=Z`C5k$mz^lYfkGRI zjlnrR$z3cSh1KgJMCW3_QQ#pQbfXH@gK^KO+$ebjg)?uFq72al>*ZcLW!bK)>q9k6 zNI8O|x|cb}#cJA5-Kl>!?Xa^pxCCRto@gO2!)6_Azm}STP7Y|iw>ZL(9_9;w;56p* zju$|Z&7DoN&O|80j1S6rJ})@^R_C(==Ww%pc8^gC5%90m*n{VpHt}I zTfhftFkZOLkekNX5u`lQuP=o*hYr}7IYrsGYQHONBv$y zQ_QFGjRG=RZs3>ZsIsnGG+svEhX_(5RLS6GjRFadyXNJ*fceN%i+`N+I|j^nK9yV# z$`^Q-;4qottLkhn*hWZTdte3(jM_M%AFiKI5gl~S2ZVpqxUceTBup7SwK(>Fdvx?< zfMc|}T*LG00Fy+*C16Zu5E^BT|9K0?e#>sii`obH8enWtPpF!i=n7Bo;%kVJ3&5cU ze&r>^%L~v5iCM@I>@dexP=mTgnT*k$KKD>|+28%^&)dG}n_u^>KmYz0{tmOj*M9#} uzxKQFmETQ(^)L610sa7h&B@7EeYXMr<=+#Bzr+9j1Hb 0 + if b[-1] == 0 b.resize(size(b)-1) + else break end + end + return b + end + + # + def init(raw) + if raw == nil || !issubclass(bytes, raw) # no payload, empty partition information + self.type = 0 + self.subtype = 0 + self.start = 0 + self.size = 0 + self.label = '' + self.flags = 0 + return + end + + #- we have a payload, parse it -# + var magic = raw.get(0,2) + if magic == 0x50AA #- partition entry -# + + self.type = raw.get(2,1) + self.subtype = raw.get(3,1) + self.start = raw.get(4,4) + self.size = raw.get(8,4) + self.label = self.remove_trailing_zeroes(raw[12..27]).asstring() + self.flags = raw.get(28,4) + + elif magic == 0xEBEB #- MD5 -# + else + import string + raise "internal_error", string.format("invalid magic number %02X", magic) + end + + end + + # check if the parition is an OTA partition + # if yes, return OTA number (starting at 0) + # if no, return nil + def is_ota() + if self.type == 0 && (self.subtype >= 0x10 && self.subtype < 0x20) + return self.subtype - 0x10 + end + end + + # check if the parition is a SPIFFS partition + # returns bool + def is_spiffs() + return self.type == 1 && self.subtype == 130 + end + + # get the actual image size give of the partition + # returns -1 if the partition is not an app ota partition + def get_image_size() + import flash + if self.is_ota() == nil return -1 end + try + var addr = self.start + var magic_byte = flash.read(addr, 1).get(0, 1) + if magic_byte != 0xE9 return -1 end + + var seg_count = flash.read(addr+1, 1).get(0, 1) + # print("Segment count", seg_count) + + var seg_offset = addr + 0x20 # sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) = 24 + 8 + + for seg_num:0..seg_count-1 + # print(string.format("Reading 0x%08X", seg_offset)) + var segment_header = flash.read(seg_offset - 8, 8) + var seg_start_addr = segment_header.get(0, 4) + var seg_size = segment_header.get(4,4) + # print(string.format("Segment %i: flash_offset=0x%08X start_addr=0x%08X size=0x%08X", seg_num, seg_offset, seg_start_addr, seg_size)) + + seg_offset += seg_size + 8 # add segment_length + sizeof(esp_image_segment_header_t) + end + var total_size = seg_offset - addr + 1 # add 1KB for safety + + # print(string.format("Total size = %i KB", total_size/1024)) + + return total_size + except .. as e, m + print("BRY: Exception> '" + e + "' - " + m) + return -1 + end + end + + def tostring() + import string + var type_s = "" + var subtype_s = "" + if self.type == 0 type_s = "app" + if self.subtype == 0 subtype_s = "factory" + elif self.subtype >= 0x10 && self.subtype < 0x20 subtype_s = "ota" + str(self.subtype - 0x10) + elif self.subtype == 0x20 subtype_s = "test" + end + elif self.type == 1 type_s = "data" + if self.subtype == 0x00 subtype_s = "otadata" + elif self.subtype == 0x01 subtype_s = "phy" + elif self.subtype == 0x02 subtype_s = "nvs" + elif self.subtype == 0x03 subtype_s = "coredump" + elif self.subtype == 0x04 subtype_s = "nvskeys" + elif self.subtype == 0x05 subtype_s = "efuse_em" + elif self.subtype == 0x80 subtype_s = "esphttpd" + elif self.subtype == 0x81 subtype_s = "fat" + elif self.subtype == 0x82 subtype_s = "spiffs" + end + end + + #- reformat strings -# + if type_s != "" type_s = " (" + type_s + ")" end + if subtype_s != "" subtype_s = " (" + subtype_s + ")" end + return string.format("", + self.type, type_s, + self.subtype, subtype_s, + self.start, self.size, + self.label, self.flags) + end + + def tobytes() + #- convert to raw bytes -# + var b = bytes('AA50') #- set magic number -# + b.resize(32).resize(2) #- pre-reserve 32 bytes -# + b.add(self.type, 1) + b.add(self.subtype, 1) + b.add(self.start, 4) + b.add(self.size, 4) + var label = bytes().fromstring(self.label) + label.resize(16) + b = b + label + b.add(self.flags, 4) + return b + end + +end +partition.Partition_info = Partition_info #------------------------------------------------------------- - OTA Data @@ -73,77 +200,302 @@ var partition = module('partition') so current ota app sub type id is x , dest bin subtype is y,total ota app count is n seq will add (x + n*1 + 1 - seq)%n -------------------------------------------------------------# -# class Partition_otadata -# var maxota #- number of highest OTA partition, default 1 (double ota0/ota1) -# -# var offset #- offset of the otadata partition (0x2000 in length), default 0xE000 -# -# var active_otadata #- which otadata block is active, 0 or 1, i.e. 0xE000 or 0xF000 -# -# var seq0 #- ota_seq of first block -# -# var seq1 #- ota_seq of second block -# -# -# #- crc32 for ota_seq as 32 bits unsigned, with init vector -1 -# -# static def crc32_ota_seq(seq) -# -# #---------------------------------------------------------------------# -# # Rest of the class -# #---------------------------------------------------------------------# -# def init(maxota, offset) -# -# #- update ota_max, needs to recompute everything -# -# def set_ota_max(n) -# -# # change the active OTA partition -# def set_active(n) -# -# #- load otadata from SPI Flash -# -# def load() -# -# # Save partition information to SPI Flash -# def save() -# -# # Produce a human-readable representation of the object with relevant information -# def tostring() -#end +class Partition_otadata + var maxota #- number of highest OTA partition, default 1 (double ota0/ota1) -# + var offset #- offset of the otadata partition (0x2000 in length), default 0xE000 -# + var active_otadata #- which otadata block is active, 0 or 1, i.e. 0xE000 or 0xF000 -# + var seq0 #- ota_seq of first block -# + var seq1 #- ota_seq of second block -# + + #------------------------------------------------------------- + - Simple CRC32 imple + - + - adapted from Python https://rosettacode.org/wiki/CRC-32#Python + -------------------------------------------------------------# + static def crc32_create_table() + var a = [] + for i:0..255 + var k = i + for j:0..7 + if k & 1 + k = (k >> 1) & 0x7FFFFFFF + k ^= 0xedb88320 + else + k = (k >> 1) & 0x7FFFFFFF + end + end + a.push(k) + end + return a + end + static crc32_table = Partition_otadata.crc32_create_table() + + static def crc32_update(buf, crc) + crc ^= 0xffffffff + for k:0..size(buf)-1 + crc = (crc >> 8 & 0x00FFFFFF) ^ Partition_otadata.crc32_table[(crc & 0xff) ^ buf[k]] + end + return crc ^ 0xffffffff + end + + #- crc32 for ota_seq as 32 bits unsigned, with init vector -1 -# + static def crc32_ota_seq(seq) + return Partition_otadata.crc32_update(bytes().add(seq, 4), 0xFFFFFFFF) + end + + #---------------------------------------------------------------------# + # Rest of the class + #---------------------------------------------------------------------# + def init(maxota, offset) + self.maxota = maxota + if self.maxota == nil self.maxota = 1 end + self.offset = offset + if self.offset == nil self.offset = 0xE000 end + self.active_otadata = 0 + self.load() + end + + #- update ota_max, needs to recompute everything -# + def set_ota_max(n) + self.maxota = n + end + + # change the active OTA partition + def set_active(n) + var seq_max = 0 #- current highest seq number -# + var block_act = 0 #- block number containing the highest seq number -# + + if self.seq0 != nil + seq_max = self.seq0 + block_act = 0 + end + if self.seq1 != nil && self.seq1 > seq_max + seq_max = self.seq1 + block_act = 1 + end + + #- compute the next sequence number -# + var actual_ota = (seq_max - 1) % (self.maxota + 1) + if actual_ota != n #- change only if different -# + if n > actual_ota seq_max += n - actual_ota + else seq_max += (self.maxota + 1) - actual_ota + n + end + + #- update internal structure -# + if block_act == 1 #- current block is 1, so update block 0 -# + self.seq0 = seq_max + else #- or write to block 1 -# + self.seq1 = seq_max + end + self._validate() + end + end + + #- load otadata from SPI Flash -# + def load() + import flash + var otadata0 = flash.read(0xE000, 32) + var otadata1 = flash.read(0xF000, 32) + self.seq0 = otadata0.get(0, 4) #- ota_seq for block 1 -# + self.seq1 = otadata1.get(0, 4) #- ota_seq for block 2 -# + var valid0 = otadata0.get(28, 4) == self.crc32_ota_seq(self.seq0) #- is CRC32 valid? -# + var valid1 = otadata1.get(28, 4) == self.crc32_ota_seq(self.seq1) #- is CRC32 valid? -# + if !valid0 self.seq0 = nil end + if !valid1 self.seq1 = nil end + + self._validate() + end + + #- internally used, validate data -# + def _validate() + self.active_otadata = 0 #- if none is valid, default to OTA0 -# + if self.seq0 != nil + self.active_otadata = (self.seq0 - 1) % (self.maxota + 1) + end + if self.seq1 != nil && (self.seq0 == nil || self.seq1 > self.seq0) + self.active_otadata = (self.seq1 - 1) % (self.maxota + 1) + end + end + + # Save partition information to SPI Flash + def save() + import flash + #- check the block number to save, 0 or 1. Choose the highest ota_seq -# + var block_to_save = -1 #- invalid -# + var seq_to_save = -1 #- invalid value -# + + # check seq0 + if self.seq0 != nil + seq_to_save = self.seq0 + block_to_save = 0 + end + if (self.seq1 != nil) && (self.seq1 > seq_to_save) + seq_to_save = self.seq1 + block_to_save = 1 + end + # if none was good + if block_to_save < 0 block_to_save = 0 end + if seq_to_save < 0 seq_to_save = 1 end + + var offset_to_save = self.offset + 0x1000 * block_to_save #- default 0xE000 or 0xF000 -# + + var bytes_to_save = bytes() + bytes_to_save.add(seq_to_save, 4) + bytes_to_save += bytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") + bytes_to_save.add(self.crc32_ota_seq(seq_to_save), 4) + + #- erase flash area and write -# + flash.erase(offset_to_save, 0x1000) + flash.write(offset_to_save, bytes_to_save) + end + + # Produce a human-readable representation of the object with relevant information + def tostring() + import string + return string.format("", + self.active_otadata, self.seq0, self.seq1, self.maxota) + end +end +partition.Partition_otadata = Partition_otadata #------------------------------------------------------------- - Class for a partition table entry -------------------------------------------------------------# -#class Partition -# var raw #- raw bytes of the partition table in flash -# -# var md5 #- md5 hash of partition list -# -# var slots -# var otadata #- instance of Partition_otadata() -# -# -# def init() -# -# # Load partition information from SPI Flash -# def load() -# -# def get_ota_slot(n) -# -# #- compute the highest ota partition -# -# def ota_max() -# -# def load_otadata() -# -# # get the active OTA app partition number -# def get_active() -# -# #- change the active partition -# -# def set_active(n) -# -# #- convert to human readble -# -# def tostring() -# -# #- convert the slots to raw bytes, ready to falsh to parition page -# -# def tobytes() -# -# #- write back to flash -# -# def save() -# -# #- invalidate SPIFFS partition to force format at next boot -# -# #- we simply erase the first byte of the first 2 blocks in the SPIFFS partition -# -# def invalidate_spiffs() -#end +class Partition + var raw #- raw bytes of the partition table in flash -# + var md5 #- md5 hash of partition list -# + var slots + var otadata #- instance of Partition_otadata() -# + + def init() + self.slots = [] + self.load() + self.parse() + self.load_otadata() + end + + # Load partition information from SPI Flash + def load() + import flash + self.raw = flash.read(0x8000,0x1000) + end + + #- parse the raw bytes to a structured list of partition items -# + def parse() + for i:0..94 # there are maximum 95 slots + md5 (0xC00) + var item_raw = self.raw[i*32..(i+1)*32-1] + var magic = item_raw.get(0,2) + if magic == 0x50AA #- partition entry -# + var slot = Partition_info(item_raw) + self.slots.push(slot) + elif magic == 0xEBEB #- MD5 -# + self.md5 = self.raw[i*32+16..i*33-1] + break + else + break + end + end + end + + def get_ota_slot(n) + for slot: self.slots + if slot.is_ota() == n return slot end + end + return nil + end + + #- compute the highest ota partition -# + def ota_max() + var ota_max = 0 + for slot:self.slots + if slot.type == 0 && (slot.subtype >= 0x10 && slot.subtype < 0x20) + var ota_num = slot.subtype - 0x10 + if ota_num > ota_max ota_max = ota_num end + end + end + return ota_max + end + + def load_otadata() + #- look for otadata partition offset, and max_ota -# + var otadata_offset = 0xE000 #- default value -# + var ota_max = self.ota_max() + for slot:self.slots + if slot.type == 1 && slot.subtype == 0 #- otadata -# + otadata_offset = slot.start + end + end + + self.otadata = Partition_otadata(ota_max, otadata_offset) + end + + # get the active OTA app partition number + def get_active() + return self.otadata.active_otadata + end + + #- change the active partition -# + def set_active(n) + if n < 0 || n > self.ota_max() raise "value_error", "Invalid ota partition number" end + self.otadata.set_ota_max(self.ota_max()) #- update ota_max if it changed -# + self.otadata.set_active(n) + end + + #- convert to human readble -# + def tostring() + var ret = " 95 raise "value_error", "Too many partiition slots" end + var b = bytes() + for slot: self.slots + b += slot.tobytes() + end + #- compute MD5 -# + var md5 = MD5() + md5.update(b) + #- add the last segment -# + b += bytes("EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF") + b += md5.finish() + #- complete -# + return b + end + + #- write back to flash -# + def save() + import flash + var b = self.tobytes() + #- erase flash area and write -# + flash.erase(0x8000, 0x1000) + flash.write(0x8000, b) + self.otadata.save() + end + + #- invalidate SPIFFS partition to force format at next boot -# + #- we simply erase the first byte of the first 2 blocks in the SPIFFS partition -# + def invalidate_spiffs() + import flash + #- we expect the SPIFFS partition to be the last one -# + var spiffs = self.slots[-1] + if !spiffs.is_spiffs() raise 'value_error', 'No SPIFFS partition found' end + + var b = bytes("00") #- flash memory: we can turn bits from '1' to '0' -# + flash.write(spiffs.start , b) #- block #0 -# + flash.write(spiffs.start + 0x1000, b) #- block #1 -# + end +end +partition.Partition = Partition ################################################################################# # Partition_manager_UI @@ -159,7 +511,7 @@ class Partition_manager_UI def web_add_button() import webserver webserver.content_send( - "

") + "

") end #- ---------------------------------------------------------------------- -# diff --git a/tasmota/berry/modules/Partition_Wizard/partition_wizard.be b/tasmota/berry/modules/partition_wizard.be similarity index 99% rename from tasmota/berry/modules/Partition_Wizard/partition_wizard.be rename to tasmota/berry/modules/partition_wizard.be index c73814e01..445a7a345 100644 --- a/tasmota/berry/modules/Partition_Wizard/partition_wizard.be +++ b/tasmota/berry/modules/partition_wizard.be @@ -4,6 +4,7 @@ # use : `import partition_wizard` # # Provides low-level objects and a Web UI +# rm Partition_Wizard.tapp; zip Partition_Wizard.tapp -j -0 Partition_Wizard/* ####################################################################### var partition_wizard = module('partition_wizard') @@ -50,7 +51,7 @@ class Partition_wizard_UI def web_add_button() import webserver webserver.content_send( - "
") + "

") end #- ---------------------------------------------------------------------- -#