From 6de1e1703db7b66f03550ed3d74ddb4ab0e04c08 Mon Sep 17 00:00:00 2001 From: SianGx0102 Date: Thu, 6 Jun 2024 17:03:27 +0800 Subject: [PATCH 1/5] lab6 --- lab6/bcm2710-rpi-3-b-plus.dtb | Bin 0 -> 32761 bytes lab6/config.txt | 3 + lab6/create_cpio.sh | 27 + lab6/create_fs/FromTA/initramfs.cpio | Bin 0 -> 247296 bytes lab6/create_fs/create_cpio.sh | 11 + lab6/create_fs/initramfs.cpio | Bin 0 -> 251904 bytes lab6/create_fs/lab3_user_proc/linker.ld | 5 + lab6/create_fs/lab3_user_proc/makefile | 23 + lab6/create_fs/lab3_user_proc/user_proc.S | 12 + lab6/create_fs/lab5_user_fork/fork_test.S | 28 + .../initramfs_providedbyTA.cpio | Bin 0 -> 247296 bytes lab6/create_fs/lab5_user_fork/makefile | 23 + lab6/create_fs/rootfs/file0.txt | 2 + lab6/create_fs/rootfs/file1.txt | 11 + lab6/initramfs.cpio | Bin 0 -> 251904 bytes lab6/kernel/Makefile | 89 +++ lab6/kernel/include/bcm2837/rpi_base.h | 7 + lab6/kernel/include/bcm2837/rpi_gpio.h | 25 + lab6/kernel/include/bcm2837/rpi_irq.h | 24 + lab6/kernel/include/bcm2837/rpi_mbox.h | 17 + lab6/kernel/include/bcm2837/rpi_mmu.h | 18 + lab6/kernel/include/bcm2837/rpi_uart1.h | 19 + lab6/kernel/include/cpio.h | 47 ++ lab6/kernel/include/debug.h | 19 + lab6/kernel/include/dtb.h | 26 + lab6/kernel/include/exception.h | 92 ++++ lab6/kernel/include/irqtask.h | 22 + lab6/kernel/include/mbox.h | 66 +++ lab6/kernel/include/memory.h | 80 +++ lab6/kernel/include/mmu.h | 101 ++++ lab6/kernel/include/power.h | 9 + lab6/kernel/include/sched.h | 75 +++ lab6/kernel/include/shell.h | 39 ++ lab6/kernel/include/signal.h | 49 ++ lab6/kernel/include/stddef.h | 12 + lab6/kernel/include/stdio.h | 10 + lab6/kernel/include/string.h | 10 + lab6/kernel/include/syscall.h | 28 + lab6/kernel/include/timer.h | 36 ++ lab6/kernel/include/u_list.h | 150 ++++++ lab6/kernel/include/uart1.h | 18 + lab6/kernel/src/boot.S | 82 +++ lab6/kernel/src/cpio.c | 82 +++ lab6/kernel/src/dtb.c | 173 ++++++ lab6/kernel/src/entry.S | 195 +++++++ lab6/kernel/src/exception.c | 367 +++++++++++++ lab6/kernel/src/linker.ld | 44 ++ lab6/kernel/src/main.c | 43 ++ lab6/kernel/src/mbox.c | 23 + lab6/kernel/src/memory.c | 491 +++++++++++++++++ lab6/kernel/src/mmu.c | 376 +++++++++++++ lab6/kernel/src/sched.S | 57 ++ lab6/kernel/src/sched.c | 270 ++++++++++ lab6/kernel/src/shell.c | 506 ++++++++++++++++++ lab6/kernel/src/signal.c | 90 ++++ lab6/kernel/src/stdio.c | 114 ++++ lab6/kernel/src/string.c | 199 +++++++ lab6/kernel/src/syscall.c | 327 +++++++++++ lab6/kernel/src/timer.c | 177 ++++++ lab6/kernel/src/uart1.c | 175 ++++++ lab6/send_img_to_bootloader.py | 62 +++ 61 files changed, 5086 insertions(+) create mode 100644 lab6/bcm2710-rpi-3-b-plus.dtb create mode 100644 lab6/config.txt create mode 100755 lab6/create_cpio.sh create mode 100644 lab6/create_fs/FromTA/initramfs.cpio create mode 100755 lab6/create_fs/create_cpio.sh create mode 100644 lab6/create_fs/initramfs.cpio create mode 100644 lab6/create_fs/lab3_user_proc/linker.ld create mode 100644 lab6/create_fs/lab3_user_proc/makefile create mode 100644 lab6/create_fs/lab3_user_proc/user_proc.S create mode 100644 lab6/create_fs/lab5_user_fork/fork_test.S create mode 100644 lab6/create_fs/lab5_user_fork/initramfs_providedbyTA.cpio create mode 100644 lab6/create_fs/lab5_user_fork/makefile create mode 100644 lab6/create_fs/rootfs/file0.txt create mode 100644 lab6/create_fs/rootfs/file1.txt create mode 100644 lab6/initramfs.cpio create mode 100644 lab6/kernel/Makefile create mode 100644 lab6/kernel/include/bcm2837/rpi_base.h create mode 100644 lab6/kernel/include/bcm2837/rpi_gpio.h create mode 100644 lab6/kernel/include/bcm2837/rpi_irq.h create mode 100644 lab6/kernel/include/bcm2837/rpi_mbox.h create mode 100644 lab6/kernel/include/bcm2837/rpi_mmu.h create mode 100644 lab6/kernel/include/bcm2837/rpi_uart1.h create mode 100644 lab6/kernel/include/cpio.h create mode 100644 lab6/kernel/include/debug.h create mode 100644 lab6/kernel/include/dtb.h create mode 100644 lab6/kernel/include/exception.h create mode 100644 lab6/kernel/include/irqtask.h create mode 100644 lab6/kernel/include/mbox.h create mode 100644 lab6/kernel/include/memory.h create mode 100644 lab6/kernel/include/mmu.h create mode 100644 lab6/kernel/include/power.h create mode 100644 lab6/kernel/include/sched.h create mode 100644 lab6/kernel/include/shell.h create mode 100644 lab6/kernel/include/signal.h create mode 100644 lab6/kernel/include/stddef.h create mode 100644 lab6/kernel/include/stdio.h create mode 100644 lab6/kernel/include/string.h create mode 100644 lab6/kernel/include/syscall.h create mode 100644 lab6/kernel/include/timer.h create mode 100644 lab6/kernel/include/u_list.h create mode 100644 lab6/kernel/include/uart1.h create mode 100644 lab6/kernel/src/boot.S create mode 100644 lab6/kernel/src/cpio.c create mode 100644 lab6/kernel/src/dtb.c create mode 100644 lab6/kernel/src/entry.S create mode 100644 lab6/kernel/src/exception.c create mode 100644 lab6/kernel/src/linker.ld create mode 100644 lab6/kernel/src/main.c create mode 100644 lab6/kernel/src/mbox.c create mode 100644 lab6/kernel/src/memory.c create mode 100644 lab6/kernel/src/mmu.c create mode 100644 lab6/kernel/src/sched.S create mode 100644 lab6/kernel/src/sched.c create mode 100644 lab6/kernel/src/shell.c create mode 100644 lab6/kernel/src/signal.c create mode 100644 lab6/kernel/src/stdio.c create mode 100644 lab6/kernel/src/string.c create mode 100644 lab6/kernel/src/syscall.c create mode 100644 lab6/kernel/src/timer.c create mode 100644 lab6/kernel/src/uart1.c create mode 100644 lab6/send_img_to_bootloader.py diff --git a/lab6/bcm2710-rpi-3-b-plus.dtb b/lab6/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 0000000000000000000000000000000000000000..38395a23fc90767680815c7f43bbfb3a290c2af0 GIT binary patch literal 32761 zcmc&-4Uim1b)G$)?rh%~jBUUMJFI-NCEFU^?%t11fWryNKZ+$wNOEigV!gLJceiN& zyt{WN0TD+6<|jZzFu_G7!6qpuKuA$QB@R#(7bGF6N(DnImAIhzsT2ePq{v?d2tWD0 z*ZpRCW@qKi9I8&-sOP!#Dpx{0e z&zmMY&GKX?Xje)DjHeu5C-IT2lX4`^8xuIm`XH}wGrZKxk_|Hg5RUmU{sAX` zDq=(8FGu`?8sDJ6A`DIcI~w1I{`(}pTIfhT(}O6S%Ha_kU(VH6PES?~<#~gk^gpQa zNIwU4OQ!#@#)s+iA$^wbPb9w6s!IOx^o;+68xH}x^~Ctc67gk+f5!i%#IJM~K!5KX z1qdJ<`5(dcHIHl9oR?uE# zVmOu4S0#?}qnu`9d`toF>k{wsIf;PZYPP%cdDk0|heiOX&>zA*Q(kU%f`){d-#%R5 zEjNJ|G`huBvst?-e>gi=n91#Kw2LdHcDHj=KHF(jipEII><${Gg<4Qt4oa2QaRRp`Hp#RL#8Q*N#J z7S6EdA$Hyg|01Hk;e-#tPnyJs-eg|>lb`(P>)y!0do4`m_I!jh-FCI*=$Xd7fN{*f z+^%-vr_=naUgkp|cET$XYvM0NvUR4ZmP;ZS#D!%nLs-?ul3y=rmP%9P@j?ezWMa)W z^QC?FI@Nls7WfP3%jhgW1N$cQZ<)+lAioF~D|y~twkkkkb zr*wQ0&L`oT$H(EP{jy=HSL9`QPw(0Umo_oZe;u75fiAz^qw5IIJ21+TPRj*8GoLn~ z7!S__jC^K#yUsrO6VVWgOxfE=CJcjC_D z#X~nADBkMrKXE+g9per8!^hk41NkEPljq?B@;tEb#6A;4AEW>r`U;_M$~$`3;au^^ zohRtYi|6JOw+W@Y4&DOE2uV`ee+ak3M~@q!iU&eIet;;&W8yh{z<4Cz$eWM6g~&Sv zuQ;m{(l%JnnM$i#q`Kvz_!jDwHkgjOt-8Z@$Tr6|#=9JrjdMPf_l9y45L=zmwYi5suTHng%FF_ZoyJaBatREw1Zu?ZD;ot8~fBam3M)Zt`;T-e=>ZGEL7h z9dWcwtd=}37Iq33nVZ3tmN)B%eFo($Wm;;LYo~G|Eh&_fj`d4?myQz_IxmjV$qOCk zO{eKdhdQBQ)?Jd$e!wDr44rAIy(k^&+^_+i18H<@!8Cu;*|h;3@)+?`kaE$^(YbUS z9Tc5Rmg^SaC+SSHlHgoAH#*^jd_rBZ_#*dPfiHA1G&Z$o8YgjRhgn8Cr{78C?`q)0 z=@df!QaV=whj_|wf8G$M4!=V8cBR`Y*M)3e#4crmO_ch(6gaL;98}&zNqVLlWAwBh zDPxW|TzbiJA69yu3SN@B!lJP}Cf)hio@AS#{TH3X>#NaSneGvOV3(xqw3W%e!{s+g z^Nt>xQ(}ggMrlsKza7`LxUR#Mw9iSJM}VVz8ePPA0**Ab{Qdebmsk32SnB>L!b;az z7Bk)C(%lK1>v7TE(Ke*Doh03t08i-hRn-VKZ%v=%ukBg;UdvOeT{sq}Rql51_G=V1 zl!4My8MyScucJ)a->|=Pcys7Yt^eo_2QQE z?l>)nw@ClBtZ8+hq<2r8-g(talGaP(v>e_xr$FirKjzB5WSO14}E;GQ!A|oZckx&f&4e@E41xsJ9&lD4f`~sDdgpHOOLqh zo2h5xxM;Hn@mfSY<&kNv)vf7~rl)B*9w8kKr;Q=*MSOxr*cQM~SWcHlvJOf;G$Pxo zG+37|4VKl0rJXN0G;C9n5u2uAS(5Td(kS=R*b9*6BV}RVt~4o+WLYW}MwuEura8hX)KH$NMa`8if-#%w+7{YF=N($w z2&Y}8{g!Io923J)26(>``$rp08{*mzt!GzONn71Q8lfxiMXhS10{|S;pzK2XLijgB zi*suct#YRrkrR5bYeElC;nU?SS>8*O7Uvq^rz5`7VAx5M`aW?VaD*SwkWLI?mj>e) zcKJxk=a~@=kqmLco0Q{H_}QOo-!X^|`x_&hO10?-hH0*_^sa$_0@rq2*W$Vk*A84R zUDmIrISxM^=_W6mMs(-7Ha@d}6-HabN|XIL-}N+1-E(A++RsrJq%7v0L`ez_t)DD# zw&8N=D(}Q`d3SlGu7$MoA-h6{QRJ8Sa8l>$Cq0)A>qY34R$>Atj`Fw@{sCi|kVltp z*3uQ)DO(DNi~97uQoFvZRmOvi<~o z(KSA)Z_MWzKt0Jiz-+2lYAqBwtqM4u<$0*;ZNCI~62@a_-SNN6`av_fh9WY0FXFZB zlOF6#=Dp2Rr8Dr;**rwYsH>TU+Dg!EHoMCbtvp6+SkqI}Q*-`;7{4g}(EC0AuO72u z+MJKVKZZ*k^8p_N*8-=2L%B)4U@9JqfrVVO>@U1fZt?XrGtopa^MD*!Cs}xDT0)rC z3F}qy$fH{qX|kbQKLxz;Y&3Rf!2#bt*w~+`QbtNt%AQA?rWrvK!B-2hQOy!|-eEsT+wo_z+ zwB&>RD{1f&*+4Muglv9@I69kG-?Gxi5{Gj9KCYd(q^!MLRs^rNtUyE>I-3{uVIDz} z31O-a&vIZ|e(IR=K>ALdd0B+%7{3|$Kpr9=wVP@3NvnIpSogZt#r&YVTc``9g?QnM zeqJt*l-u=$K@^o>)$SlNJQLS5aQd{InR5~f!?L#K(#*!=w>)dKbI&|rDktXI#-(+| zeDes?5ob`oZa#zL4V_5Mm%7b-C2x!q#BM}eekA{1Jpm%p(2+mLlX`L#-c&u|7((%$ zDm`I&c6yonAF{Mn=Q-alWx+eBl!g1K0HY%hy=4KS#6~=#Eb9cl6&KT>&4zst^_%*$ z%f`V@51lMG+kw}ro(^h&nl%0NTlwq)&+yqXeD00&$+1=34pll;TM(5c_&i56nhS+# z+hjh3@wtIs#P)!oorGo0A}z~0X`gvKNfY#jPPUfMctNLJYPlsh@mROoGDmic3un54 zC%#IhT?l=kK}TBsUti&P&U}w!$)r?0UC-Dt`&t0TF5FES*@Hjs9*s%6OKS zIE1C?D)VRENdD3IC)_T{w6u%yxdPuQZz7~bi?wEb{x$>MFf2YxDz!od5Ms`ub;ty>(1 z&%&=|+lY6zYvJ9Dd819mmfm(eL(}U7xr_M1#wvx+Gf~! zBRexLbGNK3e+k`A8<(xmgUltkB#kRO+9l>kn6_0%uLjCANzWSqhuB+H%VV%LGYI>2`x;;Ih33jPez*xmJ# zit*HY5Af;2^sd5;*>Ygh$@_@5&p~DTnbA$``%m(_2V-)w-;ZDF{;P3i>X^DBBAmtT ztCJbclQOq&Pigci>puiN%132Q@}G?I*z$SQ@7+%LoA6UFl?U?2-7|!xU76lbh$L-q zKMF+9pd)RzL+lH0!OK@yfvp3kdP`*{-=xDQ?FFBg*(cjB!)#}KQeXL`Uh)Z>C(kSG zllwaff9?iP?ca)E=|QlZ^Ki@ah9P~uG{xIAZ!^5j^0tS!Io|g2mN!Wx4fYKaBB`La z@cZ`LiISNfR5=e*Cgjh`eHil_ubqj)Vk6lOSO=MnKg$w2l!4p*&-$3CEO*;AzglLL zQx6|Okfa5MN9J4B&-PC^ZJ7^y{HA{vCh4~W$K`RxZ`G4w zf2|@W#L^yS8dp|xPMEgu+*xXmm%03`_YghAXIjiH4Brg$C2L6u%K}gP1L_jX!S@k9 zsY`sSEkv1zPOeT>JbXt~EmrHLrNCP*%uajN4)s{_z+?D`^+R@2Z@cgmIrM(|CTV)x z3J{Tojy!?~mT8`0mP}!kJL&5Clji4Jct&2+S4*|kK!&=rb~wWHY!?YR^POIhbBu%2 zd@$a<7eR_VglXP7=ZJn_;GFGikXB@n;7Pwc+=!<0xE~}TD&l8b7D3S$g{fZA<`9PZ8FuS6?cG-EkbDVmIv#pb^Hl3cL53<5 z@~QR4awYk^+``C%+Fi>x+le@a2go&btV7!?Wmyf(XLhQHfRkRY{sR$kI>sCQU%waL zSXn4v>M=VI#nbYs%=_^Qn&DU!c0tms?Dd^2-hSr7uVk6mp!QQhJe~4%?(BMBUFG^3 z@%r(pJiQh;BE#iMoi7)Aodpl3XaDHx>5NZA0u6l#4mRXm7Qqqk?D{&MVcTJx%8mAp z`G6ml$uQdq>yY^nSLIF|%0X=a-uLhhAyb24=2iygoe&9F*S5SvpON)CUzY$Bo@z(H z*YM3kb-4l(g6q~H-ycX9edO@#@MN8`FJ~bMS2?n7j4n=9AV$9Z$KKIc79+>i^0ZH5 zZ=5X$WcU~X5JSjAIA+nhboo*kik@077P-jnS-U1vBKZG0Ql4j3Ix8J;m+9=4QXI_JK@9J(AVLIlc^2@=W zS*tEq2fPEs?85X^VXwbfFWJg;Y5gi_u`Z-O7OU<08b0woRp)#Pt#z!8aJ&&aXQADy z`kKZ^BF4j!KFW_ab1#FTt`Mg7h7HN`G5p8ytIlrJUVaU@!fQv&VGobJZ3l=*Lw7!W zkyq`@QgEuPY>yb{%S(Z5^`BI+sPDh%T z(-UhWD-C>lTql_EkT2xF&fo>G`&oLFAGaPu6_u;?a!ZOaW28>VI?-}1gur!QLcn>0&@y>o_U7j`$e8=`1Y*aUSq?5YAIF(09 zAgFrhd4TzV`PenY*G`SwglvW%2eQ74_u~ONHgq-fWky9bkRs+&nF*Ygm8=8NUfJ;Q z7vR@i!ORGi-yJmNKKg$doaVIAyFo<5*uYUX))y zLbNnu?O*GG?M%wKT8_vLf3 z#uuL`9=XH2>k#ip?>Z(QXCLzp?YpCR?9My9JNA3~_Z=?syYO7-%M%PoKGMbq$~(r+ zQg$hStGO1mnW_)}TE_`I(2BKPgp+e6qEnQoXhH?l*u#Y z#eUUW#Cui6G$aNICy$RX0B6Hn=A3kh-?B5a{d-Ql)IV`;o~LwK;r#Q7uLbKEE zLOvuP&YLkG$;&PeFdxp(a6aE}G+X}Za!_3*AWS>_Z4=Zo2`$dW2^~yfVu~<)N4l1{ z+<%FEDc#_-Uz(YcXcx3c69Co9DRmAL^(Es1$)}4=oK71QT_I6itC$4R*fe@s)Qjpo z>za0zPsJsD4b%HSxJjNkZ^j)v6K7B#fw--iP=Dv9X8lgRg*0@U7j5<1aPcggME|z+ z>3}J&Ov1ZDo0(#i(uwtjuvJ^RXRP6Od0b0~hxWFW?=*D(gv;`h#!gnX|nZvvjzh*=l(tADPwng!xFV`TfGEMZu=Ur~?7dKPxuS9(OT*^J+mYb6u za4Prnt#8VYX*W~uZ#en( z`R5qT6Cgd29_(fh?1Wzc|GX1EY)FRkdl%wV7lz@dO<{W@O!CJ2X1>@CmR4$|Zqpb| z<}Wrg1Y<;s9t>ci3tPMOVW#teKp-5`z-|37ZuDJBdxnogx-u=~Op9?f5_M_`m4*|JC}@k8J%<_^*+% zmA}{y?pp~OpI<1*Eyq&aK0DrNP)i(@SVNz z5$fvo2{^}79PeEf!EcDXMn=r*gSc*VBFHDwj<7vmm0A*$mN9Y~yKFgT0Nb~(V5LGwibNxfsNKXOYLj~KsJ ztyjB-fW^W1W#o8>QwbJUjIxqGs(a++cuw}=A=d}av@F*Xxblf|0X}jH@Inf_1^9Ck zaLV?6!UxNCgyY8DiL{p??YjwYG#hA5_2w#vT_PTl4|(~0#7`yCp}t2xKzO}$+V8Z2 zpc2U(W5SU?L)`QNzTqjgmpZR*Hg4K6`0UB_vnjF6bW?uEuIA$6M(J~@XInCTZU@(x z=qPjO{>Y!>Im1`F&hw{T_}@nGIfdi>e&kDpoAWB|32{D7c3fI=$MB^4Z@`;Pq5HoP z+@(8uG2t7~#h7=Lb4+{c)pEOu*W}i&AP9VOcxNT5C*X{--*oW0r~Mix&*gO@rq3wT z=gpokd6cIgMUXGG>FRhWetne3JfdBSv-qRS&>;d8XBEpmE)ME% z=#z*a#YK73xp~bXtUUUyH5rH~E#{Y(6k(cJerQ9ZtExH8hF~(S=81Si8&5aSSqqnZ zWrPzBc#2c2Q;0SAkSXS%bchrm3n6Cotrib*8-2(ty!0U_{AfJ9^LY1r|~ee zY9vV9^W)*r?ej4nV&Sb1Tf#06I!?@(<7f4CQ{;s@+xqnASXzO}{0#C?C;S(SoijN4 zvSxdJ(g)t?0x`g4~ck~}8Qx3dE9OKz0znF}lj2~#Lcwd=}9X>nBV_%(PXN4Zx z?dZ4r<4rop$O`^W;QwF%e)1?-@`84ec2@TVqvnj`o!27P1ZqY|HTFe>7SgTCjd zK3f~@?Se7MhmBpf6LD2=lE+^V;JLAdq+F_t+C zx_eV_lgAM%?k)Xr&A})%Ey4rz;DY0WarIci5WlnmzBSW=PrjS|@SS4<$v1gPIS+kO z%4iS%G8V}2jG68cyP(eO$CP1s7j$xyOY`JrVaA1977|CGOROaP6v@ z@^F1RuC4xPJV?4T19ACA9JbMm_6@={$99EfJ3J6qx-!AN0X*E3f}47zmF?hJPNr*Z zHl1V7Cy>tkdn0Ziqx=Yu#;e4C_rQFJZ!#cX#7}DYJ04Z(7ytBKT5&VC9LfluR&`lgsBe)pDZ}{ID*ozUP+tG*E@&km) z_(3d`)1|oHCVArpT88S;;V2qE=>IZIzrp`sMvQ(ydxU=c|1gw&Rq}V^ClQEFnIIp; zyRR>vd0V&qj-3%aXpH0+ZHCwQb%{qym-y%)1dV^aiSIdpz{U^!w-W2e*sVzR;YaX@ zBMsEg*qcpR;{SQ-Q$IiD|8vI9NnX7lF>84S{htW+JGN2$dxU=P2em5C-*x2ae(0+C z5BmQQ^=r`of6z;g{hrXrCIQr^`9F~Rvz_Q8!AboV&e;QdE7Jeb`KO=cCwL*f#J6?i z`TzT$S+t2}443`^mCCvYy4%g_-G?7<2l#;gv9sm8AaUq6%xmu-EQ=>azH(JkGOG(|B)en zJlhi=*>|iLWjrgvvx`M} zoL#kiri0b4pi>3-3{G_7N7)~yVD1z(pNu1#ug z>}%<2l%F zCqo?yPj1T9O2=QTR&Xd}&yu?3Oc(E=+sw_cl&V&G<&LEZt->GjPDlGSY*E7f8#atr z;MPjl<}6m*hk}=Q=qWX1siFI2lVMbM7b2a&=-K8CyV`+Lp0UKDYBA!A)^%wk*i<`S z1asDU9jLpq>wpuBuHFRI�D&OoC_~4g9tivONVZxf$G+%wkS(-3$L@6`g_7TDCjX zZ0wGe1kn#$y$N03GHt`At5nL~a;sv6?tVfLDtBzZfvLbSPPlEX)KP=ol3y$FuZ?K# zXq{r6RCi!U&_G1m5U=65R9h>Z>G;rAvqX;HRd$z~6%TKR)pAgjR>?KEc2EoOFI}HT z(Zk+nZg2C&R%k#PL<|DCfDac}0}-x51h)~K?qcnF74kM)Fxcu&T_b z;N~L)VOxvMMmg|KwHr9ZRqhdz%wl+uLlI??rK2!lgi~v-g%I6`f&Mc>*Fc1>5Jg9` z^17#s*d9?dyRD%lOrK+iLQh^iVS_5lE(U?YdK6{9i&rZx;GjZX*QY@bZ2zJ#%`RG- zkJK}Q(H=>QUv1*wgAN>)c8|B*&27)R8E*hT~6VH+RLhvRq~;)h{3J~sayp*djcq?x^z z*=bP$8ODfDCznO<1T0!-efE&~Xu4M?b4?Ws7QJ>Z)|qMrada*+YQ<9qvbpLa3nJ%q zqJM5wVdWq~YHPXb@qjovoJ|L>VpsV3h4W*g84}b?cxp=Ca`=_C$B&co(w^hZu*X+ysto}0S)*bX?FdxfaP>9TytA4wwD77_a_A9Hp#OVEWA!Fl_#JplwLCf-}ERJi*| MwhYsc7a#HeA5G>kdjJ3c literal 0 HcmV?d00001 diff --git a/lab6/config.txt b/lab6/config.txt new file mode 100644 index 000000000..e82fa85fa --- /dev/null +++ b/lab6/config.txt @@ -0,0 +1,3 @@ +kernel=bootloader.img +arm_64bit=1 +initramfs initramfs.cpio 0x8000000 \ No newline at end of file diff --git a/lab6/create_cpio.sh b/lab6/create_cpio.sh new file mode 100755 index 000000000..dc42635e1 --- /dev/null +++ b/lab6/create_cpio.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# Make rootfs folder +# Select all files and put into archives +# '-o, --create' Run in copy-out mode +# '-H FORMAT' archive format, +# newc: SVR4 portable format + +mkdir -p rootfs + +cat < rootfs/Hello +Hello +EOL + +cat < rootfs/World +W +o +r +l +d +EOL + +cd rootfs +find . | cpio -o -H newc > ../initramfs.cpio +cd .. + +rm -rf rootfs \ No newline at end of file diff --git a/lab6/create_fs/FromTA/initramfs.cpio b/lab6/create_fs/FromTA/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..0676fb1584617bc4d73624b3b212a12133e97d8e GIT binary patch literal 247296 zcmeFadu-%ccHdV$vsx`?ted%d@}clzbt z5cc+6pPsV&-rgJ2LnUEv@5=)(_YY1F=i|de```868~ICxdZN&ZPX2Xgj9Q*v@ATj> zu|wtQU3c_uO!f^W{2WeiGEc7e-JgB;)mPqpv-^#&d?}O3JbW(m`3Ls<%hiAITl+6& zo@Vy5fAnvj&wQuN!oRd||HbjAkN>00ub=y?$?xue@VEZy-hcRefAQ`2zWW!C|N5W& zMcX&u|MkpYO?~&>=Q6)Ydh-44=RWu6zwyyWYcIAv|401(a`k`sJMTZg`@e?re>n5O zvrpUa`RBg#xlHEs`#(JX!E>L;Jo%o*e=ajVy#ML^y`}lQ-GA%3&wu&bnatX==Reo6 z|NQ4W+A^8k3zqL&&t=|z#o{xW$19(toafJd=iDbUfAC@^^MAkc;YT4}bU*s}%pdIk zVCI95tZpBDA@lSzmj0R5$?|k$-un+$GnsRr&iu@atKWM*)3N`B$4{UA;P?kd=NB_Z ze>{`D(Hz5V;=GHd%ifzG{sOUpH7|GC9yGMV4aJpSa9 z|LwWVulO{dB7cwZZ8YHfnU#IcXhEZ+nD#T2_kW$UyuXt?d+}=K?ce{mAFYj_d%V&X z(iO{qSKi%+-}r~&-3h~I&s$v#AHyMFy8nFsx)}citn=|t_Ve-Qc(B>Sl<~~!a|JCrE1; z8SlwEfsS22Gk)QV{O3$=NmG1>e=oel$Dc8J7fgPxWS;J2ere@#=G*V=cUoI9?7%gI zH!OT?_k$MhS(wc{eXO*%@@XdX;cPx_E}wQe^R(?;zTDM(nvHz;(CF^k@72uHZ>zj7 zQMS?eaz1>^(tg73-_1OIUunLcfA)=h_${MBo}W*`P>25{PvaN!;eTdf=5Ma-|FY5h z)g&&Y`}KSoe>)%khCTmH`~6*ehbHeP7vBMczUMQ)0*>$7yWD@*WcRVP3$A}Tk>gDM zI`dxUv(VTd9Dln1uPn@3_~#b>riFiM;m=$6#}-;XlcA3Nx03f4+Q7Fz`Q#T&jz9V* znWz6L@AR$l5B6U*o$^n{jdyD!ZJ&E$@AK(P-^^IkvisiTzKwfp@5XCKh~N9%lQwHF z`@6jVV!CI4K5jT=a_7EzZgu}pT{-!3zxS`kpN`vebcUt-H2gh#HEDbB@zHlPPahdy zAN{k;(>eItP2@iFA7}1C|J;vfJ{RIl_K>>}|IJT)E@SalUI(H5K5JzSA4vD+j~DZQ z%IAOXVE!-V^ZRsP{IO#GA9DGP-U0ew&gcITYcGb;{vRjr@UgW;<1JtubkD1%Z$^G( zb^l9Nm+ij}CLPbdY}c7{!sY3{;gg{p!)O1W*?U5d8a~gscJJ(#>4u;Gf6(8>_ZZ%p zy$35d7h}Eu-F#Vw`7^HFd!(#C{>zWn9{BHx~^V=3j8~HDTPP2OMed@^{T6sThvQkLf_QN6V zf0a*r&h-CPbo7hoo<4i=c2dvrAAYiFbYA!Q9w+&JC7%M zl6stboaFr%`MfVFZ*S(w50JO>+|!rP%bmBMwp;!-&)@qAe~Wqkz{l$HOXtRa{7IYT z`S&gT=Y9IjXF`3(^XYFJt?`MWKicmx{(20DZ$9_Af<9^c%#(j(?~#5c;IsFcCp!f> z`EFiL{y~tF{}%ap(d5wVg^>3B&pi3(miDV3ee|mz1sP1zfyqmT+20HDWPRwjtWAE) z`l`On+k3`4*UuTfapV2NZzOishu`?UKx6+$O($N-JjJ%!|54MCFIspm^Gg|{WqRiW z>;;qiKmWGrWb2DR_;KoO^i4l~mh|VaAuL2kVJl?N-MTmWkHI~E|0BkGxTbG4y8Bng zpIYB~5BkXZZL^Kw(QLJl&fkXy zNvEB}j?am}zaJVM=rd|I7I^FQ;> z?Ar8Lj`#oVA9%d-`<6b~qh{;1ed_%m+c(U>kMtSC_#>mi^Y2+4cHg-5V{Pa{UqZKa{U}qgVGn`(*!f;AhwG+qJ#tfWa-Jl`r3(eKzx7KYoCXoH0DHfv$pu_3x&8 zL;puz+Adl>2Q8oV|ImM*dRjT5-CEi<`d9jDOZ!sW`#*L*l$GyyEk5Ko{`POVdgbwM zLoUDY_-W=}|BdfH`+1X(*Z2P4{lUkS8EpF3sCS+p_~RNL{>A@S9J3VV^1n;klF7}p zp3Dc|yOH_ej|Vd!{7E+R!9Ty1`QZPU%zW^tv)1R&nk_VGWlcU8FbW~Q2T%mG|&s18!doIXt>a+cGp{>7Y;XnTOGHWmX<8yECy^w^9-0z)x z``gc3_)C`VlbN-zSpA+Eru&}@`sMAvYqZaG*?aicf8#%YX7cmb?D_e&%xAu5czn;& z?HcyK9i^eJ-!t9P_RaBM9#7ue)9+21PBHs+)86012GV%RXxuUy6OE!Vo7CgatWRlA zqcKtiRxV8nR;GXRdhbeJ@7X=F@ZZosT3nC|!=3TYr;G>5&fl`<1v#_y{{`vOWYh9K z`#+O$_J`m2N68p*GV=$YG97&`lleo_Z{G>yKpSIOy9nc9jm50L{NSojmzQ~sxqQ00 zD$~7QDV_243;wx{_x3$s_T1Xt)4!8XgI!m`^R3JuA){diAw;-+h6HH`@;UyZg=? zUwyCbJ#vtu?JJh{l`p;4{laTM^V+K^>8CBa%}qmfzwlFUd@&_m+v@9YeZ9?|wY~L| zZLfaqop)X{GI?IQU--$l-uZG$rWuQFd!_Bw*WY;ai%M*~y<$1veC21~ZF}YG2HIC% zYy0UpzWCZ(-7f@i9vY2DC1vHnEKjQKCw>+tx?gzrjW2!ml{a_eEGcQ*zW&C0ueT-X zuipORPrvfjS6};Ld-n_Py!NFx-hJ=2cS>lrwXKBceEPQ6U-{}6-+b*IpYOGwdE>n( z4{zb#*WP%qJ9%%$V7RzzXua|7&9+Nlw3#yd$15OoaC4ghJ;KQZC-4thphP^CBy@G= zHlrGZ8~fj@ufO&x1x+Ter$Bh=t@rFL{PZilg;(GD%2%vTLGqSW^8d#}9nURQXz zp54p~)`uYb3hlXGIiC4e)+D|62KK}N^nTkJvl=cZR?j z0^b)1v`-%I@8by4@ervk_i4p1u4U)sd~W3G`Fqm~+2MuG+~S?C?AFrA^3HPC_DlNR zz1Dk4KjL`KFW0%dve0>Jc50!sk20=bI{#8!zV1&8UgDRqf4#eJc47B6b>Hmio!Q#G zyHu~=M)%&t%C*I7U^qHAu--8_JS*C*j+OX?XYi>vHkB}59O=0)`h=~Dm3Zvy-|6E$ zSE^H^o*}n`mnR0rORHfezJ@NZjNae5JK885swo#4rX7l>R>4aA^sL?4UfUTNKCCX( z13kX-X#0Alw5vN^{pj*aY05qGZSbUV5t#v2ofKB0uW>qkrrw`H&aYFAnL;NJHBAS-E@UQ}#mN{q^pdo4Ju& zb1OUIvDsLO?&#pk{7n05sPph__te+}7N?NcI4us$t%9t7mA#Kh-#}*ZhX33Q3-Rl~>yZ-3zCF;;~@%Gl- z&5bdhAv59;8A;Qtq$7{o?n1}%;GOKPiMu16cla%3muGShJ4b2Pq`5ZLzAUji8E>I??7*X`Y_H<86^f5G(erT(6UHB*j z6P}?9Btz&*bkj-Lo8r4;rsrY-AIa17(i+d{uaE`$G^Hoxz8d*Lr`_IM*&4q(wmv!B zu?s%PCVe91+??OMB779eHbuwNkCf|Y)82g};#BXB>5i!qoMu;T{%1Hx|NLloXcW0o zyFreqD{ZM7c`BD?vORkl`q_oW17jZ9n#hu{qmQ9aVXQz~ByS@yDOV=+jBc)T?#gZf ztC`&_@wAU}^^D`ekv55qguRL!#%cWhjr&W%j=Ysy+Y}ZG)yI|_kINn|SEokAg9m?| zrjLXZ?T|R+#@DUfHL~T$WaOnT<A5QmZ!%;o1m}qY5XDqYjg;QdBld+5h1$rE~=wCJXZ?eSn|(#D9B?m=dR zOB^!xJ~^C>$9%unF*Df%AM{U^u<_66`&57OVsrWDx@Mdc>NwTDgKnC=b2Z?Bo>tun z<8hzI%BL;YP8t<29y@0*-0Gyivw9E*R@K_#JG*nYkt;CLxKDN_Wnc?nk5R7L+`^ry zP3Dhp&d!86r)yLFK^`m3k;)FGoJQeMu3X{NZu1$T@0-mowCCr5LcInq_tO6{ew95< z-O=Iv7>A(GXsg%`*q39QmzP!VLituV{zh+ZPmE>za*P9pHqPHBj&)DwGHH8h;~6hg z%0s?#b!t?6QUlswwlnGbE!|s8&KQrhdvrc?FS12celx?8I!rC~q1&a`!9;T}@MI&tFa{(Kw!3Tt`gF<8 z`q=o8_~%;XcTBBkkt^;i>7p1X=_cflITw{D8qEwvyIjba<3Uf~G;1@YVJ!h!;pgWX z8MBJ-o!-9tvU`$olG*>(Ul{f|@b~KlF*g2Qb1u9W+4P=I(Q8I1x{R;*$^LCO`SQA5 zI-2=2;iU0AHY4*|;6pp*UgdU_*tF}xwr0MhoL$MB7@9}jV1H*H>4@I7Piv8xQgA*k8Acl zkUr*D_st4bFU=!rEFn8I(eGDwy?%*tQW=EU_not|%Y}X+KX()E!`wuYTJ(H7Lw=Y? zq<_RNMXs3JQ~AxpB#n-E5Z|<$P+zmteO*0H=u~WIKUajVLXTl1`Fy3<7ec$Ee00CZ zh--~!cn(&`)KEun7%vc)#(%TopwAz21h4el+?Uu2VI0^I*6@@*4%t_rx%YBd^<3H5 z^!eydJyzJA{yDP5xKQgHJZly%F&*(Gp0)Pq=U#$LFi({q-zX0uc8%-;@>2dz@3@V# zlezbju+Z+3^__TqU3P#kKkYiMLo@EhhxDr2QmT&0+n}Ehbdf7BPn09x;!rf26?*zwTa#?iMh?_9-(Sf_04L@(8S8m_xm2F8ow5rF zHuI~{#OBvpnEF|8(i|{pnuWn(bUa2}qle*D^(~njmOL2p zlBfLsiZCyeqOWbPG-WP=9kFH6tKRU|hikYu6%$Ng6OUFEKC2Wu*a2#D< zy^-{T)z{hcsq1>;P)%8)>&N(MI8+k{2D6thKk`5DJJ637Y|rX!0rBX=YU)IY!trZ-F2QWuQS>MuGA<+usq%yWx8g_m^ z=}~y8S03?SE@ZsQxS6>s*1VYmrvA(sv(~BgQQ}yiiE*Lao3rP~HSXp9z`S6Zel#p& zIjUEkk6Ml}V*eQDm~>ySPY@ zvRkFzweXQv55?6|PFh-(_TwLa9MJTR^?rlHQW#%ra`&_PPn*Cf$+uIk|-@+a^_T}8)SsX2QPG#lJ zc>DPLl?#-oy?847v|%N_32k0(mHAq*@cRP&p3|dT3(vLg-u|)8g-4!dtK;Q)WeqKt z-Cfz(t*T@$ERI;9ZtFA;RkQxvzb_lrk!;j*tmB066>(U(Jxoq=BQ^iI3a74eS7}K z0Y6V*;M+NN2Yy|&H-&x#I<#HwU7@UIVI`d87liY?iesHS?OmtErQw83VqakwA!llL z*rmt|xG01sd-!FKsU5Som}d*wY{A!Iz$)*rQ@l1BFVR`*%uRC+#h)eQ8e6hl8>HVt zMyS91pfDz(e?niY>}o@Fk#O?5oBXlfgLa&zkyxn?w0r!{agWR=a-Te9EFu|#---EL zm-=euPYe6|*Sl!PtQp&x^LEa<-0kXIM0Qzkr=1hh=E)D%dMD6OnT%;fUm@whiZ-lt zgpI<=)8LwS^k}blZDZ$d;rupo4u3k2pgco%mT-2Vvzs$f_AC)UQ$nT@Q@oo5=U0j=B{}ucB#6NliorBK8cS<$& zKQv9x=JcNZz#Te^i#Gy&c%V%YN8d)f=Nj7BojmvBWYwk7Aw19r%a>7MkJ{{ou+oja<7p&y9yY%MIun=Q3!Xo-%X8{O+d+nCEA;im$wn>6l<6G#H=^HX4`Jb1 zN}Hq{%155ocl*|aiF8!(kCC6#k*^Tad;Xhso#13=4O0A!$|k1HmFlZ!;HdHl(f^g? zO*r8PYHj!8J!~UniGGd!u#};33mD3#Z5B43PN81rH>E^JnVyn=0JRh0Q7%MpQC{Eb z{OZW$eDDcIJ1duda{gAZ0mibu^WYS>E%7G%L}Mi4eI1&0Eq-hdvhy{1C5-p*Q(LZ{ zaXgp^r(2g2-+r zCy@qQo%V}f6Fz!Bw7b=%%@xh5l$-Noe4sqdlA)N6=!f%|`MvD2H+ipqoJQZpc!eJ_ z(GpQ(JqxK^Iw#=&Gr1K zAy{Jca=jZzSo!im`_uv$FP!9LYzf`A_WN9EP382yK+QYi`Bk;;*I8TS=yZ-!JDsx`3hK zKp%umff1Nde?ND|SciFtnFrYcje7{?hd!}4nA=UxuS1LSHBRx^=$d&$(qKbjQx(fP z8M*R!Fh?!9D#V+t=^C41sq4ml&C7rb&zOe+Cw`ifQJxO-qas|m4mMlf_NP4xmpDWo zRYqFqWxN^J;-R2ttbJgsC-L*EiJ#UU^P7^$fYKu`YE$%O!bvuCIByvAp80As|0Cop z=)wHB+mBOXoVaIxUG#j|3|wLwqK^%O|5V+FFz79J7I=1Y37OEmp3-7x3#a~p%i-H2 zot8HEG0I~^T5p4(uZW9n0>;N0BYRsS=DXSVs;lM@!K=_ep?mYTRcV;_<&?(&T?JPB z=*K9t#J-@Ms87}NxX+vFT6}~*x;xi4SHX}zS3EWw8&3}&;Klbn8o!tI*Hf@dlkZNb z9&t#yqgQ*nrSnR#&g&?~aK6pW-s!@};RaZN+0Eg#lD6l0Z^pH+6TH#~OQtklD78Ud z`;&~BUk2$d^qaQ}urs%Id#9LVrmiIzkw1?U_O{0%lB-%!so<3RA@+Vk5Cd_=?3 z_1Bu`ATDh_??8R?IvLpk8($V{me6BvAkHWMlB7p|g_R$t__F-9>d=hP)AiTLl*Z|$ zK1NgI3Ar$RO@45)U+4$0({+tJQJ*4C*8klOG5wlv*0=5v#4i61dxgB>7zNpl#_ zC-Gc3VG}V=&3)WQ9l*%x8TvWtC+1f|{`|NHds=n?@yzS3^-Xl~6Wz4%BygyPrg)Xj z>Fu3Vj0`7@*RUCtk2wLART7$gFn6)zCGR^6%t%uWf31|p*Q=bLFpru1EfjTl@~sne z5d9_nA=i_a2QRMmF$eQz^IdzBw2`!WR}%*|>`S98)t|B%D~p~Fm4?vAbM2p<^fml2 z@20f__`$y%`xH~>Nt_Hbn*KkuMqUe|1O&Cv)KrPsYe#kWEz zp7=%>^@{7tJ-P)Q9QK|V9^A+2R2SmeOX$Bj294snJ9F`-1H<0FWGo{d;!tI_O6d7x zT*4S`dZDL}wnF~|eys1IhnW{h<_3D#kU_4ACrvUAPUZ>n2P7GRj$P&bv5maCjH+2TKR5fdXEu% zlAD2##}|5j&Agd)ua=fDqF+MSdj5}djc!MmRa*w@dU4-aZ5qT zCw5jtxC7RXF8-ePPhQTr`uO;I=4LMV-lAMR!w$v9m|E!UlMRMm z3cRqF&c3D2HF=ds`~5>2dnW#y6^br$F1fE(wq#RRYE!fwXwc_lhhwLTCZS}8GJHJv z%kL9dfoq(%*%%f1!?%O^gyQUg>0tOHq^`Qx`z6$#E-!z`2X-TN7i~`17ilEl162Qy z4697ike)I;_Q<-=uj@wRBs$o@$iCjWt>Z80?2`ID`KiF3;+;}2+6|#_q73w{x2Z(~ znY%r=vWc&(^+$Iv%3lj{q>=v=u#%rZt-`zbqs^qr#ZlsrvB~-DMQCL^ z<_c$BX@kV^-q3OO4dHMu2)jV^E4YL(WdX_o6<>}OZKdd zW&0NNj+v(Iat({9mAU{+2~dki_#IXb((Ff=eRh;AdV^ba zQ{%m6;3FEsW_sa9|NW(*L4IJwZ)mt@gXf$D<6O7w7wJ~|G3EDRn*Tcb{=@K-KRa+* zUh2CqoP62X8Ip6=p;;k(nBS8}qPMlXwgIo~hveD7(BQ)D#lBtX3*mHkr1Q@9^2K3v z4DE>fSf0@JYRjrGc2XK<9;e*3#Z7dP@+hS375q#XZ{oQbAw1CUjy>!fyfHk~o}3>j zo>9UN+U%pQ2j~gL4bm6rCf}CQu615|U~+4f-?h9BMu*4gJx-A^sfBAW7|_3-sQ^!H&>9Y-u|7?$FQy>TbO#qb&c<}SNG1PnWeq0)t;&Ko8b&~ z8cygac!3`Bt2qI5f@GOc^9Uz}6WAb2MSna(uo&vy5`*47%#H*P_2Xb9d7`}vQ~5hY zuT$=D``|-ln7MfF!Nud`=lb-nn-LaJ$otHc4;aN`V@kg0YyA5}_h@{kddDGp-H+>$ zL-0j+(N78w(L;vis}ozzW2EboT3-;4$(cI*?U?V(@XMb?luss`1Cfnf$YXW^cp+cZ z8yx(P_C!2B?dc;)>&K2<)3)eKR3;(zws48Vlh#okQxn$qO3&vedfnQiJ%fMjV%3Mb z#PXnLhlTVVl*L(>Vwv-+*dgSljmP-tp0?N5zf-W`o6+t>L-h(+AxrKoSfaNk!#sib zLk>2_Hpj?MUAe~o^7D+ynEE`w=&wP}g6LL;2=8L+^X7*{pM}EbKr;bI8h_SO{ z`S+u~1Z-vB3Lor+U>Dn%Cd_G??dj>n{50y`(>!>6@a!AD)W8M%554iAr_X%T?(Knr z{H#%qFe2o>sH4JnYy$or(>vzNk8|w!txMW@EK}f3e%d=@npm$j3YWNCVZ;0hdV}!; z^OODzA!{JPUeC7=~V`!KFcBkx5w zevj}-9M4OAWSQRQj6VLu!dNFcW2kZn(b=;d*#WSk%@m(8&i3cSwzg^8K{w|6SmrT3 zPH}&$vKom=TG^tD9`O8et$rzKALY*CV^`qM@WL&P5h;`P6563}i^PNB=+(|^u}=}O zl0K(@W4=Ojg<1n7e_9=y5eIE_N8ru)limR**)6i&!+VeV#nL$XuHuOxXs=Gqjo8EY)R2E*p(aTz-*q=@or3ycT_~9kfGz z9ZRmwCZaTCNjNcfVNRZS=G{tgGX0Ib+LN%xf{g@iwfR!clDoJbCvmSjvc{{qX+H;3 zf=Mh(+nhH;{{?*bJuSv+ax+>`H_*ot&Uq%t9q#Wkp*ZbB7<#+8g`|ktOP*)qP)P~dQ zec!$k|H;Lsp`tE4yHZd=V!8XcDxl<*!xJ9a)|t8L9?X&B;TvRq9_YAIaOze;45h zb*~1WLYlk}<;IJSRl zt*crL4ok;-U_X&)Rx9(Zk`BJv^T+&@_fIGO@KeXw9_;42HYdPOYx2~c{Y}I(?)5m! zM;rSacn6e6`KK8t@lMEhl9+d4+|S+v#`S6V3CC(f=A|f8w5rY5O6kPA#xc70A#>#H zH)H*XH7otGcD4HG?ltC+nF9b@LiQ6dH_W;KbDzE}u3M@8)$*b`u$M>sbQM?6khvG_ z0;kFAtW zylWjUjW?x9#&l`^rJ37J=HrxKc?j8)_;JBW^-?|KP|uU~rsDWlc0rm%w)6kH1&iWbcBl!MktiCF=}{OetNZ(3jil*X8O_iEp1Lv_qShD#%pfTXDrylvTVd zUR9#eiqDFi7q1TEvzRh}Wpi0!ADYcU_-87|$LU(nPD?1h71qMH@{|izR{UJ?-_M~i z`F_UWtnOzBoFQ%&d!m6C=7dkC|$D|gtl#GW_y zZY*S%?{F4vK6hi<_MhD58EGu-fjtB&v-N6QJ4dRELiR6#0cXzm)+l?Gs`-)DzOg&N zx0`M2c(;A8<$}s2tevyg$l>e2HQ(I4_o(zNQ#JUMO9O7x4{n5S$9r0>QTyt+@O<0+ z^$v32eS?&%`%&VNOTO(an$>Z5@~Olx^0PE@t7I?tQE;d>PuiYd@pAI06gd!2gzRg( z-#vb_+B()F9qlmfoQ(J?a(Z%C;)QT>Yquu-Tn~&?20o?aiw0i6O=tAEKRJX-=Md@7 z#dAGFbP)BoJ*tlmE0_LI?~OBg{=OA(qOU)!4r$NPVTbjD*iqCS+bXRLA16Nm!iv5B z;HCSMz)G}PYqIs)%gFsyv`tyuXw)P&QcjxJSQzS zJ=gp-8!OR`L-3+Laed?ap|hrN{0@ z@De@tc_Y`zgyIORl_~9wS9s55<^YhF#m=6w zjnU1^JG*nYJudO}_U_f2&;w6&6Etb7yhDD9Lx*|(8jTUg?6VtZGCj^ z0(u#lkX+%5rGg zZ$(#PKMAw(&dp8V?$pUe_iB5zH_;T&3RRazhN6Y+ z>zel^c_$7X9{e5N8ZWF5pvQQ2CpS3-9>|s24%m4ciGC29L**0lZDwInE~M@09Ux1L z>3kWwZX`Y`8(OqE>ZQ7PUtK&$Hz7~FPxXiBd7f2MU(%3v^!`jou7AmVg;mZ6uHd6K zOdp3`Cz|BfpX$-*5PIyX<(-!Ehly@Nrbw?umB50;Y$#iQ$0FUE3Q$3AcA2e82= zhZ7&aN>4bQ>%5Om;O7U3Z!|V4U%c?{sFQ49;x*61JMFnNFs!t~iT;N;`fu8-*G0m| zhv1^V0=+Mvo6yD|o60W@hjZDRUDxIxjc=*nkljl<)uYj&ctW30C+Py>{TV^-H3vW_ zTSm46&uJU@D?~@rzoV=4qumi-9*@LF4Yr2*jljcH`_@>t*L;Lb23?5Gq}}t3zeeMu z@I>l$)BFm;TMf-#w_rQoy`4ucVGYR_|)dM0lKkscZ7RvRn>=f zhRmuQ+Ai2+uS|sV9@L+F!W#b>9d_p0Mt4D%F-NEV1G*YpQeLAmqI~g9{~}#7do$a| zyiWJv!!3L{(Ef@(>X5MnE9@ER4CXhm1LLz~)Ezm1j>aaOgQA|C7n5Dhz1pz%1Jp4+ z7W|G%j=+c?eTd#?Gq6g-N$=-&ZY|v(kNK|9dydEKv`^~1a%ZX?Uq#3m*P=s+41$rz zNzds!!u)sekC410p7B0}5g|5$#tF(xDBkNGiiX-9GDY2>lN&AdF{EH3c&?}*xhVumn&#cf!h0}rhayG%vZxqhHSb0!jd?0yB=2i}V z*Hd+BM5tOaJ}=_L99#0QY}+%;I7dhR1Ru_+96Se=$OQiV=o4mw{L$|tV_uffVa(g4 zl>rTOk#Hhx_8O;f!p`wHsqJm|_CDyjx_I#HeZgiJUQY7^k|u}p4JMjCM2A5On=;O; zbd15VH&>SC?3-o9b#%ScMuy^nvAxGBxlSlEmlE?Xdx0~V@w0OG@_UG`kJ}qM3u<6c zn*U1p_6K>EyL<0577srgYpUO+4voY}WeY2B8zeX-dWv*QkMiz9P`bGe1s?-+R-`A>YNkNb;Q zA@?^nX6-v0iTxD({l>bz!oBnvdvZ*kg05mdN@DTVVCvB-O*77psWlc7t-@AkiGiIVp>@N5Ta*N(~e*CcQwI(HA#d|YD(I%wt zVeO5%5as}=3u6v%Q>OJx9+R|d&LUEN+8QqL_-Lgcl)Q>3#y*UbWY;$nmvXek+hJkB zzNyg8Vyp@{nO#8nvb)o1rQ58eEyw#w#HaIKj6IS(<@e)AE)si^Hj5v>#KvMw$xm~h zMT)J3&tdOGd?#b%>hzN2D#(w?1AmDxgM)S{{n&E<*gSsM`fkhzU4Ix)t@!*nILYUB zu(?c63qOUEmj|!Nhacg@jbhttMJy`uB%G?X!G%FJq2x$d<<pzuvYQ<+ooDRxE zHCR+iLtDOeIoFF^=_h)vh(#ry#5e07vd=5k{dmuU-<2@OSBa-qd?uVU2gg_fKViqi zqkMm$aU^tG5sz{_2`AR$P9o-wP+k{C+NCkN6q){&}s}zPwuVwtD)H zbKP1U`!oK|5I95N41qHQnuCDv>#DhK4p%2jr5YS+O>?p}sxS4p?##~(&P)vQ{RsA9 z@(l^*IGLy8$2I$@_2c=>&Drejts9rq=Ar7#?a7oTjKGF-df}TI%Oi*S%kcXw<7@kl z`2tvKU%6)oXhNzZkw=jku;Ainb3MRo|nO>-n-h+mD)wkH=iT5XWLq6dRY@a_K_zXa4!t$bBRSx)o!`3SKX^EC*iDp5`Mr$=cKjn2LIx@Qb;{0 z3wcaShdh80&qXs1)xYtcBvaB$@IhN;Ea~%AThHUBgC=7U@um02Sr%Kt4t^fIAFVVD zh@*{C7JGfTCl9#OXK}7UxfLUc5x2e z$Oj+dNwVt8RbN@`` zfF0kVTeJA~(Yzon>w!TMACptdFuL3y8hl-vJ zUg?>-W3K*%q55WIg)>#WfA7yImXAvJ;7L0}Z;Rfe-J#Ky?bVt zkBULH`8+MInQsIOjn%bxr*Ck!*W;xAN`6Nw;ZW%rI;zv?#((H`ug~E}y3ePrwx0D$ zC))A_CwbAFS&WlxWcjhFghi!i$W3;3qA;_J&bIG~Ga)nnKZl#d<8PqgZZK{aKG zE}`sjbSm#pdT6+P@S*STD&aJ?d3kwz`Qk9xAXn&U^?>w$=d{6!TxYhjH z^`f6?lh_4dBON3<=t|}bq#tcRbr)E5nm;zBsW%4IlqcH4NxGbPZ`U!dBaQSaeh=v9 z_@TRLd*~zCo}BH+2IU^Tgq$Qk>vET4yIMRDdK;X%7ypdwYUFq&f|AF@Zk$Xpw8Mjs$~EMQ>im}>!Z+4$27HwHK(Bwr%ho3H)&;Ntm_T?fr- z>ePrd&}RNgd?8Ef>%v}e^EJ?OWn-(|-Z^P$3wjPNF;CJf=pxdCjeKMYLomD1KNHGB zjtcwojh5!T;x!-HDJOvyH2H&Xa6-mu6U22+FKv|gz`)N}-fx5QQP=xReFOMB6ka>M zQ`>$H#N)(RR(T17zpco>hI}DOAL{*Kt9Tg|y=H{snRf+W$^CH7`yVX6Ydh0BJGrDh zafqG)6^(-U~DmziX7IF{iLX*7Y7$PP1@=Zt?va zzvjoX1RM9hr9beemiW8Gf28?V3vyOGqoFz|JctwT0^d-H{|nN2e?anw#9k?3#QFqw zo!Y$0ZZuA!BVEe(T9B7=7=erOq+@wyH}RQbWmwt-(*!$Y3|W$X(zjs(KEXd( z=DUpa=yQz$xNjsbaoL_&%8x-*24P$dI%&3l=h1rK`hZWT>sG>|953S4eDEExseJpYc#Un2 zfBf*9?1|GZUrK!V;d@Q=6qe(w)#Al(@WWSaTdOhM+NJZO@=vF=hE~JjFn)?SIo}O6 z;tA84LANQ7y<>LAu<^Ht#5))44$H#TX%FRi%lDt&n zrGSym^O6pmnf3G8?ahgS;mtDh3dhBbdEex(5^t^cOgyv3!uZ1T2X3s>f?GZ1jlLDS zo>r@03nxNsYWCcvVMaZ`k@1elk9h!m`sp{{wKvI+c<^Pu1gw!${j|UQG-D;)7_Tw5 z05iXaQ0cwz^!DBNzqGVGXTAbD&`3+us&T?bq2GU^IK~=`W%;r1h52^Y;J9bJpEh1( z92e$;^Ly-z;~JHETH9W-mz=fl(tQI(AJ4@a9_@;6<+1-oYk!o|it^)YC;k+dtRvVu ziOsXIhevx+!rD@P&HE_zQu&0)DtlnGkM$_!iSI^+o@enG;%t16-KcpxFw%Tg5?5T4 zIx2sn&HfeSRrg0NuaWu0TO2Yknb_CZH%U9w_auGV1Uh4aF%uE{%HS7e78s z{L$zAVmiNkK25#p)4qNAx~>vB9+if;tZF}+66IBJS-n^2;d)VXk;Ko3_U%6U5 z4okP#)fs$hh+gw*csxqtmykW-^^%`Tc$GV^1rNuoO=EIE2y4U&)xoY)! z6;KyOe4B?e0JYY$9_jCn_HzC#oNZ)n0{;r)t1*&MTdCrOJ?`{N^{8`P27O{R{UYsL z`wyp0FN(L?YE=K!;^T(-5^0pK=3Fi1^W!?kFus?*0wHvC*~t*LbN?y z$&mbS@l5HOjS=H7WJo+EYfs6VW-WS3IDvyONeh(@9VPit-4)W`kyqzzNvHc}ej`u( zpc~cqz#H*=J6h)^YH5GcC6pQCLmR^`V$VUmmwa?~eSx#;oYm*N0z5Eo6kj^4%ovg~ zc(3B0u#s{lI(l!^3%%tIZQ3O?B!A-BhmFLDvY~}-Lfw3QdGE#Zokd=iM*S6gRAgU~hc=7uh;^Lm z#NL60g^gi+`oz9@Vx08NM%tHTO1@cDUZe35M$nUPgcsyl{SWdjeun1D)@pn?=zlL5Y0wlrm_i{JENbG z-wWOun4w>lu7BuCiGMoy)iZ_23j2M~E%?Ex)dv(9A!A@mnfTTKU#^i`$vh#pgXk)3 z1WsO_M28T&4|&4IOev-gAzK$`(G@x&gC**jei)b0q$2TrQ%aYDZ* zjB<64eA55Xw!=F#yBvM!^`Gj|j8Irf4|7lZL$1R)e>uTF8IAFZK152M%C@&ca^j-uLyS zL4RR;OLllq{5(It4$Zh0?Rfk|Jbkgodb0JvNjjeT&kS#LP+#;2{S~qT2FM0DqPM_8 zbjpXek2vpBLbOCX&eIHBVjAKBd1C#EHU*#9PuL35Q+}=lT`#?({I!Pk1t&!y;jnB%+FcM1Il&WgugN2ai= zRd>c}UiTE_WooHUzRU2#Mtbl=o*5^=lh+5$!p74PPMRyAzLFu@LE>W|;hlMH%}0@5 z=~fIUmC5-j$q4OHI5EGCzbxzxU*~|Ko#XW9WaV!Jdq8|aSGTA6Y z_4FEjEnewcROj}oiSBgYMaDaABCl(eS0U%eXm`AKWNOpAt*Rd*6h?$`@yqi=pxk#neaH7ALw~#BQx^N8F&fpeD!{TcHZ|C?NqvxK1Ag<8z<;NoAZ?5 zw{dG|sb_QTQh{IjEYNvyWKMA*#5bM!BLYKki)4=XfV{C*Nt=^i3)mnPmOk;{68Uq> z`yD~wF;9TqM%z=HhSz5NEAVN&^1hiP&^cD-dSfiq4yy7=V|COyG*2hKp0jzu)OP~@ z75q?APBSoqM$9w!^xN1?Jiq;LEi0_RCZur&0N`gi&~*$B)hK}Yi?4|@8h?OcB0ofO;a z@N)L%T;J%;?J&;(uj0GeA++INb4H9?i7Vg~bm@FpBTBayD*3?R{O533vs9nTTnXc4 z=wP!$3!Lc3!neQjwg5aaS8*%1wu!$(>Bf`73cCDhy-j0#?D7Xao12Wgc#d3DBR@V3 z{U3Rm8isiPqPc1=4(8R zi|{ENY_Ft0WekN)sWFuJYt>NrgfQ3wrLuB3Rz=@CDyw*Iy|k>JD-SpCOwZ)5<>xV( zmyrCmDn8;%bwht@&f{=wO6#B4=j#u_C(JJ)Ly_Gua(Q>ieE1FGdu`-K;&a2>58|g) zL*YbSc}X!PAD5Fk=j+ITzXh_NN~s9|@C4 zpHl|?o@lmeTZ1q081}J-`MB_{hcISgEXMkX$BS_?cvYI$s})1pT&;qWFi}{7la28U z^~=vGDjnl~=8TvF_n7VUj&Jir)|e-`b7%A3bXVUf^8mHrs5J!WwE|YEx56S$_T3F{ z=eW5t_Ae{FLUb7G2*?`PX`U~xWAO23@`sMYmmhK{|9)J9De?5LDmyOYB<{sa947W) zWG{v}aNGN9YrCv@$9dv=#vb&QVQ;L>kuo2EtW{gjR$`PWVLv#R+K(zAA1jXfBb zUCTZ5QtT;Ho|D7~+TtS#(M!>Khv}(c`?>WK_ELhC@*bxSDkBb=e`XJq+F#7;acI_( zH|DEw4<5{ggr8lT{G|QyuKhj%rKyF7a%oi-G_)^MaXu`Uzh3d4RxQ_}uRQTt9^#ee zxS?pIy$d}%E{$sPiEAtG2GX%~MI78qJf$uj2;y(K*_a9fxDq+E#6MONQ7txRV_?&;aGEOsQ zz?wvj25&TQKx#BDUA9D2EsX@ zddkjWn9`0#--q?C<8jLqZ>*u9PY$bBBc9v*dEs2E_)&P=`qe8x{GcZq)yCGl?~dKQ zmiQ|whcUW7;9}oG5k6{<+}EqFM=eJ@>5O2xdK@Qy{OWG-qos4m<;tQj4L+#y-xOwD z)z)VU>tRQ&V?FW-r^D)yRySmzxBvW0^o4296(?U{=2N2NoWGtcMCQbg&X%DEPI`}> zcp@A&7jf+Mtwn#UUf2z)Yg$OT(BQm-e~xY7=@ooT*xqQbCr@(ErpL%%U!U%{P_1lH zN8UAhL}%qZ4!TbE58E1`$rE|_K?AzTn$oF_%|9G0@dK-P($}L6)lvpDS=Z3nZr07^ za}B*9-VY0vA6XzRJ`lLRcZbb#J@>(Ze$>AUuC@M)P7)2B(}>>_{3w4dbv$lb(VV*3 z*{AOq+S;#uPrGM|XLf8boXr*gX(93h7PMFLAcrcqT!`!q&fFXrzPz55KRWDLwLR=} z^3qN{P4u72JZ{}<$uFAdVcJ5tx3$iW>6viW0{p}$wgUI`?ZmNnnfn80>8yUNcqitIqj1(m{MS+ zdgj}mWS%ymHl}pc^X^E`9dOv*y?Qgo;jsI)(azxS7!1Gyxf1@oAMm5?qSL`JUjMAM z?zN;>9pgS4*-{%CdpI;G4B=II2x&LS$x(3exN-i7a#XftN;X8APE%TiwbZ+sv?^C2 z=j?sI3nskF#QvRM&W(-~WKDfF_B!XnbiT^hxt43%A2JBu;)jsA7I>f^kbhhM++SBy z=cAKl=v#m>$#%0>6kA0of#qIfRv zD0Mz=9&qygvD#M0)I`^Kr@3d2{2a=57#f%uR9{Aa#&2#Rd;Pe&3LL=;zObugNBMVq z+&Uj6zv$DKATR3E`Zhc7a)xqsX|3R2l;;|EC|?}XZ+V%a|3hxr%QSLjW}a`}%0Hh^ z=dWqg(pk)biN;atSFb$c0UgB{L3-29<4%Cn#`4Ir+9RRt8on_~eZfV)wED;WH}sI- zG#koerSIZmf2eKNtIkI)M_4KBxzsT*mhD{_+PbkBkN?rDqyr~kuX5Meo1|a5GO@7J zo^2nPYG3F6;nHS*xje*!d7xu+cE0T$wT|`32S5Dj-FHrIg}M;OT#1(_^gT8MdbXNA z4}X!A!}&w?WwgI?HU;tcLeiSTT<7eT`n!76^*CiDD3$)7cBnZ-jk$!E&NribD#--T zs5g2UT%mAlZfrf)_25leq@(W@CxcffXVH_oKTaL%kym_R2cyTe?xb;i-1am^rH`Y1 z(1s3^EwG`_2M_ca_9guzvLy_~heGoqSeHG;^}vWS;EOirZ75_%;}qoH%T!_h+Vc57 z{D;z?Av65I0Q*5Y%BL-VUHtyHPgAeD9;Y1m@nd1NFL0AgVP9&V0L-K_n0I09tUk%t zExx9oW1Ne>Bc7py9`;PlgDLm;z({;RCF`kv-Q_s-t4Chdg?U2Z<3q_*sE6s8*fwSi zCO#hR^{y>%FNbkIZ3%shpI_`J^52?U+0oey>1n06{pua;@i$)*;oAt%^>Qm3Clv}O z*_j?A#(B~mde2Hvhdh_l)Mt+Wmvn@K`Lfhb+kombN_)A5%(LOm_1`d1?3E5HEnn&_D9hhsg zwK_Xn)5CeT_NnB|Idi@zIUg>J2&oJ8@H!k@Qgussw=-t>d0_DI=NFTC^mN@ToD_nk z;G{EWoE@5- zwDV}@3&ilGp2@s%;^RkjXluwBczM0g`T_Q2vE1O}C&(-MPyCz|R^s1>(%Z}zl$@Qa zh*RmA#$tWJFS~&5@igLV+9~pZpC{$jdJl8(=md=w$lFX=f>z8g_nPlTpNi)Yn!ND* zD1Ne%ek@s+P`^M~%n4vy5l3HXz2UNG%1;*SILNr(pXa$*czK$o*TbfRE8oIT% zd(qZ~);4n6j)IQL)Orv2pr_RDc|Mzklc(e9)8=kJ z+|2TvJ|DZ1wh?fe$(o&0uAP;SFW_XhCFL+CX1t?wq2RDG8=RmXC*BybEjHo=e}8397f0U zeSfTPKy$#pZ>rVTp=3|`ruh94Y>CqT(9>rPgSkSDn_3Aca1^if;mmJx&)8n`NJrLB z)8<{y$|_(k`vRLa_^>Pby=9*8<$;BgwZg;R@ku-vRtg!PF(<R6RdGPY;#fek9k6d*s zgtQfFC%*nwUk86hMSWBWr)uA2tECG#Sszq2CS~Of|Avfh@O4<~CxJO$y^mI_f3^I; ze=?3KZyy~WLv&cj1!z^vS1YB{J4V0M1B*&!NQbpj{j24rfYTA}@JhJE&tzkrHklGe zgxJd2_PryGSziPHZsV#xM6sOJ~4Sa)yn%xr}MJJHS>6W9-Q$XzQ4ds zzwV*Ai{)gcnt0afHScoL^{bW+JaZDv-H=}8Xg#M|K2JJb0Vn3`tUZ)`JH+Hmf6RR_mkV~_mc}<2fFD2M;nNYf zv2%CCuNhFjPt&T`1st3|KVijsx%c&@w1li-GJX#7W_4%YfjxxGOA?2kV=aNTQPvW) zE~PSx^9ikmllUXlJ5yXd=9OQ2*5lYOpmg;N!GB`w{3Deqo=!RxKMLVT*YwjR`ZqsE zjt*fTipKtN9hARP80YbH+0UpwK$M}hDo^*#3`P5382Qj-%%A_h2x-~x#y$(K>&dV9 z&^yq*59>*<*0MYwTqoms#;S~6S(EFzX!DPu-{U!JB|2-teXaD$rH}bYyDyiwS@CH+ zRf?0X6Q?;Yzj1l~{N(nL80Q$!ZQTU5I95N41qHQzF!bfALzsHm%5j$r^lk&>vCm%oZ>5C z!Mq*&DQzptHTHWhbmkWAEXb72!Clv0=s5rP12%kf^Y;7=`Kh~Z`-XFVe|3D#UgG(O z*;&2?_;JB2u7~bzPtpeGI@uo;<50`}z0vWGTSE^E{w-AgX^}7StFY7dnSxF5vtZvE ztp$r}(t`Kc=0af(6S}RAm9XLL9eRa#&K~Y+>U-QY{_JrpbN|o$t(9;hec?RIlY&gx?mrKJG_WJu?V z)pw$|`Ed^qIs;gcCyV3H&L@|idGF~foG0aZGumLnN%H^0+D#e;iZh?k;Vdh4FiWT6lmfwg~B_7K(nlM2nELzMMv4<>_z@Z`d*D5#-zR#eF%u5_$4xztYOh z&JIjYZr!@L(6Kz2vv0%Q9qGKokF&AE>pP?5kvu_H{<^T;Js-N>G?|KR`bJ>|Z_wg9 zYlXVy_edfWF;B<^{3+hfd|pzUQGU+(Ob&PKvgcf9_RINnkne-_JBzk9XnXK&3?v)Tfsf{x;y>0L14VZaZBO>=g8iTzV+`4d*Jc+N_h0bpD%2DtUhVgek!HBaV=rQOBD|8n3$Sk_5nf8wP=$ z{=iJ*hU~&(AKz>RE8Z)4&=u&NdSozd+eQ}olcIr>BVs31$!jrWhP=6+>y+0OW0oU6yrW5wJS z^yB%LX5s`M$P|3Aw+$Q^BM?6@_^^NWQCDG{Cm%f_fv}3uUW+ldT|n&BTg6MfwMWL7&SHze*DIIgWo#(8}f`_9a~SU zQ(7GQo;;Hm+qZM~lkYQEixW1Lon;I8#j6ihk7k6TEBguEgx>bLTx}11s7CO9K zU41<5PO?dP*g~-m!;V6B7|%!_i67|mo}?RzPpd~W;=~hS7?&6(j7NO@@@Q`lI7xS5 z>(D28Ov+s&d-R9s8gQeJ#5M&NY$%O)MGre)z9y`f$qio3hM%4{1CulwqK|IUm`?K~ zdIs;ZALyrvr%jc^1{smffb5}@(Dy3uun;|f4v;Obc_{Lw)u9=2;@OYYSvOF;bc1X@ zY)-W$`Z9ieV_QExQ~qkh#E1U+!|;s_!-Fv~eQY!B?@D;99v&z4f7q7DnA!nzC*VZ8 zESY1ldig(%*N6i@bTdEhX=h;0da=qaJp*aq2{#{8Do=Jrr8+d@nfTEh8G4904c537 z=f|GN3%0221o}XH$n5lvZ!3gv(n$Bve_?ATxUG!J2bAo_z3Qbt zewu+rB^tu1+`PD(tIqlNtbAYrp0rhP;wO6864}{_Fjl)hbwAhz$f0o3yovdoS>;EW z=7;5aXZ{?v`5NgI9hG@fq4=Oq$ddmNr#2+ND%3-HDuuKcFp|*_~=@CsziSj{I8uK4|TG(lIURbS7-BA$(ix;e%Kfr6>y5? z+>js1l0wNDe2V90hkC~vuLvK78q?uJM|=lAd&aY!;aKN9N6(dwg3qR68qV*dZzh+K z!;YED=I`-*unUkg`h9+WpAYW}d$xaTtpqFbiqB@_BYL8b++Z_tc8!;0q7r_?h8KpOt&&8 zr98~9F;}8{rSWwvxyJVu?b0MMoD=e4g~R_@<3XkE>0MJ?tCAj`aOhg3-bL zT-f+f?GBtYZVY`XwnkoeF(%55E^e}pfj&gG#S`I4<0JZ>r{Z<-4D9^&-WXUF$7art zZHi7R!6`p(11ITn*&MW6=z-J9(p=%(Xpx8HN_@6T81olw&ET8X&cIHsXL(Mj@tDV> z+;!qJqO@e$mXbAWHrjk?s^qR!uu0=1jbGww#R%+*KBl*}k)K4TnLTPYfacGUQ$Oxb z!EgjF&7iuLge)_qrZn zlOHMVy;efMeDSL;v3z;dX)I4Ueu2<-|dHMHyPtIZ;KwI{@l|} z!C~P}-!$0j$6NsISY;_B?%LE+*c$^~#h-?-h*NUKK0wx?j>|hZGcUK^JuTVM4wk4vXn`NeahV~cAk%%?L~1#X-dJM70?jeRpH>;aAEW<-Nfd(kxaqI&u? zTr0j+Lh*;Ksq1)*q4;`)>}6q(hvt;amDwuzh!61@)|vAD`>BKW4Cr~ap~_7QRR&nG zcgWBE>Y2i{{LPMo7ts`7VXZFM%zQH>`EHw@DeZAXl}8xXbnHxwkJI&W>C_{?cqs|P z_vy?Au=QWr%vw_?T|MafGD>J$`TFx|TH#uJDP%4(Z9Y=Z%#~7*Z{<*I8?E5V&htc;N4rlc}L*NX7GXy@) z2&k{CCj2<#kXE;9FsUX@TG^*PF0J0(ef{fvw`At#tZl`)G0pw}ev2cW_xb6XXY6qt zp6xEo&-n6AJ2vp|>%%qk9n%l8!}qR@w{Px_ENJg*wIO>z*~6o~_A39hVkQ0wksIbN z!KPX~4oe5d$eW+vJWW`6e7I&`Qrek?!*HnfIe6WkA1pbe-RgLGjBNgUjP_A&eUFYK^hpPrV6ILZ<)gto7E+55dA?j*4iZ|oB9mk&(PU4GiYL(-^T)fu0**{+{4e|2(W9J+SK5o*|)Bgp2raFRNpB!H8Ryy*E z*OS0Xw2>v+#r>VThx&OG?}X~tE44l0iGAVovbOB?VBGG!-#_*^X#EqOn}wC|i9^11 z=XEZ13Eyuk(;v9WcvtpLJRMy(5+lln4)0j+QT>tV6H0#6 zr}<}mUy3?%&I~N5x5uNLABZ^K{DxehT;#;-McJIltCwlgHX0k1ulk}N;6Xp$owrql z6VLU2@%I5P_`QhheAIjStN|PGBKtsnuw=SfI0+*{`YGx!nL-zM9qDn>*dDn#Djq)H z_VUGH%EJE&Klnlah!^?};-sU{-{M{GyHTO&_>eIQJnotdt&$GD(3#TXqA7lT9hz}1x(cz8CGX%x z{K&#w|I)R+HR&kkdWomK#klx;+K}3?$_F=}CheMbiTy<$`Vi&yVKcDtG(2rE5*CEq z^L%t+Z_?wWcYIhoTkPx!_VQF;`_5?pOxWif`&>)Ii8$GvvY$Mkp8sZEiwD}7$4TSz zv0UH6?C8~pdWOD0POvd6*-z#tGK}j7`r6m|LFX`eLY9<|@(c3@mbaOhq|p*ibGe>r zVL>Q;g*;7Uw+pr(&lvZSkG54#CaAOIg0z!c*^6mukuk8DTgblLcYnRm&KN_f&n15v z@6C)8PTpn#3w`tU+En5bmG&ka!IXT5=_s%QOK{lQ8R-evrl%S6fnmA5)z>d~FQFI3 zTPxv&Z6q9I2YWt|FWJe`QS^1_A?zpX*JijzZs^;w8_UlP6ib$_=e?+p<=uc)F;(lx z6E>7^lK)4~C)fC=!-fz}@$+i$=>s10^i6M@6F26Ul#jU*#s<2_Ht=K3X124KmU!}W zatThH<|B{dwPv%0o!Mn9FS}aX!V)WDF2TdqVHfF1g1}#GX(;&lnCqbRYH-=Y1kD zS4khjSduvkwQ4?9*vdJ zKjWI|5$(G~cKCA#>m)`2i>CrS_S@g8wkC$rI1@$VTB=GiAurf;KurcBSTe zz)CW2ejTov-?_q?Ho6+W;u_xz55l-VCrJ5JJoVL;ge}MUO!tK*z zVNHs80?9RFsgu;_;?sv7C$%3tC$)r3F<(GGMf>q-Z?&}TGppG!$Bqn6O@y(U zr=e@wBIQkWb&V>&d>Ck69vz8ZlWnWK&5|Y2fiBmgPhYI}DEmisV2*`nq(^7VUasgP z3*3wbvL{*ev?z=D2+?St*|pTgd3kR)D4#;|p2R=VM{dA_{+l@8E~pQ9O?LL=u`T+B zQe8{JpmP$R-NFgGT<-wA?{QKar*D7n?W&+}6J1nMmO|P@ zp1=s51`XzqCV0&rgKYV zC$EcrTzjyKlJzfdYePr2SJJP}7v?PcHgeZ*<<>SPMn-lm9(hrzEAXB6}H zLE`7A)Q^+LN7skpq_zk>%Jg)5E)5L&abBy)lKAkvrd{I~tRP=0G9-+W@It|txO7tD zw@vb6V46pQ>p%~MNVo-i=NlJIZarJ=cGSxY`Y712A>-V)zgR* z^WgZg$}R2<_gr1PSc{BQn>LK=^821Z>NMiSJPPwE@cy7@bCdPYYU`ht?)ug3il2SXHFAN@T#`Q+6ikb_m_qSnG-?2sOR+J$ms2b?aTU&JscY1#~ci6mc)Yz zvIr)c#}W=<-r&)=?S)$H);#HHlP8ap@FL`$GuEe$s&BO+7$Y|;hK*k*@a3OIoK%0+ zgFSJY`z2%_5Ot>Rta0&UEr5IdSZ_iWS+h`Hm8X!k9QM}fUUW}eDE?W)WDm6F+Z2D? zkiAcoJH54hRb`zvjNn(ivlo>$Jk=+x@tNHdd_;xsCk+(l*ObSHX?53g_9w(LrDtjR zS~X5Qv)532cY>cW<}UTKH5a9;r5?%y{;U(~-iNi6camwvbJ&}b-^(1mhudNGX%~MI78qJfzyRR+~-w$ zf4XXUG;R;Wf;~K(n=3cZ6z4x07p<8qt{eB9Ugg`6?8#++{$@|_fp1&${bc6s?st#h zT)B3)dvT=a{=|Igw|G@{Yu3Cvu2ctwU^AZ^obhKEnD4Ij2c~zrvRm3OtMaSks&!I{ zZ-so*o$t5Qibpl+!Q9q!!g)2(YaJxYb0S^|IsZd@siwZiO_S_FEK)De;mJP{m&}=P zE)V^3-1^s&pYOnk2Opk1GNl~A8+!z6(LbEmNz>smKBPgP$MNxfc6Pnw{9UWzC4S=b z!f`$PJ?FoWJ@ku@PrD`!-!!T84yG59^J(zHx+*$RXBfp_>6>ldo#-oM-!^@b_S~n{ zS#k2^qjOh^PYboC>CcY&bg_Q&=W+eHYWQp(Ite9VLl}Rz+~j1n8Xc~^;fJ+7`9;m{yoqQ;L;@cBC3%LOk z>WDmy&CP^;(%`{8_9-%kJw|!t_clEFi055-eEfAYuo6A&W6w`m7noV?<2h}CXY$_> z_kUn}dn@q^0S;iP^#zrGSSb3?k$$2~?)gDe^y9LciIen2;jF8DC#jvE;iNXA??o?k z<`%&Y`6_o#hqSDzPtM=E#GZkr-0JMzuFggLr{H6YANTlXfrexjOpqbs;(h_T&Bn;n z8@YP^p3YAamX0Hab9cMD7UAEw2cQ4?)cx(-o9hqwh8gwe4E65v-KjLc4so2mdBzyA zAUm$@({>f_{RK5chM?i=scZEu$hh9=jg6kG%VWLf>#=u6>H7QEyTHWu0Ca5cUcDLD zy_S2*pxn`+Z2Q{o#o&hyTy$0o84^x}^r@t87EWncseQqZaOxkrkXzsFTSm^{4;^t7 zUw!4U182(Z?O!*gHn%BEq_^33kDfx`)6Zxhelv0MSWV7vl#JhK2k@V5-|GM;$rFAq z%GLR(@rlkK&domRdLWz#nU{cvw7-+W3Hb&K>>J*h&MlAL+@1g@_=aC})KT$B%ZDD* z9;&fyZ^`!q()2bwG#eu?PrN&w2baF?oNC`1U+mfwPU@Fwchrwi*J&7}#cf<$yM%u+ z^cx{|tmGwobFP1Vxo=f6MO&9GcT)KHcOpIsv45Cv-BUy=RFbIT`w*W!F(zsE z$RW1C|KHx3ueFggd-yC@l05+umbJtJPA~uS=y;Nh-9Va{Q-8OghF4#@40{m#``SjRGIrlotFx$h@}W-ygmo@r~^V z+T8RRf7pujrD!h^XAHUdxp6juok`g`%*@j^Kz;+`C&oDDSKgD( z9zSi4LE1Fr6Z;AM0!H#{`t@}cFErNE&6XhcCS^Gbyn23e&UaC!ka6eOqrfJ%DL>c- z=mhUcm`(-TawYvQ4cub7E~@`l9xfHUoVH8R0$pp!}Mmrx^!%R?3@YOu;bPQ1&@&73djt zydJR;Q;@hI@2O)19~;QK)z{%&Yw9^?Ex?W6y4@oV|~^4I#s+Qd>G zpM1A2otwLysbZ~dEhC4P!RA-@k(Xi{d`jofQ@paJEW6|(gXNlx`ikeHz)JcV=d`z# zD|LDm|6=ON?#^8qY4+KaRJoOxwV6W@*VS@Y?iV%6>=wM0tOnIZ9_ z5AwwI9mYBOX|{h;Oe(*NZ~MIlo!VZR(l@|LJ!}k=h}XpGZjR-Y*BcuAmGyuP@`DW) z?J3G3tIhgT3>xa5NGm-&(}!ulwqEBl-jfa*qq_QSU;9bjiSCFP5nHD!dwQN?qa5)p zr%BgW_|?brv;KpNUsJS?zeZWg^*8E`>nw4uBw`pV-x3jVEU&{%YV(8_QAHqhd?{%Eoe#c&F8HLndBKZ)VJ-~D|~k2GG{4q z6Dz(W@`QfArlZrkp8ZW8>r!+y^{JbfzvvqPJKA2In)=v$w<&`gd-#Cy9YkBJq;-_{ z;$(_FgWc(zeWC|Bl5b?Nfm8PFGKW)lqvPQd|5jO^ckls&m2`{}lWuKGA1OW{=cXz4 z$(elJlsYC}lgCsix_p0keXpwH*%|o9Ht~DCU48nudEICo!Lc$ z9OvzKRUDo$7Us2i`etR{zI(s8wzKk~dCuInM~TBtZ9}7Fq?eSwREJ4zUSn+3cK}Z4 zwF31}HG!H)hqD(y$d?KB- zymqh&lrLHXmHF}hZ2HeBdwS7Dti!bC zI1fuFMV`18rDp&XJxaNt8>+0TL zhjtzL@VXNZKCeqVz4MsglCwuFx+9=mbuab!^bvta1RfC>ECT8x)4{ejp0&$+zv*~# zbw5_k^L{8CZ7uR*${v<R5$-)_HU|1$f(k=jN5NnAT0x z-|4LWv8Lmh8{Ug&6f9#p46JM`rkqKTr%ow6@D6qZW!RTb9&(24AV>5Ybq@WGe9lEF z50r`Zd%m6Ll#8;BJQ>p<(mD!^(wb7%5!f=3{&`p5xon;%TzQk_9-Af7&v!=8de+l-W6GIM&Q-In%in(^_KNXT_RkNF zwkIb)@0_izaJ{;?miG3ha~c!RCy%EWn%@LW$Y;%2IV|d$n?e`YJOd}_SC*F6KK2yHup35KSHGKeM4X6eBu1ou7rq>_{Z(LV-Le8I@^3xVu*-Ex0LuQjC){=-Y1@x_0hlA zcG}||^6h8?edITc@+1$#NaaPQ3|D!@$Qj#DK8{8`(MNr?ve}ctQrii*mijphH&ZQ`U_f zmiTy&Y*B9R)s)sc4v>b{^l$`{XWv+HET9m#u{^O@`s5}*_L$GrPvO=j%~&%u%1rxM17P2Ct^_2 zzqkh%^f&#Cam83m%!jSBq^ z4VlAcwLNiCPj~WDAXC0GOkC>Pf)4B@`oQ_j)Ia;5S9WI>PSU>AAJd)%m91HR19?klblcdX0Ak{#l?#d4kcn;4Ozw|u9heVF&sKp%TIe|GAgW>RF#=d7h2eg4{v#rDti zZ1#~LQ=Dr7Kfb+lp39lpL-ic8(~MJ=uu6OIv(JXPZ^We2wR0M1874NdEpZ@){)kg6 zUQrdpf->O2c*Ku;@H37WX|jiMY&z#5;9vFW)*k#S?phW5A3`hov>rKdfup zu2Oh9n1hduS0knl@ldKhSj8@)tU4OMXvE3bbnW$Wx0v^p`yJd{?i{KPBYZ6Mcb>U^ zLrufNCblC#?f#zA^SoEycx#QgJ@m_rS0jcI@8aW+I605D-kdhZwKvJXTz&)WamLy@ zoSawD20Ag;8F?7=we2DU(2340>7h(*{E!s$f@kQXAB#&bzzY4Ozl~?CH*KD8PggRO z;*O>B_sSEgF{7BD)Zx_r?WDF!2aS#O$5#1nQBPneM>((h;`Nw4u1ivv{m^=m0rU#( z{n&n88&|{elr@|>oW^Z_2XE*}=L^sbZse!4Jxfsr+OCnQ##)W|m{K41G&o_uw!PP| z&$JWRuMly>VWO0WJP^tpW1rSckWZss=H=x0~Iwrk}n*qpIl z+DDeYZ2dk4E9N-TSJFM~d+CVs-!o2)7;4CnItt&Faqh84nKMR=U4ORS=&uJS_4i*t zKOWHUEjMgj>e_=A`i?rv{T4UMQ=TtZ?`n(77bzGpKWW5wU`m1lkNnH%DO`MW_73ILXP4VdwM~s+aOFyc(YjOQRe~aZufk(GC zr7Nb`&9Tp1yI%W|=M#)?>6iV!`P_LP)2djljQ{vL*MCnu5g+5Okw<&T5aS3oxVoGC zZuE}&SsP9bTl^Y6&9VL9kn-pzaVmW@=wfjx)BWe)oBjamG1lU^W8^myt7~&(@oA*Y zWh`ro{6t*ADaP+RIQqV`J@<2uUy4unN`Ia2n@Y<#r_!3vLr+GYuV25q#5O=5H2);)@2%V#fOB?NN`GhINA%+ z@DS3LJl)jq?m?c=b!vI;o~gy_^ta`m-nmng{tL}o^icz;dFD1_Pb#9 zWpZJGc@1;raaynI^}C4E*Vk81I{A-oi_hEjug}<8d`$enk{@~C;o2zk>S}#qvAMQH-K_nw#?C&B+*Vkh0E^f@*W-py zq^G3yuJ_nU*!a`~_UuWp-=)7DlW=UUeU)uRy2kNZdfn^f{Y_~#kC}dv=X=RMitEih zhylMeCsaDm_LqbNvrpFq18I- z(!10<%6A9JOIi0Q`Mj^TBTx5T=Y7@pSkEH@j|e;>@QA=80;516j*(uEf{tOgDX;gP z4x5ibwRc-w*rWM*ee+^vb8?nFh5R^oK%RSl>gpU6{e!HxovF#0#r~9s3nn{z-@g+QYUOw`C zU)R(h+bpl|o4>o(7wN-)&G#N8J`rcuD`NX~*LUUbKHiUX@%L8fLy?a`UgJlPdMoXJ zJ+@!c*T-eAj~H==6Z!^;NnPDwk!fh0TPSHj|Hbv0`;d!%>JTS%bR8dM-qE{XpV7rP z>1_Ts5@TNZetFMYDm3`Fnm5kg=hz{!T-^8H507_!M~smBoA{P)#&_O}dn$cqie95k zFK5S^@|4Q+&p18SMG9^4OvqjNzU})JW%aa0I=zPP#h8a&=dEf0XCC)KTa< z^2>j>;kVziw&|Kk z|8qab4k>ZxS-<@D`(A|;XIiT>sMt-?Mf&U0%uDui(+|Y-wkhw<9bUeR=hEqCu^rE5 zF^3`Fzm*r|TYWcdoa*?6KKlgYzBbFd*}0={>-(p~FGy!s4msy@ymRu3xEK70U&D{s zMRjovjQha5w3`l{x5>I=$|P-+te*O;TiueMm8nYhtF{HufW!(Fc*y z)ziJ#r1oEBWa0GL!O_)hGwv_gr~}1`6uDx2R9`_;zx?+5o|wpk_c5jddI;MO9Spz3 zI_f2U7Jb$FV*1z0VUB0I_-5(6j0-6i>PPWHe(ENselGFB-zdfW%@Im}LSQ(|XdnmyRqdza6RRD=agX!S=y7xrx<}tK z@6!KDzXkJzOlx{x@-U2h+iu3vN&6$U&AauVh!wh>diLf%Z-5oobvU7~c*faiaKe7l zz9c{DYWxEBIa2)zlp6*vWgE21zr2UCu~(jWG33?p8u9TOU2Q$2=zpKZ6#d5Y`By)d zznw2!!M}5nh>>+geeRr^XC)8Ay07R;@tGR2PmFnjJ%w(Lymq=qzoVD19nkr)9Ch&A z{)z3hdVZ2)j52?u{cLlm`ER;>jm~C19Oa4rDSpGkrEJIcn`c!+`~{vdhlPLm#O{P= zu%I6?-p3z04Y{El{Sn!+ep76Mt+(qr2C{z4I^7*{;yT91DR~&iz4W7(lqvL8p$JydSlW;#k^Vq^}yCVw@~_r!0Jc6S^nXAFr_o%6W?NQPF6elptdFdJRAmuC9na?F09P%BoZ5=Q0U)Et#mxo=2|5SQRhlv?&(ubUn zN(1Qx=k9Y1qU-vK{wGd9lOBrimDil}(WcE)>7?a|6 z)V?eAd**emT1x}Vh?71(_`%;DZT%)j*`|G#e4C4T4GOzFwp(6H$2edlUy(-FK5B7V zf0bg1SL+X~x6uELBSu~5FTV4})Sn;i_;`*VoT~Th)_)@%qwNP>+MFr6(iymRB?WIhp{2z!Zq_h>~?IeI1emoAJ%=z8~6J2 z)e9~C6!@g?tP!iHk_q(^V;r`)zDsNa&R$1+^L2<7f_+f>2=KcwU*-o^`pSoeOW95x zPSC_Rb&aE2EE;1&iW6&B%c zN`eSm62@bYqp*kVV|kLH=T zfwOZM#u4Qc-Xl)K#G+eU(!^M2Ok?zQXL+j5jkoNk)AP6M&n_rG{p#!_%Odia>L7n@ z?((9Hz4qz-Y4#h?Ci3L>85h~9!%LhXNyZr(N8>kyRti0~RSUvyxl{j0jd$LAThm#nY)|DAWp7h{rW!>$* z~^hx-z54gC1;6=CZWUdJA(}c>Hlb^{E%^kQesDATzuh zamn?iH7op7%$4N7Oe62{S3DFE;k=RdepN-oTo4iqBU0soLk$WgYQ;nE1rDqyfDV{om%_I?cX> zi52};{9QfvC{%iB&%%A?=G`t$>nqG{(%1gloYk*0v8e>IH8yL2* zLXM_aE1lKe_hQ}Savgc}x*ytnw^Irp%%}4&$3v{w=l!%j=yy8tbeDEJ)!8loF6|BD z-A=UMrR`32mic#SW7zMOw0nOSI; ../initramfs.cpio +cd .. diff --git a/lab6/create_fs/initramfs.cpio b/lab6/create_fs/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..abc766ad465f9116bd3d9f20f964d2e8f5fc39d7 GIT binary patch literal 251904 zcmeFadu-fUcIQ{>9@~Q+zvcnVc*aPx_2xq)B~g5+NQ&Z{EQ*v!iXtV7RJ&WA>77S= zx_dk}X1pVN7FZ(&vQ|8R;TTwV;zhik&B9&;K_bAr+m7=`9PDCYkG=a}LiKp#4ZOi_ z>>x;I-K(6>{nfYX)a9>=Rb*AM*h8_a@9%ei_ug~v_jm5O=f2Lbcc6Em_hN5v@Abip zmj*5D?YlTVN!WXND%=;s-rh_7{a1#@r-zdGkSP35_m_)NC0Cbp*PStHd3t>l6G`Ta z<9*>`H@%Aqz03Xf{PIM9lHRWOqBjuAv;Y0{7rS5k;%77V@5ytSPy7$|`>U0I^4mKv zW}akrvVZ!2KcD$_n}vU6;m(U=Pagfv%&(vL>xu8|y!Uti_`%=!y}x|>t?&Hhqfh)16Kl@DP$ww{yQ>(A#>BzkGpR8muCq9z- znHN{yeLmB%^O;9ap8mktdq(G%GDd$alle&Ioy;vT+xg7clgx)QAKkGs;&ev$%g_bK zXWz_(`o90QfBf6;8wNX8H|l9=hMx6go>=&ao!=Q7dhwm-zkJ>5@EP6z^@%V4{)x=$ zPEVk7Ysb=ZP1%28@tI8KcQctEdVJ~m%(r}+50k&g_%<5w{nW}nVYHy}^UoF1ew6aA zbN@TZvlq{2zWn?D;o0igiAT#{4e5$yz$@?W{jdE&@?P^8K7HQmV)z&i0n?r5^Vh}r z$6%e0e{3=k(x2enlGeg&nat;(TD^H6p)8A|j$_YdR)2`PSov}KUr65d$9NCax6R%= z*WX9_e7ThI)av8kfxV05-P=3(5NQn~<2`vN(6Q^M#xH!4|AfgjX^QXgABA`L=%YsO zl*!Mz%##P1UtWHcdHao>PHRVo9k_<@vW1WAe!#*97G^U~9x3g$e42@TIFnDC%cot+ zJZU?TFLx!M=1xAmXLPsi_e$o;+bZv~lx;LVpATQRv>&qjH#1M(QJSyjpM5PKe#2;x z=bK3w>hQPoG=3=`{v8W5zp%XXD@N~Elem!X*YjokMn3#ad;VMY`v>+8P2No|z6}Py zXtD{8@7TNCdDCR~k+lo1ee7I z%$}n&EZs-o@98T^+k=m1-^o0=Z+t!bSD7cX@VA}FedcdvZbARVk7qs};!O6CyAc2N z4}Cmi@m5|3q5VE)Wex30_k|xX=KrwI|J?5UpUvm@>0bSGG5-&`{6=pV{mxZP9oO7zf?+is_r-A6?n`tkq@nQ()5Z^z(L|IU!u0>=-^7$}xO){*}Ea z^r+$Ulxz3Su9p}N6X{? z@!7BLARo{*xhcp>TOu2z{e%DW+3M$?J^SSQU;C$_&4;pfe(3R}$y(;CKfip@$_Q}} ze)#b zX7$|p;m4hp{-2wy6w;1;GNk>l@@Y?){q$KyeDd+{SiXPi^Szzq z`&K^R?;DL1nMZ#d_PT) z?^)ib79YyXeCqMvG5WvZ%NzSt;QOt7c`xVl{!J_MyN1Ir62HB0|_pFZA zpZj=0pS1nhhq?jPnsS+k@*FCFTe1|n?`fz*G+%@I(ow7 z;n9yhwhr9l?EdW^2|A)cF_4)6Wv^6xG$TZY4n z|B}A{UA2`q(mnU>ck}6xqu1=3K0IJF_UXr48MVPb$+y9O658N@2X8N08#h}lq<#C- zkN>r${p7P}zxph+?<5`aX8iy0KO(*9u$^yMJ-%UfKwsv|4~!ny&l$ZjlZ*Gime{xN zf9>}Ijh#;#R_8KLuv>RNY5mWO7M{rba>i(xPJa(u%yi0MylwrR**Wk1ICV4nru#oe z`V-h^7NY;L!!q=Xx;Ofdkm>yWj~egc8oR~l?wlKYVs^_d=%Yujo81YIW(S9K7B^%z z(0lKH?SIPSlD9(*6KtcL@cpml z@w2)I+uQ1D{5*bY_tfXlte(NnayAwG{jU~Z#IeZJ)6W==pUgbTjQ!g3*qgug2KH32 zQ#uoVsbi3n?|-!X&#jCLhNa;V>K@v@)rmC!3-8RXt&hm@{@?z-N6Wu&>4U9rc68f^ z-}&^8VFrGr<wfj0Vr&wK#0*F|!e@O@;hV?f&gw`?cjqzxL#fwy(c!W1t7$$$b6! z75LlfOv-o!O&b?bUbwb$Y`pMM8yo#9)PMuCam2_`S@Rf17u#`#;Nk`49hNGDZkA{=~*?D#!RtrS-cf zg8ZgF+c^>1`imC+vmef^zWC2heEGo(Nw~oMgA-qV+w}E|zijEgKePHptKU<@bm!wi zzkK;080`~X_8$KI&;935O@7d!C)+X~eb?}K*V1hp_Wv+SLtWoB-O~2;v0oWW-rJLR zCrqc9E?>9zNB`9*8ZQ}*Yer+dQ8Z?fdi)#f>)O+33|E1bOOt|?>EFEGJD1mcc8@Il z*GAKHOCo!QJ7dXUALnJ~@7nW%oLTz+g7j&!X?dUiAITiX`(OLRWc)pm`J)e;jy{pe z{E6weZ-+6qjbE)@gt-QdbFKe<@4Qc!mwAn6eY)8y(|xW|I^*jX{c{^j?|8oKxwX3| ze?Oll(7%?!PI&Ks_W5Ey^ZEWwJ`J{Zp|1I7l<{G+3Be@w`A1AYrak|Iz*Crqvi|$Y zcP-s)K3%{T-D2(I*&ig>n%>QPxXs?A{k#38mw)0558K{)z3t71Z?(Po${P2qz1Kl^$i=2Tnq;BybZ@Kao^e(tq5+w8xuy!r5rwx4?A^;aIg`Q{5e zyxO+w-_18(`_fx&Z;^u(ZC|vsFMsx7_X`hy=HV+T>8C8ZEtw+he&MHHdo?9V+sfx& z|7x2(YkU1C+g|y~8*e-`3VAlVU--$_-}rn=rfG|Ad%5kE&%O4ASC!b9gH0eDRAf|I~I|c3T_KZErn%^R2dv`7~eMRZ=m{ zCEnO;Z|zFa)^_VFuf5eB1jNt?;Z1uruf2J-?aZq-D{B9E)r6Y)t=eaPCgCEJ5kKL%4Z!}!SH2kJ zIe{^gS$zF16Oo^O84-EqbxZZ7S3{GynTUAXn{U1R##>!M@_h9&FIWf1zut?NF85vO z9~c~Z`6pg^_2Ew@u|EF#_{8MYwBqOOV$yy;n2&gH{O=fnV+6h@5NMw`*xv^cq=O++ zTkfNZUtG)1iMibH`IEP%=Cecdow(qU{r+0c|`{rW3es{Vbj4xkUxB!MD zv;Auw6GJni-RfA0Pk08OdSg=wZ08ht=(~J;d`%xfx@xdjUebD55^slvmFO!RJHK7k zdtYA~%U!-QdY*j9i|QAL^kt+WZTzgE+?H0YlZ)*N>D0h4)*F_rAQXbdXr@9x7 zfKPbboa%2nR>Ea_dv)r;gVVFVAI5G<>+j$dERZ|$t9_`fy+X<*Fa0TL z!Adv~f@dgWvOk2hIsY76R5Y3;Q=)gPYvAVE{hMc~L(l2!8?#sMjPeYb5s%17nqDOx zdDM32JC+7+WUr0i9PYfqZ!xNh z>l>RrtJ1yj17BV*U^7r>Frd9|ZlAx3ELQtNc4^~Fo%iOTiTvnYD8z;kKif*t@t=>22S_3Z!U-q7+u=vYwwtvE@>a@i|0Gb)po zvuB~7onP2B=8>(5ED1aM82S{(3baM?HUg7!WkS#B<~nE3Z5Obb-p&$F`zTk>I365n zlh{butH@!T#@}DQy%_AsYq`~RVWCicY`O8c?BQ~CYD7GE@YiYjNI20Bi9>FD-O61f zTYgMNUg}aVJ(!ZFW9sDC*h1F>;iFKtK6*-VK18O--v~U)l?lDT^Yqz*Jay!C6Lw^| zy83w9ru5g+)M#iE^i@8MzsCNDX1~1~;e<{i54xIX*t7B2PgpUJlW=_)SZ!=}&Yrr5 zObI7+u&-aGYuXvSU+!xU{a7V=La&n+-88;A7VJ#g7;(})$c%7_L&n~Rhm-M`@Ao>U zCwkz6{;3i+{uzCr>Q7#5F8^HDjB`RAC)>BsO*1#n2RzWzsyksk?(s%2k`2zcIPa{PES9=`iPXVe(3l z$4YagvO_7SQFxRqS2(rXd`9T|X0r3``8l9aul}>W^nZ+BWlvLgbT~i8A?P#ODz*dm z<>>m^CDpr7zSWJtk*k~IquIV3G1Jy?W`?3&E@aGcx2JE4wHeZ|mVm7A^K*@iS;hBOZ{Ka%J;^x9 z?0@So4Er4T`}Kkt8-K4k7v76(de5imH6s*V##j7g|F)ZadEG7@&HR~g(s&-5k$Elf zp`CKCayv?F+O=R?Ghb59u4GOOJ8P-?{1Q4$<)nqpz(+JhpYbT~QuDA${qnj!Ki^4O zmGW`(Mk<`FfP zkR6)n_jB7`zr;AH3_|St&Y78|Lcfroy9xJUZX!u7dcK_@Kg=W2KVp|6SIq6H{AOX2 zMn^n|Z`w_$ui5Fot{x|JDmJvAD?(SH$FPxnzS8Scq1{nFy5D2OwZ=0%2P?_dRdpWFn&fQt}`RGqQR@j~XIkLpK zQ0p8#YZfjs9q}cewf5-eUV=<8Pn93vC=VfajqC#QQvO!&n2ocOx%ZN=(C(7;op^m+ zc7QKG?K-YQGw#KQ^s3rYs*cIqpt7Cl;~C>Iw@W$n`{KC-A7PfC6HMm35*tBukt;7x zlq25aP&Aqqdiq*hlWfpNcGWfCU&%%QC+0O7>v?;*RGzS%vhxWxb1Trq=GR)7`dM(& z9588`g~48QJVsojhv8NAEtwmZJTP9iw8AMaL-)acVw{-LPO&$x40hhQvDzQTI(`p~ zUyI(0|7JZ`ofLvo!LGBpgI%%&R@UE>zJQbAz}Oj^yJKq2#?h<;CNiUPxewzO=DQ5% z@wM!^wbN?@>yvAjF68(0Fz1Wyt-S`#!k}6@)P=OFlh%l+S2|9Tr~LkkFfWs$uWhb0 zX}8IoDY6MZx6hm$0w4V*`;vJt`dIZJ;;Gs?G&7xW(wJq}+Et<5CF`N+CGw!RQ}N8F z2dgxEgww6t{lNwi{c13(C2b=x^z?&GEo^+4*H4AC*6z}AI=4N4dvR5GR0=i6UJXXn zyFlCCQ?+^OiI=C3u1T*yI?CpXnXfX;m;*>l$2@N(Y>*>x99dhrob-d$*V*%_>w4l) zO9>Q>J*qFqs*d^@buwQMQq?^Pf1 z7>DHZaeI|>kmsUPRzKAVmtFE0>%Bej5}$j82f<>mywGNDU{_rlgb{mK?)I#&YtFAy z-Nk#QH2#^=HzG{vuwI;I7u7HBTIb;4^62amV;shKn%8B1&$mNg?^>@Lfse`*FU(<6 z5AD63!BUf~_C$J2{4|gQM2_#cv#{ z{6>YM$C?!L-JTBbo;Cu0)ESvzecbzD-Xt-%VY>jCCfh73_xxFh@pN-_ltj(F)_FGPYP6c78wUet4-@9`Ro;WW36_ znYk*~yqN>0{>&M()~WST;#i-FaiQF+GbhJ1?&W^hykMGsG%RB|s#l%&TaGYd{}|_( zbYHJfd!>uz*}NS(h;{s6@6RlSu{3fP=BsQz!p4)u^n2S{`>lH|`NR)2JgHpGn{uym^{iZ|bgdFLlFziVTczH$@R3#z#nn`vU!*)BRiv&(-eUE2Hc4_dU&4$IJ7|8d@&9y?kf8zP=#KVQTxH z!g+moXl0y)5p7{Uo4c{TJvLviPK}C3hl!6?!%BP+qIb|Od*OhL1zFqUtQ`8Pn({=C zcOzZj3OIRebj`c0R)%bscsP^e_vfmv3eh|Ccbscg++HELYA-f?9VS-7#fRvIz3Skf zt9{(O&{cAVz^6gppixcPydTPp`#bu~5t`LP8&HvU@szmYv3pLXqa zIOURuAH0drW@06pcGkK7&V`$2ScfH!e!1EvNZP`FR2Z-_Ef+@av+z zDfA=Iq3vq#3S~75E8!%+Ae`q_9P8X^?>a3m4JTw0`wF`VIa9mCE=69zMIkiV!!LVG z?U=pAJe$vE3%(8mR(XG&;>gp=3Z^?my^V zy|Z<*aDE#(hd-T1P@X|MOE@#%+0B_K{5|070slM5rF?@_6D|+uRw>i#cdkW;_UPqF z?N`rz*l3*C$E0(F(8`SrPV1Zw`URY{N0K%Q9@St_O&Vm3x>A413%C$xa-Kgk)4rm< zlxI4RB#at`kIEGtXM)xLgPHn2^(|h1HX0w5pWqbE2aXmnV!vAcEC4z?JF^zf zPvc_;Uh!{*UXpIE20L$ah$eV}J@>=&ll^LUgwo}9e)>N5!b*7wRflGTqMNpVKKOG8 z@@9UHCvR`zcSq@cSdG3S4fvwB>Fe$<^##9x9;Z7?!%Mwl66z*5S>-$J0pa zJY;?abS5sp7d(Gvm*>=nwu21OR_N=AlZ{%CDbqRfZ$!V(9>T)2lr~8@l#e{EZTGDT z6X~enA0t1fBVQq;_xv~OI>E`#8l?Ccl}${YE7e!ez)|H9qW>$&n{dJp)av%>Ti8a( z68#$cVJSo77BG}e+bnE6okG3LZ%T=dGCd{#0BR?~qg;sIqP)J9xs~CGx!@Cwc2+L^ z#N4%D1B_;S=fEj$TjEXjiN;98`#Lo1TKw1^Wan%2To~`+r?y-@<9IL;PS?&PzA@AM zwShabCmSioNn;?!Gx!(NI)wDrVdE5^Yc-o8=&u!`DL3cG_&|A@B||YC(GTY_^LyE4Z}MLKIE}uG@d`g=$p47LHljT8p!ex3 z{rDK1{P+w#KC#(V@V}|?lJvR{ku~ue*P$8rqFpLe=D#R!o9p?0L$Jm!LPs-B(z+dX z?!~j+g?;kKl*c8$_T#^1;F3l|7}!4lRJ#*7pq@*cOPkD5@smx6ydXbbZYa<4tdLIh z7;7t!=n-PW%I8gtjlX9cMVaJLnavIhd{1_qjqNF(F$QHm!ShAE)ra?+-$>Gd6=M%S zW@YUcIg*b|^PkwkISf0G5!xtq*W8N7#a~OGw~|Z+zhBOObOA%dfj$VC0wXY^{(kO^ zu@3VP(|5D|8ut*&4}D^9Ft?kWUxyauYngznATR;6Lyms1`CbQM_fqaUNp68nO3qCQp6 z<34Y)YvDfr=x$tCUjakI;3FEIuD{ki2XSfhdAsVH z*U88Z*!Z$ovxFXV193k2mn1#%E3EuD#h2x;RflGTp02+}rZi43^)Z?vPsoMoYx0AW z{X##0ovv%-iTV_Avi>js%?i=QRst*5?Ef~yk`5a-ca6Fl9y_D5#KQ;srNR=j%}UD zkIe@#UU68;N2YL5xNv)VN&eTo?y82rR!LJ6P7V`~kFIHNU_v&2>GPppB%}yP7z#VP6_$ss5DBSXuOZs5FE=o@@W?u&?2Vc{i;czz_cA*r%8} zPvZ0#&soR3+1<4OE*cA~PPZ5PuJ8^@=5@_h*Bp&-QF`4gRD3Ih;)!pBQLnhJ+@o92 z!C~)-;lX{JPIV!ky@dXoW6&tByE7MWIxy_*OU5$dAr4h$tAw6E#wCp5rsjM4Xe;zj z;K%wNdYE~EWNx5$6&d83c+w=};AEbFGLvPYq>FEt6<~#5KinL zD2{OzyT345`(h3%S?^?@hGeQ_+?}8AjH!73TIE_iQWx!MR@{L?zKNFqmO67*+Rqur zKDH(XhRO5Nd52cPC5;d8K%P8KY3ZtoD~GM0n=6+_@zu~dj5Okpxm;Zzln<4&R|uUr z%|U55D!=$F&M(#1eo^^8Osfme)8Y?1&hs5#*ORxn>{i92T%FVSZ$uqpI_3Cj_4r2D z!y2ojb5jaNR7=dF1juALUp!E^(c2Bj}tzWByb65=)%#pCyoc)^Y z`|Y$ncIEONoTJt$p4hk<$b(~^P6yJ&Vdjz#tu-XvZ_-?vC%K(kqIXv7P!iA7MUlVh8dTw19>xku~ zT3jln1FyqAi%~1u9-p4o+gqIVlAoALbv@`a+N9sxUn}3uOz$ybPjWNx@%Tc|ubDTq z?$y!~M)XVQTF?JMuF>u2vTDm@WDy_lw2jUUg~IbI~6g z+U=K0^-T-WyX58lr#)Ak&MK~4co2N4(N`B}I{ z-4_=o?&^$bTo-@O`zJ4FTz!0eJ$*G7d~Z>%o?(Y#V@%F>_Q?iAF9lxMOK0Cw=bF6A zqy7FNjXe|p%?d>qIhWj5D_gRuE43-w4m9ZVvBR-bMUzl6Lm56E{N?uvtiUzS+iZ-A z{NdZdd_r+{z;rPD5mHy(>-`dHPnVZJU0%mm*4q7> zr{%AOIMT>}3RuZcAabYnNIWv9@(3G^59ND$T&rJ+-#ggBBjc4gPo?{z>8+8OtLHA@ zHv`{B+uJuMWB(%DPtE1dQI6N|;G?p^S8WnL^iGk_@`8VKzyUI z5^eK)GQc~PFCya6v$Q3yX?wS}W>?@{{LyC8#O;e;GeKYZvwSAWv2eRpz~S4TH*fs^zTK4$iViSi(Cv_sxae}8xI zodI2N;(Nl-;wPB~C-fnGiufaJG)8K3qDi|MIX6GY{e0)OnS!qYcyE8u$v#Vu6K#t+ zqIXpHYD4mhZX5<$`FDcu#?B%QctIZ<#ph`@PNGfU%{Qf!Hka&K8_o93>m4&sN!n}Y zJ3`-#zNg)ym%yx?p7t1WrgLOwZGNzSd;r}>Ug;-rqK%6VbAXa-bf(68&A>-Agw53a zEqo;y6}EEwmyWxq(b(vK;>57YeD(f99#pZwW@)6!z!ZQ?m^$!lrUtj3kmc9^9H-|fKY%ZN1LdVdKxR2!tU9YyR z`eG-gVdinlU07I07b%ZI+FrrWgz+Yxn-RhT{qE?!zJbd_gYC)rf#Mk@{GiR;@4Abg zVB8>mfo}3`DeYS4rTZr~R`^}W>tJ+voZjOEJ@vKNtJn(skZIY#@ZAi2L__b&?>n|V zwc%Y}>c6^-Z1rB*3VjUgO0tEiS6tWlUVC+KoS9yHu(8rJxpp<2p-#gI9R)AYLw+?U zfKHGs6KWpeuy6t!WU1(nM+g=}y<1|?yL;J@;GupTj3iIAS79oDhv;?69cmxAhYT|p z&po(!ocvs$-gPs=0t$JbneqXncx+6`7k!O?pXeTq&s6U?M6dgCJ#q-X=q~z6;URj+ zuzYo5t9guceOT)Y;xRc>hrb>3of&@lvxxG^WOE?0kqdduE&wm&i+Y2D|Iwa^$EQ7g zBx(KFk!#u(eTm8>#NHMzad_A|s$+88+Ft4T+(fTid$ecpk6o<#P?uO9^lYz?zJszj z>ryOpZUsApytMHcAKlaT`mSshZ1`rhJJC?R0#?Y9I}4WRt%)#CApVep_0jcF@>5r? zvA_I0BQmBwkF!vW{{yx*_JeQckwV(PbRTI|k7k6> z(;s*xXX+<<>^#>s&eSs>rRRj4lZ*MH?y{METJVuyG2*FX5hG&k>{$N&s4oFq*|)+6 zdm-4xHl_)4nr3@?Ix#E5F-}UG_<(S7s(v@`FOaq>St8VYh4T9_u1h2DMK^wr@JJlbOMPUS z-sg-y{=>ppCplxNatP7cGacD}u%gWrpE1t%=fgHOY1=_J=KEOYF+EOkf2*<@iAh@7 zqKh8z{Bf;*DQO?&&f;TN;Lq^XHH{G|ll2nXp>K=CgW<^e&I_?m5wMazr+;IJx+{` znYUoYr@0DH~bidNTT`B@4_6D!gq4*;#t&_tg#;@R`?#hbRK^Y%w zJ{+Az-EtQOr+t~S4UlJOGq+i)%Zgk!8k@NMBIVL6`eJx3`dr&>hx$5}T$@cqX~>dr zV(h}4Jn_uCmEdIh8+o-SVT}bF3EFD&rJN;qaXk*>UUg)RS98;T4yFW?SeCf=IOXR6 zd|mlw4)QuWv@|7sr02*l^Eh5_^XxEi*o&rkp0#x|@mugEkcLYf=W)u9SAxxi%s78V zqN5Pm(^`w-2>0UmFrSN0ji<_ul~ZLaj}!Hl9xuuxwiot8wu8Aq{L%4a?o%`s9%lWk zr7d2QkZ*NW(A)8|JWjrhB2Gy;%)zhqtqsWU+EMo32d1H}Hdd((rri*q-l z(<_&RkHQ<1{RMwd)xOJCN|)fY`&&VK;>NfJTY@l>w^)|I3fYqUwNm}7~G*5P#)zU zWt_x2A>T=2-i2{Ldk+}br{O0Ys|}f#qD;}MHeV~H6YmjKPu`m(rgrTSOPi|W8$9_`arTs=ePUbL6vC}JfnMrThh zGMAKA2c;nl>oZe}tE@jTx1P)w;Hy3P*0oQ|yV5;-5O^25ul7B*QabUjb+|O%lqMO| zrTLd;Za0~aQ-0+kWKZG;1t--@^^8M3Pu81?<6qeYX)>iegh#pEfrYON*D*f+UTKrP z3$_ODzNMF}GbA#lbd^G1ZmVCHt4AfieV)(`ZCv0ZbH#rzhr;B08H3}xA0u## zz%c^H2pla0)OVE&k5+B!!)-Y%YK^ZCH?3Dn8V>9s%+4&|V9yeJ-q^b_pIy4aS+u#_ z{Y7fM_T*FZa?2{wyopc_Pv%< zDwD8w&RQdfuLIY7bMw~y(z8s};8QLQxJ})?9KIdzX|+b}tK-7+ZS&V#$bt6_Qm*d% ziAOH^wzFtf$Km0p62HjL;_$VSz1;i3q1rrYdwRvo;iFRIKs*t$ukCjC*wt$5SdVnH z!?bfU;;YE%;a!Or!ikOTn)Gu$Fj5)#l#(wRcmX$^(dYi~5GtKRq(2wW^$gKL)Zg}~ z-ruWS`a``p&gA*~R=|nAey=*DJx7P_)emAvQFm;sv@(30`~V0m_WpyH?hgYi(Ppj5 z)@#oq_j}dZ*NL>0LHqFW@wH?EUG1OIkJ6tm4L>-kc;YCtV{)-y`&X2o_`}2r`mBjd zH&lz2aMC#s)in-jchI1JKwtAd>>Sip>`mfz27!FV^W}Dy%CO=&X|d_K=C9dUiEbQ% z7xjtj8{a2qE7~XU?@=y2b{Bd{G_+2td%}UUR|kB4owenec+orY`I>>3=&{cmxke@w zM_8>)X>YvJQ(xo|!cPvN#USkjR%-GzyQ?ZXa-UE2B9zK2dRM)+&^?vX3V0kzf_B_!B zRW7vQk@6H5W5n}D%ad^O{SViQCqyR1BYhC{08`R2&Zsm8fV?bp_Ke;cSwFkAJ$v2b z5?^m_pT7z{@I*I3leWq`mxYzaUhI*e{ooq} z-&fn)t9I7>^z1=@_;iCVb2g%>w#Pe)$1}~wNxB!_m}3)um)6GDJWd+VBQFQVgmy-o z#CMeRIQZLlUW1K*9S1-32edo!q_7znK|}NiCFk(w`=!1+Gu><3eXDx6vUBQzli#-^ zUcgBEp6Cxm*W2dJ!bfz(8zJKf^tI+>v15oI+~{1p-Tk1@?$oEPjm(}xFC!C@D}3?P z(*D32d78Vs)DJfJCPSxD4!Rur*rAdsomnPcb!c=5E&e!DNr>&Eew^{0Y^dzj**=ex z#%Jgee9$iw2*yW^S&hS#G%83 zzr$-|h4lgS7|(9xCMLlHxl-E!J8vV=4`Oqud_um>EG)`}v^~88WQj4IFGJUj#7AXA zi#A8SR2T27i|6PjW!}=z7(Qu^iX2&s+KdY_N%;#K*7F6Heti zZ(|eq`2pe^jg86|FT6YIBpaA`&GYb1d(QL^DXnm#{~?b4n>Oopk?`>$xTvo{@5|>V zwDHHL@=L>^T=r_$g}M7<8|pV?_mWQaXmlu^&?nSMx`23pMv!~W0T9ZTk?p{9+6Mj# z(b4qp=qmkacf^;+Bk@s#t)YG+@G#lFF`Df)A0ZP#7osz1_dMgT(fFu*(UYH9^)1AA z&de0_F7Hr%O&EvTm=vsp9rlcLo64*u#Ab!3qW)n%Zq48+{y~@L(AC&d^=Nb`E@%VD z6Mc0-cN$Ler>AuIMdO+=3;bdybHCQzcV&BQa(&YPy|Z<5n0sth)rWS5%&HvPF4$zx zjfe9d)SrC98vhv`cIMhfcR`miN2mS+x*A(jUZXLheDO{HB3&|bHQUF$PWQmQ4SYG! z{)#^8kg)_S>>23{<~Ohdcd+OYQn)G;+0{EkYFz=$7x zh~8&2uu8*8@8^1MHQgVN`L57=j>qh@PwKpUW3nAzMaUS}qC3Cc?--s>HThT0u6Mcts28!7cMq;mryOt32GucVyazSf9mUPSGQ zd-{Fhq_Ly;PzYAxTu1&KwfCdRT#sZ==@r%+AC;%_>DSfn9z5vE@tpTof=zthIbfv{ ztbergVVqMzuY`6Q&KK-HvqBpcPP^*M*#tYkQ8@czjMr1~kw`!ilii zYn;LfJICXswzt{ad$;HO!tS&81)E`LDa{W^njFeEm}vSC9R@9I$~dpmF$TxpTwa{D zZW)Dbg+8f3P6AO6(fTmG6^E>s8*@QOESzP-koo zKNlhT*j&)Mw9%LMr;i`9#MWh8$NOR|j?4|r=H_F+W8`h*Kk=D9?k{46++V&kW8c|G z?5E)GH`eVH?xoMzlVkD}bQSYa8Uvu)si$vy8arVZ__ijVeb`8hRJQ1W)$aMTB38&h zX-j>vmX{$fYqA;r-X&z1F%xBCcfn7PTlBv3;lS{-JMP=-DV|iIo=N=KArbs?7rkFzaK|(k=T>8S^W4VHWp(_ewy)&f#~h@A6#G^?UKuiq8*%lYDLmo6GdH@KZQ( zcHo?R_z{j@F1Ec^#G(>U!l_ytTo_anN{)n8ZneL#{!@vkR(w{(X}3I7gGHq@wB>7O zbG^uwexlckSXAOke6#)``@B-!5B4nhT?uo1m3V5!XTnKyaEvAJ6Lv5>%J&BvM?$w1 z@hHcWaAHo9IbA=mz_^BSEV$K6))JdMp<0foR*e@{gp6aDPY1J@UvOhi6xMd8@8|MaYiF;f+GJWikUz;_+H>Zh;^%%`mzJkh zuU11N}8DW_#Rx6wNJhsTm05m zE&Ru2>b{mT4m+)Qt|i2QG`cjYU&ivfK^!NbZk6<4r-;iLAlX*IR zT(h5AKb}utoylI`xO_Hk9;&|F9!_b(2y8f~7rv>nG`y$348PAZzP9g}&x57*m5avV z)bLbswEJzutG`+hU=@tDh3g6D_p{nV-6dBl^gWp3Gb zjhg1;(Bq?P+PA(Fi|+~THLG`>Yb{S0*_zNiB4a2Y6cBpfnd+C346Lfedw8LC( zWf6>%edGxT+zUhcTw;+^wOj7%RrhMkNjPhtfFCf?IccrC!M}K}6jBe$LLSr7ArD~0 zbJ2`L^>4f<$&~aGe9%@IOZt4(*7Kn0pvhQ7eChphmc>@EgP#ZQM=K2j;%K9k#a<3_IS$T_*jb3l>_B($k$~(_4t&W6OeJA~(Yzon>w!ZsKCptdFuL3y8hl-vJoa>pqVXpp# zq55WIg)>#WfA7yImXAvJ;7L0}Z;Rgj?ZJ`d&6S`Rktt*eIc8o@dP->t_lrTb`8+MI znQsIOjn%bxr*B}U*W;xAN`6Nw;ZW%rI;zv?#((H`ug~E}y3ePrwx0D$C))A_CwbAF zS&WlxWcjhFghi!i$W3-;yfDuMALu#SF8OGK#G(J_N5rSXdey(0azvAMk1W9tx`un% zE#Sl+akV?-j(q5&+4<~6^oo7Q_6+qx#;VoV!VtfGU`D7oLhhjhcC;_J&bIG~Ga)nnKZl#d<8PqgZZK{aKGE}`sjbSm#p zdT6M9;GXaAD&aJ`es*bd>GTlTAXn&U^iJM>_oC+3p*hvG8*xk|%T%b&BP{-;Zyc3}e{wm5oh)&_a*-G+cuz z@z@&i*aZ7+qHC<6FDav%deu9PaFU)@f2Mea$iBB5c;|6_<9q7w$F1hqt{44Go5U^v z8|fg?L02+gApL0jsk^|c)BLe1O}#OwraaLWPSWMXd%KQt9ciRb@q0i&#}D02+e078 z_T+3oHYoS#CFCUWS(iH-+tuQM(A(h5z4&KbS5v1(q!Ay&iE%!59c|G2FQ9Hb)4YK4 z?I*^f*xQ>R9xfj09` z;tN?)Ul;a*o3DYMb9Xk{?VXdBwxH+W67wXzf-WLG*vLngFa)#9SEfUG$WdWmzR}X0 zSG?vUJLNF2f+m0P4Nk~7ZGyPYsl_`bJ}~g}mG|4AeAM;!VqZT#4~5rO@8qVR1MxU9 zmQ`ND;BPDPuOVMZ(uaC~*eYH|MXwp5c;;QfS8_j;^Zo~m@7m7v&P*&SPaLAB!3Qj2 zU%`?m^Z9f}`OHU6F8DVH=Q=hvllKCR#P1sAY0N3CkafLBmD4Popj&+Z#;^IYEWyUT zZ|M*GsU`j{@gHfv)qVV_*c$)$P-_l-`HROS<_R zeYOu{Bg}D=iM^J8PJZP z4--guySF** z%VSdRx*X3wzT|v#wRq+2Aar<9k6VAo*c#u*)<=YLE#0;LTo@1H1JSP;z(YB{TPa>x z)!OEQT;<0gDuXaC2c0x?W$XT0-&(&nvZ;Lgs(6iUj(_~{o9Kzt zE}cny_~Cm^^c0rktJUJgZ}7ucZCk4`-RhZ>Bl1tDwT4#1VK07)I62=9HR2G&k}w3573;-!F*&GV8D zo0;|Vna%a_{-O0U^9l#Wjd|bXuM%&q_Dnpp#=`i*^9OFM(}G()<&C}-x}H|6UkfKf zY-;x0rC~-rz>)Ee$B%gceER7(*Y#k6AMxPJdZS4tkyZA3_Z`{F~r&U9=lQVc3`CWswA$sCbeJwM4SC9 z$gA%6TV5mciMKdpUNW(-v2T)grteAmvxD+4f|u+ zBa2Tq?)#_5hqSLCEq~*POMng*jlp85!^Kj`67Wo_+K>dn7vb+a?Lc)xPBcxgXFby29O>o!SvcFs+64X;#8+b^qqb7T3wzw@m+DdHxD5KlYWhXmx%MAUnO+oc zwbiKpsl~@-^Ci+KUCp^#%IC**jA48)eFaWB>kXgvuYL6;3MclK#{Aan9yx*z>vh$X ziA<4xbawv!VVz45g2IQ8{ib|BY(IJl`Ix(Rc^Z4O5(cs@b#7B>ITwswrh7uk)9Cu> zI_2veka%xa=rLlv;qPOfJ^yLfOI@2GKX!K7bHz#5aNdu)^G?i1(zs}Qx{@LJ-{P6l zH5((wU&xSnO4go|HO*S|lyCwEVUiXq9Xd+#p}H%izay{C*^*B8&HP55_(3#)meBUBsS)crW?L%-TF>)j6xrc?Ec2+$g?uR+%v*W$<3bKVc)~ zN_6zzs26;BJB2i9x`sT+UyKE9NHz~Llgq9wUY{E{8_Ntf2#> z$O~<0?Z(3C`%8WHZP?1b*YsRz$If33=d0ig+Pu$rPC+yqftkuCWbTZ9Mt(1NXJCeY zRk|yK=Suw3!LObvL{`}EgKohOMy)=ezz7)wTgt?@2KaJ~+)CyNu^mKLVIy$z@+3Nh z*nP+oHYWGdDSdZx7ni!bN__V6eDLhme%^hpKAj{t3fUt>Tg=Y%TdD06?0o`n%9WnN zhC-%_{V^$ve~rRPKBi0Xkvq{95ogO}@*CpwAH>o=~Y)9Ftc7m2p&(2P(trORbY%Vt48jV}zB_=PDqho-WSGhqNG z_<2GuriNzDA}g%9#Qw*WJ}pGHD4Vq#`ajWW20o%8nuO?XjZ-uR%eHT}$2j@^koGq* z)Ugc?$P*ZOd60hgbhxgzy;7dWDd=--SCyqYG$RyEFwz(WKTnz;8_o9R;&z8UK|XAN zwD<4hBzw26^iNDrj|X4SS7%NJpJG0pzeWbJ)k!D*7+Yf(9M&9^_|O;uJ;Ydpc=Lfg zhy66Tac)^Q49^*(@f=;^>z8&dd7A8N-?H;{!B+$Jwoi-vfjK%I*+fT*FG6fxdp7Ou}Owd`_>)iXko;2t$Y;Va9 z?}?x1$Je15*Pu!r9ym$IQ~&9qI~~*)JwktltbhTs0gmV`un?W{q3t8i z`;-tZ(T?*p1DBYFctD<5f1*vnC-xJzg7lQ1D?!&w?+o|adLHKZF7%y2zk##jvDc9)>}u7Wv6|OC z1$miV?33>@{IHQ8{E%nH3Gn3gL9?*&bcB=U3aGDSh<1?p7)W?$UR(1~q*uCS!%1aw zeo8VzdlXL0Z{sfud&Ac`U})z!{W)3r8^InBU(gk=qSee0+Oz>=$ooq(A2Mr2Ujs$I zFr?=_BR7QHQ+Lnv?Zv?X?cY)Rq+gd`F|Ji-^RscoW0YJ&Z!z>I$ej9GuR}e(Mqi6p z`WDr>eR8}z-FK1kPMgT<_L6-mAT#+3$=r)e9~AQbq>wbiLYmEUNH5YfPV!)l$6s9 zjGz(o%su@!b`#I9-&@TJE3gUaT_3Jz6~k1YJqcy>B6N1YlYASWS}UB>_q>v)+5bcz zn;F|$GL1b&`%5q=`d`CNsEA8Rd$hBSd3b)Ps~+Z%dM{C?@+q&u&{zIe_C(T*dDw5ZqNEU<1U^f7uCp*PecDlUgm~n zqf@@tQ4-2YU#n|E`bNJt-gBmZz`P$8))Yz8YTM9yA|*1NdGWzMS~n@b-iFY1L3TQP;R` z^}L^$9ylxibj+cPE@7);14C&r7Rb>z!&`fepw!LcMS) zSB`A=qaaJdh>$r1KUW#>ipCe^>b$S`{8;d);Uvr$gK5r%Hh}%<$H@D_B+}=ULBA)O zt=iV$OFV{stYJPbeCr{MSs074KH~9WoD5!-=JjgDP&QYq;3P~Gmf&P#{6hWmbBapG zxSu&A=DTfJkO{E#)~Np9R&zctm>H^MwXEjVfo0eY=~mFlgqh?9MH!`nG-u8jT5 zO0N(d#ySGB26md~i|ZJC{F(frVDhnFgm#H`(mdjtScu%XAYtdJp_$&|cN^{UqG}7LM zo*k4%HTgwLVKsS_MtRagrKv}lR=(ouQGPSZ5WhaGH(g)0zpgi(MwjP#=eiN}nn9xx zd>@y2jKDDh#|RuFaE!qB8Uk^jy`TFJDrS|iV9trX_{@vw$9;Uxzg!td8MAVAvT^*% z^^JkEd`s8%_g>qKRe0(4(9Q|Hl}gZ@QV58o_(m)vl?8=;T6ZT zC)D<*UN7v`Xpn8+2>d-p$PVA0(Yb)Qp7pw?{4S#f?MBq8-en4-EB*c998f)FXD>`? z$D;4Ude`xw<%u`eP|zoP)vFQDZT`G)u2uXfJZSyul^=f46OC$PYuz_TZ(d0J6_vvn zT_13(U%4vRQYcTv#x6EGlliA z{noJ_`GnJ6bx5llGSGYFNr)cY*9zvHF`v6 z{+!v>~r$cPCZTZ zpUOOF-D}A&n&@HLLb$iJ&W@?+aMl9+#3!}__w?<=v3HsKU1#a6eyrnyfqi@IF5fj< z?95H^tv38Z*gEe>?B{@V(3ajRr|)d zHla4Abky_aaL)~J*xWvUHO67D`_+-o;O`g=zyi4v{=6UXqwS*8!7yI`thMg7q*oo| zJ{s9l8ydYgI3Nt+Re1<$H^|9;aPhct{)lo^wq!~+M4C=hT7|XLyPC8rS0U%@eZLDP zyvxM?omRcgeKqzv=fZTp%GbG;YuX<&2;Sm{khvCkpdXNbTmRf&S5xQxr13O# zjeL8oq^B<58EE%@>1Yq=TJq_vUM;x9X|J8{2s%)F5MG>2{Ef>-pv}edw4ZwKCy(cg zYwTSxQ2UZCH`vkD<8k7-o>l9+DaOX%)7I2CB0~$EouibC?x8sQLR6Aw;sZMvJ+5^pjpO6Cr!gvh9PNWPw3lpw z4Sha%pwF-`=^v3TVJJQnnh(Lc>?y7XMw9_xv^j4>Av+qUAopIT3iH>N&;Q{+l>Q8v z;RgoT57JRSZTais_rHCbde!wH<-m_03#)yBn`8?6Qu730CY`~&3u9;XNxp9JHT@jp zT>KsJ3>|c@XL1fqxyJ`a;sYvKPxb3A2dQ5@@~SS(6AB+6N~S_ROvl8wF=H_CasNT@ z>eA*?828hb(8u`s#eO3Hwb|t@oz0M*R(jj7-oYM!^Cc0!jR0LQx1w=ap>UF&=`muQ zC*7g+8=Mm|KNkgmspvM^CuhsRfiEH1A zIM3ETnVdOi&i63q!-Wwcb)gxP?ZPR@ z)Y)yyh9-HyRcj2~d%l}_E&kETtS8amBU75IEb(0teD+uld+!CDbmok+Lo*Y09?g7# z7@pKKnKw>+{D=;14LJiZulHF$z@99Y8+`l(c}4$;pTojR{QFRPoB4v0vr`puDm~L! ztS|Uw=g~c$Mtn^>MLzKJq`X@1VGbUhps@mZn<-1siuvVU^S$U(@f<>v7oP9OPgc^8 zCF>IE7buH40cit1h*K(mB$5^mEwevYoJ_prbOi-UB}9DfN4v&t~D|>3I6Ix$F1VvplEI z$F8Jp1e~U`X6KY^XXWDyIGJrpIgE)J@9118I5CG4$_{PZ-j(&Etb2Lh{I%!5S=XLE zzAWJxj5N=y=eyctm6(}-yAH}={y}B=kavO123^KkNlVMzsn*%KZx$AN(eZrW9_{Pb z9I)@3YV~y}*^|C0et!g8qO?Es^jX7Tu2AEqR>BD!#VdU{^PAi=w%0t;zV*|Td6%=Y z3Yg2jz-A3T?23MGnJ2u|KVPy|xYs*AjOW5iA>%XVM7ZByf7kUAb{F}jk4x-TYr9w0 zPZj3DMOWcrU{Ebh@kmJDEgy(s+)|}ZQkx@`J*0BITuz)FIJksH2UU$pS$V_1A!8eS9hUk@V2)Ssqt)tPEkE#|jAP2% zM+e6c9oBIQTGjH^O6l~D(J%GDqEZ>sVXajEYI!N(v`;&{5-#yG*;q$Sri2k8wsN-p z!M?^UF&^daH5Yi4abg}D8Dw1CFuX#an7o~8<^8bJd0FC`c|1Q4&iD`CUtp$R_u%a5 zadvmP!F7rrMKKhn=o~6Z3V}9!kC)V)CUw=02Fq1v_v{;~NaXkDu`H>4>|tb#vIS z8Bo4Y)2i169GpKtVa0m6_w}W;gsfpQeh%_xb!XmzJ%r3l5{I5+ErGRB))KTXr80{1 z39W^b_#@OiQ(Qdem0x?-l%cdLPxs9XMSFJ``Osv{pZ~rHY1!|_J`1kv$*=g(JJ7uk z>q)QHvOFJLC*yg>s*GJ(lj}Kc^N*q5<2h?3I%~mwt@O&JkNHTuFPFDj@o79&ij%Dq zr#UFUae4m!pk>!1zvn0I+S5pTt~j6WAlE8S;X%r(XI}9`xL3J8ZG62~-ddik>{{|P zBW*Ppi4WC5q2iCjV+4*7I7Z+Yfnx-|R}fGi=)>=ox|ge`$D-Qna%Fvx;wxdnydC=~ zZ7a$J_Iu8E<`(QM$fV7|UDRIaIREzoHhgpQ`rKvtsk>1pQ_n>L~+2dBm$zv4z$vG$nw zgUcmyC7yhE*cghJ8^hP`#{BPfe|u|TWUn+@Td9Fz&g)=RA-*ng(#8bZ3K@STn;lw!!U$<(mg%dVXrS#)N zxv;k|O>zLFPX^y@&BjU?(Wh0aXSruOtB*~TmIe%vA)PB$--+Jl z$2~mg3}8W?ERH`rpImz8y{E5mo|Na!XoCqS$^Z9iH)$9s&U`|Lv#ivSAN5DRu+7mg zo=&-I;Q_ALBBYy~FZ$^cEke@zavF)1r^7Y8VaK3HkZ;cy_vP$L zaqaYc$I?K~z72PCxbp@-&c+U{ZH%w;TeCT@JWGc4l8-*3TL5uIK73!AX zBZ*AJJRukGr+7Q_c}8tU`8nq^G1Rfmo^zeqFXz)iz7N)JEZEwh?ZLM(kaRqHk~qrq z?~LcjJ?~8IShO2~lgeg~gzB1{mE(Jyr8>dRzXhJ@3$cL+{kuf|kP*&5?S+Z3@gZle zub-a}I*NCucOkv+`vWOMO;;0L}$Utyy#@;D*C;XH6; z$7SboYr;wLB)(?mJG;><`@u&T#^3n_BhH4P$Dkvu&{^Cgv*@a3+E1#l_wB&@12c^q zvhxdle6tm-c(3F^SD<$ef{$=Qhoiqo*Uv6dru_HZ-yR$pIX55nchJ7!E3K_HLxzMC z??*aP{TX9lo+D2;MmB>?(NELn=nwIuf-F%t-aopU`{jitJL7wLwjMu^6?0qAkLO>S zi4%ArQ}DswHgI5!Kz#qey(=^Ky9(nx`RKVbvR?4xEW8z>Z(^Ll6&*w$i2RU0PLp=e zJ~aHbP`3Iv*$Sf9Oswcrq<_GQwg(^PD`zJ76YCia<9qeNv=?LtJwiRuc*bMG+ff+prw3iVIy%;*`fCIAK%SS+*KXr5HFXClqp~K77)yLEB zB%73nEfni8>?mZ1@r?A5_<=s}NxG5vw0blnPCOBYafxBVc*Msqjr8__lXMrh4tHGXYelj zfqt5J+Eh7gkP+Do$R0WgeXsKN3ef}T0NLW2haz8E9hwm*p8Z&zbpypqH^}D0=2Tmv zFXP8Iw)N99<*znOeCV&;3*XoYRVi$_EzUNm~Ucexiphk)0V2W3`Kuw}V}P9117Ro0!j;6@HXyepoJc z=Fef9uaQpCQJIGoiVy09EcqXCYD4m?LOqnHQb>CN6UmIy($<6%Z7;;<=LXSDrRV<7 zZE2q8u<#LG_=I@Yz&M!})#m&BPLN*fD+9 z{5_rwb^&rmzt7L_^Wj}#&tBPBEy0Ss;Ep98QKy|fU_Xy?p%`Let}O7Y$7Q2e4#i#A>RgltNU`+|=?)2+-&DG&2& z%$4X~X?z_^uJL_EyEI9R=Z`gBVQq_kvuAzv4DzV+e&lI3HlnBcrG>HwVw^OG=f`)9 zYbk^FQG!dp&+>8Vzw}P%BQ!3SAKbg!W3!A^yd1R>PT(iZq^~rGsCFkC0h>wd2bv>7 z-+D~auGLp+-T|DDNk2az*@Bl=vBf1@K7>EsEjmi`1Bw0D_0rAJ-UaRFVk|7VAdl>Z zG<*~%oEVenouq}#5oSBicigc#LT~qbJ`ej^eAC9H$JM4r@AVB}NBVv$!Dx4XE^K_L zb_Y%xH-^3xTO+T#7!&127S>tEKp!I8;)(FE@ezH`Q}McZ26k@q!6;Z2$7artZHi7R z!6`p(11ITn*&MW6=z-Jn;%wpEXpx8HN_@6T81olw&ET8X&cIHtWqD4h@tDV>+;!qJ zqO@e$mXbAWHrjk?s^qR!uu0=1jbGww#R%+*KBhM|k)K4TnLTPYfacGUQ$Oxb!EgjF&7iuLghj9(3KsCf`#o zYLTHRt=S6&+o=^XN#jX45i*CMG{{z?uwtK#=!#yehvGMcHiykxgLqyXS)WVhi7L0F zz3{xW(bo>{j8&L>Vy;efMeC@9;v3z;dX)I4Ueu2<-}QT|R~h3oZ;KwI{@l|}!D0SJ z-xS#D$6NsISY;_B?!x3^*c$^~#UF*Rh*NUKK0wx?4$3 zTVM4w4@#$5`NeahV~cAk%%?L~1#X-d+v~?%jeRpH>;aAEW<-Nfd(kxaqI&u?Tr0j+ zLh*;Ksq1)*q4;`)>}6q(hvt;amDwuzh!61@)|vAD`>BKW4Cr~ap~_7QRR&nGcgWBE z>Y2i{{LPMo7ts`7VXZFM%zQH>`EHw@DeXZ+l}8xXbnHxwkJI%*>C_{?cqs|P_vy?A zu=QWr%vw_?T|MafGD>J$`TFx|TH#uJDP%4(Z9Y=ZP91#~7*Z{<*I8?0YRNhtc;M4#)L9M&KBMV+20P2&k{C zCj21dkXE;9FsUX@TG>ZEF0J0(eOK1_Zprl38QY3;d5Zl3{1%2gZ}ZbN&)DNQG}B#} zpYi1#b!_0@*N1E7JErbthi+XMYhT|Up4Z;jYD4ybvWG`|?N$C!#Y+4WA~(!kf=#t} z?3E6TkvBiTd6cm7_;Ag>q_i^&d*M*+bMU%8H&Aj$yVddX7}@;yDD9)#`W`eLI!^Rk z87J}BvwC}rwaxwLo^n`G7H2}sJy*Q#T`jB$iyt2zHh$uTb>P2%W{52Gun!)Hjp0 zKRqoCag-%q2yI{SlJ|Q<++kuR-qVIz=Edoa_|5XUm$IdwveB7j^r~eE5Om+mlJ~6b?t#srSuZMw^ zXd_Fsi`!c__w@59-U-#OS89906Z^vFWo_B(!MNRdzklp;(E2AlHw!D_6Nh~3&g)$2 z629M7rcLU*_OvbV0B7n%9qI22-|M!z@kbnTl0SpA6w8>-w6XWfV@TP&M_*o}v5K)N z+~?(;u?T$e?x{1+eH-8zZHaaQhK2ljEaH3gvCg){&+t_sTF^^$-cSzN6HZ{?d*$RQ z;;>hI8I8nBbZBevsBxF=BUsfl=}`GJ;JuT6Z0=m(SLuAnH@>f(?+EA4Sl8tY_5G#3 zf?tSxTkHM!e9&+F{Mude`}PG^vJZGi;a%A~@pN?ENQ@{OI=o}ONA*XdPbm3OpXQ(O zeJSe5IWw@J-X4!~ejws_^BZ!Ca*-3S7iDuIuU@7}+h}Z5zUqs9fCv3}civVJPCVE9 z#oq_G;P)b~^M3E;vj%L$i|hmS!IJ4_;UtU*>8Gf_WC~s2b)?5hV|(Ogzj*k3n@gvM zC=359{NM-uBVOn`h?9;&e~Wj$??#29<3q+M@WgwJ+aB`+dcW#}mWOlZqhNnN*6>{< zUwxhj{AOI6P5c?Dop~9Cwts((!bjzL-gM1)0-or*&{xE({~DURwt44T;!_O$%`(HNiU*M*(*wwl9 zb1RGM!SA8h56Y_$S*Ql5z0%N6Ql`d$v_Zy0qSGvFJRQ*n6WP;hXKG`E9bG;49pr+Z z*S;-6WMOD}YXo^<&sdBB`e)JlLUeSsZIyKJh0c^77ftc&>(GpA(N&0zEO`en;)myF zuPk18uqqwJTrcsow-^_HPa9GjR{7xO)1+O~F0sGJLm#5NK5Payo`$ClM#6%Sd!CQX zKbY`1=^gLY&K5d*g1tQ1*ST}7T#(Oj4 zgp;>fz(U`=y)c>hM5Vn6M=&MdUOEb_z!DrbwuXDcwdrZbd|+5^Z}r8q-HYf&@zzQ> zVH*ht*}v=EgV|h1VRZP`7@`Mc~ zoaFz}^T{>->98S$Q~bQzd-{O8J$+M~=ERNpCFNtTgt39{u?_rKvzhHIrX`;IoLqtv z=QDipJxmQAG!~FiSs@Yn5(1@ zVJyiUh1xjf#Jo529{T*LO-ZJ(&x>+1w}S65?Hi{(N#}yeR&SsA)PC@Qb3Ga>qkqst zl#M>-tfTsQt$78?HYXU$o*A$?@u6UgYrY9y;3MJi@NuH9@TBpJu+sRPc{}gtiu!vy zhqicU>*g?c@zZ>t>W9pMljH}Sq?g*K2MYefxF%0L*CQK+XU&u$PYc@U2-%gI>j5jt zy!mywV1DNcYue~){EBOQFFXk2{+u|;lVr`O=N$weZJd7%GRv8ext!)N;6vkY@_F8y zb?y1pwYQ^Gua4<+r+5yYk^{#2(p||}1@q%)=NMIv52-i!#dF$96Z`?@&k46rjfOQT z<_RR%jHM1!pNmf)dYsgL?3~mhGR1rW{S@uTuMP36aK6>jwok8Q!yG#@I5{51YMzF! zX^WIM+0`|o{PJO-d3kgsdQG;i@-|DBLb>~g&W^uEVQZJfRV9yERuZwe0sAJG&Kl6kFNmb9yazD;ydMOg}I6L|t7 zbQ(06le#*S_|wGJ3^;*j=e!&Xzl_EpJC<#v$e2GgZC4So^ zKQ=Zpd^n>$**}na#?|v69$PK+JTk7>j~^)cvr}2<>csyqK7bOLTs$*9x4ODmn13QI zSSXLeR>Q~hBOa5sR=b~&V9#5<^=E#}?|PZD^V#e8U0XZ77RH05^Yo9>HN0bY`});( zjsIwqAAHsmmbBM%TgVeXt&JU3tb#05(Z7|}e?PLzTca5iyt~{0M-&*9PmbB=3y_=(im3U72^TxKjfM@Wzkx)H~I57{7 zAFJHLgQ1@D3#V(5k!sV1ab14j6G$CJoR~*pJ_X+I_N=e7{#kAP)6!i$zj>N6@G-_% zSYjb|1qllC0uX?a2 zPIJG6>;t0C)SWdheyjy>uOI78$RcYN%B%7evX;Z%I^B!zQ47UCYnbeT)_j}d4;r%f ziE^hlmd>lJqlOXuig)&+vWBPngf%|1dxDRs@cpFz!u*=@_%N;Rdd~iYSf=zWEnlm~ ziD&j2YVS_)GsfJdezxYKbhXq&dBC4_Lf!kYmhuiWt#}T5Q}TP6!#asDBFwMDk+xP| zRlfGL>Rw^3D~2hYrdb%oZap2v8&4$ zZgwvW_uL+zEBzL)%5Ke?SI3p=pb%{4as$);3K#J%~l>{ zhtb*TuumF1xW_(4#<0gIkNn<-Cm->=E02%AZU$DOhkfk%3F`vWD}6ktE$~eKJL3Ki zY_D%5ej&gCEVaI%^7jfwA3D-cl*v6mXo`MZRx@#uz9^h^weKXg^D~^(M)bYt`Oe$| z*dbr#&gqbrHT8+PYiHOqu$Wt!x!KjZfd3SHZ1LkB-z?CO%z_CrL|oi2K)2Z#d3wX= zPu|k`Ny5@`#8B>Lch>^^`}W}TU!1(Xd3}BDF5fVt{+yxSUb;D%=GP&P(>Ko;BNk-G zwSC&I;=RA1X2=jUd_8roz6BZAJH33T=ls%WulaiHomRRlSJt|~#P$GmY;K>w8rQv+ z`~SbaGmVYwy6*U+Bs+=h+F4xGNYaSfC5j>`iIhlD%ShZsN>oUSi%E&{mRN{lSxZo( zb{hpQ&;aoVD>2XlX@aE9hd4=-pa_bpNCBfQ3Ih$0W@*2*A)TZt+MsB*)E=Xc-y zXU;sn87>lM$Uu~z&wcmZ<(&UJ_uTE>Gn7HOhnrh>4oz+ee(1nOXSL8F;RK~mC4ISY zO2bO+3x0%CQ}gED;mO8+^bG#65livaR}4FFrrd_6VKZvoqryaXoA2(iQ`md@8GVOe zPMkbeZ9O9e^EcW7{I~8rUjt6kC;VI#lX^eY;_^4#-WiLiL4 z&C%Cs&e^iFbpo6;uGHL2={?0~PZE=~d-Ra8fW}b4|5Mf{9eoCUYi@U=pQ)(=M?@iKj7Pw<# zbb|LHokGVo$F2l6zD~)**Z`ZLd#IoHYTo6a6HfYs6i$cFbk;QOi_Zalvk~TZex*xLY>v0}^jW@L z`m_qmmS=X2hOs7dDauB#WG}fdH#WXL>gONt4x6nxvBti%MUAI4W}vO0BjlqEN?uXy zH2omYlKQ4JqG0I9P-=6GRp6)6{(6L!a6;E*v!Uo0&x9B4k~IS2uuEKonFC8^D0-%~ z1@ayq8ScfNgDdkC>^Ay{t*4FpF%sii`7F@dled}Txe`=3!H>s@`@9Te6KBsioasN* z70wW%E1Fl(W>_D=u4{Y*PWim5p%m>2do1-^j|6|Ow0rS_PDzg|fe&?xbH)O^Klo$4 z8y=a*Xnt}##}5PGOIjQM5zh%?^?hwc2i z`73J;x=S27nB0?*z2bQ#uoD0Da~f|;uVm9>{};6zPn|qu{(0j+bW8he=$P6jIt51H z4oGr#Zo&wvchGv^cu%Mk-!`U4DmOkq9s69<_+NZLD`lgEPZ||}@iXH+ zaTcF5ugqzDUO%5zJnd6h6|Rvgg;6^*B)n*YJkkCR{T%HyjDO81mEMbT>wPUZReecH z+W;%sVfjGuc-3^A3cj4eenVEiWI14i{xAmf<0;aitGV*c2MuM{*iH}6w1%m6t#UP& z(LHpzF-j|6^=tej+llS)7~xwdPCGVXzEOsG7O2_!7{7FXeky-SmwTuJ#oO_O7}<5WL36Md4N7x)Y_ER@cC_cRvZmusKqgC~b&yf>&kQ1n7)W%rIX z?#z{8_KN4UHLaEVc@*-ioaM%%RQci|Z5*6E=hL6_lhwIxGACaSpF-aTJKN&9oyI*{zg0OA#d}1bu+MXBwC(Guy-CJ2ijAf` z*(T;MS{nd6>h7qmJ($az)4`s8)__?%@MEncua&$PPNIxw7Je8lHc^l8Z$x^chiUoEtp z`o!E@&PP8D`U0Q*!E(c?YB1;DeqF!9~&QP)i+qwt9P{;sNOB> zzka^46da1>VP4Ey0c&8nwa-pmNokpDjz<-fI$ zYs^1gJt1Mmob5zwYnR6>DFryNmz9k7_v7{F$M~ifTf{z0evY%cY?7CWuyFE}wHI_i z`v#mX;9^~r^*G{_7i+uPi}z&_*0%&NnG{aLOYitf2YW;vt{jhkXtozuLlH4uy-!pyz3{ zSe`rac|E&>MQH@2SEWxLPbGP5Za) z4^0m(mR|b)}wTiPnTQ_Z_T`gATrKb1$o1O>0)kK#S2c64xd1J&2 z80oyrQswsfuuThTuidS7y3=rA|0Vg3xL+ylQ#d7g^fD`q&E^}&zD~9i8BVtGWJwg6lePdh|6yuSEzuI7U(;AEfd z=ls8*xAcu%tz82r^wG)UN#}JNeUeWD&ub+xvOT3>BN)qg{(Ts`Oq9ceA|?* zBTYH*p$_rGnakXH!uFj(?-{dr{&~;XS)KJ%UQapG$+>Fwb@}}_e6Pr#%D}|naNn+7 zM^27+wG-}W>9TKo?VLuAk4mr=5Wp z>1fM5$8Ks2wcI#)nb8sHHGPoI2Z9s)^GrH~Z1}vG4}*m~_c#sK#XgOMllJ7fS04yA z=rp<|{+AOc)#0hmo5B}io`DnmOP5-^4lc-#VJVCzCx>!nc%1NQB#fYXFT6MIHAeS5 zFDFKn?du|pj{7+-eHZbq2m2b~UuQcxYgh_{QqRb%_CwkH#vpbo)MM@L#L4!YAHM>e zvgehFlb(}@f6I+i5-Zk%;Dd`crnb)+IB?QEem{oKp5B5DMi;Qj+?T>f&klFTzGWmM z_TKAL5+|Ke^z$LcXv$v>j8uo}^leVIK+oiR7&)=oiWkL)h_EO{@vlO^2gcZa{AsB? z+IQEH4lu^_ZRa`N80gI zqfOo(C2{mPb=FP>Nk8Y8!X>@y^d}Pt*b7`EmmMZT7p539^1@8!G~56nx$T)%guA3H&qXUuP8&(rk7$Dxnd zIr@IZGq0hop>vE`RiAK@oi4Ucflet;IdMs=3qBYx(FP_OY9AUn(tfI;dDOm3ZL8PW zaMFMQm?1ZPTUx)S@fKKNxBU8}n4*uMHx?=537(uaH%9G^1ocH2^Hdc3Fd`#aoL(wrk zXD@B|NG9it?VoF-7)|>`j z%88AyOE^H`-{X|`R}}lOAPsoXA8~OHe)1y*wee8!O{aMX_{VKJ{|$cZcP;k);OBG2 za6&g}!{XKRU#_s~jwvz?HX%pAE9+ASe<*PqjC~i8RyLY-QIC^+(-oG>T}$|`T<<~O zmTL}`h7oHlw0E9q|Avyvg^jOA@)WN3j7@}Z<>hZJ>$it?8Su*bFd{E&{2nLGqg8I8 z*?w)OtuH6v0poG{+BBRruc8iYqA%0Su-swQiw?jiHZ#c&X;S@%n9mEIVUOBcTDO7~ z_DSn)JY&D<#6(|xtV8B^%+B9SpP=#?#rz})Vm)S3~_NdpK!0t+e?avSBARUw~(DBi_#Tw0a#V2%}Tk zy&B;oN_mW@!HMx}LB8zxOydN;SMWHohR3CO4P{bJCH^Fjr&`YlIA!NnY2zv{b4|yl z3}yJeNUdYB27qjgqkJBPIlD(*##kOF=E%(dSff(EPzj8ZbqXuyq2gETLD+N2l}072 zA9FLe(HMPv@^oLSKDjZcub2AKrK7z=BVffGNBkxEF896o@cO@CoU%UD&>`6<)~@8| zp7AJiMvt-fpH;74uLmdD?>(Id2Wj_8S8iO=>Vp^Bj%<{^x0qL-!hAW-tFgG`f`S3_ zldNy3Cbd(ZwQq^{p*0VeF6YOn`I6Fju0)(TqP_4wwO&0RPO`nc#jGKL%nG^163-by3H@m{RZ#Z`z`n1?rEB!xf zo!vt<8-1PEvWyj)k@X7Vg?w-|8(26UZ?z` z;$E8@Y3_Vx(P^@C#npsQMR2kvI01S9Twle0O=A5^J0Z zJHF^PRw94AzYy1)VYI>}U_)#-cAt*_cZ*Kk{ob#V|_7C(EkTz1|`7J?37#^CU0m0~nwiV8}c+ z4G-nx8GBo-5o_H=^?0iEK8~>BR~q$vGJoScPUfhr$Fio2KCo`W8WR^-auEj}+8bqF z9q%u+*o4r5w*!d14)aCXkz{1y0c%|Xv`APD6tM`nP7~@k8*z-+-+MWG&jNzEy z`%2d3`C5r#@vCp0bUz=B=P~tL!+g)iM}EJVXXMY7$-a7S995`ys%Ir)<9QOF3-#fs z^ymhAq>LdwMtMB)`!r#GXmi7O9eFNJo}ZN%&dXdFnvd7Q)VgE;)Y@I}Hx_?mpeGBV z^VM0&=f(J6C{M-mmx@=}$ux>zi8RTp?r()xm61korQAy9T~1k&Wmi(p+f}!h>2{ZS zyUM#$&K(5qAaDnPI|$rCpb`l9K2qUI@KNqMCF|{`<(6Z)>RT)>e4}}!`^4Gy6T2Gu zrjUzs2gK>ypR_WUi~r>;Hz^0-fgvmBneZ#{-m`tX2hY`p?>bqpV-J8U?RU8Ky$+P` zEcy=BpE=Rmdy;QJ^}EHYZ#iYU-DQhssI56}LnfV<_cGtEFy;F?li}Mf->sJC`D6W> z_r09>c%0d<@b#yKZ&kkAk>B&h@2${=yd29JW*yzzE&Kj;MD3EczEZyR5k{Qhgums) zB&}?)2s~uZEhKrs{`vix+o2arDML76qtoO_#tqkHK&9OOf$b^9UpKem=RyH~l;L{5O?)CW>7n%|gzO<@CwY^G|+yR2CH8 z{F#tjm3y)IW6sif^L#2S`NKE5#=GK^6rH1N&NwEYCGXYW={wjo9mIz58&=|1bg}X- zCB5o`rty}PhkM3Mq{r5#Jy)F4(WVqvjH*r1=b_i(th?dt(|bGb`6j#+*%y;1Ss(Ar z^OhDS4f!}5mG)e5v`Nx|KWzp*M90vb*mC@xe}SD{Im0=hk&~m_@q59A{~9iQ7p3_%klzRLQm-94 zFVGczAEv&MHW$*Fz6wv-yGr8JwsYG#aDWHqyR-{^8!>jOxvrG#!eAj3e^AuXG`j1= zNdKYSSu*Sw@w_K+0XL1o(Q#}Y?~OG4TWb4RNo- zVmN^f_456S^oKUb9NhD%@KWSmY97@IMVI&v$;T1KXUbxIKY|%;5FPCp>)!!Y`<0F~ zk8K_to@~td{RJD@K;Z;Mujn6Tui$B^@-8)>Fp&(p_dXS{LyY~f!N`lRqlNg-qOGbt zPxrK+3I0r5cD7C={Xz;0*+=1p{YKAJ&Qj%FYChF#KkR$xbnW2T-qzj|gJ(~hf8U07 zo`Fs9FE$+e7gKt0TZp|HKQ+{(_DnhC(YHCk-77JtFu}h2{u=ze6W$;|> zld)6B#Axs_%KVY~!IPSD#2<2Trsr=GTa8((US&2X41kJTSv+FvG zik$^3e-=n<)z}pI$&&1(MGkPn_W1IBnDIbzo+AB8qiUy=QE8k4Rvk6%__@%SQ?k)c zSi?rIjy4}3A)Yl&;RI$O&Ym$3l759U!?}dPGrR}Jw(2ifzf8j!;#Jw49hx zCv8acQSkt+;oN=jK{VH1(f))}r`aK&FB#^XkH)kCD=QnjlZJ_pL+5DgT-bcgV^n^* zal*#%&RC~ok4|d|$P~+m9}xUH>KsZueily9w6PF=$Ko=!PYNgbWtnf^2E5Q;VUkA6 zjT3#6e~%j9CGC5VwJY9B151yS*7%Tz^=?1b&tVkCw3}^hvnA|7F)sJ@Cd1-mC151E zJdfJ@NX4mpyZI82_aE4Aq5a8^7-eC0{7K6AfU~akJNmNiRv6*0AolY^9{L843t{GejN2J&`FUWH z_j27QW#eA!`LYXn`{d-L?R4R*C)NqsCHgqV;##|8Y{1!Tk8cP&Um=VSl4}I4yD(qo z0xPYRmkXC6Yo@e9Ho5G$Ty^LV(*Iioz~=7FGc18oJ^PWZHnqouFp|-Mrxu z%^YuV+qskY78~9&e1LfyIBO0=KO+4^c8^mzu_#rSc%rY9Ph;$Laea!O`OPepZU^q~Rr;plVCG^%iHBgqyx~ z$?KElOKGPq7I$Xrrj{f|+;_LfzWg*d5f5qnt)w{d8B^A!65|1PkDVz@-_q~ranh?a zd=xj>cs%^htJX~@ZzbU|A1^_E^W{+rC)yL^^)SXV+mqHtX>ZtU;o>RwiD$dpPpzo_ zY(8xKb8t%aJ?`|WB!-D}*elwfF4oGGpSiX4((|wy!ZA)qdL_%U(lEA z@5vrb8cxDUG%Zaf;=~VYt?awqE&Au)?_YA z{p`0er$xrLiQ2;p!47@ldl+=lH)8Py{ikMH9(EyXQ{s-AMvH2&D@i1$5u zPYmpC+{zv%a_ge)5XUq2@z|eY?$3Gv`xMDCGdm6r^1XCR_Pf1!&Tab*>`9w{ws@VY za6X+Z!{3(^A77Vvz;5{UZ^bW~hP8y6cCB0SyLx=15Zk4mLCv8HZ6UbX+Flro&h<4W z9z5Tb2#XKCv(R_uid!7D{T1dm)^~!3_T^avr5x5`3h~L$D+7M+_tPqY!+doL3)a2; zy3l<2{BxBN@W5Aj*aI}Z%Jvn3W--iTg&x&+#5Sw2?fJ4-O4!S&@KShF-eMFym`{f* z_(M#$=S!)3x$_j0=~n73R%WUATdA)cd5iIWD|HtuGZ}v?b(A}Al6T$T3Lh%N(_1O; z*EO%lN8w*rS?|d8>xn>={j18-HCg)dKdcR*KhDz6WNE_z`?sf|q2bv6&gM>|4b6Kx z+Mx~mI+_b;L&Ki^jm^z_TaLGc__ntAxn&9WmLp4(q(c$!yL9CPlh+=9u#oWma#w@hoLnnrL10 zHp(4Ol$lwVFSBleWxn6i{ZFL>PW*68vF z-zF&35_glK>=BDdjV7eztr8B-h>Ype0`h4~o zvgG(Y8nwXZD?VS6Pb+uo{^;g^xcrj!jc2|Rbj#lL%=D#b=GCjw%=dpMn)$&q(aaA& z9L@aubJ5I?{?O!ZTX$n>dzS8kuDxNpHZyhi^|wzwYWny7=;o`2-}g6H-8jE4^OEVw zOXt@eGg|f1w8c;TS=EhKP2Z+BWM=GLy*Twv(^HH4$i3IU{pH!&Kbrbx=H?sEd@H=4 zpWXk?*Noqp>3gD?pRHZ<1u%y{sOj}ju1BVW_r&3cEgV@Jc&sXVz}mpfm{FcZQKn_X zi_ztcJL9y`I^)60^UtpDh=yiIqML6u-I*TA+?-llRTEu%&tMc)-4i{%VQ|WxDSh;E z^j^}K?%tD&PnP-h=<-Wh-a`F9h%Wb-eyWTOU#+_Q5j{`leZK1QF>6~7zcX|5{F=ga8cyfeD_h^3pfG=H8*v(C~ya(8B?`q|7U zGEwv~z1`YCOW-fd&s#ixFH~KgzHfPXnjH-GiuZc? zKf%WMvNrjTf#1Qb9kMj=`|_!;eLVWgD?dG7JM~k;=f9BM$B`$q#_VCgmDzv&=Crlb zqfb;flXvPzYyV>E8_)mLaQWn#*N=aq`t=Wg;&^2Bn0`e+|NZYo(VCA%uYLGCn=CG4 zxJ>tFZf;y>@7&6=cmK9E7N;^dS()%TZDmednN`mo`{YI|GqN&GKVshPxycmks+EO& z-}t5Jg2_ZUsxnzE-t_Xlp5H&c>-s<_-*k<1C)Zdy!tK%JA6p*mTw1<0>*9RJkU!Sb zUSv2LMIU(nSF=N40sqF|$EG$%GnXhw?PRLz^2YTk@A=RIbkC(p(Y+boNtE(Vz%MdP zqk9e4@0kvM&)Vyj=<)@0;O^@K)*n9*8TIdB+S1TA)80k&dV8$nDY$>>b;CW0XJ#He zt!~~!)dKN+m&fxP*3R!K^K>$9d05o3YOwi~?Dw-^u8_NjWGSlh+)5?FZ*`T1`56{jHQ7@PJr1hOP{HY$Y;ZJS#Qx_hq-ujqv zX@Bp#aOLW?>PMfraPcwX588v;>PMfv76+cXcEtiu*H&MBs+z$1=<4H-UV8GeMPvxI zMA1_ZUwQn=Yt>IYe&um7VD*G*11me8{LsaVJEO?@jqq3Xy93d>r{7ccu6s8`)fV%h zU48#MJA2vykB;5f@Tt2$eb<_SfBV<_?3TX=>^fxE)BiU+TW!?RytUIF63+|0Zt*+f z`0DO#{6)KeAtn9~EdDbo@qc3RUrm$`zhATKuPk1?Q|Bwhr<5^e@qcge?=}jL9mWgc z*X(-5;$Mv8Us&_0O`qQQXe=MHKWK6vdTn<08+X~wvHQ+{;@-8FtG;tzkgw66{rHX9 z*~U2UTYIg{`imDHslWKx?u!?m{Ls_8AAb1CqfhK_th;)tZck(?7vsXHyzA7NXz1DB zuCD*<`~K-h)n9(+gI|8|Z`WRY?$Z=i>W|l;E19n9U29vLe>FRMuRZwO&+VOA_~*Zv zoxNuC0egpLJ7*6W{hZOqjDFqd^G3gG^h-v6Z1n3!quJTn9~gbmXk^$l7=6*`X`|;& z-it&%v0#-;7D_|L@6$;?kq& zm$PwwCcC0?X_q7LN|x_pW&1f)JT+?GbG$LkdFGo#HSE>YXudhrF(rK8g^Q0j)Lnb} zS~NcN#D%NX_8(Ez4QJPncRzmd;-%`5OII#Fw(;!x0=}5z+1zfyd>zQvwsepdx4y1}yFK>5_3NVo{sIsSo_jXz5nrP7&OJYL_3 el1) system calls +.section ".text" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b diff --git a/lab6/create_fs/lab5_user_fork/fork_test.S b/lab6/create_fs/lab5_user_fork/fork_test.S new file mode 100644 index 000000000..463d19529 --- /dev/null +++ b/lab6/create_fs/lab5_user_fork/fork_test.S @@ -0,0 +1,28 @@ +void fork_test(){ + printf("\nFork Test, pid %d\n", get_pid()); + int cnt = 1; + int ret = 0; + if ((ret = fork()) == 0) { // child + long long cur_sp; + asm volatile("mov %0, sp" : "=r"(cur_sp)); + printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + ++cnt; + + if ((ret = fork()) != 0){ + asm volatile("mov %0, sp" : "=r"(cur_sp)); + printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + } + else{ + while (cnt < 5) { + asm volatile("mov %0, sp" : "=r"(cur_sp)); + printf("second child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + delay(1000000); + ++cnt; + } + } + exit(); + } + else { + printf("parent here, pid %d, child %d\n", get_pid(), ret); + } +} diff --git a/lab6/create_fs/lab5_user_fork/initramfs_providedbyTA.cpio b/lab6/create_fs/lab5_user_fork/initramfs_providedbyTA.cpio new file mode 100644 index 0000000000000000000000000000000000000000..0676fb1584617bc4d73624b3b212a12133e97d8e GIT binary patch literal 247296 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 0x14000 +#define ALIGN_UP(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1)) +// e.g. size=0x13200, alignment=0x1000 -> 0x13000 +#define ALIGN_DOWN(size, alignment) ((size) & ~((alignment) - 1)) + +#define IS_NOT_ALIGN(ptr, alignment) (((unsigned long)ptr & ((alignment) - 1)) != 0) + +#endif /*_RPI_MMU_H_ */ diff --git a/lab6/kernel/include/bcm2837/rpi_uart1.h b/lab6/kernel/include/bcm2837/rpi_uart1.h new file mode 100644 index 000000000..959130656 --- /dev/null +++ b/lab6/kernel/include/bcm2837/rpi_uart1.h @@ -0,0 +1,19 @@ +#ifndef _RPI_UART1_H_ +#define _RPI_UART1_H_ + +#include "bcm2837/rpi_base.h" + +#define AUX_ENABLES ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215004)) +#define AUX_MU_IO_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215040)) +#define AUX_MU_IER_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215044)) +#define AUX_MU_IIR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215048)) +#define AUX_MU_LCR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x0021504C)) +#define AUX_MU_MCR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215050)) +#define AUX_MU_LSR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215054)) +#define AUX_MU_MSR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215058)) +#define AUX_MU_SCRATCH ((volatile unsigned int*)(PERIPHERAL_BASE+0x0021505C)) +#define AUX_MU_CNTL_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215060)) +#define AUX_MU_STAT_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215064)) +#define AUX_MU_BAUD_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215068)) + +#endif /*_RPI_UART1_H_ */ diff --git a/lab6/kernel/include/cpio.h b/lab6/kernel/include/cpio.h new file mode 100644 index 000000000..bfe2c7044 --- /dev/null +++ b/lab6/kernel/include/cpio.h @@ -0,0 +1,47 @@ +#ifndef _CPIO_H_ +#define _CPIO_H_ + +/* + cpio format : https://manpages.ubuntu.com/manpages/bionic/en/man5/cpio.5.html + We are using "newc" format + header, file path, file data, header ...... + header + file path (padding 4 bytes) + file data (padding 4 bytes) (max size 4gb) +*/ + +#define CPIO_NEWC_HEADER_MAGIC "070701" // big endian constant, to check whether it is big endian or little endian + +// Using newc archive format +struct cpio_newc_header +{ + char c_magic[6]; // fixed, "070701". + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +}; + +/* write pathname, data, next header into corresponding parameter*/ +int cpio_newc_parse_header(struct cpio_newc_header *this_header_pointer, + char **pathname, unsigned int *filesize, char **data, + struct cpio_newc_header **next_header_pointer); + +unsigned int padding_4byte(unsigned int size); + +extern void *CPIO_DEFAULT_START; + +#define CPIO_for_each(c_filepath, c_filesize, c_filedata) \ + struct cpio_newc_header *header_ptr = CPIO_DEFAULT_START; \ + int err = cpio_newc_parse_header(header_ptr, c_filepath, c_filesize, c_filedata, &header_ptr); \ + for (; header_ptr&&!err; cpio_newc_parse_header(header_ptr, c_filepath, c_filesize, c_filedata, &header_ptr)) + +#endif /* _CPIO_H_ */ \ No newline at end of file diff --git a/lab6/kernel/include/debug.h b/lab6/kernel/include/debug.h new file mode 100644 index 000000000..2e7d97904 --- /dev/null +++ b/lab6/kernel/include/debug.h @@ -0,0 +1,19 @@ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "uart1.h" + +#define CYAN "\e[0;36m" // 青色 +#define HRED "\e[0;91m" +#define CRESET "\e[0m" + +#define WARING(fmt, ...) PRINT_MESSAGE(LEVEL_ERROR, "WARING", CYAN, fmt, ##__VA_ARGS__) +#define ERROR(fmt, ...) PRINT_MESSAGE(LEVEL_ERROR, "ERROR", HRED, fmt, ##__VA_ARGS__) +#define PRINT_MESSAGE(level, prefix, color, fmt, ...) \ + do \ + { \ + uart_sendlinek(color "[" prefix "] " CRESET fmt, ##__VA_ARGS__); \ + } while (0) + +#endif /* _DEBUG_H_ */ \ No newline at end of file diff --git a/lab6/kernel/include/dtb.h b/lab6/kernel/include/dtb.h new file mode 100644 index 000000000..7076d8683 --- /dev/null +++ b/lab6/kernel/include/dtb.h @@ -0,0 +1,26 @@ +#ifndef _DTB_H_ +#define _DTB_H_ + +#define uint32_t unsigned int +#define uint64_t unsigned long long + +// manipulate device tree with dtb file format +// linux kernel fdt.h +#define FDT_BEGIN_NODE 0x00000001 +#define FDT_END_NODE 0x00000002 +#define FDT_PROP 0x00000003 +#define FDT_NOP 0x00000004 +#define FDT_END 0x00000009 + +typedef void (*dtb_callback)(uint32_t node_type, char *name, void *value, uint32_t name_size); + +uint32_t uint32_endian_big2little(uint32_t data); +uint64_t uint64_endian_big2little(uint64_t data); + +void traverse_device_tree(void *base, dtb_callback callback); // traverse dtb tree +void dtb_callback_show_tree(uint32_t node_type, char *name, void *value, uint32_t name_size); +void dtb_callback_initramfs(uint32_t node_type, char *name, void *value, uint32_t name_size); + +void dtb_find_and_store_reserved_memory(); + +#endif \ No newline at end of file diff --git a/lab6/kernel/include/exception.h b/lab6/kernel/include/exception.h new file mode 100644 index 000000000..eb975a1aa --- /dev/null +++ b/lab6/kernel/include/exception.h @@ -0,0 +1,92 @@ +#ifndef _EXCEPTION_H_ +#define _EXCEPTION_H_ + +#include "u_list.h" +#include "bcm2837/rpi_mmu.h" + +#define SYSCALL(number, function) \ + case number: \ + function; \ + break; + +// https://github.com/Tekki/raspberrypi-documentation/blob/master/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf p16 +#define CORE0_INTERRUPT_SOURCE ((volatile unsigned int *)(PHYS_TO_KERNEL_VIRT(0x40000060))) +#define INTERRUPT_SOURCE_CNTPNSIRQ (1 << 1) +#define INTERRUPT_SOURCE_GPU (1 << 8) +#define IRQ_PENDING_1_AUX_INT (1 << 29) + +typedef struct trapframe +{ + unsigned long x0; + unsigned long x1; + unsigned long x2; + unsigned long x3; + unsigned long x4; + unsigned long x5; + unsigned long x6; + unsigned long x7; + unsigned long x8; + unsigned long x9; + unsigned long x10; + unsigned long x11; + unsigned long x12; + unsigned long x13; + unsigned long x14; + unsigned long x15; + unsigned long x16; + unsigned long x17; + unsigned long x18; + unsigned long x19; + unsigned long x20; + unsigned long x21; + unsigned long x22; + unsigned long x23; + unsigned long x24; + unsigned long x25; + unsigned long x26; + unsigned long x27; + unsigned long x28; + unsigned long x29; + unsigned long x30; + unsigned long spsr_el1; + unsigned long elr_el1; + unsigned long sp_el0; + +} trapframe_t; + +#define MEMFAIL_DATA_ABORT_LOWER 0b100100 // esr_el1 +#define MEMFAIL_INST_ABORT_LOWER 0b100000 // EC, bits [31:26] + +#define TF_LEVEL0 0b000100 // iss IFSC, bits [5:0] +#define TF_LEVEL1 0b000101 +#define TF_LEVEL2 0b000110 +#define TF_LEVEL3 0b000111 + +#define ESR_EL1_EC_SHIFT 26 +#define ESR_EL1_EC_MASK 0x3F +#define ESR_EL1_EC_SVC64 0x15 + +typedef struct +{ + unsigned int iss : 25, // Instruction specific syndrome + il : 1, // Instruction length bit + ec : 6; // Exception class +} esr_el1_t; + +void el1_interrupt_enable(); +void el1_interrupt_disable(); + +void lock(); +void unlock(); + +void el1h_sync_router(trapframe_t *tpf); +void el1h_irq_router(trapframe_t *tpf); +void el0_sync_router(trapframe_t *tpf); +void el0_irq_router(trapframe_t *tpf); + +void invalid_exception_router(unsigned long long x0); // exception_handler.S + +const char *get_exception_name(unsigned long esr_el1); + + +#endif /*_EXCEPTION_H_*/ diff --git a/lab6/kernel/include/irqtask.h b/lab6/kernel/include/irqtask.h new file mode 100644 index 000000000..52783e26b --- /dev/null +++ b/lab6/kernel/include/irqtask.h @@ -0,0 +1,22 @@ +#ifndef _IRQTASK_H_ +#define _IRQTASK_H_ + +#include "u_list.h" + +// smaller is more preemptive +#define UART_IRQ_PRIORITY 1 +#define TIMER_IRQ_PRIORITY 0 + +typedef struct irqtask +{ + struct list_head listhead; + unsigned long long priority; // store priority (smaller number is more preemptive) + void *task_function; // task function pointer +} irqtask_t; + +void irqtask_add(void *task_function, unsigned long long priority); +void irqtask_run(irqtask_t *the_task); +void irqtask_run_preemptive(); +void irqtask_list_init(); + +#endif diff --git a/lab6/kernel/include/mbox.h b/lab6/kernel/include/mbox.h new file mode 100644 index 000000000..39270518e --- /dev/null +++ b/lab6/kernel/include/mbox.h @@ -0,0 +1,66 @@ +#ifndef _MBOX_H_ +#define _MBOX_H_ + +extern volatile unsigned int pt[64]; + +// Mailbox Register MMIO +// https://jsandler18.github.io/extra/mailbox.html +// include/bcm2837/rpi_mbox.h + +// Mailbox Channels +// https://github.com/raspberrypi/firmware/wiki/Mailboxes +typedef enum +{ + MBOX_POWER_MANAGEMENT = 0, + MBOX_FRAMEBUFFER, + MBOX_VIRTUAL_UART, + MBOX_VCHIQ, + MBOX_LEDS, + MBOX_BUTTONS, + MBOX_TOUCHSCREEN, + MBOX_UNUSED, + MBOX_TAGS_ARM_TO_VC, + MBOX_TAGS_VC_TO_ARM, +} mbox_channel_type; + +// Status Code from Broadcom Videocode Driver +// brcm_usrlib/dag/vmcsx/vcinclude/bcm2708_chip/arm_control.h +enum mbox_status_reg_bits +{ + BCM_ARM_VC_MS_FULL = 0x80000000, + BCM_ARM_VC_MS_EMPTY = 0x40000000, + BCM_ARM_VC_MS_LEVEL = 0x400000FF, +}; + +enum mbox_buffer_status_code +{ + MBOX_REQUEST_PROCESS = 0x00000000, + MBOX_REQUEST_SUCCEED = 0x80000000, + MBOX_REQUEST_FAILED = 0x80000001, +}; + +// Tag +// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface +// Included partition only +typedef enum +{ + /* Videocore */ + MBOX_TAG_GET_FIRMWARE_VERSION = 0x1, + + /* Hardware */ + MBOX_TAG_GET_BOARD_MODEL = 0x10001, + MBOX_TAG_GET_BOARD_REVISION, + MBOX_TAG_GET_BOARD_MAC_ADDRESS, + MBOX_TAG_GET_BOARD_SERIAL, + MBOX_TAG_GET_ARM_MEMORY, + MBOX_TAG_GET_VC_MEMORY, + MBOX_TAG_GET_CLOCKS, + +} mbox_tag_type; + +#define MBOX_TAG_REQUEST_CODE 0x00000000 +#define MBOX_TAG_LAST_BYTE 0x00000000 + +int mbox_call(mbox_channel_type, unsigned int); + +#endif /*_MBOX_H_*/ diff --git a/lab6/kernel/include/memory.h b/lab6/kernel/include/memory.h new file mode 100644 index 000000000..35f7ddb16 --- /dev/null +++ b/lab6/kernel/include/memory.h @@ -0,0 +1,80 @@ +#ifndef _MEMORY_H_ +#define _MEMORY_H_ + +#include "u_list.h" +#include "bcm2837/rpi_mmu.h" +/* Lab2 */ +void *allocator(unsigned int size); +// void free(void* ptr); + +/* Lab4 */ +#define BUDDY_MEMORY_BASE PHYS_TO_KERNEL_VIRT(0x0) // 0x10000000 - 0x20000000 (SPEC) -> Advanced #3 for all memory region +#define BUDDY_MEMORY_PAGE_COUNT 0x3C000 // let BUDDY_MEMORY use 0x0 ~ 0x3C000000 (SPEC) +#define PAGESIZE 0x1000 // 4KB + +#define CACHE_SEG 0x8 +#define CACHE_offset 3 +#define CACHE_record_num 8 + +// #define MAX_PAGES 0x10000 // 65536 (Entries), PAGESIZE * MAX_PAGES = 0x10000000 (SPEC) + +typedef enum +{ + FRAME_FREE = -2, + FRAME_ALLOCATED = -1, + FRAME_IDX_0 = 0, // 0x1000 + FRAME_IDX_8 = 8, + FRAME_IDX_FINAL = 17, // 0x20 000 000 + FRAME_MAX_IDX = 18 +} frame_value_type; + +typedef enum +{ + CACHE_IDX_0 = 0, // 0x20 + CACHE_IDX_FINAL = 6, // 0x800 + CACHE_MAX_IDX = 7 // 0x1000 +} cache_value_type; + +typedef struct frame +{ + struct list_head listhead; // store freelist + int val; // store order + int used; + unsigned int idx; +} frame_t; + +typedef struct cache +{ + struct list_head listhead; // store freelist + void *data_base; + int cache_order; + int max_available; + int available; + unsigned long long cache_record[CACHE_record_num]; +} cache_t; + +void allocator_init(); +frame_t *release_redundant(frame_t *frame); +frame_t *get_buddy(frame_t *frame); +int coalesce(frame_t *frame_ptr); + +void dump_page_info(); +void dump_cache_info(); + +// buddy system +void *page_malloc(unsigned int size); +void page_free(frame_t *ptr); +void page2caches(int order); +void *cache_malloc(unsigned int size); +void cache_free(void *ptr); + +void *kmalloc(unsigned int size); +void kfree(void *ptr); +void memory_reserve(unsigned long long start, unsigned long long end); + +void freelist_init(); +void page2caches(int c_val); +void *find_CACHE(cache_t *ptr); +frame_t *find_free_page(int val); + +#endif /* _MEMORY_H_ */ \ No newline at end of file diff --git a/lab6/kernel/include/mmu.h b/lab6/kernel/include/mmu.h new file mode 100644 index 000000000..bb58ee390 --- /dev/null +++ b/lab6/kernel/include/mmu.h @@ -0,0 +1,101 @@ +#ifndef _MMU_H_ +#define _MMU_H_ + +#include "stddef.h" +// tcr_el1: The control register for stage 1 of the EL1&0 translation regime. +#define TCR_CONFIG_REGION_48bit (((64 - 48) << 0) | ((64 - 48) << 16)) // T0SZ 和 T1SZ 設為 16 +#define TCR_CONFIG_4KB ((0b00 << 14) | (0b10 << 30)) // TG0 和 TG1 設為 4KB +#define TCR_CONFIG_DEFAULT (TCR_CONFIG_REGION_48bit | TCR_CONFIG_4KB) + +#define MAIR_DEVICE_nGnRnE 0b00000000 // 設備記憶體,無全局無讀取無寫入權限 +#define MAIR_NORMAL_NOCACHE 0b01000100 // 普通記憶體,不緩存 +#define MAIR_IDX_DEVICE_nGnRnE 0 // 設備記憶體索引 +#define MAIR_IDX_NORMAL_NOCACHE 1 // 普通記憶體索引 + +#define PD_TABLE 0b11L // Table Entry Armv8_a_address_translation p.14 +#define PD_BLOCK 0b01L // Block Entry +#define PD_UNX (1L << 54) // non-executable page frame for EL0 if set +#define PD_KNX (1L << 53) // non-executable page frame for EL1 if set +#define PD_ACCESS (1L << 10) // a page fault is generated if not set +#define PD_RDONLY (1L << 7) // 0 for read-write, 1 for read-only. +#define PD_UK_ACCESS (1L << 6) // 0 for only kernel access, 1 for user/kernel access. + +#define PERIPHERAL_START 0x3C000000L +#define PERIPHERAL_END 0x3F000000L +#define USER_DATA_BASE 0x00000000L +#define USER_STACK_BASE 0x0000fffffffff000L +#define USER_SIGNAL_WRAPPER_VA 0x0000FFFFFFFAF000L //<------------------------------------- +#define USER_EXEC_WRAPPER_VA 0x0000FFFFFFFBF000L //<------------------------------------- + +#define MMU_PGD_BASE 0x1000L +#define MMU_PGD_ADDR (MMU_PGD_BASE + 0x0000L) +#define MMU_PUD_ADDR (MMU_PGD_BASE + 0x1000L) +#define MMU_PTE_ADDR (MMU_PGD_BASE + 0x2000L) + +// Used for EL1 +#define BOOT_PGD_ATTR (PD_TABLE) +#define BOOT_PUD_ATTR (PD_TABLE | PD_ACCESS) +#define BOOT_PTE_ATTR_nGnRnE (PD_BLOCK | PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_UNX | PD_KNX | PD_UK_ACCESS) // p.17 +#define BOOT_PTE_ATTR_NOCACHE (PD_BLOCK | PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2)) + +#ifndef __ASSEMBLER__ + +#include "sched.h" +#include "exception.h" +#include "u_list.h" +#include "stddef.h" + + +#define PERMISSION_INVAILD(userId,VMA_Permission) (userId&~VMA_Permission) +#define DUMP_NAME(number, name) \ + case number: \ + uart_sendlinek(name); \ + uart_sendlinek("\n"); \ + break; + +typedef enum +{ + UNKNOW_AREA = -1, + USER_DATA, + USER_STACK, + PERIPHERAL, + USER_SIGNAL_WRAPPER, + USER_EXEC_WRAPPER +} vma_name_type; + +typedef enum +{ + PGD, + PUD, + PMD, + PTE, +} pagetable_type; + +typedef struct vm_area_struct +{ + list_head_t listhead; + unsigned long virt_addr; + unsigned long phys_addr; + unsigned long area_size; + unsigned long rwx; // 1, 2, 4 + int is_alloced; + vma_name_type name; +} vm_area_struct_t; + +void *set_2M_kernel_mmu(void *x0); +void map_one_page(size_t *pgd_p, size_t va, size_t pa, size_t flag); +void mmu_add_vma(struct thread *t, size_t va, size_t size, size_t pa, size_t rwx, int is_alloced, vma_name_type name); +void mmu_del_vma(struct thread *t); +void mmu_free_page_tables(size_t *page_table, int level); +// void mmu_set_PTE_readonly(size_t *page_table, int level); +// void mmu_pagetable_copy(unsigned long *dst_page_table, unsigned long *src_page_table, int level); +void mmu_memfail_abort_handle(esr_el1_t *esr_el1); + +vm_area_struct_t *check_vma_overlap(thread_t *t,unsigned long user_va, unsigned long size); +int check_permission(int userId, int requiredPermission); +void dump_vma(); +void dump_pagetable(unsigned long user_va, unsigned long pa); + +#endif //__ASSEMBLER__ + +#endif /* _MMU_H_ */ diff --git a/lab6/kernel/include/power.h b/lab6/kernel/include/power.h new file mode 100644 index 000000000..07da61847 --- /dev/null +++ b/lab6/kernel/include/power.h @@ -0,0 +1,9 @@ +#ifndef _POWER_H_ +#define _POWER_H_ + +#include "bcm2837/rpi_mmu.h" +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC PHYS_TO_KERNEL_VIRT(0x3F10001c) +#define PM_WDOG PHYS_TO_KERNEL_VIRT(0x3F100024) + +#endif /*_POWER_H_*/ diff --git a/lab6/kernel/include/sched.h b/lab6/kernel/include/sched.h new file mode 100644 index 000000000..b4b8bf34c --- /dev/null +++ b/lab6/kernel/include/sched.h @@ -0,0 +1,75 @@ +#ifndef _SCHED_H_ +#define _SCHED_H_ + +#include "u_list.h" + +#define PIDMAX 32768 +#define USTACK_SIZE 0x10000 +#define KSTACK_SIZE 0x10000 +#define SIGNAL_MAX 64 +#define STACK_BASE_OFFSET 0x00 + +extern void switch_to(void *curr_context, void *next_context); +extern void *get_current(); +extern void store_context(void *curr_context); +extern void load_context(void *curr_context); + +// arch/arm64/include/asm/processor.h - cpu_context +typedef struct thread_context +{ + unsigned long x19; // callee saved registers: the called function will preserve them and restore them before returning + unsigned long x20; + unsigned long x21; + unsigned long x22; + unsigned long x23; + unsigned long x24; + unsigned long x25; + unsigned long x26; + unsigned long x27; + unsigned long x28; + unsigned long fp; // base pointer for local variable in stack + unsigned long lr; // store return address + unsigned long sp; // stack pointer, varys from function calls + void* pgd; // use for MMU mapping (user space) +} thread_context_t; + +typedef struct thread +{ + list_head_t listhead; // Freelist node + thread_context_t context; // Thread registers + char *data; // Process itself + unsigned int datasize; // Process size + int iszombie; // Process statement + int pid; // Process ID + int isused; // Freelist node statement + char *stack_alloced_ptr; // Process Stack (Process itself) + char *kernel_stack_alloced_ptr; // Process Stack (Kernel syscall) + void (*signal_handler[SIGNAL_MAX + 1])(); // Signal handlers for different signal + int sigcount[SIGNAL_MAX + 1]; // Signal Pending buffer + void (*curr_signal_handler)(); // Allow Signal handler overwritten by others + int signal_is_checking; // Signal Processing Lock + thread_context_t signal_savedContext; // Store registers before signal handler involving + list_head_t vma_list; +} thread_t; + +typedef struct execfile +{ + char *data; + unsigned int filesize; +} execfile; + + +void schedule_timer(char *notuse); +void thread_sched_init(); +void idle(); +void schedule(); +void kill_zombies(); +void thread_exit(); +thread_t *thread_create(void *start); +int exec_thread(); +void exec_proc(); +void exec_wrapper(); + +void foo(); + +#endif /* _SCHED_H_ */ diff --git a/lab6/kernel/include/shell.h b/lab6/kernel/include/shell.h new file mode 100644 index 000000000..0ab060fe2 --- /dev/null +++ b/lab6/kernel/include/shell.h @@ -0,0 +1,39 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ + +#define CLI_MAX_CMD 14 +#define CMD_MAX_LEN 32 +#define CMD_MAX_PARAM 10 +#define MSG_MAX_LEN 128 + +typedef struct CLI_CMDS +{ + char command[CMD_MAX_LEN]; + char help[MSG_MAX_LEN]; + int (*func)(int, char **); +} CLI_CMDS; + +int _parse_args(char *buffer, int *argc, char **argv); + +void start_shell(); + +void cli_flush_buffer(char *, int); +void cli_cmd_read(char *); +void cli_cmd_exec(char *); +void cli_print_banner(); + +int do_cmd_help(int argc, char **argv); +int do_cmd_hello(int argc, char **argv); +int do_cmd_info(int argc, char **argv); +int do_cmd_reboot(int argc, char **argv); +int do_cmd_ls(int argc, char **argv); +int do_cmd_cat(int argc, char **argv); +int do_cmd_malloc(int argc, char **argv); +int do_cmd_dtb(int argc, char **argv); +int do_cmd_exec(int argc, char **argv); +int do_cmd_setTimeout(int argc, char **argv); +int do_cmd_set2sAlert(int argc, char **argv); +int do_cmd_mtest(int argc, char **argv); +int do_cmd_ttest(int argc, char **argv); +int do_cmd_ftest(int argc, char **argv); +#endif /* _SHELL_H_ */ diff --git a/lab6/kernel/include/signal.h b/lab6/kernel/include/signal.h new file mode 100644 index 000000000..afe2c1617 --- /dev/null +++ b/lab6/kernel/include/signal.h @@ -0,0 +1,49 @@ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +#include "exception.h" +#include "memory.h" + +#define SIGHUP 1 /* Hangup (POSIX). */ +#define SIGINT 2 /* Interrupt (ANSI). */ +#define SIGQUIT 3 /* Quit (POSIX). */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ +#define SIGTRAP 5 /* Trace trap (POSIX). */ +#define SIGABRT 6 /* Abort (ANSI). */ +#define SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define SIGBUS 7 /* BUS error (4.2 BSD). */ +#define SIGFPE 8 /* Floating-point exception (ANSI). */ +#define SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ +#define SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ +#define SIGPIPE 13 /* Broken pipe (POSIX). */ +#define SIGALRM 14 /* Alarm clock (POSIX). */ +#define SIGTERM 15 /* Termination (ANSI). */ +#define SIGSTKFLT 16 /* Stack fault. */ +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGCHLD 17 /* Child status has changed (POSIX). */ +#define SIGCONT 18 /* Continue (POSIX). */ +#define SIGSTOP 19 /* Stop, unblockable (POSIX). */ +#define SIGTSTP 20 /* Keyboard stop (POSIX). */ +#define SIGTTIN 21 /* Background read from tty (POSIX). */ +#define SIGTTOU 22 /* Background write to tty (POSIX). */ +#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ +#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ +#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ +#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ +#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ +#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ +#define SIGPOLL SIGIO /* Pollable event occurred (System V). */ +#define SIGIO 29 /* I/O now possible (4.2 BSD). */ +#define SIGPWR 30 /* Power failure restart (System V). */ +#define SIGSYS 31 /* Bad system call. */ +#define SIGUNUSED 31 + +void signal_default_handler(); +void check_signal(trapframe_t *tpf); +void run_signal(trapframe_t *tpf, int signal); +//void __attribute__((aligned(PAGESIZE))) signal_handler_wrapper(); +void signal_handler_wrapper(); + +#endif diff --git a/lab6/kernel/include/stddef.h b/lab6/kernel/include/stddef.h new file mode 100644 index 000000000..61b71d842 --- /dev/null +++ b/lab6/kernel/include/stddef.h @@ -0,0 +1,12 @@ +#ifndef STDDEF_H +#define STDDEF_H + +#define size_t unsigned long +#define NULL ((void *)0) + +// typedef enum { +// false = 0, +// true = 1 +// } boolean; + +#endif \ No newline at end of file diff --git a/lab6/kernel/include/stdio.h b/lab6/kernel/include/stdio.h new file mode 100644 index 000000000..17eaf0d49 --- /dev/null +++ b/lab6/kernel/include/stdio.h @@ -0,0 +1,10 @@ + +char getchar(); +void putchar(char c); +void put_int(int num); +void puts(const char *s); +void put_hex(unsigned int num); +int atoi(char* str); +void Readfile(char *str,int size); +int fake_log2(unsigned long long n); +void delay(int s); \ No newline at end of file diff --git a/lab6/kernel/include/string.h b/lab6/kernel/include/string.h new file mode 100644 index 000000000..4a0fd9198 --- /dev/null +++ b/lab6/kernel/include/string.h @@ -0,0 +1,10 @@ +#include "stddef.h" +#define VSPRINT_MAX_BUF_SIZE 0x100 + +size_t strlen(const char *str); +int strcmp(const char *p1, const char *p2); +int strncmp(const char *s1, const char *s2, unsigned long long n); +char *strcpy(char *dest, const char *src); +unsigned int vsprintf(char *dst, char *fmt, __builtin_va_list args); +void *memset(void *s, int c, size_t n); +char* memcpy(void *dest, const void *src, unsigned long long len); diff --git a/lab6/kernel/include/syscall.h b/lab6/kernel/include/syscall.h new file mode 100644 index 000000000..72de04223 --- /dev/null +++ b/lab6/kernel/include/syscall.h @@ -0,0 +1,28 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ + +#include "exception.h" +#include + +int getpid(trapframe_t *tpf); +size_t uartread(trapframe_t *tpf, char buf[], size_t size); +size_t uartwrite(trapframe_t *tpf, const char buf[], size_t size); +int exec(trapframe_t *tpf, const char *name, char *const argv[]); +int fork(trapframe_t *tpf); +void exit(trapframe_t *tpf, int status); +int syscall_mbox_call(trapframe_t *tpf, unsigned char ch, unsigned int *mbox); +void kill(trapframe_t *tpf, int pid); + +void signal_register(int signal, void (*handler)()); +void signal_kill(int pid, int signal); +void sigreturn(trapframe_t *tpf); + +void *mmap(trapframe_t *tpf, void *addr, size_t len, int prot, int flags, int fd, int file_offset); + +void syscall_lock(trapframe_t *tpf); +void syscall_unlock(trapframe_t *tpf); + +unsigned int get_file_size(char *thefilepath); +char *get_file_start(char *thefilepath); + +#endif /* _SYSCALL_H_*/ diff --git a/lab6/kernel/include/timer.h b/lab6/kernel/include/timer.h new file mode 100644 index 000000000..8b02b6b8d --- /dev/null +++ b/lab6/kernel/include/timer.h @@ -0,0 +1,36 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ + +#include "u_list.h" +#include "bcm2837/rpi_mmu.h" +#define CORE0_TIMER_IRQ_CTRL PHYS_TO_VIRT(0x40000040) //-------------------------------------------------------------------------- + +void core_timer_enable(); +void core_timer_disable(); +void core_timer_handler(); + +typedef struct timer_event +{ + struct list_head listhead; + unsigned long long interrupt_time; // store as tick time after cpu start + void *callback; // interrupt -> timer_callback -> callback(args) + char *args; // need to free the string by event callback function +} timer_event_t; + +typedef enum +{ + setSecond = 0, + setTick = 1 +} timer_type_t; + +// now the callback only support "funcion(char *)", char* in args +void timer_event_callback(timer_event_t *timer_event); +void add_timer(void *callback, unsigned long long timeout, char *args, int inTickFormat); +unsigned long long get_tick_plus_s(unsigned long long second); +void set_core_timer_interrupt(unsigned long long expired_time); +void set_core_timer_interrupt_by_tick(unsigned long long tick); +void timer_set2sAlert(char *str); +void timer_list_init(); +int timer_list_get_size(); + +#endif /* _TIMER_H_ */ diff --git a/lab6/kernel/include/u_list.h b/lab6/kernel/include/u_list.h new file mode 100644 index 000000000..79767f194 --- /dev/null +++ b/lab6/kernel/include/u_list.h @@ -0,0 +1,150 @@ +#ifndef _U_LIST_H_ +#define _U_LIST_H_ + +/* + * Circular doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + * + * https://github.com/torvalds/linux/blob/master/include/linux/list. + * https://elixir.bootlin.com/linux/latest/source/scripts/kconfig/list.h#L24 + */ + +typedef struct list_head +{ + struct list_head *next, *prev; +} list_head_t; + +#define LIST_HEAD_INIT(name) \ + { \ + &(name), &(name) \ + } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * INIT_LIST_HEAD - Initialize a list_head structure + * @list: list_head structure to be initialized. + * + * Initializes the list_head to point to itself. If it is a list header, + * the result is an empty list. + */ +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +static inline void list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_is_head - tests whether @list is the list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_head(const struct list_head *list, const struct list_head *head) +{ + return list == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; \ + !list_is_head(pos, (head)); \ + pos = n, n = pos->next) + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_size(const struct list_head *head) +{ + list_head_t *pos; + int i = 0; + list_for_each(pos, head) + { + i++; + } + return i; +} + +#endif /* _U_LIST_H_ */ diff --git a/lab6/kernel/include/uart1.h b/lab6/kernel/include/uart1.h new file mode 100644 index 000000000..7b6bd70ce --- /dev/null +++ b/lab6/kernel/include/uart1.h @@ -0,0 +1,18 @@ +#ifndef _UART1_H_ +#define _UART1_H_ + +void uart_init(); +void uart_flush_FIFO(); +char uart_recv(); +void uart_send(unsigned int c); + +void uart_r_irq_handler(); +void uart_w_irq_handler(); +char uart_async_recv(); +void uart_async_send(char c); + +int uart_sendlinek(char* fmt, ...); +void uart_interrupt_enable(); +void uart_interrupt_disable(); + +#endif /*_UART1_H_*/ diff --git a/lab6/kernel/src/boot.S b/lab6/kernel/src/boot.S new file mode 100644 index 000000000..456dfeb7d --- /dev/null +++ b/lab6/kernel/src/boot.S @@ -0,0 +1,82 @@ +#include "mmu.h" + +.section ".text.boot" + +.global _kernel_start + +_kernel_start: + bl from_el2_to_el1 + +set_mmu_configuration: + // set paging configuration (up : 0xffff000000000000 low : 0x0000000000000000) + ldr x4, = TCR_CONFIG_DEFAULT + msr tcr_el1, x4 + + // Set Used Memory Attributes + ldr x4, =((MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8))) + msr mair_el1, x4 + + // set and enable MMU + ldr x4, = MMU_PGD_ADDR // PGD's page frame at 0x1000 + ldr x1, = MMU_PUD_ADDR // PUD's page frame at 0x2000 + + ldr x2, = BOOT_PGD_ATTR + orr x2, x1, x2 // combine the physical address of next level page with attribute. + str x2, [x4] // [MMU_PGD_ADDR] = MMU_PUD_ADDR | BOOT_PGD_ATTR + + ldr x2, = BOOT_PUD_ATTR + mov x3, 0x00000000 + orr x3, x2, x3 // [MMU_PUD_ADDR] = 0x00000000 | BOOT_PUD_ATTR + str x3, [x1] // 1st 1GB mapped by the 1st entry of PUD + mov x3, 0x40000000 + orr x3, x2, x3 // [MMU_PUD_ADDR + 8] = 0x40000000 | BOOT_PUD_ATTR + str x3, [x1, 8] // 2nd 1GB mapped by the 2nd entry of PUD + + msr ttbr0_el1, x4 // load PGD to the bottom translation-based register. + msr ttbr1_el1, x4 // also load PGD to the upper translation based register. + + mov sp, 0x3c000000 // temp stack + bl set_2M_kernel_mmu + + mrs x2, sctlr_el1 // sctlr_el1: Provides top level control of the system, including its memory system, at EL1 and EL0. + orr x2 , x2, 1 // sctlr_el1[0]: EL1&0 stage 1 address translation enabled/disabled. + msr sctlr_el1, x2 + + // indirect branch to the upper virtual address + ldr x2, =set_exception_vector_table + br x2 + +set_exception_vector_table: + adr x1, exception_vector_table // vbar_el1: Vector Base Address Register (EL1) + msr vbar_el1, x1 // Holds the exception base address for any exception that is taken to EL1. + +setup_stack: + ldr x1, =_stack_top + mov sp, x1 + +setup_bss: + ldr x1, =_bss_start + ldr w2, =_bss_size + +init_bss: + cbz w2, run_main + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, init_bss + +run_main: + ldr x1, =dtb_ptr + str x0, [x1], #8 + bl main + +proc_hang: + wfe + b proc_hang + +from_el2_to_el1: + mov x1, (1 << 31) // EL1 uses aarch64 + msr hcr_el2, x1 + mov x1, 0x3c5 // EL1h (SPSel = 1) with interrupt disabled + msr spsr_el2, x1 + msr elr_el2, lr + eret // return to EL1 \ No newline at end of file diff --git a/lab6/kernel/src/cpio.c b/lab6/kernel/src/cpio.c new file mode 100644 index 000000000..56fdfc4e8 --- /dev/null +++ b/lab6/kernel/src/cpio.c @@ -0,0 +1,82 @@ +#include "string.h" +#include "cpio.h" +#include "stdio.h" + +/* Parse an ASCII hex string into an integer. (big endian)*/ +static unsigned int parse_hex_str(char *s, unsigned int max_len) +{ + unsigned int r = 0; + + for (unsigned int i = 0; i < max_len; i++) + { + r *= 16; + if (s[i] >= '0' && s[i] <= '9') + { + r += s[i] - '0'; + } + else if (s[i] >= 'a' && s[i] <= 'f') + { + r += s[i] - 'a' + 10; + } + else if (s[i] >= 'A' && s[i] <= 'F') + { + r += s[i] - 'A' + 10; + } + else + { + return r; + } + } + return r; +} + +/* write pathname, data, next header into corresponding parameter */ +/* if no next header, next_header_pointer = 0 */ +/* return -1 if parse error*/ +int cpio_newc_parse_header(struct cpio_newc_header *this_header_pointer, char **pathname, unsigned int *filesize, char **data, struct cpio_newc_header **next_header_pointer) +{ + /* Ensure magic header exists. */ + if (strncmp(this_header_pointer->c_magic, CPIO_NEWC_HEADER_MAGIC, sizeof(this_header_pointer->c_magic)) != 0) + { + *next_header_pointer = 0; + puts("cpio parse error\r\n"); + return -1; + } + + // transfer big endian 8 byte hex string to unsigned int and store into *filesize + *filesize = parse_hex_str(this_header_pointer->c_filesize, 8); + + // end of header is the pathname + *pathname = ((char *)this_header_pointer) + sizeof(struct cpio_newc_header); + + // get file data, file data is just after pathname + unsigned int pathname_length = parse_hex_str(this_header_pointer->c_namesize, 8); + unsigned int offset = pathname_length + sizeof(struct cpio_newc_header); + // The file data is padded to a multiple of four bytes + offset = padding_4byte(offset); + *data = (char *)this_header_pointer + offset; + + // get next header pointer + if (*filesize == 0) + { + *next_header_pointer = (struct cpio_newc_header *)*data; + } + else + { + offset = *filesize; + *next_header_pointer = (struct cpio_newc_header *)(*data + padding_4byte(offset)); + } + + // if filepath is TRAILER!!! means there is no more files. + if (strncmp(*pathname, "TRAILER!!!", sizeof("TRAILER!!!")) == 0) + { + *next_header_pointer = 0; + } + + return 0; +} + +unsigned int padding_4byte(unsigned int size) +{ + return size + (4 - size % 4) % 4; +} \ No newline at end of file diff --git a/lab6/kernel/src/dtb.c b/lab6/kernel/src/dtb.c new file mode 100644 index 000000000..df97d64fc --- /dev/null +++ b/lab6/kernel/src/dtb.c @@ -0,0 +1,173 @@ +#include "dtb.h" +#include "uart1.h" +#include "cpio.h" +#include "string.h" +#include "stdio.h" +#include "memory.h" +#include "bcm2837/rpi_mmu.h" +#include "debug.h" + +void *CPIO_DEFAULT_START; +void *CPIO_DEFAULT_END; +char *dtb_ptr; + +// stored as big endian +struct fdt_header +{ + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +}; + +struct fdt_reserve_entry +{ + uint64_t address; + uint64_t size; +}; + +uint32_t uint32_endian_big2little(uint32_t data) +{ + char *r = (char *)&data; + return (r[3] << 0) | (r[2] << 8) | (r[1] << 16) | (r[0] << 24); +} + +uint64_t uint64_endian_big2little(uint64_t data) +{ + char *r = (char *)&data; + return ((unsigned long long)r[7] << 0) | ((unsigned long long)r[6] << 8) | ((unsigned long long)r[5] << 16) | ((unsigned long long)r[4] << 24) | ((unsigned long long)r[3] << 32) | ((unsigned long long)r[2] << 40) | ((unsigned long long)r[1] << 48) | ((unsigned long long)r[0] << 56); +} + +void traverse_device_tree(void *dtb_ptr, dtb_callback callback) +{ + struct fdt_header *header = dtb_ptr; + if (uint32_endian_big2little(header->magic) != 0xD00DFEED) + { + ERROR("traverse_device_tree : wrong magic in traverse_device_tree\n"); + return; + } + // https://abcamus.github.io/2016/12/28/uboot%E8%AE%BE%E5%A4%87%E6%A0%91-%E8%A7%A3%E6%9E%90%E8%BF%87%E7%A8%8B/ + // https://blog.csdn.net/wangdapao12138/article/details/82934127 + uint32_t struct_size = uint32_endian_big2little(header->size_dt_struct); + char *dt_struct_ptr = (char *)((char *)header + uint32_endian_big2little(header->off_dt_struct)); + char *dt_strings_ptr = (char *)((char *)header + uint32_endian_big2little(header->off_dt_strings)); + + char *end = (char *)dt_struct_ptr + struct_size; + char *pointer = dt_struct_ptr; + + while (pointer < end) + { + uint32_t token_type = uint32_endian_big2little(*(uint32_t *)pointer); + + pointer += 4; + if (token_type == FDT_BEGIN_NODE) + { + callback(token_type, pointer, 0, 0); + pointer += strlen(pointer); + pointer += 4 - (unsigned long long)pointer % 4; // alignment 4 byte + } + else if (token_type == FDT_END_NODE) + { + callback(token_type, 0, 0, 0); + } + else if (token_type == FDT_PROP) + { + uint32_t len = uint32_endian_big2little(*(uint32_t *)pointer); + pointer += 4; + char *name = (char *)dt_strings_ptr + uint32_endian_big2little(*(uint32_t *)pointer); + pointer += 4; + callback(token_type, name, pointer, len); + pointer += len; + if ((unsigned long long)pointer % 4 != 0) + pointer += 4 - (unsigned long long)pointer % 4; // alignment 4 byte + } + else if (token_type == FDT_NOP) + { + callback(token_type, 0, 0, 0); + } + else if (token_type == FDT_END) + { + callback(token_type, 0, 0, 0); + } + else + { + puts("error type:"); + put_hex(token_type); + puts("\n"); + return; + } + } +} + +void dtb_callback_show_tree(uint32_t node_type, char *name, void *data, uint32_t name_size) +{ + static int level = 0; + if (node_type == FDT_BEGIN_NODE) + { + for (int i = 0; i < level; i++) + puts(" "); + puts(name); + puts("{\n"); + level++; + } + else if (node_type == FDT_END_NODE) + { + level--; + for (int i = 0; i < level; i++) + puts(" "); + puts("}\n"); + } + else if (node_type == FDT_PROP) + { + for (int i = 0; i < level; i++) + puts(" "); + puts(name); + puts("\n"); + } +} + +void dtb_callback_initramfs(uint32_t node_type, char *name, void *value, uint32_t name_size) +{ + // https://github.com/stweil/raspberrypi-documentation/blob/master/configuration/device-tree.md + // linux,initrd-start will be assigned by start.elf based on config.txt + if (node_type == FDT_PROP && strcmp(name, "linux,initrd-start") == 0) + { + CPIO_DEFAULT_START = (void *)(unsigned long long)PHYS_TO_KERNEL_VIRT(uint32_endian_big2little(*(uint32_t *)value)); + } + if (node_type == FDT_PROP && strcmp(name, "linux,initrd-end") == 0) + { + CPIO_DEFAULT_END = (void *)(unsigned long long)PHYS_TO_KERNEL_VIRT(uint32_endian_big2little(*(uint32_t *)value)); + } +} + +void dtb_find_and_store_reserved_memory() +{ + struct fdt_header *header = (struct fdt_header *)dtb_ptr; + if (uint32_endian_big2little(header->magic) != 0xD00DFEED) + { + ERROR("traverse_device_tree : wrong magic in traverse_device_tree\n"); + return; + } + + // off_mem_rsvmap stores all of reserve memory map with address and size + char *dt_mem_rsvmap_ptr = (char *)((char *)header + uint32_endian_big2little(header->off_mem_rsvmap)); + struct fdt_reserve_entry *reverse_entry = (struct fdt_reserve_entry *)dt_mem_rsvmap_ptr; + + // reserve memory which is defined by dtb + while (reverse_entry->address != 0 || reverse_entry->size != 0) + { + unsigned long long start = PHYS_TO_KERNEL_VIRT(uint64_endian_big2little(reverse_entry->address)); + unsigned long long end = uint64_endian_big2little(reverse_entry->size) + start; + memory_reserve(start, end); + reverse_entry++; + } + + // reserve device tree itself + memory_reserve((unsigned long long)dtb_ptr, (unsigned long long)dtb_ptr + uint32_endian_big2little(header->totalsize)); +} \ No newline at end of file diff --git a/lab6/kernel/src/entry.S b/lab6/kernel/src/entry.S new file mode 100644 index 000000000..284a07e73 --- /dev/null +++ b/lab6/kernel/src/entry.S @@ -0,0 +1,195 @@ +// save general registers to stack +.macro save_all + sub sp, sp, 32 * 9 + stp x0, x1, [sp ,16 * 0] // store pair of registers + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + str x30, [sp, 16 * 15] + // information for nested interrupt + mrs x0, spsr_el1 + str x0, [sp, 16 * 15 + 8] + mrs x0, elr_el1 + str x0, [sp, 16 * 16] + mrs x0, sp_el0 + str x0, [sp, 16 * 16 + 8] + ldp x0, x1, [sp, 16 * 0] +.endm + +// load general registers from stack +.macro load_all + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + ldr x30, [sp, 16 * 15] + // information for nested interrupt + ldr x0, [sp, 16 * 15 + 8] + msr spsr_el1,x0 + ldr x0, [sp, 16 * 16] + msr elr_el1, x0 + ldr x0, [sp, 16 * 16 + 8] + msr sp_el0, x0 + ldp x0, x1, [sp ,16 * 0] // restore x0 instead of elr_el1 + add sp, sp, 32 * 9 +.endm + +.macro ventry label + .align 7 // entry should be aligned to 0x80 (2^7) + b \label +.endm + +.align 11 // vector table should be aligned to 0x800 (2^11) +.global exception_vector_table + +// exception_vector_table definition +// https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/entry.S#L367 +exception_vector_table: + //Exception from the current EL while using SP_EL0 + ventry el1t_sync_invalid // Synchronous EL1t + ventry el1t_irq_invalid // IRQ EL1t + ventry el1t_fiq_invalid // FIQ EL1t + ventry el1t_error_invalid // Error EL1t + + //Exception from the current EL while using SP_ELx + ventry el1h_sync // Synchronous EL1h + ventry el1h_irq // IRQ EL1h + ventry el1h_fiq_invalid // FIQ EL1h + ventry el1h_error_invalid // Error EL1h + + //Exception from a lower EL and at least one lower EL is AArch64 + ventry el0_sync_64 // Synchronous 64-bit EL0 + ventry el0_irq_64 // IRQ 64-bit EL0 + ventry el0_fiq_invalid_64 // FIQ 64-bit EL0 + ventry el0_error_invalid_64 // Error 64-bit EL0 + + //Exception from a lower EL and at least all lower EL are AArch32 + ventry el0_sync_invalid_32 // Synchronous 32-bit EL0 + ventry el0_irq_invalid_32 // IRQ 32-bit EL0 + ventry el0_fiq_invalid_32 // FIQ 32-bit EL0 + ventry el0_error_invalid_32 // Error 32-bit EL0 + + +el1t_sync_invalid: + save_all + mov x0,0 + bl invalid_exception_router + load_all + eret +el1t_irq_invalid: + save_all + mov x0,1 + bl invalid_exception_router + load_all + eret +el1t_fiq_invalid: + save_all + mov x0,2 + bl invalid_exception_router + load_all + eret +el1t_error_invalid: + save_all + mov x0,3 + bl invalid_exception_router + load_all + eret + + +el1h_sync: + save_all + mov x0, sp + bl el1h_sync_router + load_all + eret +el1h_irq: + save_all + mov x0, sp + bl el1h_irq_router + load_all + eret +el1h_fiq_invalid: + save_all + mov x0,6 + bl invalid_exception_router + load_all + eret +el1h_error_invalid: + save_all + mov x0,7 + bl invalid_exception_router + load_all + eret + +el0_sync_64: + save_all + mov x0, sp + bl el0_sync_router + load_all + eret +el0_irq_64: + save_all + mov x0, sp + bl el0_irq_router // ----------------------------------- + load_all + eret +el0_fiq_invalid_64: + save_all + mov x0,10 + bl invalid_exception_router + load_all + eret +el0_error_invalid_64: + save_all + mov x0,11 + bl invalid_exception_router + load_all + eret + + +el0_sync_invalid_32: + save_all + mov x0,12 + bl invalid_exception_router + load_all + eret +el0_irq_invalid_32: + save_all + mov x0,13 + bl invalid_exception_router + load_all + eret +el0_fiq_invalid_32: + save_all + mov x0,14 + bl invalid_exception_router + load_all + eret +el0_error_invalid_32: + save_all + mov x0,15 + bl invalid_exception_router + load_all + eret diff --git a/lab6/kernel/src/exception.c b/lab6/kernel/src/exception.c new file mode 100644 index 000000000..3fabcd772 --- /dev/null +++ b/lab6/kernel/src/exception.c @@ -0,0 +1,367 @@ +#include "bcm2837/rpi_irq.h" +#include "bcm2837/rpi_uart1.h" +#include "uart1.h" +#include "exception.h" +#include "timer.h" +#include "syscall.h" +#include "signal.h" +#include "sched.h" +#include "memory.h" +#include "irqtask.h" +#include "mmu.h" +#include "debug.h" + +// 讀取ESR_EL1暫存器的值 +static inline unsigned long read_esr_el1(void) +{ + unsigned long value; + asm volatile("mrs %0, esr_el1" : "=r"(value)); + return value; +} + +// 判斷異常是否由EL0觸發的syscall +static inline int is_el0_syscall() +{ + unsigned long esr_el1 = read_esr_el1(); + unsigned long ec = (esr_el1 >> ESR_EL1_EC_SHIFT) & ESR_EL1_EC_MASK; + if (ec == ESR_EL1_EC_SVC64) + { + return 1; + } + return 0; +} + +// 定義異常類型名稱 +const char *exception_type[] = { + "Unknown reason", + "Trapped WFI or WFE instruction execution", + "Trapped MCR or MRC access with (coproc==0b1111) (AArch32)", + "Trapped MCRR or MRRC access with (coproc==0b1111) (AArch32)", + "Trapped MCR or MRC access with (coproc==0b1110) (AArch32)", + "Trapped LDC or STC access (AArch32)", + "Trapped FP access", + "Trapped VMRS access", + "Trapped PSTATE (AArch32)", + "Instruction Abort from a lower Exception level", + "Instruction Abort taken without a change in Exception level", + "PC alignment fault", + "Data Abort from a lower Exception level", + "Data Abort taken without a change in Exception level", + "SP alignment fault", + "Trapped floating-point exception", + "SError interrupt", + "Breakpoint from a lower Exception level", + "Breakpoint taken without a change in Exception level", + "Software Step from a lower Exception level", + "Software Step taken without a change in Exception level", + "Watchpoint from a lower Exception level", + "Watchpoint taken without a change in Exception level", + "BKPT instruction execution (AArch32)", + "Vector Catch exception (AArch32)", + "BRK instruction execution (AArch64)"}; + +extern list_head_t *run_queue; + +// DAIF, Interrupt Mask Bits +void el1_interrupt_enable() +{ + __asm__ __volatile__("msr daifclr, 0xf"); // umask all DAIF +} + +void el1_interrupt_disable() +{ + __asm__ __volatile__("msr daifset, 0xf"); // mask all DAIF +} + +unsigned long long int lock_counter = 0; + +void lock() +{ + el1_interrupt_disable(); + lock_counter++; +} + +void unlock() +{ + // uart_sendlinek("This is unlock\n"); + lock_counter--; + if (lock_counter < 0) + { + while (1) + ; + } + else if (lock_counter == 0) + { + el1_interrupt_enable(); + } +} + +void el1h_sync_router(trapframe_t *tpf) +{ + uart_sendlinek("\n"); + uart_sendlinek("spsr_el1 : %x\n ", tpf->spsr_el1); + uart_sendlinek("elr_el1 : %x\n ", tpf->elr_el1); + uart_sendlinek("sp_el0 : %x\n ", tpf->sp_el0); + //dump_vma(); + while (1) + ; +} + +void el1h_irq_router(trapframe_t *tpf) +{ + lock(); + // decouple the handler into irqtask queue + // (1) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.113 + // (2) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.16 + if (*IRQ_PENDING_1 & IRQ_PENDING_1_AUX_INT && *CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_GPU) // from aux && from GPU0 -> uart exception + { + if (*AUX_MU_IER_REG & 2) + { + *AUX_MU_IER_REG &= ~(2); // disable write interrupt + irqtask_add(uart_w_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); // run the queued task before returning to the program. + } + else if (*AUX_MU_IER_REG & 1) + { + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + irqtask_add(uart_r_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + } + } + else if (*CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_CNTPNSIRQ) // from CNTPNS (core_timer) // A1 - setTimeout run in el1 + { + core_timer_disable(); + irqtask_add(core_timer_handler, TIMER_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + core_timer_enable(); + + if (list_size(run_queue) > 1) + { + // uart_sendlinek("el1h_irq_router\n"); + schedule(); + } + } + else + { + unlock(); + uart_sendlinek("Hello World el1 64 router other interrupt!\r\n"); + } + + // only do signal handler when return to user mode + if ((tpf->spsr_el1 & 0b1100) == 0) + { + check_signal(tpf); + } +} + +void el0_sync_router(trapframe_t *tpf) +{ + static int count = 0; + unsigned long long esr_el1 = read_esr_el1(); + + // esr_el1: Holds syndrome information for an exception taken to EL1. + esr_el1_t *esr = (esr_el1_t *)&esr_el1; + if (esr->ec == MEMFAIL_DATA_ABORT_LOWER || esr->ec == MEMFAIL_INST_ABORT_LOWER) + { + mmu_memfail_abort_handle(esr); + return; + } + + if (!is_el0_syscall()) + { + const char *exception_name = get_exception_name(esr_el1); + if (count == 0) + ERROR("el0_sync_router: exception occurred - %s\r\n", exception_name); + count++; + return; + } + + el1_interrupt_enable(); // Allow UART input during exception + unsigned long long syscall_no = tpf->x8; + if (syscall_no > 2) + { + uart_sendlinek("SYSCALL No: %d\n", syscall_no); + } + // uart_sendlinek("tpf->x8 : %d\n",tpf->x8); + switch (syscall_no) + { + SYSCALL(0, getpid(tpf)) + SYSCALL(1, uartread(tpf, (char *)tpf->x0, tpf->x1)) + SYSCALL(2, uartwrite(tpf, (char *)tpf->x0, tpf->x1)) + SYSCALL(3, exec(tpf, (char *)tpf->x0, (char **)tpf->x1)) + SYSCALL(4, fork(tpf)) + SYSCALL(5, exit(tpf, tpf->x0)) + SYSCALL(6, syscall_mbox_call(tpf, (unsigned char)tpf->x0, (unsigned int *)tpf->x1)) + SYSCALL(7, kill(tpf, (int)tpf->x0)) + SYSCALL(8, signal_register(tpf->x0, (void (*)())tpf->x1)) + SYSCALL(9, signal_kill(tpf->x0, tpf->x1)) + SYSCALL(10, mmap(tpf,(void *)tpf->x0,tpf->x1,tpf->x2,tpf->x3,tpf->x4,tpf->x5);) + SYSCALL(50, sigreturn(tpf)) + SYSCALL(114, syscall_lock(tpf)) + SYSCALL(514, syscall_unlock(tpf)) + default: + uart_sendlinek("el0_sync_router other syscall, syscall_no: %d\r\n", syscall_no); + break; + } +} + +void el0_irq_router(trapframe_t *tpf) +{ + lock(); + // decouple the handler into irqtask queue + // (1) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.113 + // (2) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.16 + if (*IRQ_PENDING_1 & IRQ_PENDING_1_AUX_INT && *CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_GPU) // from aux && from GPU0 -> uart exception + { + if (*AUX_MU_IER_REG & 2) + { + *AUX_MU_IER_REG &= ~(2); // disable write interrupt + irqtask_add(uart_w_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); // run the queued task before returning to the program. + } + else if (*AUX_MU_IER_REG & 1) + { + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + irqtask_add(uart_r_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + } + } + else if (*CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_CNTPNSIRQ) // from CNTPNS (core_timer) // A1 - setTimeout run in el1 + { + core_timer_disable(); + irqtask_add(core_timer_handler, TIMER_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + core_timer_enable(); + + if (list_size(run_queue) > 1) + { + // uart_sendlinek("el0_irq_router\n"); + schedule(); + } + } + else + { + unlock(); + uart_sendlinek("Hello World el0 64 router other interrupt!\r\n"); + } + + // only do signal handler when return to user mode + if ((tpf->spsr_el1 & 0b1100) == 0) + { + check_signal(tpf); + } +} + +void invalid_exception_router(unsigned long long x0) +{ + uart_sendlinek("\n invalid exception %x \n", x0); + while (1) + ; +} + +// 獲取異常類型名稱 +const char *get_exception_name(unsigned long esr_el1) +{ + unsigned long ec = (esr_el1 >> ESR_EL1_EC_SHIFT) & ESR_EL1_EC_MASK; + if (ec < sizeof(exception_type) / sizeof(exception_type[0])) + { + return exception_type[ec]; + } + return "Unknown exception"; +} + +// ------------------------------------------------------------------------------------------ + +/* +Preemption +Now, any interrupt handler can preempt the task’s execution, but the newly enqueued task still needs to wait for the currently running task’s completion. +It’d be better if the newly enqueued task with a higher priority can preempt the currently running task. +To achieve the preemption, the kernel can check the last executing task’s priority before returning to the previous interrupt handler. +If there are higher priority tasks, execute the highest priority task. +*/ + +int curr_task_priority = 9999; // Small number has higher priority + +struct list_head *task_list; +void irqtask_list_init() +{ + task_list = allocator(sizeof(list_head_t)); + INIT_LIST_HEAD(task_list); +} + +void irqtask_add(void *task_function, unsigned long long priority) +{ + irqtask_t *the_task = kmalloc(sizeof(irqtask_t)); // free by irq_tasl_run_preemptive() + + // store all the related information into irqtask node + // manually copy the device's buffer + the_task->priority = priority; + the_task->task_function = task_function; + INIT_LIST_HEAD(&(the_task->listhead)); + + // add the timer_event into timer_event_list (sorted) + // if the priorities are the same -> FIFO + struct list_head *curr; + + // mask the device's interrupt line + // el1_interrupt_disable(); + // enqueue the processing task to the event queue with sorting. + list_for_each(curr, task_list) + { + if (((irqtask_t *)curr)->priority > the_task->priority) + { + list_add(&(the_task->listhead), curr->prev); + break; + } + } + // if the priority is lowest + if (list_is_head(curr, task_list)) + { + list_add_tail(&(the_task->listhead), task_list); + } + // unmask the interrupt line + // el1_interrupt_enable(); +} + +void irqtask_run_preemptive() +{ + // el1_interrupt_enable(); + while (!list_empty(task_list)) + { + // critical section protects new coming node + + lock(); + irqtask_t *the_task = (irqtask_t *)task_list->next; + // Run new task (early return) if its priority is lower than the scheduled task. + if (curr_task_priority <= the_task->priority) + { + unlock(); + break; + } + // get the scheduled task and run it. + list_del_entry((struct list_head *)the_task); + int prev_task_priority = curr_task_priority; + curr_task_priority = the_task->priority; + // uart_sendlinek("preemptive curr_task_priority: %d\r\n", curr_task_priority); + unlock(); + + irqtask_run(the_task); + + lock(); + curr_task_priority = prev_task_priority; + unlock(); + // free(the_task); + } +} + +void irqtask_run(irqtask_t *the_task) +{ + ((void (*)())the_task->task_function)(); + kfree(the_task); +} diff --git a/lab6/kernel/src/linker.ld b/lab6/kernel/src/linker.ld new file mode 100644 index 000000000..45b64f607 --- /dev/null +++ b/lab6/kernel/src/linker.ld @@ -0,0 +1,44 @@ +_heap_stack_size = 50M; + +SECTIONS +{ + . = 0xffff000000000000; + . += 0x80000; + _kernel_start = .; + + .text : { + *(.text.boot) + *(.text) + } + + .rodata : { + *(.rodata) + } + + .data : { + *(.data) + } + + .bss : { + . = ALIGN(8); + _bss_start = .; + *(.bss) + *(COMMON) + } + _bss_end = .; + _bss_size = (_bss_end - _bss_start)>>3; + + .heap : { + . = ALIGN(8); + _heap_top = .; + . += _heap_stack_size; + _heap_end = .; + } + + _kernel_end = .; + + . = 0xffff00002c000000; + _stack_end = .; + . = 0xffff00003c000000; + _stack_top = .; +} \ No newline at end of file diff --git a/lab6/kernel/src/main.c b/lab6/kernel/src/main.c new file mode 100644 index 000000000..427fa1eab --- /dev/null +++ b/lab6/kernel/src/main.c @@ -0,0 +1,43 @@ +#include "uart1.h" +#include "shell.h" +#include "memory.h" +#include "dtb.h" +#include "exception.h" +#include "timer.h" +#include "sched.h" +#include "uart1.h" +#include "irqtask.h" +//#include "bcm2837/rpi_mmu.h" + +extern list_head_t *run_queue; +extern char *dtb_ptr; +int Set_dtb = 0; + +void main(char *arg) +{ + // uart_sendlinek("in main\n"); + dtb_ptr = (char *)PHYS_TO_KERNEL_VIRT(arg); + if (!Set_dtb) + { + traverse_device_tree(dtb_ptr, dtb_callback_initramfs); + Set_dtb = 1; + } + uart_init(); + allocator_init(); + irqtask_list_init(); + timer_list_init(); + thread_sched_init(); + //uart_sendlinek("in main\n"); + + core_timer_enable(); + uart_interrupt_enable(); + uart_flush_FIFO(); + + el1_interrupt_enable(); // enable interrupt in EL1 -> EL1 + + //start_shell(); + // uart_sendlinek("RQ size : %d \n",list_size(run_queue)); + + //schedule(); + load_context(&((((thread_t*)run_queue->next))->context)); +} diff --git a/lab6/kernel/src/mbox.c b/lab6/kernel/src/mbox.c new file mode 100644 index 000000000..e59dee6ee --- /dev/null +++ b/lab6/kernel/src/mbox.c @@ -0,0 +1,23 @@ +#include "bcm2837/rpi_mbox.h" +#include "mbox.h" + +/* Aligned to 16-byte boundary while we have 28-bits for VC */ +volatile unsigned int __attribute__((aligned(16))) pt[64]; + +int mbox_call( mbox_channel_type channel, unsigned int value ) +{ + // Add channel to lower 4 bit + value &= ~(0xF); + value |= channel; + while ( (*MBOX_STATUS & BCM_ARM_VC_MS_FULL) != 0 ) {} + // Write to Register + *MBOX_WRITE = value; + while(1) { + while ( *MBOX_STATUS & BCM_ARM_VC_MS_EMPTY ) {} + // Read from Register + if (value == *MBOX_READ) + return pt[1] == MBOX_REQUEST_SUCCEED; + } + return 0; +} + diff --git a/lab6/kernel/src/memory.c b/lab6/kernel/src/memory.c new file mode 100644 index 000000000..a80a1219a --- /dev/null +++ b/lab6/kernel/src/memory.c @@ -0,0 +1,491 @@ +#include "memory.h" +#include "u_list.h" +#include "uart1.h" +#include "exception.h" +#include "dtb.h" +#include "stdio.h" +#include "mmu.h" +#include "bcm2837/rpi_mmu.h" + +extern char _heap_top; +static char *htop_ptr = &_heap_top; + +extern char _kernel_start; +extern char _kernel_end; +extern char *CPIO_DEFAULT_START; +extern char *CPIO_DEFAULT_END; +extern char _stack_end; +extern char _stack_top; + +void *allocator(unsigned int size) +{ + lock(); + // -> htop_ptr + // htop_ptr + 0x02: heap_block size + // htop_ptr + 0x10 ~ htop_ptr + 0x10 * k: + // { heap_block } + // -> htop_ptr + // header 0x10 bytes block + // |--------------------------------------------------------------| + // | fill zero 0x8 bytes | size 0x8 bytes | size padding to 0x16 | + // |--------------------------------------------------------------| + + // 0x10 for heap_block header + char *r = htop_ptr + 0x10; + // size paddling to multiple of 0x10 + size = 0x10 + size - size % 0x10; + *(unsigned int *)(r - 0x8) = size; + htop_ptr += size; + unlock(); + return r; +} + +// void free(void* ptr) { +// // TBD +// } + +// ------------------------------------------------------------ + +static frame_t *frame_array; // store memory's statement and page's corresponding index +static list_head_t frame_freelist[FRAME_MAX_IDX]; // store available block for page +static list_head_t cache_list[CACHE_MAX_IDX]; // store available block for cache + +void allocator_init() +{ + frame_array = allocator(BUDDY_MEMORY_PAGE_COUNT * sizeof(frame_t)); + + // init frame freelist + for (int i = FRAME_IDX_0; i <= FRAME_IDX_FINAL; i++) + { + INIT_LIST_HEAD(&frame_freelist[i]); + } + + // init cache list + for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + { + INIT_LIST_HEAD(&cache_list[i]); + } + + for (int i = 0; i < BUDDY_MEMORY_PAGE_COUNT; i++) + { + // init listhead for each frame + INIT_LIST_HEAD(&(frame_array[i].listhead)); + frame_array[i].idx = i; + } + freelist_init(); + dump_page_info(); + + /* Startup reserving the following region: + Spin tables for multicore boot (0x0000 - 0x1000) + Devicetree (Optional, if you have implement it) + Kernel image in the physical memory + Your simple allocator (startup allocator) (Stack + Heap in my case) + Initramfs + */ + uart_sendlinek("\r\n* Startup Allocation *\r\n"); + uart_sendlinek("buddy system: usable memory region: 0x%x ~ 0x%x\n", BUDDY_MEMORY_BASE, BUDDY_MEMORY_BASE + BUDDY_MEMORY_PAGE_COUNT * PAGESIZE); + dtb_find_and_store_reserved_memory(); // find spin tables in dtb + memory_reserve(PHYS_TO_KERNEL_VIRT(MMU_PGD_ADDR), PHYS_TO_KERNEL_VIRT(MMU_PTE_ADDR + 0x2000)); // // PGD's page frame at 0x1000 // PUD's page frame at 0x2000 PMD 0x3000-0x5000 + memory_reserve((unsigned long long)&_kernel_start, (unsigned long long)&_kernel_end); // kernel + memory_reserve((unsigned long long)&_stack_end, (unsigned long long)&_stack_top); + memory_reserve((unsigned long long)CPIO_DEFAULT_START, (unsigned long long)CPIO_DEFAULT_END); +} + +void freelist_init() +{ + int PAGE_COUNT = BUDDY_MEMORY_PAGE_COUNT; + for (int i = 0; i <= FRAME_IDX_FINAL; i++) + { + // uart_sendlinek("\n %ld,%ld \n",PAGE_COUNT,(1 << i)); + if ((PAGE_COUNT & (1 << i))) + { + PAGE_COUNT -= (1 << i); + frame_array[PAGE_COUNT].val = i; + frame_array[PAGE_COUNT].used = FRAME_FREE; + list_add(&(frame_array[PAGE_COUNT].listhead), &frame_freelist[i]); + } + if (i == FRAME_IDX_FINAL && PAGE_COUNT) + { + while (PAGE_COUNT) + { + PAGE_COUNT -= (1 << i); + frame_array[PAGE_COUNT].val = FRAME_IDX_FINAL; + frame_array[PAGE_COUNT].used = FRAME_FREE; + list_add(&(frame_array[PAGE_COUNT].listhead), &frame_freelist[FRAME_IDX_FINAL]); + } + } + } +} + +frame_t *release_redundant(frame_t *frame) +{ + // order -1 -> add its buddy to free list (frame itself will be used in master function) + frame->val -= 1; + frame_t *buddyptr = get_buddy(frame); + buddyptr->val = frame->val; + buddyptr->used = FRAME_FREE; + list_add(&(buddyptr->listhead), &frame_freelist[buddyptr->val]); + return frame; +} + +frame_t *get_buddy(frame_t *frame) +{ + // XOR(idx, order) + if ((frame->idx ^ (1 << frame->val)) > BUDDY_MEMORY_PAGE_COUNT) + { + uart_sendlinek("[!] BUDDY of Page: 0x%x at level: %d Does not exit", frame->idx, frame->val); + // return -1; + } + return &frame_array[frame->idx ^ (1 << frame->val)]; +} + +void dump_page_info() +{ + // unsigned int exp2 = 1; + // uart_sendlinek(" ┌───────────────────── [ Number of Available Page Blocks ] ─────────────────────┐\r\n │ "); + // for (int i = FRAME_IDX_0; i < FRAME_IDX_8; i++) + // { + // uart_sendlinek("%4dKB(%1d) ", 4 * exp2, i); + // exp2 *= 2; + // } + // uart_sendlinek("│\r\n │ "); + // for (int i = FRAME_IDX_0; i < FRAME_IDX_8; i++) + // uart_sendlinek(" %4d ", list_size(&frame_freelist[i])); + // uart_sendlinek("│\r\n "); + // uart_sendlinek("└────────────────────────────────────────"); + // uart_sendlinek("─────────────────────────────────────────┘\r\n"); + + // exp2 = 1; + // uart_sendlinek(" ┌──────────────────────────────────── "); + // uart_sendlinek("[ Number of Available Page Blocks ]"); + // uart_sendlinek(" ───────────────────────────────────┐\r\n │"); + // for (int i = FRAME_IDX_8; i < FRAME_MAX_IDX; i++) + // { + // uart_sendlinek("%4dMB(%2d) ", exp2, i); + // exp2 *= 2; + // } + // uart_sendlinek("│\r\n │"); + // for (int i = FRAME_IDX_8; i < FRAME_MAX_IDX; i++) + // uart_sendlinek(" %4d ", list_size(&frame_freelist[i])); + // uart_sendlinek("│\r\n "); + // uart_sendlinek("└──────────────────────────────────────────────────────"); + // uart_sendlinek("────────────────────────────────────────────────────────┘\r\n"); +} + +void dump_cache_info() +{ + // unsigned int exp2 = 1; + // uart_sendlinek(" ┌──────────────── [ Number of Available Cache Blocks ] ────────────────┐\r\n │ "); + // for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + // { + // uart_sendlinek("%4dB(%1d) ", CACHE_SEG * exp2, i); + // exp2 *= 2; + // } + // uart_sendlinek("│\r\n │ "); + // ; + // for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + // { + // if (!list_empty(&cache_list[i])) + // { + // // uart_sendlinek("I free !!!!!!!!!!!!"); + // int num = 0; + // list_head_t *pos; + // list_for_each(pos, &cache_list[i]) + // { + // num += ((cache_t *)pos)->available; + // } + // uart_sendlinek("%5d ", num); + // } + // else + // { + // uart_sendlinek("%5d ", 0); + // } + // } + + // uart_sendlinek("│\r\n "); + // uart_sendlinek("└───────────────────────────────────"); + // uart_sendlinek("────────────────────────────────────┘\r\n"); +} + +void memory_reserve(unsigned long long start, unsigned long long end) +{ + start -= start % PAGESIZE; // floor (align 0x1000) + end = end % PAGESIZE ? end + PAGESIZE - (end % PAGESIZE) : end; // ceiling (align 0x1000) + + // uart_sendlinek("Reserved Memory: "); + // uart_sendlinek("start 0x%x ~ ", start); + // uart_sendlinek("end 0x%x\r\n", end); + + // delete page from free list + for (int order = FRAME_IDX_FINAL; order >= 0; order--) + { + list_head_t *pos; + // uart_sendlinek("\n use %d level page to match \n",order); + list_for_each(pos, &frame_freelist[order]) + { + unsigned long long pagestart = ((frame_t *)pos)->idx * PAGESIZE + BUDDY_MEMORY_BASE; + unsigned long long pageend = pagestart + (PAGESIZE << order); + // uart_sendlinek("\n from 0x%x to 0x%x\n",pagestart,pageend); + + if (start <= pagestart && end >= pageend) // if page all in reserved memory -> delete it from freelist + { + ((frame_t *)pos)->used = FRAME_ALLOCATED; + // uart_sendlinek(" [!] Reserved page in 0x%x - 0x%x\n", pagestart, pageend); + // uart_sendlinek(" Before\n"); + // dump_page_info(); + list_del_entry(pos); + // uart_sendlinek(" Remove usable block for reserved memory: order %d\r\n", order); + // uart_sendlinek(" After\n"); + // dump_page_info(); + } + else if (start >= pageend || end <= pagestart) // no intersection + { + continue; + } + else // partial intersection, separate the page into smaller size. + { + // dump_page_info(); + list_del_entry(pos); + list_head_t *temppos = pos->prev; + list_add(&release_redundant((frame_t *)pos)->listhead, &frame_freelist[order - 1]); + pos = temppos; + // dump_page_info(); + } + } + } +} + +void *kmalloc(unsigned int size) +{ + lock(); + + // uart_sendlinek("\n\n"); + // uart_sendlinek("================================\r\n"); + // uart_sendlinek("[+] Request kmalloc size: %d\r\n", size); + // uart_sendlinek("================================\r\n"); + // if size is larger than cache size, go for page + if (size > (CACHE_SEG << CACHE_IDX_FINAL)) + { + void *r = page_malloc(size); + unlock(); + return r; + } + // go for cache + void *r = cache_malloc(size); + unlock(); + return r; +}; + +void *page_malloc(unsigned int size) +{ + // uart_sendlinek("this is page_malloc \r\n"); + int val; + int find_PageSize = 0; + frame_t *target_frame_ptr; + // turn size into minimum 4KB * 2**val + for (int i = FRAME_IDX_0; i <= FRAME_IDX_FINAL; i++) + { + + if (size <= (PAGESIZE << i) && !find_PageSize) + { + val = i; + // uart_sendlinek(" block size = 0x%x\n", PAGESIZE << i); + find_PageSize = 1; + } + + if (find_PageSize && !list_empty(&frame_freelist[i])) + { + // uart_sendlinek(" free page at level : %d\n", i); + target_frame_ptr = (frame_t *)(frame_freelist[i].next); + for (int min_FreePageLevel = i; min_FreePageLevel > val; min_FreePageLevel--) // ex: 10000 -> 01111 + { + target_frame_ptr = release_redundant(target_frame_ptr); + } + break; + } + + if (i == FRAME_IDX_FINAL) + { + // uart_sendlinek("[!] request size exceeded for page_malloc!!!!\r\n"); + return (void *)0; + } + } + // get the available frame from freelist + target_frame_ptr->used = FRAME_ALLOCATED; + + // uart_sendlinek(" [+] Allocate page - size : %d(0x%x)\r\n", size, size); + // uart_sendlinek(" Before\r\n"); + // dump_page_info(); + list_del_entry((struct list_head *)target_frame_ptr); + // uart_sendlinek(" physical address : 0x%x\n", BUDDY_MEMORY_BASE + (PAGESIZE * (target_frame_ptr->idx))); + // uart_sendlinek(" After\r\n"); + // dump_page_info(); + + return (void *)BUDDY_MEMORY_BASE + (PAGESIZE * (target_frame_ptr->idx)); +}; + +void *cache_malloc(unsigned int size) +{ + int c_val; + // uart_sendlinek("this is cache_malloc \r\n"); + for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + { + if (size <= (CACHE_SEG << i)) + { + c_val = i; + break; + } + } + + if (list_empty(&cache_list[c_val])) + { + // uart_sendlinek("[!] No free size for cache \r\n"); //--------------------------------------------------- + page2caches(c_val); + } + + // cache_t *ptr = (cache_t *)(cache_list[c_val].prev); + + // uart_sendlinek("this is cache_malloc \r\n"); + // uart_sendlinek("[+] Allocate cache - size : %d(0x%x)\r\n", size, size); + // uart_sendlinek(" Before\r\n"); + // dump_cache_info(); + + void *ptr = find_CACHE((cache_t *)cache_list[c_val].next); + // uart_sendlinek("ptr : %x\n",ptr); + // uart_sendlinek(" After\r\n"); + // dump_cache_info(); + + return ptr; +}; + +void *find_CACHE(cache_t *ptr) +{ + // uart_sendlinek("ptr : %x\n",ptr); + unsigned long long num; + int record_num; + for (record_num = 0; ptr->cache_record[record_num] + 1 == 0 && record_num < CACHE_record_num; record_num++) + ; + + num = ptr->cache_record[record_num] + 1; + num = ((~num) & (ptr->cache_record[record_num])) + 1; + + // uart_sendlinek("before cache_record[%d] : %x\n", record_num, ptr->cache_record[record_num]); + ptr->cache_record[record_num] += num; + ptr->available--; + // uart_sendlinek("after cache_record[%d] : %x\n", record_num, ptr->cache_record[record_num]); + + int val = fake_log2(num) + record_num * 64; + void *target = ptr->data_base + val * (CACHE_SEG << (ptr->cache_order)); + // uart_sendlinek("data_base addr : 0x%x\n", ptr->data_base); + // uart_sendlinek("target addr : 0x%x\n", target); + + if (!(ptr->available)) + { + list_del_entry((list_head_t *)ptr); + } + + return target; +} + +void page2caches(int c_val) +{ + // uart_sendlinek("[!] Split Page for cache\r\n"); + void *ptr = page_malloc(PAGESIZE); + // uart_sendlinek("ptr : %x\n",ptr); + cache_t *Pageinfo = (cache_t *)ptr; + Pageinfo->data_base = ptr; + Pageinfo->cache_order = c_val; + Pageinfo->max_available = (PAGESIZE >> (CACHE_offset + c_val)); + + while (sizeof(*Pageinfo) >= Pageinfo->data_base - ptr) + { + Pageinfo->data_base += (CACHE_SEG << c_val); + (Pageinfo->max_available)--; + } + Pageinfo->available = Pageinfo->max_available; + + for (int i = 0; i < CACHE_record_num; i++) + Pageinfo->cache_record[i] = 0; + + // uart_sendlinek(" max_available : %d\n", Pageinfo->max_available); + // uart_sendlinek(" Pageinfo size : 0x%x\n", sizeof(*Pageinfo)); + // uart_sendlinek(" offset size : 0x%x\n", (CACHE_SEG << c_val)); + + list_add(&(Pageinfo->listhead), &cache_list[c_val]); + // return Pageinfo; +} + +//------------------------------------------------------------------------------------------------------------------------------- kfree + +void kfree(void *ptr) +{ + // uart_sendlinek("\r\n"); + // uart_sendlinek("==========================\r\n"); + //uart_sendlinek("[+] Request kfree 0x%x\r\n", ptr); + // uart_sendlinek("==========================\r\n"); + + // If no cache assigned, go for page + lock(); + frame_t *target_frame_ptr = &frame_array[((unsigned long long)ptr - BUDDY_MEMORY_BASE) >> 12]; + if ((unsigned long long)ptr % PAGESIZE == 0) + { + page_free(target_frame_ptr); + unlock(); + return; + } + // go for cache + cache_free(ptr); + unlock(); +}; + +void page_free(frame_t *target_frame_ptr) +{ + frame_t *buddyptr = get_buddy(target_frame_ptr); + target_frame_ptr->used = FRAME_FREE; + while (buddyptr->used == FRAME_FREE && buddyptr->val == target_frame_ptr->val) + { + list_del_entry((list_head_t *)buddyptr); + target_frame_ptr = &frame_array[(target_frame_ptr->idx) & (buddyptr->idx)]; + target_frame_ptr->val++; + buddyptr = get_buddy(target_frame_ptr); + if (buddyptr < 0) + break; + } + + // uart_sendlinek(" Before\r\n"); + // dump_page_info(); + list_add(&(target_frame_ptr->listhead), &frame_freelist[target_frame_ptr->val]); + // uart_sendlinek(" After\r\n"); + // dump_page_info(); +} + +void cache_free(void *ptr) +{ + // uart_sendlinek("ptr : %x\n",ptr); + int idx = ((unsigned long long)ptr - BUDDY_MEMORY_BASE) >> 12; + frame_t *target_frame_ptr = &frame_array[idx]; + cache_t *cache_ptr = (cache_t *)((unsigned long long)(idx * PAGESIZE) + BUDDY_MEMORY_BASE); //<------- + // uart_sendlinek("target_frame_ptr : %x\n",target_frame_ptr); + //uart_sendlinek("cache_ptr : %x\n",cache_ptr); + int num = (ptr - cache_ptr->data_base) / (CACHE_SEG << cache_ptr->cache_order); + //uart_sendlinek("num : %d\n",num); + int record_num = (num >> 6); + num = num - (record_num << 6); + cache_ptr->cache_record[record_num] -= (1 << num); + + // uart_sendlinek("[+] Free cache: 0x%x, val = %d\r\n", ptr, cache_ptr->cache_order); + // uart_sendlinek(" Before\r\n"); + // dump_cache_info(); + if (cache_ptr->available == 0) + { + list_add(&(cache_ptr->listhead), &cache_list[cache_ptr->cache_order]); + } + cache_ptr->available++; + if (cache_ptr->available == cache_ptr->max_available) + { + list_del_entry((list_head_t *)cache_ptr); + page_free(target_frame_ptr); + } + // uart_sendlinek(" After\r\n"); + // dump_cache_info(); +} \ No newline at end of file diff --git a/lab6/kernel/src/mmu.c b/lab6/kernel/src/mmu.c new file mode 100644 index 000000000..769948ae6 --- /dev/null +++ b/lab6/kernel/src/mmu.c @@ -0,0 +1,376 @@ +#include "bcm2837/rpi_mmu.h" +#include "mmu.h" +#include "memory.h" +#include "string.h" +#include "uart1.h" +#include "debug.h" + +extern thread_t *curr_thread; + +void *set_2M_kernel_mmu(void *x0) +{ + // Turn + // Two-level Translation (1GB) - in boot.S + // to + // Three-level Translation (2MB) - set PUD point to new table + unsigned long *pud_table = (unsigned long *)MMU_PUD_ADDR; + + unsigned long *pte_table1 = (unsigned long *)MMU_PTE_ADDR; + unsigned long *pte_table2 = (unsigned long *)(MMU_PTE_ADDR + 0x1000L); + for (int i = 0; i < 512; i++) + { + unsigned long addr = 0x200000L * i; + if (addr >= PERIPHERAL_END) + { + pte_table1[i] = (0x00000000 + addr) + BOOT_PTE_ATTR_nGnRnE; + continue; + } + pte_table1[i] = (0x00000000 + addr) | BOOT_PTE_ATTR_NOCACHE; // 0 * 2MB // No definition for 3-level attribute, use nocache. + pte_table2[i] = (0x40000000 + addr) | BOOT_PTE_ATTR_NOCACHE; // 512 * 2MB + } + + // set PUD + pud_table[0] = (unsigned long)pte_table1 | BOOT_PUD_ATTR; + pud_table[1] = (unsigned long)pte_table2 | BOOT_PUD_ATTR; + + return x0; +} + +void map_one_page(size_t *virt_pgd_p, size_t user_va, size_t pa, size_t flag) +{ + size_t *table_p = virt_pgd_p; + for (int level = 0; level < 4; level++) + { + unsigned int idx = (user_va >> (39 - level * 9)) & 0x1ff; // p.14, 9-bit only + + if (level == 3) + { + table_p[idx] = pa; + table_p[idx] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_KNX | flag; // el0 only + return; + } + + if (!table_p[idx]) + { + size_t *newtable_p = kmalloc(0x1000); // create a table + memset(newtable_p, 0, 0x1000); + table_p[idx] = KERNEL_VIRT_TO_PHYS((size_t)newtable_p); // point to that table + table_p[idx] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2); + } + + table_p = (size_t *)PHYS_TO_KERNEL_VIRT((size_t)(table_p[idx] & ENTRY_ADDR_MASK)); // PAGE_SIZE + } +} + +void mmu_add_vma(struct thread *t, size_t va, size_t size, size_t pa, size_t rwx, int is_alloced, vma_name_type name) +{ + if (IS_NOT_ALIGN(pa, PAGESIZE) || IS_NOT_ALIGN(va, PAGESIZE)) + { + // ERROR("CHECK_ALIGN : 0x%x\n",CHECK_ALIGN(pa,PAGESIZE)); + uart_sendlinek("\n\n"); + ERROR("Input User Vitural Address or Physical Address Should be Aliged to PAGESIZE\n"); + ERROR("Input User Vitural Address : 0x%x\n", va); + ERROR("Input Physical Address : 0x%x\n", pa); + return; + } + vm_area_struct_t *the_area_ptr = check_vma_overlap(t, va, (unsigned long)size); + if (the_area_ptr != 0) + { + uart_sendlinek("\n\n"); + ERROR("check_vma_overlap : 0x%x\n", the_area_ptr); + ERROR("Vitural Memory Area is Overlap !!\n"); + // dump_vma(); + return; + } + + size = ALIGN_UP(size, PAGESIZE); + vm_area_struct_t *new_area = kmalloc(sizeof(vm_area_struct_t)); + new_area->rwx = rwx; + new_area->area_size = size; + new_area->virt_addr = va; + new_area->phys_addr = pa; + new_area->is_alloced = is_alloced; + new_area->name = name; + list_add_tail((list_head_t *)new_area, &t->vma_list); +} + +void mmu_del_vma(struct thread *t) +{ + list_head_t *curr = &t->vma_list; + list_head_t *n; + list_for_each_safe(curr, n, &t->vma_list) + { + vm_area_struct_t *vma = (vm_area_struct_t *)curr; + if (vma->is_alloced) + { + kfree((void *)PHYS_TO_KERNEL_VIRT(vma->phys_addr)); + } + list_del_entry(curr); + kfree(curr); + } +} + +void mmu_free_page_tables(size_t *page_table, int level) +{ + size_t *table_virt = (size_t *)PHYS_TO_KERNEL_VIRT(page_table); + for (int i = 0; i < 512; i++) + { + if (table_virt[i] != 0) + { + size_t *next_table = (size_t *)(table_virt[i] & ENTRY_ADDR_MASK); + if ((table_virt[i] & PD_TABLE) == PD_TABLE) + { + if (level < PMD) + mmu_free_page_tables(next_table, level + 1); + table_virt[i] = 0L; + kfree((void *)PHYS_TO_KERNEL_VIRT(next_table)); + } + } + } +} + +// void mmu_set_PTE_readonly(size_t *page_table, int level) +// { +// size_t *table_virt = (size_t *)PHYS_TO_KERNEL_VIRT(page_table); +// for (int i = 0; i < 512; i++) +// { +// if (table_virt[i] != 0) +// { +// size_t *next_table = (size_t)(table_virt[i] & ENTRY_ADDR_MASK); +// if (table_virt[i] & PD_TABLE == PD_TABLE) +// { +// if (level < PMD) +// { +// mmu_set_PTE_readonly(next_table, level + 1); +// } +// else +// { +// table_virt[i] &= PD_RDONLY; +// } +// } +// } +// } +// } + +// mmu_pagetable_copy(size_t *dst_page_table, size_t *src_page_table, int level) +// { +// size_t *dst_page_table_va = (size_t *)PHYS_TO_KERNEL_VIRT(dst_page_table); +// size_t *src_page_table_va = (size_t *)PHYS_TO_KERNEL_VIRT(src_page_table); +// for (int i = 0; i < 512; i++) +// { +// if (src_page_table_va[i] != 0) +// { +// size_t *next_src_table = (size_t)(src_page_table_va[i] & ENTRY_ADDR_MASK); +// size_t *next_dst_table = (size_t)(dst_page_table_va[i] & ENTRY_ADDR_MASK); +// if (src_page_table_va[i] & PD_TABLE == PD_TABLE) +// { +// if (level < PMD) +// { +// mmu_pagetable_copy(next_dst_table,next_src_table,level); +// } +// else +// { +// //-------- +// } +// } +// } +// } +// } + +void mmu_memfail_abort_handle(esr_el1_t *esr_el1) +{ + lock(); + unsigned long long far_el1; + __asm__ __volatile__("mrs %0, FAR_EL1\n\t" : "=r"(far_el1)); + + list_head_t *pos; + vm_area_struct_t *vma; + vm_area_struct_t *the_area_ptr = 0; + list_for_each(pos, &curr_thread->vma_list) + { + vma = (vm_area_struct_t *)pos; + if (vma->virt_addr <= far_el1 && vma->virt_addr + vma->area_size >= far_el1) + { + the_area_ptr = vma; + break; + } + } + // area is not part of process's address space + if (!the_area_ptr) + { + uart_sendlinek("\n\n"); + ERROR("[Segmentation fault]: Kill Process\r\n"); + ERROR("Invilad Vitural Address Access: %x\n", far_el1); + thread_exit(); + // dump_vma(); + unlock(); + while (1) + schedule(); + + return; + } + + // For translation fault, only map one page frame for the fault address + if ((esr_el1->iss & 0x3f) == TF_LEVEL0 || + (esr_el1->iss & 0x3f) == TF_LEVEL1 || + (esr_el1->iss & 0x3f) == TF_LEVEL2 || + (esr_el1->iss & 0x3f) == TF_LEVEL3) + { + uart_sendlinek("\n"); + WARING("[Translation fault]: 0x%x\r\n", far_el1); // far_el1: Fault address register. + // Holds the faulting Virtual Address for all synchronous Instruction or Data Abort, PC alignment fault and Watchpoint exceptions that are taken to EL1. + + size_t addr_offset = (far_el1 - the_area_ptr->virt_addr); + // addr_offset = (addr_offset % 0x1000) == 0 ? addr_offset : addr_offset - (addr_offset % 0x1000); + addr_offset = ALIGN_DOWN(addr_offset, 0x1000); + + size_t flag = 0; + if (!(the_area_ptr->rwx & (0b1 << 2))) + flag |= PD_UNX; // 4: executable + if (!(the_area_ptr->rwx & (0b1 << 1))) + flag |= PD_RDONLY; // 2: writable + if (the_area_ptr->rwx & (0b1 << 0)) + flag |= PD_UK_ACCESS; // 1: readable / accessible + map_one_page((size_t *)PHYS_TO_KERNEL_VIRT(curr_thread->context.pgd), the_area_ptr->virt_addr + addr_offset, the_area_ptr->phys_addr + addr_offset, flag); + // dump_pagetable(the_area_ptr->virt_addr + addr_offset,the_area_ptr->phys_addr + addr_offset); + } + else + { + // For other Fault (permisson ...etc) + // uart_sendlinek("[Other Fault]: Kill Process\r\n"); + // uart_sendlinek("esr_el1: 0x%x\r\n", esr_el1); + uart_sendlinek("\n\n"); + if ((unsigned long)esr_el1 & (1 << 10)) + { + ERROR("[Permission Fault] due to a write of an Allocation Tag to Canonically Tagged memory.\r\n"); + } + if ((unsigned long)esr_el1 & (1 << 9)) + { + ERROR("[Permission Fault] due to the NoTagAccess memory attribute..\r\n"); + } + // check_permission(,the_area_ptr->rwx); + thread_exit(); + // dump_vma(); + unlock(); + while (1) + schedule(); + } + unlock(); +} + +vm_area_struct_t *check_vma_overlap(thread_t *t, unsigned long user_va, unsigned long size) +{ + list_head_t *pos; + vm_area_struct_t *vma; + list_for_each(pos, &t->vma_list) + { + vma = (vm_area_struct_t *)pos; + // Detect existing vma overlapped + if (!(vma->virt_addr >= (unsigned long)(user_va + size) || vma->virt_addr + vma->area_size <= (unsigned long)user_va)) + { + return vma; + } + } + return 0; +} + +int check_permission(int userId, int VMA_Permission) +{ + switch (PERMISSION_INVAILD(userId, VMA_Permission)) + { + DUMP_NAME(1, "Read is Invaild in This Vitural Memory Area") + DUMP_NAME(2, "Write is Invaild in This Vitural Memory Area") + DUMP_NAME(3, "Write & Read is Invaild in This Vitural Memory Area") + DUMP_NAME(4, "Exec is Invaild in This Vitural Memory Area") + DUMP_NAME(5, "Exec & Read is Invaild in This Vitural Memory Area") + DUMP_NAME(6, "Exec & Write is Invaild in This Vitural Memory Area") + DUMP_NAME(7, "Exec & Write & Read is Invaild in This Vitural Memory Area") + default: + uart_sendlinek("[other Fault]: UNKNOW FAULT"); + break; + } + return PERMISSION_INVAILD(userId, VMA_Permission); +} + +void dump_vma() +{ + uart_sendlinek(" +--------------------------+\n"); + uart_sendlinek(" | DUMP Vitural Memory Area |\n"); + uart_sendlinek(" +--------------------------+\n"); + list_head_t *pos; + list_for_each(pos, &curr_thread->vma_list) + { + uart_sendlinek("===============================================\n"); + vm_area_struct_t *vma_ptr = (vm_area_struct_t *)pos; + + uart_sendlinek("Vitural Memory Area Name : "); + switch (vma_ptr->name) + { + DUMP_NAME(UNKNOW_AREA, "UNKNOW_AREA") + DUMP_NAME(USER_DATA, "USER_DATA") + DUMP_NAME(USER_STACK, "USER_STACK") + DUMP_NAME(PERIPHERAL, "PERIPHERAL") + DUMP_NAME(USER_SIGNAL_WRAPPER, "USER_SIGNAL_WRAPPER") + DUMP_NAME(USER_EXEC_WRAPPER, "USER_EXEC_WRAPPER") + default: + uart_sendlinek("unnamed: %d\n", vma_ptr->name); + break; + } + uart_sendlinek("Base Vitural Address : 0x%x\n", ((vm_area_struct_t *)pos)->virt_addr); + uart_sendlinek("Base Physical Address : 0x%x\n", ((vm_area_struct_t *)pos)->phys_addr); + uart_sendlinek("Area Size : 0x%x\n", ((vm_area_struct_t *)pos)->area_size); + uart_sendlinek("Exec, Write, Read : 0x%x\n", ((vm_area_struct_t *)pos)->rwx); + uart_sendlinek("===============================================\n\n"); + } +} + +void dump_pagetable(unsigned long user_va, unsigned long pa) +{ + uart_sendlinek(" +---------------------------+\n"); + uart_sendlinek(" | DUMP PAGE TABLE & ADDRESS |\n"); + uart_sendlinek(" +---------------------------+\n"); + unsigned long *pagetable_pa = curr_thread->context.pgd; + unsigned long *pagetable_kernel_va = (unsigned long *)PHYS_TO_KERNEL_VIRT(pagetable_pa); + + uart_sendlinek("===============================================\n"); + uart_sendlinek("User Physical Address : 0x%x\n", pa); + uart_sendlinek("User Vitural Address : 0x%x\n", user_va); + unsigned long offset = user_va & 0xFFF; + uart_sendlinek("Vitural Address offset: 0x%x\n", offset); + for (int level = 0; level < 4; level++) + { + uart_sendlinek("-----------------------------------------------\n"); + uart_sendlinek("PAGE TABLE : "); + switch (level) + { + DUMP_NAME(PGD, "PGD") + DUMP_NAME(PUD, "PUD") + DUMP_NAME(PMD, "PMD") + DUMP_NAME(PTE, "PTE") + + default: + uart_sendlinek("unnamed: %d\n", level); + break; + } + uart_sendlinek("Pagetable Physical Address: 0x%x\n", pagetable_pa); + uart_sendlinek("Pagetable Vitural Address: 0x%x\n", pagetable_kernel_va); + + unsigned int idx = (user_va >> (39 - level * 9)) & 0x1FF; + uart_sendlinek("Index of Pagetable: 0x%x\n", idx); + uart_sendlinek("Entry %x of Pagetable: 0x%x\n", idx, pagetable_kernel_va[idx]); + if (level == PTE) + { + pagetable_pa = (unsigned long *)(pagetable_kernel_va[idx] & ENTRY_ADDR_MASK); + uart_sendlinek("The Page Base Physical Address: 0x%x\n", pagetable_pa); + uart_sendlinek("The Physical Address: 0x%x\n", (unsigned long)pagetable_pa | offset); + } + else + { + pagetable_pa = (unsigned long *)(pagetable_kernel_va[idx] & ENTRY_ADDR_MASK); + uart_sendlinek("next Pagetable Physical Address: 0x%x\n", pagetable_pa); + pagetable_kernel_va = (unsigned long *)PHYS_TO_KERNEL_VIRT(pagetable_pa); + uart_sendlinek("next Pagetable Vitural Address: 0x%x\n", pagetable_kernel_va); + } + uart_sendlinek("-----------------------------------------------\n"); + } +} \ No newline at end of file diff --git a/lab6/kernel/src/sched.S b/lab6/kernel/src/sched.S new file mode 100644 index 000000000..7d0f93cd2 --- /dev/null +++ b/lab6/kernel/src/sched.S @@ -0,0 +1,57 @@ +.global switch_to +switch_to: // (prev, next) = (x0, x1) + stp x19, x20, [x0, 16 * 0] // store callee saved register + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] // store sp, fp, lr + mov x9, sp + str x9, [x0, 16 * 6] + + ldp x19, x20, [x1, 16 * 0] // load callee saved register + ldp x21, x22, [x1, 16 * 1] + ldp x23, x24, [x1, 16 * 2] + ldp x25, x26, [x1, 16 * 3] + ldp x27, x28, [x1, 16 * 4] + ldp fp, lr, [x1, 16 * 5] // load sp, fp, lr + ldp x9, x0, [x1, 16 * 6] + mov sp, x9 + msr tpidr_el1, x1 // update current thread id + + dsb ish // ensure write has completed, lock for context switch + msr ttbr0_el1, x0 // switch translation based address. + tlbi vmalle1is // invalidate all TLB entries in stage 1, el1 and inner shareable + dsb ish // ensure completion of TLB invalidatation + isb // clear pipeline + + ret + +.global get_current +get_current: + mrs x0, tpidr_el1 // get the current thread id + ret + +.global store_context +store_context: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + ret + +.global load_context +load_context: + ldp x19, x20, [x0, 16 * 0] + ldp x21, x22, [x0, 16 * 1] + ldp x23, x24, [x0, 16 * 2] + ldp x25, x26, [x0, 16 * 3] + ldp x27, x28, [x0, 16 * 4] + ldp fp, lr, [x0, 16 * 5] + ldr x9, [x0, 16 * 6] + mov sp, x9 + ret diff --git a/lab6/kernel/src/sched.c b/lab6/kernel/src/sched.c new file mode 100644 index 000000000..1f38fad95 --- /dev/null +++ b/lab6/kernel/src/sched.c @@ -0,0 +1,270 @@ +#include "sched.h" +#include "uart1.h" +#include "exception.h" +#include "memory.h" +#include "timer.h" +#include "shell.h" +#include "signal.h" +#include "stdio.h" +#include "mmu.h" +#include "string.h" + +list_head_t *run_queue; +execfile c_execfile; + +thread_t threads[PIDMAX + 1]; +thread_t *curr_thread; + +int pid_history = 0; +int timer_sched_flag = 0; +int shell_flag = 0; + +void thread_sched_init() +{ + lock(); + // init thread freelist and run_queue + run_queue = kmalloc(sizeof(list_head_t)); + INIT_LIST_HEAD(run_queue); + + // init pids + for (int i = 0; i <= PIDMAX; i++) + { + threads[i].isused = 0; + threads[i].pid = i; + threads[i].iszombie = 0; + } + + thread_t *idlethread = thread_create(start_shell); + curr_thread = idlethread; + asm volatile("msr tpidr_el1, %0" ::"r"(&curr_thread->context)); // Don't let thread structure NULL as we enable the functionality + + // thread_create(idle); + unlock(); +} + +thread_t *thread_create(void *start) +{ + lock(); + thread_t *r; + // find usable PID, don't use the previous one + if (pid_history > PIDMAX) + { + unlock(); + return 0; + } + + if (!threads[pid_history].isused) + { + r = &threads[pid_history]; + pid_history += 1; + } + else + { + unlock(); + return 0; + } + + INIT_LIST_HEAD(&r->vma_list); + r->iszombie = 0; + r->isused = 1; + r->stack_alloced_ptr = kmalloc(USTACK_SIZE); + r->kernel_stack_alloced_ptr = kmalloc(KSTACK_SIZE); + r->context.lr = (unsigned long long)start; + r->context.sp = (unsigned long long)r->kernel_stack_alloced_ptr + KSTACK_SIZE - STACK_BASE_OFFSET; + r->context.fp = r->context.sp; // frame pointer for local variable, which is also in stack. + + // new <--------------------------------------------------------------------------------------------------------------- + // r->data = kmalloc(c_execfile.filesize); + // r->datasize = c_execfile.filesize; + r->context.pgd = kmalloc(0x1000); + // uart_sendlinek("r->context.pgd: %x\n", r->context.pgd); + memset(r->context.pgd, 0, 0x1000); + r->context.pgd = (void *)KERNEL_VIRT_TO_PHYS(r->context.pgd); + // new <--------------------------------------------------------------------------------------------------------------- + + r->signal_is_checking = 0; + // initial all signal handler with signal_default_handler (kill thread) + + // uart_sendlinek("signal_default_handler : 0x%x\n", signal_default_handler); + for (int i = 0; i < SIGNAL_MAX; i++) + { + r->signal_handler[i] = signal_default_handler; + r->sigcount[i] = 0; + } + + list_add_tail(&r->listhead, run_queue); + unlock(); + return r; +} + +void schedule() +{ + lock(); + // uart_sendlinek("Run queue size :%d \n", list_size(run_queue)); + do + { + // uart_sendlinek("Run queue size :%d \n", list_size(run_queue)); + curr_thread = (thread_t *)curr_thread->listhead.next; + } while (list_is_head(&curr_thread->listhead, run_queue)); // find a runnable thread + unlock(); + // uart_sendlinek("curr_thread :%d \n",curr_thread->pid); + // uart_sendlinek("curr_thread->context.lr :0x%x \n",curr_thread->context.lr); + switch_to(get_current(), &curr_thread->context); +} + +void idle() +{ + // uart_sendlinek("This is idle\n"); + while (shell_flag > 0) + // while (list_size(run_queue) > 1) + { + // uart_sendlinek("This is idle\n"); + kill_zombies(); // reclaim threads marked as DEAD + schedule(); // switch to next thread in run queue + // delay(10000); + } + kill_zombies(); +} + +void thread_exit() +{ + // thread cannot deallocate the stack while still using it, wait for someone to recycle it. + // In this lab, idle thread handles this task, instead of parent thread. + lock(); + curr_thread->iszombie = 1; + shell_flag--; + unlock(); + // delay(10000); + // schedule(); +} + +void kill_zombies() +{ + lock(); + list_head_t *curr; + thread_t *t; + list_for_each(curr, run_queue) + { + t = (thread_t *)curr; + if (t->iszombie) + { + list_del_entry(curr); + mmu_free_page_tables(t->context.pgd, 0); + mmu_del_vma(t); + kfree(t->kernel_stack_alloced_ptr); + kfree((void*)PHYS_TO_KERNEL_VIRT(t->context.pgd)); + t->iszombie = 0; + t->isused = 0; + } + } + unlock(); +} + +void foo() +{ + // Lab5 Basic 1 Test function + for (int i = 0; i < 10; ++i) + { + uart_sendlinek("Thread id: %d %d\n", curr_thread->pid, i); + int r = 1000000; + while (r--) + { + asm volatile("nop"); + } + schedule(); + } + // uart_sendlinek("exit\n"); + thread_exit(); +} + +int exec_thread() +{ + lock(); + shell_flag++; + thread_t *t = thread_create(exec_proc); + curr_thread = t; + // uart_sendlinek("timer_sched_flag : %d\n", timer_sched_flag); + if (!timer_sched_flag) + { + timer_sched_flag = 1; + add_timer(schedule_timer, 1, "", setSecond); // start scheduler --------------------------------------------------------- + } + + unlock(); + schedule(); + + return 0; +} + +void exec_proc() +{ + lock(); + char *data = c_execfile.data; + unsigned int filesize = c_execfile.filesize; + thread_t *t = curr_thread; + // uart_sendlinek("filesize : %d\n", filesize); + t->data = kmalloc(filesize); + t->datasize = filesize; + // t->context.lr = (unsigned long)t->data; // set return address to program if function call completes + + mmu_add_vma(t, USER_DATA_BASE, t->datasize, (size_t)KERNEL_VIRT_TO_PHYS(t->data), 0b111, 1, USER_DATA); + mmu_add_vma(t, USER_STACK_BASE - USTACK_SIZE, USTACK_SIZE, (size_t)KERNEL_VIRT_TO_PHYS(t->stack_alloced_ptr), 0b111, 1, USER_STACK); + mmu_add_vma(t, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0, PERIPHERAL); + mmu_add_vma(t, USER_SIGNAL_WRAPPER_VA, 0x1000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(signal_handler_wrapper), PAGESIZE), 0b101, 0, USER_SIGNAL_WRAPPER); + mmu_add_vma(t, USER_EXEC_WRAPPER_VA, 0x2000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(exec_wrapper), PAGESIZE), 0b101, 0, USER_EXEC_WRAPPER); + + // t->context.pgd = KERNEL_VIRT_TO_PHYS(t->context.pgd); + t->context.sp = USER_STACK_BASE - STACK_BASE_OFFSET; + t->context.fp = USER_STACK_BASE - STACK_BASE_OFFSET; + t->context.lr = USER_DATA_BASE; + + // copy file into data + for (int i = 0; i < filesize; i++) + { + t->data[i] = data[i]; + } + // dump_vma(); + // eret to exception level 0 + // lock(); + + // asm("dsb ish\n\t" // ensure write has completed + // "msr ttbr0_el1, %0\n\t" + // "tlbi vmalle1is\n\t" // invalidate all TLB entries + // "dsb ish\n\t" // ensure completion of TLB invalidatation + // "isb\n\t" // clear pipeline" + // ::"r"(t->context.pgd)); + + asm("msr tpidr_el1, %0\n\t" // Hold the "kernel(el1)" thread structure information + "msr elr_el1, %1\n\t" // When el0 -> el1, store return address for el1 -> el0 + "msr spsr_el1, xzr\n\t" // EL1h (SPSel = 1) with interrupt disabled + "msr sp_el0, %2\n\t" // el0 stack pointer for el1 process + "mov sp, %3\n\t" // sp is reference for the same el process. For example, el2 cannot use sp_el2, it has to use sp to find its own stack. + "mov x0, %4\n\t" ::"r"(&t->context), + "r"(exec_wrapper), "r"(t->context.sp), "r"(t->kernel_stack_alloced_ptr + KSTACK_SIZE - STACK_BASE_OFFSET), "r"(t->context.lr)); + + //unlock(); + asm("eret\n\t"); +} + +void exec_wrapper() +{ + // unlock + // uart_sendlinek("exec_handler : %x\n", exec_addr); + // uart_sendlinek("curr_thread : %x\n", curr_thread); + // uart_sendlinek(curr_thread->context.lr)); + asm("mov x8,514\n\t" + "svc 0\n\t"); + + asm("blr x0\n\t" + "mov x8,50\n\t" + "svc 0\n\t"); +} + +void schedule_timer(char *notuse) +{ + unsigned long long cntfrq_el0; + __asm__ __volatile__("mrs %0, cntfrq_el0\n\t" : "=r"(cntfrq_el0)); + add_timer(schedule_timer, cntfrq_el0 >> 5, "", setTick); + // schedule(); + // 32 * default timer -> trigger next schedule timer +} diff --git a/lab6/kernel/src/shell.c b/lab6/kernel/src/shell.c new file mode 100644 index 000000000..bd8a3f5b0 --- /dev/null +++ b/lab6/kernel/src/shell.c @@ -0,0 +1,506 @@ +#include "shell.h" +#include "mbox.h" +#include "power.h" +#include "stdio.h" +#include "string.h" +#include "cpio.h" +#include "memory.h" +#include "dtb.h" +#include "timer.h" +#include "sched.h" +#include "signal.h" +#include "syscall.h" + +#include "uart1.h" + +#define USTACK_SIZE 0x10000 + +extern unsigned long long int lock_counter; +extern list_head_t *run_queue; +extern execfile c_execfile; + +struct CLI_CMDS cmd_list[CLI_MAX_CMD] = { + {.command = "cat", .help = "concatenate files and print on the standard output", .func = do_cmd_cat}, + {.command = "dtb", .help = "show device tree", .func = do_cmd_dtb}, + {.command = "hello", .help = "print Hello World!", .func = do_cmd_hello}, + {.command = "help", .help = "print all available commands", .func = do_cmd_help}, + {.command = "info", .help = "get device information via mailbox", .func = do_cmd_info}, + {.command = "ls", .help = "list directory contents", .func = do_cmd_ls}, + {.command = "malloc", .help = "test malloc", .func = do_cmd_malloc}, + {.command = "reboot", .help = "reboot the device", .func = do_cmd_reboot}, + {.command = "exec", .help = "execute user programs ", .func = do_cmd_exec}, + {.command = "setTime", .help = "setTime [MESSAGE] [SECONDS] ", .func = do_cmd_setTimeout}, + {.command = "2sAlert", .help = "set core timer interrupt every 2 second ", .func = do_cmd_set2sAlert}, + {.command = "mtest", .help = "memory testcase generator, allocate and free", .func = do_cmd_mtest}, + {.command = "ttest", .help = "thread tester with dummy function - foo()", .func = do_cmd_ttest}, + {.command = "ftest", .help = "get run_queue size", .func = do_cmd_ftest}}; + +extern char *dtb_ptr; + +extern void *CPIO_DEFAULT_START; + +void start_shell() +{ + // uart_sendlinek("In start_shell\n"); + char input_buffer[CMD_MAX_LEN]; + cli_print_banner(); + while (1) + { + cli_flush_buffer(input_buffer, CMD_MAX_LEN); + // uart_sendlinek("lock_counter : %d\n",lock_counter); + puts("【 Ciallo~(∠・ω< )⌒★ 】 # "); + cli_cmd_read(input_buffer); + cli_cmd_exec(input_buffer); + idle(); + // uart_sendlinek("idle finish\n"); + } + // return 0; +} + +void cli_flush_buffer(char *buffer, int length) +{ + for (int i = 0; i < length; i++) + { + buffer[i] = '\0'; + } +}; + +void cli_cmd_read(char *buffer) +{ + char c = '\0'; + int idx = 0; + while (idx < CMD_MAX_LEN - 1) + { + c = getchar(); + if (c == 127) // backspace + { + if (idx != 0) + { + puts("\b \b"); + idx--; + } + } + else if (c == '\n') + { + break; + } + else if (c <= 16 || c >= 32 || c < 127) + { + putchar(c); + buffer[idx++] = c; + } + } + buffer[idx] = '\0'; + puts("\r\n"); +} + +int _parse_args(char *buffer, int *argc, char **argv) +{ + char get_cmd = 0; + for (int i = 0; buffer[i] != '\0'; i++) + { + if (!get_cmd) + { + if (buffer[i] == ' ') + { + buffer[i] = '\0'; + get_cmd = 1; + } + } + else + { + if (buffer[i - 1] == '\0' && buffer[i] != ' ' && buffer[i] != '\0') + { + if (*argc >= CMD_MAX_PARAM) + { + return -1; + } + argv[*argc] = buffer + i; + (*argc)++; + } + else if (buffer[i] == ' ') + { + buffer[i] = '\0'; + } + } + } + return 0; +} + +void print_args(int argc, char **argv) +{ + puts("argc: "); + put_int(argc); + puts("\r\n"); + for (int i = 0; i < argc; i++) + { + puts("argv["); + put_int(i); + puts("]: "); + puts(argv[i]); + puts("\r\n"); + } +} + +void cli_cmd_exec(char *buffer) +{ + char *cmd = buffer; + int argc = 0; + char *argv[CMD_MAX_PARAM]; + if (_parse_args(buffer, &argc, argv) == -1) + { + puts("Too many arguments\r\n"); + return; + } + // print_args(argc, argv); + + for (int i = 0; i < CLI_MAX_CMD; i++) + { + if (strcmp(cmd, cmd_list[i].command) == 0) + { + cmd_list[i].func(argc, argv); + return; + } + } + if (*buffer) + { + puts(buffer); + puts(": command not found\r\n"); + } +} + +void cli_print_banner() +{ + // uart_sendlinek("In cli_print_banner\n"); + puts("\r\n"); + puts("============================================================================================\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@-@@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ *@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@# =@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= :@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@- %@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% *@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#%@@@@@@@@@@@@@@@@@@@* -@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@% *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:=@@@@@@@@@@@@@@@@@@@: %@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@- :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@* #@@@@@@@@@@@@@@@@@* -@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@#- :#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+ +%@@@@@@@@@@@@@@+ -%@@@@@@@@@@@@\r\n"); + puts("@@@@*=: :=#@@@@@@@@#=: =*@@@@@@@@@@\r\n"); + puts("@@@@@#= =*%@@@@@@@@@@*+- :=*%@@@@@@@@@@\r\n"); + puts("@@@@@@@- @@@@@@@@@@@# -@@@@@@@@@@@@@@@@@@%: -%@%@@@@@@@@@@@@@@%= :#@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@= @%++*%@@@@@%: +@@@@#==#@@@@@@@@@@@% %* -%@@#-=+%@@@@@@@- %@@@@@+::=*%@@@@\r\n"); + puts("@@@@@@@= @% =%@+ #@+ =%@@\r\n"); + puts("@@@@@@@= @% ************- =@ #+ :%@@\r\n"); + puts("@@@@@@@= @% @@@@@@@@@@@@+ @@% #= += %@@@* =@@@@- :@@@@\r\n"); + puts("@@@@@@@= @% ##########%@+ :@@% #= +@@@@@@= %@#= -#@@= -@@@@\r\n"); + puts("@@@@@@@= @% :::::::::::@+ :@@% #= +#+=++@= -: -: -@@@@\r\n"); + puts("@@@@@@@= @% @@@@@@@@@@@@+ :@@% #= ++ @= - : -@@@@\r\n"); + puts("@@@@@@@= :@% @@@@@@@@@@@@+ :@@% #= ++ @= %@#- :*%@- -@@@@\r\n"); + puts("@@@@@@@= =@% :@@% #= ++ @= %@@@+ -@@@@- -@@@@\r\n"); + puts("@@@@@@@- #@% ****: +**= +@@% #= ++ @= *####: #####: -@@@@\r\n"); + puts("@@@@@@@ :@@%-=*%@@@@@- #@@#+*#%@@@@% #= ++ =@+ -@@@@\r\n"); + puts("@@@@@@* %@@@@#*=--@@@- #@@#-=+*%@@@% %= *+ =@@+ +@@@@@= :@@@@@# -@@@@\r\n"); + puts("@@@@@@: *@%+- =@@- #@#: :=*+ :@= +*=%@@@+ =%@@@@@* -@@@@@@+: -@@@@\r\n"); + puts("@@@@@= *#- *- #- *@= +@@@@@@#+*@@@@@@*- :+%@@@@@#+*@@@@\r\n"); + puts("@@@@+ -%@: -=**%@@@- #@@%#*+=: *@@= *@@@@@@@@@@@@=: :-%@@@@@@@@@\r\n"); + puts("@@@+ -#@@@%- =@@@@@@@@@- #@@@@@@@@% =%@@@= *@@@@@@@@@@@@@#- :*%@@@@@@@@@@\r\n"); + puts("@@=:+%@@@@@@@%+--=*%@@@@@- :@@@@@@#*=-=*@@@@@@= #@@@@@@@@@@@@@@@* =@@@@@@@@@@@@@\r\n"); + puts("@%%@@@@@@@@@@@@@@@%##@@@@- #@@@@%#%@@@@@@@@@@@= +@@@@@@@@@@@@@@@@@* -@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@- =%@@@@@@@@@@@@@@@@@@@= *@@@@@@@@@@@@@@@@@@@: %@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@++%@@@@@@@@@@@@@@@@@@@@@*+%@@@@@@@@@@@@@@@@@@@@+ -@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% +@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= %@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= :@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@* =@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% =@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ *@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@-%@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@=@@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@@@@@@@@@@@@@@@\r\n"); + puts("============================================================================================\r\n"); +} + +int do_cmd_help(int argc, char **argv) +{ + for (int i = 0; i < CLI_MAX_CMD; i++) + { + puts(cmd_list[i].command); + puts("\t\t\t: "); + puts(cmd_list[i].help); + puts("\r\n"); + } + return 0; +} + +int do_cmd_hello(int argc, char **argv) +{ + puts("Hello World!\r\n"); + return 0; +} + +int do_cmd_info(int argc, char **argv) +{ + // print hw revision + pt[0] = 8 * 4; + pt[1] = MBOX_REQUEST_PROCESS; + pt[2] = MBOX_TAG_GET_BOARD_REVISION; + pt[3] = 4; + pt[4] = MBOX_TAG_REQUEST_CODE; + pt[5] = 0; + pt[6] = 0; + pt[7] = MBOX_TAG_LAST_BYTE; + + if (mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt))) + { + puts("Hardware Revision\t: 0x"); + // put_hex(pt[6]); + put_hex(pt[5]); + puts("\r\n"); + } + // print arm memory + pt[0] = 8 * 4; + pt[1] = MBOX_REQUEST_PROCESS; + pt[2] = MBOX_TAG_GET_ARM_MEMORY; + pt[3] = 8; + pt[4] = MBOX_TAG_REQUEST_CODE; + pt[5] = 0; + pt[6] = 0; + pt[7] = MBOX_TAG_LAST_BYTE; + + if (mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt))) + { + puts("ARM Memory Base Address\t: 0x"); + put_hex(pt[5]); + puts("\r\n"); + puts("ARM Memory Size\t\t: 0x"); + put_hex(pt[6]); + puts("\r\n"); + } + return 0; +} + +int do_cmd_reboot(int argc, char **argv) +{ + if (argc == 0) + { + + puts("Reboot in 10 seconds ...\r\n\r\n"); + volatile unsigned int *rst_addr = (unsigned int *)PM_RSTC; + *rst_addr = PM_PASSWORD | 0x20; + volatile unsigned int *wdg_addr = (unsigned int *)PM_WDOG; + *wdg_addr = PM_PASSWORD | 0x70000; + } + else if (argc == 1 && strcmp(argv[0], "-c") == 0) + { + puts("Cancel reboot...\r\n"); + volatile unsigned int *rst_addr = (unsigned int *)PM_RSTC; + *rst_addr = PM_PASSWORD | 0x0; + volatile unsigned int *wdg_addr = (unsigned int *)PM_WDOG; + *wdg_addr = PM_PASSWORD | 0x0; + } + return 0; +} + +int do_cmd_ls(int argc, char **argv) +{ + char *c_filepath; + char *c_filedata; + unsigned int c_filesize; + + CPIO_for_each(&c_filepath, &c_filesize, &c_filedata) + { + if (header_ptr != 0) + { + puts(c_filepath); + puts("\r\n"); + } + } + return 0; +} + +int do_cmd_cat(int argc, char **argv) +{ + int FLAG_getfile = 0; + char *filepath; + char *c_filepath; + char *c_filedata; + unsigned int c_filesize; + + if (argc == 1) + { + filepath = argv[0]; + } + else + { + puts("Too many arguments\r\n"); + return -1; + } + + CPIO_for_each(&c_filepath, &c_filesize, &c_filedata) + { + if (strcmp(c_filepath, filepath) == 0) + { + FLAG_getfile = 1; + Readfile(c_filedata, c_filesize); + break; + } + } + + if (!FLAG_getfile) + { + puts("cat: "); + puts(filepath); + puts(": No such file or directory\r\n"); + } + return 0; +} + +int do_cmd_malloc(int argc, char **argv) +{ + // test malloc + char *test1 = allocator(0x18); + strcpy(test1, "test malloc1"); + puts(test1); + puts("\r\n"); + + char *test2 = allocator(0x20); + strcpy(test2, "test malloc2"); + puts(test2); + puts("\r\n"); + + char *test3 = allocator(0x28); + strcpy(test3, "test malloc3"); + puts(test3); + puts("\r\n"); + return 0; +} + +int do_cmd_dtb(int argc, char **argv) +{ + traverse_device_tree(dtb_ptr, dtb_callback_show_tree); + return 0; +} + +int do_cmd_exec(int argc, char **argv) +{ + int FLAG_getfile = 0; + char *filepath; + char *c_filepath; + char *c_filedata; + unsigned int c_filesize; + + if (argc == 1) + { + filepath = argv[0]; + } + else + { + puts("Too many arguments\r\n"); + return -1; + } + + CPIO_for_each(&c_filepath, &c_filesize, &c_filedata) + { + if (strcmp(c_filepath, filepath) == 0) + { + // exec c_filedata + FLAG_getfile = 1; + // char *ustack = allocator(USTACK_SIZE); + // asm("msr elr_el1, %0\n\t" // elr_el1: Set the address to return to: c_filedata + // "mov x1, 0x3c0\n\t" + // "msr spsr_el1, x1\n\t" // enable interrupt (PSTATE.DAIF) -> spsr_el1[9:6]=4b0. In Basic#1 sample, EL1 interrupt is disabled. + // "msr sp_el0, %1\n\t" // user program stack pointer set to new stack. + // "eret\n\t" // Perform exception return. EL1 -> EL0 + // ::"r"(c_filedata), + // "r"(ustack + USTACK_SIZE)); + // free(ustack); + // break; + + // thread_create((exec_thread)(c_filedata, c_filesize)); + // schedule(); + c_execfile.data = c_filedata; + c_execfile.filesize = c_filesize; + exec_thread(); + } + } + + if (!FLAG_getfile) // header_ptr + { + puts("cat: "); + puts(filepath); + puts(": No such file or directory\r\n"); + } + return 0; +} + +int do_cmd_setTimeout(int argc, char **argv) +{ + char *msg; + int sec; + if (argc == 2) + { + msg = argv[0]; + sec = atoi(argv[1]); + } + else + { + puts("setTimeout [MESSAGE] [SECONDS]\r\n"); + return -1; + } + add_timer(puts, sec, msg, setSecond); + return 0; +} + +int do_cmd_set2sAlert(int argc, char **argv) +{ + add_timer(timer_set2sAlert, 2, "2sAlert", setSecond); + return 0; +} + +int do_cmd_mtest(int argc, char **argv) +{ + // char *a = kmalloc(513); + // uart_sendlinek("a : %x\n", a); + // //kfree(a); + + // char *b = kmalloc(512); + // uart_sendlinek("b : %x\n", b); + // //kfree(b); + + // char *c = kmalloc(8); + // //kfree(c); + + return 0; +} + +int do_cmd_ttest(int argc, char **argv) +{ + // for (int i = 0; i < 5; ++i) + // { // N should > 2 + // thread_create(foo); + // } + // // idle(); + // // schedule(); + uart_sendlinek("getcurrent thread : %x\n", get_current()); + uart_sendlinek("signal_handler_wrapper : 0x%x\n", signal_handler_wrapper); + return 0; +} + +int do_cmd_ftest(int argc, char **argv) +{ + uart_sendlinek("run_queue size : %d\n", list_size(run_queue)); + list_head_t *pos; + list_for_each(pos, run_queue) + { + uart_sendlinek("pid : %d\n", ((thread_t *)pos)->pid); + for (int i = 0; i < SIGNAL_MAX; i++) + { + uart_sendlinek("signal_handler : 0x%x\n", ((thread_t *)pos)->signal_handler[i]); + } + } + return 0; +} \ No newline at end of file diff --git a/lab6/kernel/src/signal.c b/lab6/kernel/src/signal.c new file mode 100644 index 000000000..454315f6e --- /dev/null +++ b/lab6/kernel/src/signal.c @@ -0,0 +1,90 @@ +#include "signal.h" +#include "syscall.h" +#include "sched.h" +#include "memory.h" +#include "mmu.h" + +extern thread_t *curr_thread; + +/** + ( ) + [Signal] [UserProcess] ( [ Registered Signal Handler ] ) [UserProcess] + | \ ( / \ ) / + | \ ( / \ ) / +-------|--------------------[SystemCall]-------------------------------------(-----------------/---------------------------------\----------------------)--/--------------- + | \ [Signal Check] (-> \ ) / + V \ / ^ ( \ \ )/ + [Job Pending] [Exception Handler] | ( \ [ Default Signal Handler ]-------- [Exception Handler]) + | | ( ) + --------------------- ( CONTENT SWITCHING FOR SIGNAL HANDLER ) + +**/ + +void check_signal(trapframe_t *tpf) +{ + if (curr_thread->signal_is_checking) + return; + lock(); + // Prevent nested running signal handler. No need to handle + curr_thread->signal_is_checking = 1; + unlock(); + for (int i = 0; i <= SIGNAL_MAX; i++) + { + store_context(&curr_thread->signal_savedContext); + if (curr_thread->sigcount[i] > 0) + { + lock(); + curr_thread->sigcount[i]--; + unlock(); + run_signal(tpf, i); + } + } + lock(); + curr_thread->signal_is_checking = 0; + unlock(); +} + +void run_signal(trapframe_t *tpf, int signal) +{ + curr_thread->curr_signal_handler = curr_thread->signal_handler[signal]; + + // run default handler in kernel + if (curr_thread->curr_signal_handler == signal_default_handler) + { + signal_default_handler(); + return; + } + + // run registered handler in userspace + // char *temp_signal_userstack = kmalloc(USTACK_SIZE); + // asm("msr elr_el1, %0\n\t" + // "msr sp_el0, %1\n\t" + // "msr spsr_el1, %2\n\t" + // "eret\n\t" ::"r"(signal_handler_wrapper), + // "r"(temp_signal_userstack + USTACK_SIZE), + // "r"(tpf->spsr_el1)); + + asm("msr elr_el1, %0\n\t" + "msr sp_el0, %1\n\t" + "msr spsr_el1, %2\n\t" + "mov x0, %3\n\t" + "eret\n\t" ::"r"(USER_SIGNAL_WRAPPER_VA + ((size_t)signal_handler_wrapper % 0x1000)), + "r"(tpf->sp_el0), + "r"(tpf->spsr_el1), + "r"(curr_thread->curr_signal_handler)); +} + +void signal_handler_wrapper() +{ + //(curr_thread->curr_signal_handler)(); + // system call sigreturn + // uart_sendlinek("signal_handler_wrapper\n"); + asm("blr x0\n\t" + "mov x8,50\n\t" + "svc 0\n\t"); +} + +void signal_default_handler() +{ + kill(0, curr_thread->pid); +} diff --git a/lab6/kernel/src/stdio.c b/lab6/kernel/src/stdio.c new file mode 100644 index 000000000..62aec7591 --- /dev/null +++ b/lab6/kernel/src/stdio.c @@ -0,0 +1,114 @@ +#include "uart1.h" + +char getchar() +{ + char c = uart_async_recv(); + return c == '\r' ? '\n' : c; +} + +void putchar(char c) +{ + uart_async_send(c); +} + +void puts(const char *s) +{ + while (*s) + putchar(*s++); +} + +void Readfile(char *str, int size) +{ + while (size--) + { + putchar(*str++); + } +} + +// Function to print an integer to the UART +void put_int(int num) +{ + // Handle the case when the number is 0 + if (num == 0) + { + putchar('0'); + return; + } + + // Temporary array to store the reversed digits as characters + char temp[12]; // Assuming int can have at most 10 digits + int idx = 0; + + // Handle negative numbers + if (num < 0) + { + putchar('-'); + num = -num; + } + + // Convert the number to characters and store in the temporary array in reverse order + while (num > 0) + { + temp[idx++] = (char)(num % 10 + '0'); + num /= 10; + } + + // Reverse output the character digits + while (idx > 0) + { + putchar(temp[--idx]); + } +} + +void put_hex(unsigned int num) +{ + unsigned int hex; + int index = 28; + puts("0x"); + while (index >= 0) + { + hex = (num >> index) & 0xF; + hex += hex > 9 ? 0x37 : 0x30; + putchar(hex); + index -= 4; + } +} + +// A simple atoi() function +int atoi(char *str) +{ + // Initialize result + int res = 0; + + // Iterate through all characters + // of input string and update result + // take ASCII character of corresponding digit and + // subtract the code from '0' to get numerical + // value and multiply res by 10 to shuffle + // digits left to update running total + for (int i = 0; str[i] != '\0'; ++i) + { + if (str[i] > '9' || str[i] < '0') + return res; + res = res * 10 + str[i] - '0'; + } + + // return result. + return res; +} + +int fake_log2(unsigned long long n) +{ + int val = 0; + while (n >>= 1) + val++; + return val; +} + +void delay(int r) +{ + while (r--) + { + asm volatile("nop"); + } +} diff --git a/lab6/kernel/src/string.c b/lab6/kernel/src/string.c new file mode 100644 index 000000000..e47fd4d39 --- /dev/null +++ b/lab6/kernel/src/string.c @@ -0,0 +1,199 @@ +#include "string.h" + +size_t strlen(const char *str) +{ + size_t count = 0; + while ((unsigned char)*str++) + count++; + return count; +} + +int strcmp(const char *p1, const char *p2) +{ + const unsigned char *s1 = (const unsigned char *)p1; + const unsigned char *s2 = (const unsigned char *)p2; + unsigned char c1, c2; + + do + { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0') + return c1 - c2; + } while (c1 == c2); + return c1 - c2; +} + +int strncmp(const char *s1, const char *s2, unsigned long long n) +{ + unsigned char c1 = '\0'; + unsigned char c2 = '\0'; + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + } while (--n4 > 0); + n &= 3; + } + while (n > 0) + { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + n--; + } + return c1 - c2; +} + +char *strcpy(char *dest, const char *src) +{ + while ((*dest++ = *src++)) + ; + return dest; +} + +unsigned int vsprintf(char *dst, char* fmt, __builtin_va_list args) +{ + long int arg; + int len, sign, i; + char *p, *orig=dst, tmpstr[19]; + + // failsafes + if(dst==(void*)0 || fmt==(void*)0) { + return 0; + } + + // main loop + arg = 0; + while(*fmt) { + if(dst-orig > VSPRINT_MAX_BUF_SIZE-0x10) + { + return -1; + } + // argument access + if(*fmt=='%') { + fmt++; + // literal % + if(*fmt=='%') { + goto put; + } + len=0; + // size modifier + while(*fmt>='0' && *fmt<='9') { + len *= 10; + len += *fmt-'0'; + fmt++; + } + // skip long modifier + if(*fmt=='l') { + fmt++; + } + // character + if(*fmt=='c') { + arg = __builtin_va_arg(args, int); + *dst++ = (char)arg; + fmt++; + continue; + } else + // decimal number + if(*fmt=='d') { + arg = __builtin_va_arg(args, int); + // check input + sign=0; + if((int)arg<0) { + arg*=-1; + sign++; + } + if(arg>99999999999999999L) { + arg=99999999999999999L; + } + // convert to string + i=18; + tmpstr[i]=0; + do { + tmpstr[--i]='0'+(arg%10); + arg/=10; + } while(arg!=0 && i>0); + if(sign) { + tmpstr[--i]='-'; + } + if(len>0 && len<18) { + while(i>18-len) { + tmpstr[--i]=' '; + } + } + p=&tmpstr[i]; + goto copystring; + } else + if(*fmt=='x') { + arg = __builtin_va_arg(args, long int); + i=16; + tmpstr[i]=0; + do { + char n=arg & 0xf; + tmpstr[--i]=n+(n>9?0x37:0x30); + arg>>=4; + } while(arg!=0 && i>0); + if(len>0 && len<=16) { + while(i>16-len) { + tmpstr[--i]='0'; + } + } + p=&tmpstr[i]; + goto copystring; + } else + if(*fmt=='s') { + p = __builtin_va_arg(args, char*); +copystring: if(p==(void*)0) { + p="(null)"; + } + while(*p) { + *dst++ = *p++; + } + } + } else { +put: *dst++ = *fmt; + } + fmt++; + } + *dst=0; + return dst-orig; +} + +void *memset(void *s, int c, size_t n) +{ + char *start = s; + for (size_t i = 0; i < n; i++) + { + start[i] = c; + } + + return s; +} + +char* memcpy(void *dest, const void *src, unsigned long long len) +{ + char *d = dest; + const char *s = src; + while (len--) + *d++ = *s++; + return dest; +} \ No newline at end of file diff --git a/lab6/kernel/src/syscall.c b/lab6/kernel/src/syscall.c new file mode 100644 index 000000000..cd750f6b1 --- /dev/null +++ b/lab6/kernel/src/syscall.c @@ -0,0 +1,327 @@ +#include "bcm2837/rpi_mbox.h" +#include "syscall.h" +#include "sched.h" +#include "uart1.h" +#include "stdio.h" +#include "exception.h" +#include "memory.h" +#include "mbox.h" +#include "signal.h" +#include "string.h" + +#include "debug.h" +#include "cpio.h" +#include "dtb.h" +#include "mmu.h" + +extern void *CPIO_DEFAULT_START; +extern thread_t *curr_thread; +extern thread_t threads[PIDMAX + 1]; + +// trap is like a shared buffer for user space and kernel space +// Because general-purpose registers are used for both arguments and return value, +// We may receive the arguments we need, and overwrite them with return value. + +int getpid(trapframe_t *tpf) +{ + // uart_sendlinek("this is getpid"); + tpf->x0 = curr_thread->pid; + return curr_thread->pid; +} + +size_t uartread(trapframe_t *tpf, char buf[], size_t size) +{ + int i = 0; + for (int i = 0; i < size; i++) + { + buf[i] = uart_async_recv(); + // buf[i] = uart_recv(); + } + tpf->x0 = i; + return i; +} + +size_t uartwrite(trapframe_t *tpf, const char buf[], size_t size) +{ + int i = 0; + // uart_sendlinek("buf[i]: %s\n",buf); + // uart_sendlinek("buf[i] size: %d\n",size); + for (int i = 0; i < size; i++) + { + uart_async_send(buf[i]); + // uart_send(buf[i]); + } + tpf->x0 = i; + return i; +} + +// In this lab, you won’t have to deal with argument passing +int exec(trapframe_t *tpf, const char *name, char *const argv[]) +{ + mmu_del_vma(curr_thread); + INIT_LIST_HEAD(&curr_thread->vma_list); + + curr_thread->datasize = get_file_size((char *)name); + char *new_data = get_file_start((char *)name); + curr_thread->data = kmalloc(curr_thread->datasize); + curr_thread->stack_alloced_ptr = kmalloc(USTACK_SIZE); + + asm("dsb ish\n\t"); // ensure write has completed + mmu_free_page_tables(curr_thread->context.pgd, 0); + memset(PHYS_TO_VIRT(curr_thread->context.pgd), 0, 0x1000); + asm("tlbi vmalle1is\n\t" // invalidate all TLB entries + "dsb ish\n\t" // ensure completion of TLB invalidatation + "isb\n\t"); // clear pipeline + + memcpy(curr_thread->signal_handler, curr_thread->signal_handler, SIGNAL_MAX * 8); + memcpy(curr_thread->data, new_data, curr_thread->datasize); + mmu_add_vma(curr_thread, USER_DATA_BASE, curr_thread->datasize, (size_t)KERNEL_VIRT_TO_PHYS(curr_thread->data), 0b111, 1, USER_DATA); + mmu_add_vma(curr_thread, USER_STACK_BASE - USTACK_SIZE, USTACK_SIZE, (size_t)KERNEL_VIRT_TO_PHYS(curr_thread->stack_alloced_ptr), 0b011, 1, USER_STACK); + mmu_add_vma(curr_thread, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0, PERIPHERAL); + mmu_add_vma(curr_thread, USER_SIGNAL_WRAPPER_VA, 0x1000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(signal_handler_wrapper), 0x1000), 0b101, 0, USER_SIGNAL_WRAPPER); + mmu_add_vma(curr_thread, USER_EXEC_WRAPPER_VA, 0x2000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(exec_wrapper), PAGESIZE), 0b101, 0, USER_EXEC_WRAPPER); + + tpf->elr_el1 = USER_DATA_BASE; + tpf->sp_el0 = USER_STACK_BASE-STACK_BASE_OFFSET; + tpf->x0 = 0; + return 0; +} + +// extern unsigned long long int lock_counter; +int fork(trapframe_t *tpf) +{ + lock(); + thread_t *newt = thread_create(curr_thread->data); + + // mmu_set_PTE_readonly(curr_thread->context.pgd,0); + // mmu_pagetable_copy(newt->context.pgd,curr_thread->context.pgd,0); + //uart_sendlinek("fork\n"); + memcpy(newt->signal_handler, curr_thread->signal_handler, SIGNAL_MAX * 8); + memcpy(newt->stack_alloced_ptr, curr_thread->kernel_stack_alloced_ptr, USTACK_SIZE); + memcpy(newt->kernel_stack_alloced_ptr, curr_thread->kernel_stack_alloced_ptr, KSTACK_SIZE); + mmu_add_vma(newt, USER_DATA_BASE, curr_thread->datasize, (size_t)KERNEL_VIRT_TO_PHYS(curr_thread->data), 0b111, 1, USER_DATA); + mmu_add_vma(newt, USER_STACK_BASE - USTACK_SIZE, USTACK_SIZE, (size_t)KERNEL_VIRT_TO_PHYS(newt->stack_alloced_ptr), 0b011, 1, USER_STACK); + mmu_add_vma(newt, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0, PERIPHERAL); + mmu_add_vma(newt, USER_SIGNAL_WRAPPER_VA, 0x1000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(signal_handler_wrapper), 0x1000), 0b101, 0, USER_SIGNAL_WRAPPER); + mmu_add_vma(newt, USER_EXEC_WRAPPER_VA, 0x2000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(exec_wrapper), PAGESIZE), 0b101, 0, USER_EXEC_WRAPPER); + + int parent_pid = curr_thread->pid; + + store_context(get_current()); + // for child + if (parent_pid != curr_thread->pid) + { + goto child; + } + + // 除了PGD以外的context都複製。 + void *temp_pgd = newt->context.pgd; + newt->context = curr_thread->context; + newt->context.pgd = temp_pgd; + + newt->context.fp += newt->kernel_stack_alloced_ptr - curr_thread->kernel_stack_alloced_ptr; // move fp + newt->context.sp += newt->kernel_stack_alloced_ptr - curr_thread->kernel_stack_alloced_ptr; // move kernel sp + + unlock(); + + tpf->x0 = newt->pid; + return newt->pid; + +child: + tpf->x0 = 0; + return 0; +} + +void exit(trapframe_t *tpf, int status) +{ + thread_exit(); + while (1) + schedule(); +} + +int syscall_mbox_call(trapframe_t *tpf, unsigned char ch, unsigned int *mbox) +{ + lock(); + + unsigned int size_of_mbox = mbox[0]; + memcpy((char *)pt, mbox, size_of_mbox); + mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt)); + memcpy(mbox, (char *)pt, size_of_mbox); + + // tpf->x0 = 8; + unlock(); + return 0; +} + +// only need to implement the anonymous page mapping in this Lab. +void *mmap(trapframe_t *tpf, void *addr, size_t len, int prot, int flags, int fd, int file_offset) +{ + len = ALIGN_UP(len, PAGESIZE); + unsigned long base_user_va = ALIGN_DOWN((unsigned long)addr, PAGESIZE); + uart_sendlinek("+\n"); + uart_sendlinek("| User request new vma base vitural address: 0x%x\n", (unsigned long)addr); + uart_sendlinek("| Aligned to PAGESIZE: 0x%x\n", base_user_va); + uart_sendlinek("| User request new vma size: 0x%x\n", len); + uart_sendlinek("| Exec, Write, Read : 0x%d\n", prot); + uart_sendlinek("+\n"); + + // Req #2 check if overlap + vm_area_struct_t *the_area_ptr = check_vma_overlap(curr_thread, base_user_va, (unsigned long)len); + // take as a hint to decide new region's start address + if (the_area_ptr) + { + WARING("Vitural Memory Area Overlap\n"); + WARING("Find another vma base vitural address\n"); + tpf->x0 = (unsigned long)mmap(tpf, (void *)(the_area_ptr->virt_addr + the_area_ptr->area_size), len, prot, flags, fd, file_offset); + return (void *)tpf->x0; + } + // create new valid region, map and set the page attributes (prot) + mmu_add_vma(curr_thread, base_user_va, len, KERNEL_VIRT_TO_PHYS((unsigned long)kmalloc(len)), prot, 1, UNKNOW_AREA); + tpf->x0 = base_user_va; + return (void *)tpf->x0; +} + +void kill(trapframe_t *tpf, int pid) +{ + if (pid < 0 || pid >= PIDMAX || !threads[pid].isused) + return; + + lock(); + + if (pid == curr_thread->pid) + { + uart_sendlinek("[!] you kill youself !! \n"); + thread_exit(); + unlock(); + while (1) + schedule(); + } + else + { + threads[pid].iszombie = 1; + unlock(); + } + schedule(); +} + +void signal_register(int signal, void (*handler)()) +{ + if (signal > SIGNAL_MAX || signal < 0) + return; + // uart_sendlinek("handler : 0x%x\n", handler); + curr_thread->signal_handler[signal] = handler; +} + +void signal_kill(int pid, int signal) +{ + if (pid > PIDMAX || pid < 0 || !threads[pid].isused) + return; + lock(); + threads[pid].sigcount[signal]++; + unlock(); +} + +void sigreturn(trapframe_t *tpf) +{ + // unsigned long signal_ustack = tpf->sp_el0 % USTACK_SIZE == 0 ? tpf->sp_el0 - USTACK_SIZE : tpf->sp_el0 & (~(USTACK_SIZE - 1)); + // kfree((char *)signal_ustack); + load_context(&curr_thread->signal_savedContext); +} + +void syscall_unlock(trapframe_t *tpf) +{ + unlock(); +} + +void syscall_lock(trapframe_t *tpf) +{ + lock(); +} + +char *get_file_start(char *thefilepath) +{ + int FLAG_getfile = 0; + char *filepath; + char *filedata; + unsigned int filesize; + // struct cpio_newc_header *header_pointer = CPIO_DEFAULT_START; + + CPIO_for_each(&filepath, &filesize, &filedata) + { + if (strcmp(thefilepath, filepath) == 0) + { + FLAG_getfile = 1; + return filedata; + } + } + + if (!FLAG_getfile) + { + uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + } + + // while (header_pointer != 0) + // { + // int error = cpio_newc_parse_header(header_pointer, &filepath, &filesize, &filedata, &header_pointer); + // //if parse header error + // if (error) + // { + // uart_sendlinek("error"); + // break; + // } + + // if (strcmp(thefilepath, filepath) == 0) + // { + // return filedata; + // } + + // //if this is TRAILER!!! (last of file) + // if (header_pointer == 0) + // uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + // } + + return 0; +} + +unsigned int get_file_size(char *thefilepath) +{ + int FLAG_getfile = 0; + char *filepath; + char *filedata; + unsigned int filesize; + + CPIO_for_each(&filepath, &filesize, &filedata) + { + if (strcmp(thefilepath, filepath) == 0) + { + FLAG_getfile = 1; + return filesize; + } + } + + if (!FLAG_getfile) + { + uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + } + + // while (header_pointer != 0) + // { + // int error = cpio_newc_parse_header(header_pointer, &filepath, &filesize, &filedata, &header_pointer); + // // if parse header error + // if (error) + // { + // uart_sendlinek("error"); + // break; + // } + + // if (strcmp(thefilepath, filepath) == 0) + // { + // return filesize; + // } + + // // if this is TRAILER!!! (last of file) + // if (header_pointer == 0) + // uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + // } + return 0; +} diff --git a/lab6/kernel/src/timer.c b/lab6/kernel/src/timer.c new file mode 100644 index 000000000..061bbb05d --- /dev/null +++ b/lab6/kernel/src/timer.c @@ -0,0 +1,177 @@ +#include "timer.h" +#include "uart1.h" +#include "memory.h" +#include "string.h" +#include "exception.h" +#include + +#define STR(x) #x +#define XSTR(s) STR(s) + +struct list_head *timer_event_list; // first head has nothing, store timer_event_t after it + +void timer_list_init() +{ + uint64_t tmp; + asm volatile("mrs %0, cntkctl_el1" : "=r"(tmp)); + tmp |= 1; + asm volatile("msr cntkctl_el1, %0" ::"r"(tmp)); + + timer_event_list = allocator(sizeof(list_head_t)); + INIT_LIST_HEAD(timer_event_list); +} + +void core_timer_enable() +{ + __asm__ __volatile__( + "mov x1, 1\n\t" + "msr cntp_ctl_el0, x1\n\t" // cntp_ctl_el0[0]: enable, Control register for the EL1 physical timer. + // cntp_tval_el0: Holds the timer value for the EL1 physical timer + "mov x2, 2\n\t" + "ldr x1, =" XSTR(CORE0_TIMER_IRQ_CTRL) "\n\t" + "str w2, [x1]\n\t" // QA7_rev3.4.pdf: Core0 Timer IRQ allows Non-secure physical timer(nCNTPNSIRQ) + ); +} + +void core_timer_disable() +{ + __asm__ __volatile__( + "mov x2, 0\n\t" + "ldr x1, =" XSTR(CORE0_TIMER_IRQ_CTRL) "\n\t" + "str w2, [x1]\n\t" // QA7_rev3.4.pdf: Mask all timer interrupt + ); +} + +void core_timer_handler() +{ + lock(); + //uart_sendlinek("\nThis is core_timer_handler\n"); + if (list_empty(timer_event_list)) + { + uart_sendlinek("\ntimer_event_list is empty\n"); + set_core_timer_interrupt(10000); // disable timer interrupt (set a very big value) + unlock(); + return; + } + timer_event_callback((timer_event_t *)timer_event_list->next); // do callback and set new interrupt + unlock(); +} + +void timer_event_callback(timer_event_t *timer_event) +{ + list_del_entry((struct list_head *)timer_event); // delete the event in queue + // free(timer_event->args); // free the event's space + // free(timer_event); + ((void (*)(char *))timer_event->callback)(timer_event->args); // call the event + + kfree(timer_event->args); + kfree(timer_event); + + // set queue linked list to next time event if it exists + if (!list_empty(timer_event_list)) + { + set_core_timer_interrupt_by_tick(((timer_event_t *)timer_event_list->next)->interrupt_time); + } + else + { + set_core_timer_interrupt(10000); // disable timer interrupt (set a very big value) + } +} + +void timer_set2sAlert(char *str) +{ + unsigned long long cntpct_el0; + __asm__ __volatile__("mrs %0, cntpct_el0\n\t" : "=r"(cntpct_el0)); // tick auchor + unsigned long long cntfrq_el0; + __asm__ __volatile__("mrs %0, cntfrq_el0\n\t" : "=r"(cntfrq_el0)); // tick frequency + + uart_sendlinek("\n"); + uart_sendlinek("[Interrupt start]\n"); + for (int i = 0; i < 1000000000; i++) + ; + uart_sendlinek("[Interrupt finish]\n"); + + // uart_sendlinek("[Interrupt][el1_irq][%s] %d seconds after booting\n", str, cntpct_el0 / cntfrq_el0); + + add_timer(timer_set2sAlert, 2, "2sAlert",setSecond); +} + +void add_timer(void *callback, unsigned long long timeout, char *args, int inTickFormat) +{ + timer_event_t *the_timer_event = kmalloc(sizeof(timer_event_t)); // free by timer_event_callback + // store all the related information in timer_event + the_timer_event->args = kmalloc(strlen(args) + 1); + strcpy(the_timer_event->args, args); + + if (inTickFormat == 0) + { + the_timer_event->interrupt_time = get_tick_plus_s(timeout); // store interrupt time into timer_event + } + else + { + the_timer_event->interrupt_time = get_tick_plus_s(0) + timeout; + } + + the_timer_event->callback = callback; + INIT_LIST_HEAD(&the_timer_event->listhead); + + // add the timer_event into timer_event_list (sorted) + struct list_head *curr; + lock(); + list_for_each(curr, timer_event_list) + { + if (((timer_event_t *)curr)->interrupt_time > the_timer_event->interrupt_time) + { + list_add(&the_timer_event->listhead, curr->prev); // add this timer at the place just before the bigger one (sorted) + break; + } + } + // if the timer_event is the biggest, run this code block + if (list_is_head(curr, timer_event_list)) + { + list_add_tail(&the_timer_event->listhead, timer_event_list); + } + // set interrupt to first event + set_core_timer_interrupt_by_tick(((timer_event_t *)timer_event_list->next)->interrupt_time); + unlock(); +} + +// get cpu tick add some second +unsigned long long get_tick_plus_s(unsigned long long second) +{ + unsigned long long cntpct_el0 = 0; + __asm__ __volatile__("mrs %0, cntpct_el0\n\t" : "=r"(cntpct_el0)); // tick auchor + unsigned long long cntfrq_el0 = 0; + __asm__ __volatile__("mrs %0, cntfrq_el0\n\t" : "=r"(cntfrq_el0)); // tick frequency + return (cntpct_el0 + cntfrq_el0 * second); +} + +// set timer interrupt time to [expired_time] seconds after now (relatively) +void set_core_timer_interrupt(unsigned long long expired_time) +{ + __asm__ __volatile__( + "mrs x1, cntfrq_el0\n\t" // cntfrq_el0 -> frequency of the timer + "mul x1, x1, %0\n\t" // cntpct_el0 = cntfrq_el0 * seconds: relative timer to cntfrq_el0 + "msr cntp_tval_el0, x1\n\t" // Set expired time to cntp_tval_el0, which stores time value of EL1 physical timer. + : "=r"(expired_time)); +} + +// directly set timer interrupt time to a cpu tick (directly) +void set_core_timer_interrupt_by_tick(unsigned long long tick) +{ + __asm__ __volatile__( + "msr cntp_cval_el0, %0\n\t" // cntp_cval_el0 -> absolute timer + : "=r"(tick)); +} + +// get timer pending queue size +int timer_list_get_size() +{ + int r = 0; + struct list_head *curr; + list_for_each(curr, timer_event_list) + { + r++; + } + return r; +} diff --git a/lab6/kernel/src/uart1.c b/lab6/kernel/src/uart1.c new file mode 100644 index 000000000..b3eea3222 --- /dev/null +++ b/lab6/kernel/src/uart1.c @@ -0,0 +1,175 @@ +#include "bcm2837/rpi_gpio.h" +#include "bcm2837/rpi_uart1.h" +#include "bcm2837/rpi_irq.h" +#include "uart1.h" +#include "string.h" +#include "exception.h" + +// implement first in first out buffer with a read index and a write index +static char uart_tx_buffer[VSPRINT_MAX_BUF_SIZE]; +unsigned int uart_tx_buffer_widx = 0; // write index +unsigned int uart_tx_buffer_ridx = 0; // read index +static char uart_rx_buffer[VSPRINT_MAX_BUF_SIZE]; +unsigned int uart_rx_buffer_widx = 0; +unsigned int uart_rx_buffer_ridx = 0; + +void uart_init() +{ + register unsigned int selector; + + /* initialize UART */ + *AUX_ENABLES = 1; // enable UART1 + *AUX_MU_CNTL_REG = 0; // disable TX/RX + + /* configure UART */ + *AUX_MU_IER_REG = 0; // disable interrupt + *AUX_MU_LCR_REG = 3; // 8 bit data size + *AUX_MU_MCR_REG = 0; // disable flow control + *AUX_MU_BAUD_REG = 270; // 115200 baud rate + + /* map UART1 to GPIO pins */ + selector = *GPFSEL1; + selector &= ~(7 << 12); // clean gpio14, and (11 111 111 111 111 111 000 111 111 111 111)2 + selector |= 2 << 12; // set gpio14 to alt5 + selector &= ~(7 << 15); // clean gpio15, and (11 111 111 111 111 000 111 111 111 111 111)2 + selector |= 2 << 15; // set gpio15 to alt5 + *GPFSEL1 = selector; + + /* enable pin 14, 15 - ref: Page 101 */ + *GPPUD = 0; + selector = 150; + while (selector--) + { + asm volatile("nop"); + } + *GPPUDCLK0 = (1 << 14) | (1 << 15); + selector = 150; + while (selector--) + { + asm volatile("nop"); + } + *GPPUDCLK0 = 0; + + *AUX_MU_CNTL_REG = 3; +} + +void uart_flush_FIFO() +{ + // On write: + // Writing with bit 1 set will clear the receive FIFO + // Writing with bit 2 set will clear the transmit FIFOF + *AUX_MU_IIR_REG |= 6; +} + +char uart_recv() +{ + char r; + while (!(*AUX_MU_LSR_REG & 0x01)) + ; + r = (char)(*AUX_MU_IO_REG); + return r; +} + +void uart_send(unsigned int c) +{ + while (!(*AUX_MU_LSR_REG & 0x20)) + ; + *AUX_MU_IO_REG = c; +} + +// AUX_MU_IER_REG -> BCM2837-ARM-Peripherals.pdf - Pg.12 +void uart_interrupt_enable() +{ + *AUX_MU_IER_REG |= 1; // enable read interrupt + *AUX_MU_IER_REG |= 2; // enable write interrupt + *ENABLE_IRQS_1 |= 1 << 29; // Pg.112 +} + +void uart_interrupt_disable() +{ + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + *AUX_MU_IER_REG &= ~(2); // disable write interrupt +} + +// scanf +void uart_r_irq_handler() +{ + if ((uart_rx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_rx_buffer_ridx) + { + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + return; + } + uart_rx_buffer[uart_rx_buffer_widx++] = uart_recv(); + if (uart_rx_buffer_widx >= VSPRINT_MAX_BUF_SIZE) + uart_rx_buffer_widx = 0; + *AUX_MU_IER_REG |= 1; +} + +// printf +void uart_w_irq_handler() +{ + if (uart_tx_buffer_ridx == uart_tx_buffer_widx) + { + *AUX_MU_IER_REG &= ~(2); // disable write interrupt + return; // buffer empty + } + uart_send(uart_tx_buffer[uart_tx_buffer_ridx++]); + if (uart_tx_buffer_ridx >= VSPRINT_MAX_BUF_SIZE) + uart_tx_buffer_ridx = 0; + *AUX_MU_IER_REG |= 2; // enable write interrupt +} + +// uart_async_getc read from buffer +// uart_r_irq_handler write to buffer then output +char uart_async_recv() +{ + *AUX_MU_IER_REG |= 1; // enable read interrupt + // do while if buffer empty + while (uart_rx_buffer_ridx == uart_rx_buffer_widx) + { + *AUX_MU_IER_REG |= 1; // enable read interrupt + } + lock(); + char r = uart_rx_buffer[uart_rx_buffer_ridx++]; + if (uart_rx_buffer_ridx >= VSPRINT_MAX_BUF_SIZE) + uart_rx_buffer_ridx = 0; + unlock(); + return r; +} + +// uart_async_putc writes to buffer +// uart_w_irq_handler read from buffer then output +void uart_async_send(char c) +{ + // if buffer full, wait for uart_w_irq_handler + while ((uart_tx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_tx_buffer_ridx) + { + // uart_puts("buffer full\r\n"); + *AUX_MU_IER_REG |= 2; // enable write interrupt + } + lock(); + uart_tx_buffer[uart_tx_buffer_widx++] = c; + if (uart_tx_buffer_widx >= VSPRINT_MAX_BUF_SIZE) + uart_tx_buffer_widx = 0; // cycle pointer + unlock(); + *AUX_MU_IER_REG |= 2; // enable write interrupt +} + +int uart_sendlinek(char *fmt, ...) +{ + __builtin_va_list args; + __builtin_va_start(args, fmt); + char buf[VSPRINT_MAX_BUF_SIZE]; + + char *str = (char *)buf; + int count = vsprintf(str, fmt, args); + + while (*str) + { + if (*str == '\n') + uart_send('\r'); + uart_send(*str++); + } + __builtin_va_end(args); + return count; +} \ No newline at end of file diff --git a/lab6/send_img_to_bootloader.py b/lab6/send_img_to_bootloader.py new file mode 100644 index 000000000..29d43b781 --- /dev/null +++ b/lab6/send_img_to_bootloader.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 + +from serial import Serial +from pwn import * +import argparse +from sys import platform + +if platform == "linux" or platform == "linux2": + parser = argparse.ArgumentParser(description='NYCU OSDI kernel sender') + parser.add_argument('--filename', metavar='PATH', default='kernel8.img', type=str, help='path to kernel8.img') + parser.add_argument('--device', metavar='TTY',default='/dev/ttyUSB0', type=str, help='path to UART device') + parser.add_argument('--baud', metavar='Hz',default=115200, type=int, help='baud rate') + args = parser.parse_args() + + with open(args.filename,'rb') as fd: + with Serial(args.device, args.baud) as ser: + + kernel_raw = fd.read() + length = len(kernel_raw) + + print("Kernel image size : ", hex(length)) + for i in range(8): + ser.write(p64(length)[i:i+1]) + ser.flush() + + print("Start sending kernel image by uart1...") + for i in range(length): + # Use kernel_raw[i: i+1] is byte type. Instead of using kernel_raw[i] it will retrieve int type then cause error + ser.write(kernel_raw[i: i+1]) + ser.flush() + if i % 100 == 0: + print("{:>6}/{:>6} bytes".format(i, length)) + print("{:>6}/{:>6} bytes".format(length, length)) + print("Transfer finished!") + +else: + parser = argparse.ArgumentParser(description='NYCU OSDI kernel sender') + parser.add_argument('--filename', metavar='PATH', default='kernel8.img', type=str, help='path to kernel8.img') + parser.add_argument('--device', metavar='COM',default='COM3', type=str, help='COM# to UART device') + parser.add_argument('--baud', metavar='Hz',default=115200, type=int, help='baud rate') + args = parser.parse_args() + + with open(args.filename,'rb') as fd: + with Serial(args.device, args.baud) as ser: + + kernel_raw = fd.read() + length = len(kernel_raw) + + print("Kernel image size : ", hex(length)) + for i in range(8): + ser.write(p64(length)[i:i+1]) + ser.flush() + + print("Start sending kernel image by uart1...") + for i in range(length): + # Use kernel_raw[i: i+1] is byte type. Instead of using kernel_raw[i] it will retrieve int type then cause error + ser.write(kernel_raw[i: i+1]) + ser.flush() + if i % 100 == 0: + print("{:>6}/{:>6} bytes".format(i, length)) + print("{:>6}/{:>6} bytes".format(length, length)) + print("Transfer finished!") \ No newline at end of file From eb36fd07868927ac24a579978702a9cf6b36945e Mon Sep 17 00:00:00 2001 From: SianGx0102 Date: Mon, 17 Jun 2024 22:57:46 +0800 Subject: [PATCH 2/5] Lab7 --- lab6/kernel/src/sched.c | 7 +- lab6/kernel/src/syscall.c | 1 + lab7/bcm2710-rpi-3-b-plus.dtb | Bin 0 -> 32761 bytes lab7/config.txt | 3 + lab7/create_fs/FromTA/initramfs.cpio | Bin 0 -> 247296 bytes lab7/create_fs/create_cpio.sh | 11 + lab7/create_fs/lab3_user_proc/linker.ld | 5 + lab7/create_fs/lab3_user_proc/makefile | 23 + lab7/create_fs/lab3_user_proc/user_proc.S | 12 + lab7/create_fs/lab5_user_fork/fork_test.S | 28 + .../initramfs_providedbyTA.cpio | Bin 0 -> 247296 bytes lab7/create_fs/lab5_user_fork/makefile | 23 + lab7/create_fs/rootfs/file0.txt | 2 + lab7/create_fs/rootfs/file1.txt | 11 + lab7/initramfs.cpio | Bin 0 -> 656384 bytes lab7/kernel/Makefile | 89 +++ lab7/kernel/include/bcm2837/rpi_base.h | 7 + lab7/kernel/include/bcm2837/rpi_gpio.h | 25 + lab7/kernel/include/bcm2837/rpi_irq.h | 24 + lab7/kernel/include/bcm2837/rpi_mbox.h | 17 + lab7/kernel/include/bcm2837/rpi_mmu.h | 18 + lab7/kernel/include/bcm2837/rpi_uart1.h | 19 + lab7/kernel/include/cpio.h | 47 ++ lab7/kernel/include/debug.h | 19 + lab7/kernel/include/dtb.h | 26 + lab7/kernel/include/exception.h | 92 +++ lab7/kernel/include/irqtask.h | 22 + lab7/kernel/include/mbox.h | 66 ++ lab7/kernel/include/memory.h | 80 +++ lab7/kernel/include/mmu.h | 101 +++ lab7/kernel/include/power.h | 9 + lab7/kernel/include/sched.h | 79 +++ lab7/kernel/include/shell.h | 40 ++ lab7/kernel/include/signal.h | 49 ++ lab7/kernel/include/stddef.h | 12 + lab7/kernel/include/stdio.h | 29 + lab7/kernel/include/string.h | 12 + lab7/kernel/include/syscall.h | 38 ++ lab7/kernel/include/timer.h | 36 ++ lab7/kernel/include/u_list.h | 150 +++++ lab7/kernel/include/uart1.h | 18 + lab7/kernel/include/vfs.h | 103 +++ lab7/kernel/include/vfs_dev_framebuffer.h | 24 + lab7/kernel/include/vfs_dev_uart.h | 15 + lab7/kernel/include/vfs_initramfs.h | 39 ++ lab7/kernel/include/vfs_tmpfs.h | 41 ++ lab7/kernel/src/boot.S | 82 +++ lab7/kernel/src/cpio.c | 82 +++ lab7/kernel/src/dtb.c | 173 ++++++ lab7/kernel/src/entry.S | 199 ++++++ lab7/kernel/src/exception.c | 376 +++++++++++ lab7/kernel/src/linker.ld | 44 ++ lab7/kernel/src/main.c | 45 ++ lab7/kernel/src/mbox.c | 23 + lab7/kernel/src/memory.c | 491 +++++++++++++++ lab7/kernel/src/mmu.c | 380 +++++++++++ lab7/kernel/src/sched.S | 57 ++ lab7/kernel/src/sched.c | 270 ++++++++ lab7/kernel/src/shell.c | 588 ++++++++++++++++++ lab7/kernel/src/signal.c | 90 +++ lab7/kernel/src/stdio.c | 121 ++++ lab7/kernel/src/string.c | 242 +++++++ lab7/kernel/src/syscall.c | 352 +++++++++++ lab7/kernel/src/syscall_fs.c | 146 +++++ lab7/kernel/src/timer.c | 177 ++++++ lab7/kernel/src/uart1.c | 177 ++++++ lab7/kernel/src/vfs.c | 433 +++++++++++++ lab7/kernel/src/vfs_dev_framebuffer.c | 131 ++++ lab7/kernel/src/vfs_dev_uart.c | 53 ++ lab7/kernel/src/vfs_initramfs.c | 190 ++++++ lab7/kernel/src/vfs_tmpfs.c | 253 ++++++++ lab7/send_img_to_bootloader.py | 62 ++ 72 files changed, 6706 insertions(+), 3 deletions(-) create mode 100644 lab7/bcm2710-rpi-3-b-plus.dtb create mode 100644 lab7/config.txt create mode 100644 lab7/create_fs/FromTA/initramfs.cpio create mode 100755 lab7/create_fs/create_cpio.sh create mode 100644 lab7/create_fs/lab3_user_proc/linker.ld create mode 100644 lab7/create_fs/lab3_user_proc/makefile create mode 100644 lab7/create_fs/lab3_user_proc/user_proc.S create mode 100644 lab7/create_fs/lab5_user_fork/fork_test.S create mode 100644 lab7/create_fs/lab5_user_fork/initramfs_providedbyTA.cpio create mode 100644 lab7/create_fs/lab5_user_fork/makefile create mode 100644 lab7/create_fs/rootfs/file0.txt create mode 100644 lab7/create_fs/rootfs/file1.txt create mode 100644 lab7/initramfs.cpio create mode 100644 lab7/kernel/Makefile create mode 100644 lab7/kernel/include/bcm2837/rpi_base.h create mode 100644 lab7/kernel/include/bcm2837/rpi_gpio.h create mode 100644 lab7/kernel/include/bcm2837/rpi_irq.h create mode 100644 lab7/kernel/include/bcm2837/rpi_mbox.h create mode 100644 lab7/kernel/include/bcm2837/rpi_mmu.h create mode 100644 lab7/kernel/include/bcm2837/rpi_uart1.h create mode 100644 lab7/kernel/include/cpio.h create mode 100644 lab7/kernel/include/debug.h create mode 100644 lab7/kernel/include/dtb.h create mode 100644 lab7/kernel/include/exception.h create mode 100644 lab7/kernel/include/irqtask.h create mode 100644 lab7/kernel/include/mbox.h create mode 100644 lab7/kernel/include/memory.h create mode 100644 lab7/kernel/include/mmu.h create mode 100644 lab7/kernel/include/power.h create mode 100644 lab7/kernel/include/sched.h create mode 100644 lab7/kernel/include/shell.h create mode 100644 lab7/kernel/include/signal.h create mode 100644 lab7/kernel/include/stddef.h create mode 100644 lab7/kernel/include/stdio.h create mode 100644 lab7/kernel/include/string.h create mode 100644 lab7/kernel/include/syscall.h create mode 100644 lab7/kernel/include/timer.h create mode 100644 lab7/kernel/include/u_list.h create mode 100644 lab7/kernel/include/uart1.h create mode 100644 lab7/kernel/include/vfs.h create mode 100644 lab7/kernel/include/vfs_dev_framebuffer.h create mode 100644 lab7/kernel/include/vfs_dev_uart.h create mode 100644 lab7/kernel/include/vfs_initramfs.h create mode 100644 lab7/kernel/include/vfs_tmpfs.h create mode 100644 lab7/kernel/src/boot.S create mode 100644 lab7/kernel/src/cpio.c create mode 100644 lab7/kernel/src/dtb.c create mode 100644 lab7/kernel/src/entry.S create mode 100644 lab7/kernel/src/exception.c create mode 100644 lab7/kernel/src/linker.ld create mode 100644 lab7/kernel/src/main.c create mode 100644 lab7/kernel/src/mbox.c create mode 100644 lab7/kernel/src/memory.c create mode 100644 lab7/kernel/src/mmu.c create mode 100644 lab7/kernel/src/sched.S create mode 100644 lab7/kernel/src/sched.c create mode 100644 lab7/kernel/src/shell.c create mode 100644 lab7/kernel/src/signal.c create mode 100644 lab7/kernel/src/stdio.c create mode 100644 lab7/kernel/src/string.c create mode 100644 lab7/kernel/src/syscall.c create mode 100644 lab7/kernel/src/syscall_fs.c create mode 100644 lab7/kernel/src/timer.c create mode 100644 lab7/kernel/src/uart1.c create mode 100644 lab7/kernel/src/vfs.c create mode 100644 lab7/kernel/src/vfs_dev_framebuffer.c create mode 100644 lab7/kernel/src/vfs_dev_uart.c create mode 100644 lab7/kernel/src/vfs_initramfs.c create mode 100644 lab7/kernel/src/vfs_tmpfs.c create mode 100644 lab7/send_img_to_bootloader.py diff --git a/lab6/kernel/src/sched.c b/lab6/kernel/src/sched.c index 1f38fad95..effebb8aa 100644 --- a/lab6/kernel/src/sched.c +++ b/lab6/kernel/src/sched.c @@ -198,7 +198,8 @@ int exec_thread() void exec_proc() { - lock(); + //lock(); + el1_interrupt_disable(); // daif 會在 eret 時更改。 char *data = c_execfile.data; unsigned int filesize = c_execfile.filesize; thread_t *t = curr_thread; @@ -252,8 +253,8 @@ void exec_wrapper() // uart_sendlinek("exec_handler : %x\n", exec_addr); // uart_sendlinek("curr_thread : %x\n", curr_thread); // uart_sendlinek(curr_thread->context.lr)); - asm("mov x8,514\n\t" - "svc 0\n\t"); + // asm("mov x8,514\n\t" + // "svc 0\n\t"); asm("blr x0\n\t" "mov x8,50\n\t" diff --git a/lab6/kernel/src/syscall.c b/lab6/kernel/src/syscall.c index cd750f6b1..6f9705f32 100644 --- a/lab6/kernel/src/syscall.c +++ b/lab6/kernel/src/syscall.c @@ -72,6 +72,7 @@ int exec(trapframe_t *tpf, const char *name, char *const argv[]) asm("tlbi vmalle1is\n\t" // invalidate all TLB entries "dsb ish\n\t" // ensure completion of TLB invalidatation "isb\n\t"); // clear pipeline + mmu_del_vma(curr_thread); memcpy(curr_thread->signal_handler, curr_thread->signal_handler, SIGNAL_MAX * 8); memcpy(curr_thread->data, new_data, curr_thread->datasize); diff --git a/lab7/bcm2710-rpi-3-b-plus.dtb b/lab7/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 0000000000000000000000000000000000000000..38395a23fc90767680815c7f43bbfb3a290c2af0 GIT binary patch literal 32761 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�D&OoC_~4g9tivONVZxf$G+%wkS(-3$L@6`g_7TDCjX zZ0wGe1kn#$y$N03GHt`At5nL~a;sv6?tVfLDtBzZfvLbSPPlEX)KP=ol3y$FuZ?K# zXq{r6RCi!U&_G1m5U=65R9h>Z>G;rAvqX;HRd$z~6%TKR)pAgjR>?KEc2EoOFI}HT z(Zk+nZg2C&R%k#PL<|DCfDac}0}-x51h)~K?qcnF74kM)Fxcu&T_b z;N~L)VOxvMMmg|KwHr9ZRqhdz%wl+uLlI??rK2!lgi~v-g%I6`f&Mc>*Fc1>5Jg9` z^17#s*d9?dyRD%lOrK+iLQh^iVS_5lE(U?YdK6{9i&rZx;GjZX*QY@bZ2zJ#%`RG- zkJK}Q(H=>QUv1*wgAN>)c8|B*&27)R8E*hT~6VH+RLhvRq~;)h{3J~sayp*djcq?x^z z*=bP$8ODfDCznO<1T0!-efE&~Xu4M?b4?Ws7QJ>Z)|qMrada*+YQ<9qvbpLa3nJ%q zqJM5wVdWq~YHPXb@qjovoJ|L>VpsV3h4W*g84}b?cxp=Ca`=_C$B&co(w^hZu*X+ysto}0S)*bX?FdxfaP>9TytA4wwD77_a_A9Hp#OVEWA!Fl_#JplwLCf-}ERJi*| MwhYsc7a#HeA5G>kdjJ3c literal 0 HcmV?d00001 diff --git a/lab7/config.txt b/lab7/config.txt new file mode 100644 index 000000000..e82fa85fa --- /dev/null +++ b/lab7/config.txt @@ -0,0 +1,3 @@ +kernel=bootloader.img +arm_64bit=1 +initramfs initramfs.cpio 0x8000000 \ No newline at end of file diff --git a/lab7/create_fs/FromTA/initramfs.cpio b/lab7/create_fs/FromTA/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..0676fb1584617bc4d73624b3b212a12133e97d8e GIT binary patch literal 247296 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 ../initramfs.cpio +cd .. diff --git a/lab7/create_fs/lab3_user_proc/linker.ld b/lab7/create_fs/lab3_user_proc/linker.ld new file mode 100644 index 000000000..faee5d7b1 --- /dev/null +++ b/lab7/create_fs/lab3_user_proc/linker.ld @@ -0,0 +1,5 @@ +SECTIONS +{ + . = 0x80000; + .text : { *(.text) } +} diff --git a/lab7/create_fs/lab3_user_proc/makefile b/lab7/create_fs/lab3_user_proc/makefile new file mode 100644 index 000000000..590bdf420 --- /dev/null +++ b/lab7/create_fs/lab3_user_proc/makefile @@ -0,0 +1,23 @@ +ARMGNU ?= aarch64-linux-gnu + +BUILD_DIR = build +#--------------------------------------------------------------------------------------- + +ASM_FILES = $(wildcard *.S) +OBJ_FILES += $(ASM_FILES:%.S=$(BUILD_DIR)/%_s.o) + +DEP_FILES = $(OBJ_FILES:%.o=%.d) +-include $(DEP_FILES) + +$(BUILD_DIR)/%_s.o: %.S + @mkdir -p $(@D) + $(ARMGNU)-gcc -c $< -o $@ + +user_proc.img: linker.ld $(OBJ_FILES) + $(ARMGNU)-ld -T linker.ld -o $(BUILD_DIR)/user_proc.elf $(OBJ_FILES) + $(ARMGNU)-objcopy $(BUILD_DIR)/user_proc.elf -O binary user_proc.img + +all: user_proc.img + +clean: + rm -rf $(BUILD_DIR) *.img diff --git a/lab7/create_fs/lab3_user_proc/user_proc.S b/lab7/create_fs/lab3_user_proc/user_proc.S new file mode 100644 index 000000000..2d9837651 --- /dev/null +++ b/lab7/create_fs/lab3_user_proc/user_proc.S @@ -0,0 +1,12 @@ +// Run `svc 0` 5 times; svc (el0 -> el1) system calls +.section ".text" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b diff --git a/lab7/create_fs/lab5_user_fork/fork_test.S b/lab7/create_fs/lab5_user_fork/fork_test.S new file mode 100644 index 000000000..463d19529 --- /dev/null +++ b/lab7/create_fs/lab5_user_fork/fork_test.S @@ -0,0 +1,28 @@ +void fork_test(){ + printf("\nFork Test, pid %d\n", get_pid()); + int cnt = 1; + int ret = 0; + if ((ret = fork()) == 0) { // child + long long cur_sp; + asm volatile("mov %0, sp" : "=r"(cur_sp)); + printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + ++cnt; + + if ((ret = fork()) != 0){ + asm volatile("mov %0, sp" : "=r"(cur_sp)); + printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + } + else{ + while (cnt < 5) { + asm volatile("mov %0, sp" : "=r"(cur_sp)); + printf("second child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + delay(1000000); + ++cnt; + } + } + exit(); + } + else { + printf("parent here, pid %d, child %d\n", get_pid(), ret); + } +} diff --git a/lab7/create_fs/lab5_user_fork/initramfs_providedbyTA.cpio b/lab7/create_fs/lab5_user_fork/initramfs_providedbyTA.cpio new file mode 100644 index 0000000000000000000000000000000000000000..0676fb1584617bc4d73624b3b212a12133e97d8e GIT binary patch literal 247296 zcmeFadu-%ccHdV$vsx`?ted%d@}clzbt z5cc+6pPsV&-rgJ2LnUEv@5=)(_YY1F=i|de```868~ICxdZN&ZPX2Xgj9Q*v@ATj> zu|wtQU3c_uO!f^W{2WeiGEc7e-JgB;)mPqpv-^#&d?}O3JbW(m`3Ls<%hiAITl+6& zo@Vy5fAnvj&wQuN!oRd||HbjAkN>00ub=y?$?xue@VEZy-hcRefAQ`2zWW!C|N5W& zMcX&u|MkpYO?~&>=Q6)Ydh-44=RWu6zwyyWYcIAv|401(a`k`sJMTZg`@e?re>n5O zvrpUa`RBg#xlHEs`#(JX!E>L;Jo%o*e=ajVy#ML^y`}lQ-GA%3&wu&bnatX==Reo6 z|NQ4W+A^8k3zqL&&t=|z#o{xW$19(toafJd=iDbUfAC@^^MAkc;YT4}bU*s}%pdIk zVCI95tZpBDA@lSzmj0R5$?|k$-un+$GnsRr&iu@atKWM*)3N`B$4{UA;P?kd=NB_Z ze>{`D(Hz5V;=GHd%ifzG{sOUpH7|GC9yGMV4aJpSa9 z|LwWVulO{dB7cwZZ8YHfnU#IcXhEZ+nD#T2_kW$UyuXt?d+}=K?ce{mAFYj_d%V&X z(iO{qSKi%+-}r~&-3h~I&s$v#AHyMFy8nFsx)}citn=|t_Ve-Qc(B>Sl<~~!a|JCrE1; z8SlwEfsS22Gk)QV{O3$=NmG1>e=oel$Dc8J7fgPxWS;J2ere@#=G*V=cUoI9?7%gI zH!OT?_k$MhS(wc{eXO*%@@XdX;cPx_E}wQe^R(?;zTDM(nvHz;(CF^k@72uHZ>zj7 zQMS?eaz1>^(tg73-_1OIUunLcfA)=h_${MBo}W*`P>25{PvaN!;eTdf=5Ma-|FY5h z)g&&Y`}KSoe>)%khCTmH`~6*ehbHeP7vBMczUMQ)0*>$7yWD@*WcRVP3$A}Tk>gDM zI`dxUv(VTd9Dln1uPn@3_~#b>riFiM;m=$6#}-;XlcA3Nx03f4+Q7Fz`Q#T&jz9V* znWz6L@AR$l5B6U*o$^n{jdyD!ZJ&E$@AK(P-^^IkvisiTzKwfp@5XCKh~N9%lQwHF z`@6jVV!CI4K5jT=a_7EzZgu}pT{-!3zxS`kpN`vebcUt-H2gh#HEDbB@zHlPPahdy zAN{k;(>eItP2@iFA7}1C|J;vfJ{RIl_K>>}|IJT)E@SalUI(H5K5JzSA4vD+j~DZQ z%IAOXVE!-V^ZRsP{IO#GA9DGP-U0ew&gcITYcGb;{vRjr@UgW;<1JtubkD1%Z$^G( zb^l9Nm+ij}CLPbdY}c7{!sY3{;gg{p!)O1W*?U5d8a~gscJJ(#>4u;Gf6(8>_ZZ%p zy$35d7h}Eu-F#Vw`7^HFd!(#C{>zWn9{BHx~^V=3j8~HDTPP2OMed@^{T6sThvQkLf_QN6V zf0a*r&h-CPbo7hoo<4i=c2dvrAAYiFbYA!Q9w+&JC7%M zl6stboaFr%`MfVFZ*S(w50JO>+|!rP%bmBMwp;!-&)@qAe~Wqkz{l$HOXtRa{7IYT z`S&gT=Y9IjXF`3(^XYFJt?`MWKicmx{(20DZ$9_Af<9^c%#(j(?~#5c;IsFcCp!f> z`EFiL{y~tF{}%ap(d5wVg^>3B&pi3(miDV3ee|mz1sP1zfyqmT+20HDWPRwjtWAE) z`l`On+k3`4*UuTfapV2NZzOishu`?UKx6+$O($N-JjJ%!|54MCFIspm^Gg|{WqRiW z>;;qiKmWGrWb2DR_;KoO^i4l~mh|VaAuL2kVJl?N-MTmWkHI~E|0BkGxTbG4y8Bng zpIYB~5BkXZZL^Kw(QLJl&fkXy zNvEB}j?am}zaJVM=rd|I7I^FQ;> z?Ar8Lj`#oVA9%d-`<6b~qh{;1ed_%m+c(U>kMtSC_#>mi^Y2+4cHg-5V{Pa{UqZKa{U}qgVGn`(*!f;AhwG+qJ#tfWa-Jl`r3(eKzx7KYoCXoH0DHfv$pu_3x&8 zL;puz+Adl>2Q8oV|ImM*dRjT5-CEi<`d9jDOZ!sW`#*L*l$GyyEk5Ko{`POVdgbwM zLoUDY_-W=}|BdfH`+1X(*Z2P4{lUkS8EpF3sCS+p_~RNL{>A@S9J3VV^1n;klF7}p zp3Dc|yOH_ej|Vd!{7E+R!9Ty1`QZPU%zW^tv)1R&nk_VGWlcU8FbW~Q2T%mG|&s18!doIXt>a+cGp{>7Y;XnTOGHWmX<8yECy^w^9-0z)x z``gc3_)C`VlbN-zSpA+Eru&}@`sMAvYqZaG*?aicf8#%YX7cmb?D_e&%xAu5czn;& z?HcyK9i^eJ-!t9P_RaBM9#7ue)9+21PBHs+)86012GV%RXxuUy6OE!Vo7CgatWRlA zqcKtiRxV8nR;GXRdhbeJ@7X=F@ZZosT3nC|!=3TYr;G>5&fl`<1v#_y{{`vOWYh9K z`#+O$_J`m2N68p*GV=$YG97&`lleo_Z{G>yKpSIOy9nc9jm50L{NSojmzQ~sxqQ00 zD$~7QDV_243;wx{_x3$s_T1Xt)4!8XgI!m`^R3JuA){diAw;-+h6HH`@;UyZg=? zUwyCbJ#vtu?JJh{l`p;4{laTM^V+K^>8CBa%}qmfzwlFUd@&_m+v@9YeZ9?|wY~L| zZLfaqop)X{GI?IQU--$l-uZG$rWuQFd!_Bw*WY;ai%M*~y<$1veC21~ZF}YG2HIC% zYy0UpzWCZ(-7f@i9vY2DC1vHnEKjQKCw>+tx?gzrjW2!ml{a_eEGcQ*zW&C0ueT-X zuipORPrvfjS6};Ld-n_Py!NFx-hJ=2cS>lrwXKBceEPQ6U-{}6-+b*IpYOGwdE>n( z4{zb#*WP%qJ9%%$V7RzzXua|7&9+Nlw3#yd$15OoaC4ghJ;KQZC-4thphP^CBy@G= zHlrGZ8~fj@ufO&x1x+Ter$Bh=t@rFL{PZilg;(GD%2%vTLGqSW^8d#}9nURQXz zp54p~)`uYb3hlXGIiC4e)+D|62KK}N^nTkJvl=cZR?j z0^b)1v`-%I@8by4@ervk_i4p1u4U)sd~W3G`Fqm~+2MuG+~S?C?AFrA^3HPC_DlNR zz1Dk4KjL`KFW0%dve0>Jc50!sk20=bI{#8!zV1&8UgDRqf4#eJc47B6b>Hmio!Q#G zyHu~=M)%&t%C*I7U^qHAu--8_JS*C*j+OX?XYi>vHkB}59O=0)`h=~Dm3Zvy-|6E$ zSE^H^o*}n`mnR0rORHfezJ@NZjNae5JK885swo#4rX7l>R>4aA^sL?4UfUTNKCCX( z13kX-X#0Alw5vN^{pj*aY05qGZSbUV5t#v2ofKB0uW>qkrrw`H&aYFAnL;NJHBAS-E@UQ}#mN{q^pdo4Ju& zb1OUIvDsLO?&#pk{7n05sPph__te+}7N?NcI4us$t%9t7mA#Kh-#}*ZhX33Q3-Rl~>yZ-3zCF;;~@%Gl- z&5bdhAv59;8A;Qtq$7{o?n1}%;GOKPiMu16cla%3muGShJ4b2Pq`5ZLzAUji8E>I??7*X`Y_H<86^f5G(erT(6UHB*j z6P}?9Btz&*bkj-Lo8r4;rsrY-AIa17(i+d{uaE`$G^Hoxz8d*Lr`_IM*&4q(wmv!B zu?s%PCVe91+??OMB779eHbuwNkCf|Y)82g};#BXB>5i!qoMu;T{%1Hx|NLloXcW0o zyFreqD{ZM7c`BD?vORkl`q_oW17jZ9n#hu{qmQ9aVXQz~ByS@yDOV=+jBc)T?#gZf ztC`&_@wAU}^^D`ekv55qguRL!#%cWhjr&W%j=Ysy+Y}ZG)yI|_kINn|SEokAg9m?| zrjLXZ?T|R+#@DUfHL~T$WaOnT<A5QmZ!%;o1m}qY5XDqYjg;QdBld+5h1$rE~=wCJXZ?eSn|(#D9B?m=dR zOB^!xJ~^C>$9%unF*Df%AM{U^u<_66`&57OVsrWDx@Mdc>NwTDgKnC=b2Z?Bo>tun z<8hzI%BL;YP8t<29y@0*-0Gyivw9E*R@K_#JG*nYkt;CLxKDN_Wnc?nk5R7L+`^ry zP3Dhp&d!86r)yLFK^`m3k;)FGoJQeMu3X{NZu1$T@0-mowCCr5LcInq_tO6{ew95< z-O=Iv7>A(GXsg%`*q39QmzP!VLituV{zh+ZPmE>za*P9pHqPHBj&)DwGHH8h;~6hg z%0s?#b!t?6QUlswwlnGbE!|s8&KQrhdvrc?FS12celx?8I!rC~q1&a`!9;T}@MI&tFa{(Kw!3Tt`gF<8 z`q=o8_~%;XcTBBkkt^;i>7p1X=_cflITw{D8qEwvyIjba<3Uf~G;1@YVJ!h!;pgWX z8MBJ-o!-9tvU`$olG*>(Ul{f|@b~KlF*g2Qb1u9W+4P=I(Q8I1x{R;*$^LCO`SQA5 zI-2=2;iU0AHY4*|;6pp*UgdU_*tF}xwr0MhoL$MB7@9}jV1H*H>4@I7Piv8xQgA*k8Acl zkUr*D_st4bFU=!rEFn8I(eGDwy?%*tQW=EU_not|%Y}X+KX()E!`wuYTJ(H7Lw=Y? zq<_RNMXs3JQ~AxpB#n-E5Z|<$P+zmteO*0H=u~WIKUajVLXTl1`Fy3<7ec$Ee00CZ zh--~!cn(&`)KEun7%vc)#(%TopwAz21h4el+?Uu2VI0^I*6@@*4%t_rx%YBd^<3H5 z^!eydJyzJA{yDP5xKQgHJZly%F&*(Gp0)Pq=U#$LFi({q-zX0uc8%-;@>2dz@3@V# zlezbju+Z+3^__TqU3P#kKkYiMLo@EhhxDr2QmT&0+n}Ehbdf7BPn09x;!rf26?*zwTa#?iMh?_9-(Sf_04L@(8S8m_xm2F8ow5rF zHuI~{#OBvpnEF|8(i|{pnuWn(bUa2}qle*D^(~njmOL2p zlBfLsiZCyeqOWbPG-WP=9kFH6tKRU|hikYu6%$Ng6OUFEKC2Wu*a2#D< zy^-{T)z{hcsq1>;P)%8)>&N(MI8+k{2D6thKk`5DJJ637Y|rX!0rBX=YU)IY!trZ-F2QWuQS>MuGA<+usq%yWx8g_m^ z=}~y8S03?SE@ZsQxS6>s*1VYmrvA(sv(~BgQQ}yiiE*Lao3rP~HSXp9z`S6Zel#p& zIjUEkk6Ml}V*eQDm~>ySPY@ zvRkFzweXQv55?6|PFh-(_TwLa9MJTR^?rlHQW#%ra`&_PPn*Cf$+uIk|-@+a^_T}8)SsX2QPG#lJ zc>DPLl?#-oy?847v|%N_32k0(mHAq*@cRP&p3|dT3(vLg-u|)8g-4!dtK;Q)WeqKt z-Cfz(t*T@$ERI;9ZtFA;RkQxvzb_lrk!;j*tmB066>(U(Jxoq=BQ^iI3a74eS7}K z0Y6V*;M+NN2Yy|&H-&x#I<#HwU7@UIVI`d87liY?iesHS?OmtErQw83VqakwA!llL z*rmt|xG01sd-!FKsU5Som}d*wY{A!Iz$)*rQ@l1BFVR`*%uRC+#h)eQ8e6hl8>HVt zMyS91pfDz(e?niY>}o@Fk#O?5oBXlfgLa&zkyxn?w0r!{agWR=a-Te9EFu|#---EL zm-=euPYe6|*Sl!PtQp&x^LEa<-0kXIM0Qzkr=1hh=E)D%dMD6OnT%;fUm@whiZ-lt zgpI<=)8LwS^k}blZDZ$d;rupo4u3k2pgco%mT-2Vvzs$f_AC)UQ$nT@Q@oo5=U0j=B{}ucB#6NliorBK8cS<$& zKQv9x=JcNZz#Te^i#Gy&c%V%YN8d)f=Nj7BojmvBWYwk7Aw19r%a>7MkJ{{ou+oja<7p&y9yY%MIun=Q3!Xo-%X8{O+d+nCEA;im$wn>6l<6G#H=^HX4`Jb1 zN}Hq{%155ocl*|aiF8!(kCC6#k*^Tad;Xhso#13=4O0A!$|k1HmFlZ!;HdHl(f^g? zO*r8PYHj!8J!~UniGGd!u#};33mD3#Z5B43PN81rH>E^JnVyn=0JRh0Q7%MpQC{Eb z{OZW$eDDcIJ1duda{gAZ0mibu^WYS>E%7G%L}Mi4eI1&0Eq-hdvhy{1C5-p*Q(LZ{ zaXgp^r(2g2-+r zCy@qQo%V}f6Fz!Bw7b=%%@xh5l$-Noe4sqdlA)N6=!f%|`MvD2H+ipqoJQZpc!eJ_ z(GpQ(JqxK^Iw#=&Gr1K zAy{Jca=jZzSo!im`_uv$FP!9LYzf`A_WN9EP382yK+QYi`Bk;;*I8TS=yZ-!JDsx`3hK zKp%umff1Nde?ND|SciFtnFrYcje7{?hd!}4nA=UxuS1LSHBRx^=$d&$(qKbjQx(fP z8M*R!Fh?!9D#V+t=^C41sq4ml&C7rb&zOe+Cw`ifQJxO-qas|m4mMlf_NP4xmpDWo zRYqFqWxN^J;-R2ttbJgsC-L*EiJ#UU^P7^$fYKu`YE$%O!bvuCIByvAp80As|0Cop z=)wHB+mBOXoVaIxUG#j|3|wLwqK^%O|5V+FFz79J7I=1Y37OEmp3-7x3#a~p%i-H2 zot8HEG0I~^T5p4(uZW9n0>;N0BYRsS=DXSVs;lM@!K=_ep?mYTRcV;_<&?(&T?JPB z=*K9t#J-@Ms87}NxX+vFT6}~*x;xi4SHX}zS3EWw8&3}&;Klbn8o!tI*Hf@dlkZNb z9&t#yqgQ*nrSnR#&g&?~aK6pW-s!@};RaZN+0Eg#lD6l0Z^pH+6TH#~OQtklD78Ud z`;&~BUk2$d^qaQ}urs%Id#9LVrmiIzkw1?U_O{0%lB-%!so<3RA@+Vk5Cd_=?3 z_1Bu`ATDh_??8R?IvLpk8($V{me6BvAkHWMlB7p|g_R$t__F-9>d=hP)AiTLl*Z|$ zK1NgI3Ar$RO@45)U+4$0({+tJQJ*4C*8klOG5wlv*0=5v#4i61dxgB>7zNpl#_ zC-Gc3VG}V=&3)WQ9l*%x8TvWtC+1f|{`|NHds=n?@yzS3^-Xl~6Wz4%BygyPrg)Xj z>Fu3Vj0`7@*RUCtk2wLART7$gFn6)zCGR^6%t%uWf31|p*Q=bLFpru1EfjTl@~sne z5d9_nA=i_a2QRMmF$eQz^IdzBw2`!WR}%*|>`S98)t|B%D~p~Fm4?vAbM2p<^fml2 z@20f__`$y%`xH~>Nt_Hbn*KkuMqUe|1O&Cv)KrPsYe#kWEz zp7=%>^@{7tJ-P)Q9QK|V9^A+2R2SmeOX$Bj294snJ9F`-1H<0FWGo{d;!tI_O6d7x zT*4S`dZDL}wnF~|eys1IhnW{h<_3D#kU_4ACrvUAPUZ>n2P7GRj$P&bv5maCjH+2TKR5fdXEu% zlAD2##}|5j&Agd)ua=fDqF+MSdj5}djc!MmRa*w@dU4-aZ5qT zCw5jtxC7RXF8-ePPhQTr`uO;I=4LMV-lAMR!w$v9m|E!UlMRMm z3cRqF&c3D2HF=ds`~5>2dnW#y6^br$F1fE(wq#RRYE!fwXwc_lhhwLTCZS}8GJHJv z%kL9dfoq(%*%%f1!?%O^gyQUg>0tOHq^`Qx`z6$#E-!z`2X-TN7i~`17ilEl162Qy z4697ike)I;_Q<-=uj@wRBs$o@$iCjWt>Z80?2`ID`KiF3;+;}2+6|#_q73w{x2Z(~ znY%r=vWc&(^+$Iv%3lj{q>=v=u#%rZt-`zbqs^qr#ZlsrvB~-DMQCL^ z<_c$BX@kV^-q3OO4dHMu2)jV^E4YL(WdX_o6<>}OZKdd zW&0NNj+v(Iat({9mAU{+2~dki_#IXb((Ff=eRh;AdV^ba zQ{%m6;3FEsW_sa9|NW(*L4IJwZ)mt@gXf$D<6O7w7wJ~|G3EDRn*Tcb{=@K-KRa+* zUh2CqoP62X8Ip6=p;;k(nBS8}qPMlXwgIo~hveD7(BQ)D#lBtX3*mHkr1Q@9^2K3v z4DE>fSf0@JYRjrGc2XK<9;e*3#Z7dP@+hS375q#XZ{oQbAw1CUjy>!fyfHk~o}3>j zo>9UN+U%pQ2j~gL4bm6rCf}CQu615|U~+4f-?h9BMu*4gJx-A^sfBAW7|_3-sQ^!H&>9Y-u|7?$FQy>TbO#qb&c<}SNG1PnWeq0)t;&Ko8b&~ z8cygac!3`Bt2qI5f@GOc^9Uz}6WAb2MSna(uo&vy5`*47%#H*P_2Xb9d7`}vQ~5hY zuT$=D``|-ln7MfF!Nud`=lb-nn-LaJ$otHc4;aN`V@kg0YyA5}_h@{kddDGp-H+>$ zL-0j+(N78w(L;vis}ozzW2EboT3-;4$(cI*?U?V(@XMb?luss`1Cfnf$YXW^cp+cZ z8yx(P_C!2B?dc;)>&K2<)3)eKR3;(zws48Vlh#okQxn$qO3&vedfnQiJ%fMjV%3Mb z#PXnLhlTVVl*L(>Vwv-+*dgSljmP-tp0?N5zf-W`o6+t>L-h(+AxrKoSfaNk!#sib zLk>2_Hpj?MUAe~o^7D+ynEE`w=&wP}g6LL;2=8L+^X7*{pM}EbKr;bI8h_SO{ z`S+u~1Z-vB3Lor+U>Dn%Cd_G??dj>n{50y`(>!>6@a!AD)W8M%554iAr_X%T?(Knr z{H#%qFe2o>sH4JnYy$or(>vzNk8|w!txMW@EK}f3e%d=@npm$j3YWNCVZ;0hdV}!; z^OODzA!{JPUeC7=~V`!KFcBkx5w zevj}-9M4OAWSQRQj6VLu!dNFcW2kZn(b=;d*#WSk%@m(8&i3cSwzg^8K{w|6SmrT3 zPH}&$vKom=TG^tD9`O8et$rzKALY*CV^`qM@WL&P5h;`P6563}i^PNB=+(|^u}=}O zl0K(@W4=Ojg<1n7e_9=y5eIE_N8ru)limR**)6i&!+VeV#nL$XuHuOxXs=Gqjo8EY)R2E*p(aTz-*q=@or3ycT_~9kfGz z9ZRmwCZaTCNjNcfVNRZS=G{tgGX0Ib+LN%xf{g@iwfR!clDoJbCvmSjvc{{qX+H;3 zf=Mh(+nhH;{{?*bJuSv+ax+>`H_*ot&Uq%t9q#Wkp*ZbB7<#+8g`|ktOP*)qP)P~dQ zec!$k|H;Lsp`tE4yHZd=V!8XcDxl<*!xJ9a)|t8L9?X&B;TvRq9_YAIaOze;45h zb*~1WLYlk}<;IJSRl zt*crL4ok;-U_X&)Rx9(Zk`BJv^T+&@_fIGO@KeXw9_;42HYdPOYx2~c{Y}I(?)5m! zM;rSacn6e6`KK8t@lMEhl9+d4+|S+v#`S6V3CC(f=A|f8w5rY5O6kPA#xc70A#>#H zH)H*XH7otGcD4HG?ltC+nF9b@LiQ6dH_W;KbDzE}u3M@8)$*b`u$M>sbQM?6khvG_ z0;kFAtW zylWjUjW?x9#&l`^rJ37J=HrxKc?j8)_;JBW^-?|KP|uU~rsDWlc0rm%w)6kH1&iWbcBl!MktiCF=}{OetNZ(3jil*X8O_iEp1Lv_qShD#%pfTXDrylvTVd zUR9#eiqDFi7q1TEvzRh}Wpi0!ADYcU_-87|$LU(nPD?1h71qMH@{|izR{UJ?-_M~i z`F_UWtnOzBoFQ%&d!m6C=7dkC|$D|gtl#GW_y zZY*S%?{F4vK6hi<_MhD58EGu-fjtB&v-N6QJ4dRELiR6#0cXzm)+l?Gs`-)DzOg&N zx0`M2c(;A8<$}s2tevyg$l>e2HQ(I4_o(zNQ#JUMO9O7x4{n5S$9r0>QTyt+@O<0+ z^$v32eS?&%`%&VNOTO(an$>Z5@~Olx^0PE@t7I?tQE;d>PuiYd@pAI06gd!2gzRg( z-#vb_+B()F9qlmfoQ(J?a(Z%C;)QT>Yquu-Tn~&?20o?aiw0i6O=tAEKRJX-=Md@7 z#dAGFbP)BoJ*tlmE0_LI?~OBg{=OA(qOU)!4r$NPVTbjD*iqCS+bXRLA16Nm!iv5B z;HCSMz)G}PYqIs)%gFsyv`tyuXw)P&QcjxJSQzS zJ=gp-8!OR`L-3+Laed?ap|hrN{0@ z@De@tc_Y`zgyIORl_~9wS9s55<^YhF#m=6w zjnU1^JG*nYJudO}_U_f2&;w6&6Etb7yhDD9Lx*|(8jTUg?6VtZGCj^ z0(u#lkX+%5rGg zZ$(#PKMAw(&dp8V?$pUe_iB5zH_;T&3RRazhN6Y+ z>zel^c_$7X9{e5N8ZWF5pvQQ2CpS3-9>|s24%m4ciGC29L**0lZDwInE~M@09Ux1L z>3kWwZX`Y`8(OqE>ZQ7PUtK&$Hz7~FPxXiBd7f2MU(%3v^!`jou7AmVg;mZ6uHd6K zOdp3`Cz|BfpX$-*5PIyX<(-!Ehly@Nrbw?umB50;Y$#iQ$0FUE3Q$3AcA2e82= zhZ7&aN>4bQ>%5Om;O7U3Z!|V4U%c?{sFQ49;x*61JMFnNFs!t~iT;N;`fu8-*G0m| zhv1^V0=+Mvo6yD|o60W@hjZDRUDxIxjc=*nkljl<)uYj&ctW30C+Py>{TV^-H3vW_ zTSm46&uJU@D?~@rzoV=4qumi-9*@LF4Yr2*jljcH`_@>t*L;Lb23?5Gq}}t3zeeMu z@I>l$)BFm;TMf-#w_rQoy`4ucVGYR_|)dM0lKkscZ7RvRn>=f zhRmuQ+Ai2+uS|sV9@L+F!W#b>9d_p0Mt4D%F-NEV1G*YpQeLAmqI~g9{~}#7do$a| zyiWJv!!3L{(Ef@(>X5MnE9@ER4CXhm1LLz~)Ezm1j>aaOgQA|C7n5Dhz1pz%1Jp4+ z7W|G%j=+c?eTd#?Gq6g-N$=-&ZY|v(kNK|9dydEKv`^~1a%ZX?Uq#3m*P=s+41$rz zNzds!!u)sekC410p7B0}5g|5$#tF(xDBkNGiiX-9GDY2>lN&AdF{EH3c&?}*xhVumn&#cf!h0}rhayG%vZxqhHSb0!jd?0yB=2i}V z*Hd+BM5tOaJ}=_L99#0QY}+%;I7dhR1Ru_+96Se=$OQiV=o4mw{L$|tV_uffVa(g4 zl>rTOk#Hhx_8O;f!p`wHsqJm|_CDyjx_I#HeZgiJUQY7^k|u}p4JMjCM2A5On=;O; zbd15VH&>SC?3-o9b#%ScMuy^nvAxGBxlSlEmlE?Xdx0~V@w0OG@_UG`kJ}qM3u<6c zn*U1p_6K>EyL<0577srgYpUO+4voY}WeY2B8zeX-dWv*QkMiz9P`bGe1s?-+R-`A>YNkNb;Q zA@?^nX6-v0iTxD({l>bz!oBnvdvZ*kg05mdN@DTVVCvB-O*77psWlc7t-@AkiGiIVp>@N5Ta*N(~e*CcQwI(HA#d|YD(I%wt zVeO5%5as}=3u6v%Q>OJx9+R|d&LUEN+8QqL_-Lgcl)Q>3#y*UbWY;$nmvXek+hJkB zzNyg8Vyp@{nO#8nvb)o1rQ58eEyw#w#HaIKj6IS(<@e)AE)si^Hj5v>#KvMw$xm~h zMT)J3&tdOGd?#b%>hzN2D#(w?1AmDxgM)S{{n&E<*gSsM`fkhzU4Ix)t@!*nILYUB zu(?c63qOUEmj|!Nhacg@jbhttMJy`uB%G?X!G%FJq2x$d<<pzuvYQ<+ooDRxE zHCR+iLtDOeIoFF^=_h)vh(#ry#5e07vd=5k{dmuU-<2@OSBa-qd?uVU2gg_fKViqi zqkMm$aU^tG5sz{_2`AR$P9o-wP+k{C+NCkN6q){&}s}zPwuVwtD)H zbKP1U`!oK|5I95N41qHQnuCDv>#DhK4p%2jr5YS+O>?p}sxS4p?##~(&P)vQ{RsA9 z@(l^*IGLy8$2I$@_2c=>&Drejts9rq=Ar7#?a7oTjKGF-df}TI%Oi*S%kcXw<7@kl z`2tvKU%6)oXhNzZkw=jku;Ainb3MRo|nO>-n-h+mD)wkH=iT5XWLq6dRY@a_K_zXa4!t$bBRSx)o!`3SKX^EC*iDp5`Mr$=cKjn2LIx@Qb;{0 z3wcaShdh80&qXs1)xYtcBvaB$@IhN;Ea~%AThHUBgC=7U@um02Sr%Kt4t^fIAFVVD zh@*{C7JGfTCl9#OXK}7UxfLUc5x2e z$Oj+dNwVt8RbN@`` zfF0kVTeJA~(Yzon>w!TMACptdFuL3y8hl-vJ zUg?>-W3K*%q55WIg)>#WfA7yImXAvJ;7L0}Z;Rfe-J#Ky?bVt zkBULH`8+MInQsIOjn%bxr*Ck!*W;xAN`6Nw;ZW%rI;zv?#((H`ug~E}y3ePrwx0D$ zC))A_CwbAFS&WlxWcjhFghi!i$W3;3qA;_J&bIG~Ga)nnKZl#d<8PqgZZK{aKG zE}`sjbSm#pdT6+P@S*STD&aJ?d3kwz`Qk9xAXn&U^?>w$=d{6!TxYhjH z^`f6?lh_4dBON3<=t|}bq#tcRbr)E5nm;zBsW%4IlqcH4NxGbPZ`U!dBaQSaeh=v9 z_@TRLd*~zCo}BH+2IU^Tgq$Qk>vET4yIMRDdK;X%7ypdwYUFq&f|AF@Zk$Xpw8Mjs$~EMQ>im}>!Z+4$27HwHK(Bwr%ho3H)&;Ntm_T?fr- z>ePrd&}RNgd?8Ef>%v}e^EJ?OWn-(|-Z^P$3wjPNF;CJf=pxdCjeKMYLomD1KNHGB zjtcwojh5!T;x!-HDJOvyH2H&Xa6-mu6U22+FKv|gz`)N}-fx5QQP=xReFOMB6ka>M zQ`>$H#N)(RR(T17zpco>hI}DOAL{*Kt9Tg|y=H{snRf+W$^CH7`yVX6Ydh0BJGrDh zafqG)6^(-U~DmziX7IF{iLX*7Y7$PP1@=Zt?va zzvjoX1RM9hr9beemiW8Gf28?V3vyOGqoFz|JctwT0^d-H{|nN2e?anw#9k?3#QFqw zo!Y$0ZZuA!BVEe(T9B7=7=erOq+@wyH}RQbWmwt-(*!$Y3|W$X(zjs(KEXd( z=DUpa=yQz$xNjsbaoL_&%8x-*24P$dI%&3l=h1rK`hZWT>sG>|953S4eDEExseJpYc#Un2 zfBf*9?1|GZUrK!V;d@Q=6qe(w)#Al(@WWSaTdOhM+NJZO@=vF=hE~JjFn)?SIo}O6 z;tA84LANQ7y<>LAu<^Ht#5))44$H#TX%FRi%lDt&n zrGSym^O6pmnf3G8?ahgS;mtDh3dhBbdEex(5^t^cOgyv3!uZ1T2X3s>f?GZ1jlLDS zo>r@03nxNsYWCcvVMaZ`k@1elk9h!m`sp{{wKvI+c<^Pu1gw!${j|UQG-D;)7_Tw5 z05iXaQ0cwz^!DBNzqGVGXTAbD&`3+us&T?bq2GU^IK~=`W%;r1h52^Y;J9bJpEh1( z92e$;^Ly-z;~JHETH9W-mz=fl(tQI(AJ4@a9_@;6<+1-oYk!o|it^)YC;k+dtRvVu ziOsXIhevx+!rD@P&HE_zQu&0)DtlnGkM$_!iSI^+o@enG;%t16-KcpxFw%Tg5?5T4 zIx2sn&HfeSRrg0NuaWu0TO2Yknb_CZH%U9w_auGV1Uh4aF%uE{%HS7e78s z{L$zAVmiNkK25#p)4qNAx~>vB9+if;tZF}+66IBJS-n^2;d)VXk;Ko3_U%6U5 z4okP#)fs$hh+gw*csxqtmykW-^^%`Tc$GV^1rNuoO=EIE2y4U&)xoY)! z6;KyOe4B?e0JYY$9_jCn_HzC#oNZ)n0{;r)t1*&MTdCrOJ?`{N^{8`P27O{R{UYsL z`wyp0FN(L?YE=K!;^T(-5^0pK=3Fi1^W!?kFus?*0wHvC*~t*LbN?y z$&mbS@l5HOjS=H7WJo+EYfs6VW-WS3IDvyONeh(@9VPit-4)W`kyqzzNvHc}ej`u( zpc~cqz#H*=J6h)^YH5GcC6pQCLmR^`V$VUmmwa?~eSx#;oYm*N0z5Eo6kj^4%ovg~ zc(3B0u#s{lI(l!^3%%tIZQ3O?B!A-BhmFLDvY~}-Lfw3QdGE#Zokd=iM*S6gRAgU~hc=7uh;^Lm z#NL60g^gi+`oz9@Vx08NM%tHTO1@cDUZe35M$nUPgcsyl{SWdjeun1D)@pn?=zlL5Y0wlrm_i{JENbG z-wWOun4w>lu7BuCiGMoy)iZ_23j2M~E%?Ex)dv(9A!A@mnfTTKU#^i`$vh#pgXk)3 z1WsO_M28T&4|&4IOev-gAzK$`(G@x&gC**jei)b0q$2TrQ%aYDZ* zjB<64eA55Xw!=F#yBvM!^`Gj|j8Irf4|7lZL$1R)e>uTF8IAFZK152M%C@&ca^j-uLyS zL4RR;OLllq{5(It4$Zh0?Rfk|Jbkgodb0JvNjjeT&kS#LP+#;2{S~qT2FM0DqPM_8 zbjpXek2vpBLbOCX&eIHBVjAKBd1C#EHU*#9PuL35Q+}=lT`#?({I!Pk1t&!y;jnB%+FcM1Il&WgugN2ai= zRd>c}UiTE_WooHUzRU2#Mtbl=o*5^=lh+5$!p74PPMRyAzLFu@LE>W|;hlMH%}0@5 z=~fIUmC5-j$q4OHI5EGCzbxzxU*~|Ko#XW9WaV!Jdq8|aSGTA6Y z_4FEjEnewcROj}oiSBgYMaDaABCl(eS0U%eXm`AKWNOpAt*Rd*6h?$`@yqi=pxk#neaH7ALw~#BQx^N8F&fpeD!{TcHZ|C?NqvxK1Ag<8z<;NoAZ?5 zw{dG|sb_QTQh{IjEYNvyWKMA*#5bM!BLYKki)4=XfV{C*Nt=^i3)mnPmOk;{68Uq> z`yD~wF;9TqM%z=HhSz5NEAVN&^1hiP&^cD-dSfiq4yy7=V|COyG*2hKp0jzu)OP~@ z75q?APBSoqM$9w!^xN1?Jiq;LEi0_RCZur&0N`gi&~*$B)hK}Yi?4|@8h?OcB0ofO;a z@N)L%T;J%;?J&;(uj0GeA++INb4H9?i7Vg~bm@FpBTBayD*3?R{O533vs9nTTnXc4 z=wP!$3!Lc3!neQjwg5aaS8*%1wu!$(>Bf`73cCDhy-j0#?D7Xao12Wgc#d3DBR@V3 z{U3Rm8isiPqPc1=4(8R zi|{ENY_Ft0WekN)sWFuJYt>NrgfQ3wrLuB3Rz=@CDyw*Iy|k>JD-SpCOwZ)5<>xV( zmyrCmDn8;%bwht@&f{=wO6#B4=j#u_C(JJ)Ly_Gua(Q>ieE1FGdu`-K;&a2>58|g) zL*YbSc}X!PAD5Fk=j+ITzXh_NN~s9|@C4 zpHl|?o@lmeTZ1q081}J-`MB_{hcISgEXMkX$BS_?cvYI$s})1pT&;qWFi}{7la28U z^~=vGDjnl~=8TvF_n7VUj&Jir)|e-`b7%A3bXVUf^8mHrs5J!WwE|YEx56S$_T3F{ z=eW5t_Ae{FLUb7G2*?`PX`U~xWAO23@`sMYmmhK{|9)J9De?5LDmyOYB<{sa947W) zWG{v}aNGN9YrCv@$9dv=#vb&QVQ;L>kuo2EtW{gjR$`PWVLv#R+K(zAA1jXfBb zUCTZ5QtT;Ho|D7~+TtS#(M!>Khv}(c`?>WK_ELhC@*bxSDkBb=e`XJq+F#7;acI_( zH|DEw4<5{ggr8lT{G|QyuKhj%rKyF7a%oi-G_)^MaXu`Uzh3d4RxQ_}uRQTt9^#ee zxS?pIy$d}%E{$sPiEAtG2GX%~MI78qJf$uj2;y(K*_a9fxDq+E#6MONQ7txRV_?&;aGEOsQ zz?wvj25&TQKx#BDUA9D2EsX@ zddkjWn9`0#--q?C<8jLqZ>*u9PY$bBBc9v*dEs2E_)&P=`qe8x{GcZq)yCGl?~dKQ zmiQ|whcUW7;9}oG5k6{<+}EqFM=eJ@>5O2xdK@Qy{OWG-qos4m<;tQj4L+#y-xOwD z)z)VU>tRQ&V?FW-r^D)yRySmzxBvW0^o4296(?U{=2N2NoWGtcMCQbg&X%DEPI`}> zcp@A&7jf+Mtwn#UUf2z)Yg$OT(BQm-e~xY7=@ooT*xqQbCr@(ErpL%%U!U%{P_1lH zN8UAhL}%qZ4!TbE58E1`$rE|_K?AzTn$oF_%|9G0@dK-P($}L6)lvpDS=Z3nZr07^ za}B*9-VY0vA6XzRJ`lLRcZbb#J@>(Ze$>AUuC@M)P7)2B(}>>_{3w4dbv$lb(VV*3 z*{AOq+S;#uPrGM|XLf8boXr*gX(93h7PMFLAcrcqT!`!q&fFXrzPz55KRWDLwLR=} z^3qN{P4u72JZ{}<$uFAdVcJ5tx3$iW>6viW0{p}$wgUI`?ZmNnnfn80>8yUNcqitIqj1(m{MS+ zdgj}mWS%ymHl}pc^X^E`9dOv*y?Qgo;jsI)(azxS7!1Gyxf1@oAMm5?qSL`JUjMAM z?zN;>9pgS4*-{%CdpI;G4B=II2x&LS$x(3exN-i7a#XftN;X8APE%TiwbZ+sv?^C2 z=j?sI3nskF#QvRM&W(-~WKDfF_B!XnbiT^hxt43%A2JBu;)jsA7I>f^kbhhM++SBy z=cAKl=v#m>$#%0>6kA0of#qIfRv zD0Mz=9&qygvD#M0)I`^Kr@3d2{2a=57#f%uR9{Aa#&2#Rd;Pe&3LL=;zObugNBMVq z+&Uj6zv$DKATR3E`Zhc7a)xqsX|3R2l;;|EC|?}XZ+V%a|3hxr%QSLjW}a`}%0Hh^ z=dWqg(pk)biN;atSFb$c0UgB{L3-29<4%Cn#`4Ir+9RRt8on_~eZfV)wED;WH}sI- zG#koerSIZmf2eKNtIkI)M_4KBxzsT*mhD{_+PbkBkN?rDqyr~kuX5Meo1|a5GO@7J zo^2nPYG3F6;nHS*xje*!d7xu+cE0T$wT|`32S5Dj-FHrIg}M;OT#1(_^gT8MdbXNA z4}X!A!}&w?WwgI?HU;tcLeiSTT<7eT`n!76^*CiDD3$)7cBnZ-jk$!E&NribD#--T zs5g2UT%mAlZfrf)_25leq@(W@CxcffXVH_oKTaL%kym_R2cyTe?xb;i-1am^rH`Y1 z(1s3^EwG`_2M_ca_9guzvLy_~heGoqSeHG;^}vWS;EOirZ75_%;}qoH%T!_h+Vc57 z{D;z?Av65I0Q*5Y%BL-VUHtyHPgAeD9;Y1m@nd1NFL0AgVP9&V0L-K_n0I09tUk%t zExx9oW1Ne>Bc7py9`;PlgDLm;z({;RCF`kv-Q_s-t4Chdg?U2Z<3q_*sE6s8*fwSi zCO#hR^{y>%FNbkIZ3%shpI_`J^52?U+0oey>1n06{pua;@i$)*;oAt%^>Qm3Clv}O z*_j?A#(B~mde2Hvhdh_l)Mt+Wmvn@K`Lfhb+kombN_)A5%(LOm_1`d1?3E5HEnn&_D9hhsg zwK_Xn)5CeT_NnB|Idi@zIUg>J2&oJ8@H!k@Qgussw=-t>d0_DI=NFTC^mN@ToD_nk z;G{EWoE@5- zwDV}@3&ilGp2@s%;^RkjXluwBczM0g`T_Q2vE1O}C&(-MPyCz|R^s1>(%Z}zl$@Qa zh*RmA#$tWJFS~&5@igLV+9~pZpC{$jdJl8(=md=w$lFX=f>z8g_nPlTpNi)Yn!ND* zD1Ne%ek@s+P`^M~%n4vy5l3HXz2UNG%1;*SILNr(pXa$*czK$o*TbfRE8oIT% zd(qZ~);4n6j)IQL)Orv2pr_RDc|Mzklc(e9)8=kJ z+|2TvJ|DZ1wh?fe$(o&0uAP;SFW_XhCFL+CX1t?wq2RDG8=RmXC*BybEjHo=e}8397f0U zeSfTPKy$#pZ>rVTp=3|`ruh94Y>CqT(9>rPgSkSDn_3Aca1^if;mmJx&)8n`NJrLB z)8<{y$|_(k`vRLa_^>Pby=9*8<$;BgwZg;R@ku-vRtg!PF(<R6RdGPY;#fek9k6d*s zgtQfFC%*nwUk86hMSWBWr)uA2tECG#Sszq2CS~Of|Avfh@O4<~CxJO$y^mI_f3^I; ze=?3KZyy~WLv&cj1!z^vS1YB{J4V0M1B*&!NQbpj{j24rfYTA}@JhJE&tzkrHklGe zgxJd2_PryGSziPHZsV#xM6sOJ~4Sa)yn%xr}MJJHS>6W9-Q$XzQ4ds zzwV*Ai{)gcnt0afHScoL^{bW+JaZDv-H=}8Xg#M|K2JJb0Vn3`tUZ)`JH+Hmf6RR_mkV~_mc}<2fFD2M;nNYf zv2%CCuNhFjPt&T`1st3|KVijsx%c&@w1li-GJX#7W_4%YfjxxGOA?2kV=aNTQPvW) zE~PSx^9ikmllUXlJ5yXd=9OQ2*5lYOpmg;N!GB`w{3Deqo=!RxKMLVT*YwjR`ZqsE zjt*fTipKtN9hARP80YbH+0UpwK$M}hDo^*#3`P5382Qj-%%A_h2x-~x#y$(K>&dV9 z&^yq*59>*<*0MYwTqoms#;S~6S(EFzX!DPu-{U!JB|2-teXaD$rH}bYyDyiwS@CH+ zRf?0X6Q?;Yzj1l~{N(nL80Q$!ZQTU5I95N41qHQzF!bfALzsHm%5j$r^lk&>vCm%oZ>5C z!Mq*&DQzptHTHWhbmkWAEXb72!Clv0=s5rP12%kf^Y;7=`Kh~Z`-XFVe|3D#UgG(O z*;&2?_;JB2u7~bzPtpeGI@uo;<50`}z0vWGTSE^E{w-AgX^}7StFY7dnSxF5vtZvE ztp$r}(t`Kc=0af(6S}RAm9XLL9eRa#&K~Y+>U-QY{_JrpbN|o$t(9;hec?RIlY&gx?mrKJG_WJu?V z)pw$|`Ed^qIs;gcCyV3H&L@|idGF~foG0aZGumLnN%H^0+D#e;iZh?k;Vdh4FiWT6lmfwg~B_7K(nlM2nELzMMv4<>_z@Z`d*D5#-zR#eF%u5_$4xztYOh z&JIjYZr!@L(6Kz2vv0%Q9qGKokF&AE>pP?5kvu_H{<^T;Js-N>G?|KR`bJ>|Z_wg9 zYlXVy_edfWF;B<^{3+hfd|pzUQGU+(Ob&PKvgcf9_RINnkne-_JBzk9XnXK&3?v)Tfsf{x;y>0L14VZaZBO>=g8iTzV+`4d*Jc+N_h0bpD%2DtUhVgek!HBaV=rQOBD|8n3$Sk_5nf8wP=$ z{=iJ*hU~&(AKz>RE8Z)4&=u&NdSozd+eQ}olcIr>BVs31$!jrWhP=6+>y+0OW0oU6yrW5wJS z^yB%LX5s`M$P|3Aw+$Q^BM?6@_^^NWQCDG{Cm%f_fv}3uUW+ldT|n&BTg6MfwMWL7&SHze*DIIgWo#(8}f`_9a~SU zQ(7GQo;;Hm+qZM~lkYQEixW1Lon;I8#j6ihk7k6TEBguEgx>bLTx}11s7CO9K zU41<5PO?dP*g~-m!;V6B7|%!_i67|mo}?RzPpd~W;=~hS7?&6(j7NO@@@Q`lI7xS5 z>(D28Ov+s&d-R9s8gQeJ#5M&NY$%O)MGre)z9y`f$qio3hM%4{1CulwqK|IUm`?K~ zdIs;ZALyrvr%jc^1{smffb5}@(Dy3uun;|f4v;Obc_{Lw)u9=2;@OYYSvOF;bc1X@ zY)-W$`Z9ieV_QExQ~qkh#E1U+!|;s_!-Fv~eQY!B?@D;99v&z4f7q7DnA!nzC*VZ8 zESY1ldig(%*N6i@bTdEhX=h;0da=qaJp*aq2{#{8Do=Jrr8+d@nfTEh8G4904c537 z=f|GN3%0221o}XH$n5lvZ!3gv(n$Bve_?ATxUG!J2bAo_z3Qbt zewu+rB^tu1+`PD(tIqlNtbAYrp0rhP;wO6864}{_Fjl)hbwAhz$f0o3yovdoS>;EW z=7;5aXZ{?v`5NgI9hG@fq4=Oq$ddmNr#2+ND%3-HDuuKcFp|*_~=@CsziSj{I8uK4|TG(lIURbS7-BA$(ix;e%Kfr6>y5? z+>js1l0wNDe2V90hkC~vuLvK78q?uJM|=lAd&aY!;aKN9N6(dwg3qR68qV*dZzh+K z!;YED=I`-*unUkg`h9+WpAYW}d$xaTtpqFbiqB@_BYL8b++Z_tc8!;0q7r_?h8KpOt&&8 zr98~9F;}8{rSWwvxyJVu?b0MMoD=e4g~R_@<3XkE>0MJ?tCAj`aOhg3-bL zT-f+f?GBtYZVY`XwnkoeF(%55E^e}pfj&gG#S`I4<0JZ>r{Z<-4D9^&-WXUF$7art zZHi7R!6`p(11ITn*&MW6=z-J9(p=%(Xpx8HN_@6T81olw&ET8X&cIHsXL(Mj@tDV> z+;!qJqO@e$mXbAWHrjk?s^qR!uu0=1jbGww#R%+*KBl*}k)K4TnLTPYfacGUQ$Oxb z!EgjF&7iuLge)_qrZn zlOHMVy;efMeDSL;v3z;dX)I4Ueu2<-|dHMHyPtIZ;KwI{@l|} z!C~P}-!$0j$6NsISY;_B?%LE+*c$^~#h-?-h*NUKK0wx?j>|hZGcUK^JuTVM4wk4vXn`NeahV~cAk%%?L~1#X-dJM70?jeRpH>;aAEW<-Nfd(kxaqI&u? zTr0j+Lh*;Ksq1)*q4;`)>}6q(hvt;amDwuzh!61@)|vAD`>BKW4Cr~ap~_7QRR&nG zcgWBE>Y2i{{LPMo7ts`7VXZFM%zQH>`EHw@DeZAXl}8xXbnHxwkJI&W>C_{?cqs|P z_vy?Au=QWr%vw_?T|MafGD>J$`TFx|TH#uJDP%4(Z9Y=Z%#~7*Z{<*I8?E5V&htc;N4rlc}L*NX7GXy@) z2&k{CCj2<#kXE;9FsUX@TG^*PF0J0(ef{fvw`At#tZl`)G0pw}ev2cW_xb6XXY6qt zp6xEo&-n6AJ2vp|>%%qk9n%l8!}qR@w{Px_ENJg*wIO>z*~6o~_A39hVkQ0wksIbN z!KPX~4oe5d$eW+vJWW`6e7I&`Qrek?!*HnfIe6WkA1pbe-RgLGjBNgUjP_A&eUFYK^hpPrV6ILZ<)gto7E+55dA?j*4iZ|oB9mk&(PU4GiYL(-^T)fu0**{+{4e|2(W9J+SK5o*|)Bgp2raFRNpB!H8Ryy*E z*OS0Xw2>v+#r>VThx&OG?}X~tE44l0iGAVovbOB?VBGG!-#_*^X#EqOn}wC|i9^11 z=XEZ13Eyuk(;v9WcvtpLJRMy(5+lln4)0j+QT>tV6H0#6 zr}<}mUy3?%&I~N5x5uNLABZ^K{DxehT;#;-McJIltCwlgHX0k1ulk}N;6Xp$owrql z6VLU2@%I5P_`QhheAIjStN|PGBKtsnuw=SfI0+*{`YGx!nL-zM9qDn>*dDn#Djq)H z_VUGH%EJE&Klnlah!^?};-sU{-{M{GyHTO&_>eIQJnotdt&$GD(3#TXqA7lT9hz}1x(cz8CGX%x z{K&#w|I)R+HR&kkdWomK#klx;+K}3?$_F=}CheMbiTy<$`Vi&yVKcDtG(2rE5*CEq z^L%t+Z_?wWcYIhoTkPx!_VQF;`_5?pOxWif`&>)Ii8$GvvY$Mkp8sZEiwD}7$4TSz zv0UH6?C8~pdWOD0POvd6*-z#tGK}j7`r6m|LFX`eLY9<|@(c3@mbaOhq|p*ibGe>r zVL>Q;g*;7Uw+pr(&lvZSkG54#CaAOIg0z!c*^6mukuk8DTgblLcYnRm&KN_f&n15v z@6C)8PTpn#3w`tU+En5bmG&ka!IXT5=_s%QOK{lQ8R-evrl%S6fnmA5)z>d~FQFI3 zTPxv&Z6q9I2YWt|FWJe`QS^1_A?zpX*JijzZs^;w8_UlP6ib$_=e?+p<=uc)F;(lx z6E>7^lK)4~C)fC=!-fz}@$+i$=>s10^i6M@6F26Ul#jU*#s<2_Ht=K3X124KmU!}W zatThH<|B{dwPv%0o!Mn9FS}aX!V)WDF2TdqVHfF1g1}#GX(;&lnCqbRYH-=Y1kD zS4khjSduvkwQ4?9*vdJ zKjWI|5$(G~cKCA#>m)`2i>CrS_S@g8wkC$rI1@$VTB=GiAurf;KurcBSTe zz)CW2ejTov-?_q?Ho6+W;u_xz55l-VCrJ5JJoVL;ge}MUO!tK*z zVNHs80?9RFsgu;_;?sv7C$%3tC$)r3F<(GGMf>q-Z?&}TGppG!$Bqn6O@y(U zr=e@wBIQkWb&V>&d>Ck69vz8ZlWnWK&5|Y2fiBmgPhYI}DEmisV2*`nq(^7VUasgP z3*3wbvL{*ev?z=D2+?St*|pTgd3kR)D4#;|p2R=VM{dA_{+l@8E~pQ9O?LL=u`T+B zQe8{JpmP$R-NFgGT<-wA?{QKar*D7n?W&+}6J1nMmO|P@ zp1=s51`XzqCV0&rgKYV zC$EcrTzjyKlJzfdYePr2SJJP}7v?PcHgeZ*<<>SPMn-lm9(hrzEAXB6}H zLE`7A)Q^+LN7skpq_zk>%Jg)5E)5L&abBy)lKAkvrd{I~tRP=0G9-+W@It|txO7tD zw@vb6V46pQ>p%~MNVo-i=NlJIZarJ=cGSxY`Y712A>-V)zgR* z^WgZg$}R2<_gr1PSc{BQn>LK=^821Z>NMiSJPPwE@cy7@bCdPYYU`ht?)ug3il2SXHFAN@T#`Q+6ikb_m_qSnG-?2sOR+J$ms2b?aTU&JscY1#~ci6mc)Yz zvIr)c#}W=<-r&)=?S)$H);#HHlP8ap@FL`$GuEe$s&BO+7$Y|;hK*k*@a3OIoK%0+ zgFSJY`z2%_5Ot>Rta0&UEr5IdSZ_iWS+h`Hm8X!k9QM}fUUW}eDE?W)WDm6F+Z2D? zkiAcoJH54hRb`zvjNn(ivlo>$Jk=+x@tNHdd_;xsCk+(l*ObSHX?53g_9w(LrDtjR zS~X5Qv)532cY>cW<}UTKH5a9;r5?%y{;U(~-iNi6camwvbJ&}b-^(1mhudNGX%~MI78qJfzyRR+~-w$ zf4XXUG;R;Wf;~K(n=3cZ6z4x07p<8qt{eB9Ugg`6?8#++{$@|_fp1&${bc6s?st#h zT)B3)dvT=a{=|Igw|G@{Yu3Cvu2ctwU^AZ^obhKEnD4Ij2c~zrvRm3OtMaSks&!I{ zZ-so*o$t5Qibpl+!Q9q!!g)2(YaJxYb0S^|IsZd@siwZiO_S_FEK)De;mJP{m&}=P zE)V^3-1^s&pYOnk2Opk1GNl~A8+!z6(LbEmNz>smKBPgP$MNxfc6Pnw{9UWzC4S=b z!f`$PJ?FoWJ@ku@PrD`!-!!T84yG59^J(zHx+*$RXBfp_>6>ldo#-oM-!^@b_S~n{ zS#k2^qjOh^PYboC>CcY&bg_Q&=W+eHYWQp(Ite9VLl}Rz+~j1n8Xc~^;fJ+7`9;m{yoqQ;L;@cBC3%LOk z>WDmy&CP^;(%`{8_9-%kJw|!t_clEFi055-eEfAYuo6A&W6w`m7noV?<2h}CXY$_> z_kUn}dn@q^0S;iP^#zrGSSb3?k$$2~?)gDe^y9LciIen2;jF8DC#jvE;iNXA??o?k z<`%&Y`6_o#hqSDzPtM=E#GZkr-0JMzuFggLr{H6YANTlXfrexjOpqbs;(h_T&Bn;n z8@YP^p3YAamX0Hab9cMD7UAEw2cQ4?)cx(-o9hqwh8gwe4E65v-KjLc4so2mdBzyA zAUm$@({>f_{RK5chM?i=scZEu$hh9=jg6kG%VWLf>#=u6>H7QEyTHWu0Ca5cUcDLD zy_S2*pxn`+Z2Q{o#o&hyTy$0o84^x}^r@t87EWncseQqZaOxkrkXzsFTSm^{4;^t7 zUw!4U182(Z?O!*gHn%BEq_^33kDfx`)6Zxhelv0MSWV7vl#JhK2k@V5-|GM;$rFAq z%GLR(@rlkK&domRdLWz#nU{cvw7-+W3Hb&K>>J*h&MlAL+@1g@_=aC})KT$B%ZDD* z9;&fyZ^`!q()2bwG#eu?PrN&w2baF?oNC`1U+mfwPU@Fwchrwi*J&7}#cf<$yM%u+ z^cx{|tmGwobFP1Vxo=f6MO&9GcT)KHcOpIsv45Cv-BUy=RFbIT`w*W!F(zsE z$RW1C|KHx3ueFggd-yC@l05+umbJtJPA~uS=y;Nh-9Va{Q-8OghF4#@40{m#``SjRGIrlotFx$h@}W-ygmo@r~^V z+T8RRf7pujrD!h^XAHUdxp6juok`g`%*@j^Kz;+`C&oDDSKgD( z9zSi4LE1Fr6Z;AM0!H#{`t@}cFErNE&6XhcCS^Gbyn23e&UaC!ka6eOqrfJ%DL>c- z=mhUcm`(-TawYvQ4cub7E~@`l9xfHUoVH8R0$pp!}Mmrx^!%R?3@YOu;bPQ1&@&73djt zydJR;Q;@hI@2O)19~;QK)z{%&Yw9^?Ex?W6y4@oV|~^4I#s+Qd>G zpM1A2otwLysbZ~dEhC4P!RA-@k(Xi{d`jofQ@paJEW6|(gXNlx`ikeHz)JcV=d`z# zD|LDm|6=ON?#^8qY4+KaRJoOxwV6W@*VS@Y?iV%6>=wM0tOnIZ9_ z5AwwI9mYBOX|{h;Oe(*NZ~MIlo!VZR(l@|LJ!}k=h}XpGZjR-Y*BcuAmGyuP@`DW) z?J3G3tIhgT3>xa5NGm-&(}!ulwqEBl-jfa*qq_QSU;9bjiSCFP5nHD!dwQN?qa5)p zr%BgW_|?brv;KpNUsJS?zeZWg^*8E`>nw4uBw`pV-x3jVEU&{%YV(8_QAHqhd?{%Eoe#c&F8HLndBKZ)VJ-~D|~k2GG{4q z6Dz(W@`QfArlZrkp8ZW8>r!+y^{JbfzvvqPJKA2In)=v$w<&`gd-#Cy9YkBJq;-_{ z;$(_FgWc(zeWC|Bl5b?Nfm8PFGKW)lqvPQd|5jO^ckls&m2`{}lWuKGA1OW{=cXz4 z$(elJlsYC}lgCsix_p0keXpwH*%|o9Ht~DCU48nudEICo!Lc$ z9OvzKRUDo$7Us2i`etR{zI(s8wzKk~dCuInM~TBtZ9}7Fq?eSwREJ4zUSn+3cK}Z4 zwF31}HG!H)hqD(y$d?KB- zymqh&lrLHXmHF}hZ2HeBdwS7Dti!bC zI1fuFMV`18rDp&XJxaNt8>+0TL zhjtzL@VXNZKCeqVz4MsglCwuFx+9=mbuab!^bvta1RfC>ECT8x)4{ejp0&$+zv*~# zbw5_k^L{8CZ7uR*${v<R5$-)_HU|1$f(k=jN5NnAT0x z-|4LWv8Lmh8{Ug&6f9#p46JM`rkqKTr%ow6@D6qZW!RTb9&(24AV>5Ybq@WGe9lEF z50r`Zd%m6Ll#8;BJQ>p<(mD!^(wb7%5!f=3{&`p5xon;%TzQk_9-Af7&v!=8de+l-W6GIM&Q-In%in(^_KNXT_RkNF zwkIb)@0_izaJ{;?miG3ha~c!RCy%EWn%@LW$Y;%2IV|d$n?e`YJOd}_SC*F6KK2yHup35KSHGKeM4X6eBu1ou7rq>_{Z(LV-Le8I@^3xVu*-Ex0LuQjC){=-Y1@x_0hlA zcG}||^6h8?edITc@+1$#NaaPQ3|D!@$Qj#DK8{8`(MNr?ve}ctQrii*mijphH&ZQ`U_f zmiTy&Y*B9R)s)sc4v>b{^l$`{XWv+HET9m#u{^O@`s5}*_L$GrPvO=j%~&%u%1rxM17P2Ct^_2 zzqkh%^f&#Cam83m%!jSBq^ z4VlAcwLNiCPj~WDAXC0GOkC>Pf)4B@`oQ_j)Ia;5S9WI>PSU>AAJd)%m91HR19?klblcdX0Ak{#l?#d4kcn;4Ozw|u9heVF&sKp%TIe|GAgW>RF#=d7h2eg4{v#rDti zZ1#~LQ=Dr7Kfb+lp39lpL-ic8(~MJ=uu6OIv(JXPZ^We2wR0M1874NdEpZ@){)kg6 zUQrdpf->O2c*Ku;@H37WX|jiMY&z#5;9vFW)*k#S?phW5A3`hov>rKdfup zu2Oh9n1hduS0knl@ldKhSj8@)tU4OMXvE3bbnW$Wx0v^p`yJd{?i{KPBYZ6Mcb>U^ zLrufNCblC#?f#zA^SoEycx#QgJ@m_rS0jcI@8aW+I605D-kdhZwKvJXTz&)WamLy@ zoSawD20Ag;8F?7=we2DU(2340>7h(*{E!s$f@kQXAB#&bzzY4Ozl~?CH*KD8PggRO z;*O>B_sSEgF{7BD)Zx_r?WDF!2aS#O$5#1nQBPneM>((h;`Nw4u1ivv{m^=m0rU#( z{n&n88&|{elr@|>oW^Z_2XE*}=L^sbZse!4Jxfsr+OCnQ##)W|m{K41G&o_uw!PP| z&$JWRuMly>VWO0WJP^tpW1rSckWZss=H=x0~Iwrk}n*qpIl z+DDeYZ2dk4E9N-TSJFM~d+CVs-!o2)7;4CnItt&Faqh84nKMR=U4ORS=&uJS_4i*t zKOWHUEjMgj>e_=A`i?rv{T4UMQ=TtZ?`n(77bzGpKWW5wU`m1lkNnH%DO`MW_73ILXP4VdwM~s+aOFyc(YjOQRe~aZufk(GC zr7Nb`&9Tp1yI%W|=M#)?>6iV!`P_LP)2djljQ{vL*MCnu5g+5Okw<&T5aS3oxVoGC zZuE}&SsP9bTl^Y6&9VL9kn-pzaVmW@=wfjx)BWe)oBjamG1lU^W8^myt7~&(@oA*Y zWh`ro{6t*ADaP+RIQqV`J@<2uUy4unN`Ia2n@Y<#r_!3vLr+GYuV25q#5O=5H2);)@2%V#fOB?NN`GhINA%+ z@DS3LJl)jq?m?c=b!vI;o~gy_^ta`m-nmng{tL}o^icz;dFD1_Pb#9 zWpZJGc@1;raaynI^}C4E*Vk81I{A-oi_hEjug}<8d`$enk{@~C;o2zk>S}#qvAMQH-K_nw#?C&B+*Vkh0E^f@*W-py zq^G3yuJ_nU*!a`~_UuWp-=)7DlW=UUeU)uRy2kNZdfn^f{Y_~#kC}dv=X=RMitEih zhylMeCsaDm_LqbNvrpFq18I- z(!10<%6A9JOIi0Q`Mj^TBTx5T=Y7@pSkEH@j|e;>@QA=80;516j*(uEf{tOgDX;gP z4x5ibwRc-w*rWM*ee+^vb8?nFh5R^oK%RSl>gpU6{e!HxovF#0#r~9s3nn{z-@g+QYUOw`C zU)R(h+bpl|o4>o(7wN-)&G#N8J`rcuD`NX~*LUUbKHiUX@%L8fLy?a`UgJlPdMoXJ zJ+@!c*T-eAj~H==6Z!^;NnPDwk!fh0TPSHj|Hbv0`;d!%>JTS%bR8dM-qE{XpV7rP z>1_Ts5@TNZetFMYDm3`Fnm5kg=hz{!T-^8H507_!M~smBoA{P)#&_O}dn$cqie95k zFK5S^@|4Q+&p18SMG9^4OvqjNzU})JW%aa0I=zPP#h8a&=dEf0XCC)KTa< z^2>j>;kVziw&|Kk z|8qab4k>ZxS-<@D`(A|;XIiT>sMt-?Mf&U0%uDui(+|Y-wkhw<9bUeR=hEqCu^rE5 zF^3`Fzm*r|TYWcdoa*?6KKlgYzBbFd*}0={>-(p~FGy!s4msy@ymRu3xEK70U&D{s zMRjovjQha5w3`l{x5>I=$|P-+te*O;TiueMm8nYhtF{HufW!(Fc*y z)ziJ#r1oEBWa0GL!O_)hGwv_gr~}1`6uDx2R9`_;zx?+5o|wpk_c5jddI;MO9Spz3 zI_f2U7Jb$FV*1z0VUB0I_-5(6j0-6i>PPWHe(ENselGFB-zdfW%@Im}LSQ(|XdnmyRqdza6RRD=agX!S=y7xrx<}tK z@6!KDzXkJzOlx{x@-U2h+iu3vN&6$U&AauVh!wh>diLf%Z-5oobvU7~c*faiaKe7l zz9c{DYWxEBIa2)zlp6*vWgE21zr2UCu~(jWG33?p8u9TOU2Q$2=zpKZ6#d5Y`By)d zznw2!!M}5nh>>+geeRr^XC)8Ay07R;@tGR2PmFnjJ%w(Lymq=qzoVD19nkr)9Ch&A z{)z3hdVZ2)j52?u{cLlm`ER;>jm~C19Oa4rDSpGkrEJIcn`c!+`~{vdhlPLm#O{P= zu%I6?-p3z04Y{El{Sn!+ep76Mt+(qr2C{z4I^7*{;yT91DR~&iz4W7(lqvL8p$JydSlW;#k^Vq^}yCVw@~_r!0Jc6S^nXAFr_o%6W?NQPF6elptdFdJRAmuC9na?F09P%BoZ5=Q0U)Et#mxo=2|5SQRhlv?&(ubUn zN(1Qx=k9Y1qU-vK{wGd9lOBrimDil}(WcE)>7?a|6 z)V?eAd**emT1x}Vh?71(_`%;DZT%)j*`|G#e4C4T4GOzFwp(6H$2edlUy(-FK5B7V zf0bg1SL+X~x6uELBSu~5FTV4})Sn;i_;`*VoT~Th)_)@%qwNP>+MFr6(iymRB?WIhp{2z!Zq_h>~?IeI1emoAJ%=z8~6J2 z)e9~C6!@g?tP!iHk_q(^V;r`)zDsNa&R$1+^L2<7f_+f>2=KcwU*-o^`pSoeOW95x zPSC_Rb&aE2EE;1&iW6&B%c zN`eSm62@bYqp*kVV|kLH=T zfwOZM#u4Qc-Xl)K#G+eU(!^M2Ok?zQXL+j5jkoNk)AP6M&n_rG{p#!_%Odia>L7n@ z?((9Hz4qz-Y4#h?Ci3L>85h~9!%LhXNyZr(N8>kyRti0~RSUvyxl{j0jd$LAThm#nY)|DAWp7h{rW!>$* z~^hx-z54gC1;6=CZWUdJA(}c>Hlb^{E%^kQesDATzuh zamn?iH7op7%$4N7Oe62{S3DFE;k=RdepN-oTo4iqBU0soLk$WgYQ;nE1rDqyfDV{om%_I?cX> zi52};{9QfvC{%iB&%%A?=G`t$>nqG{(%1gloYk*0v8e>IH8yL2* zLXM_aE1lKe_hQ}Savgc}x*ytnw^Irp%%}4&$3v{w=l!%j=yy8tbeDEJ)!8loF6|BD z-A=UMrR`32mic#SW7zMOw0nOSI;9@~Q+zvcnVc*aPx_2xq)B~g5+NQ&Z{EQ*v!iXtV7RJ&WA>77S= zx_dk}X1pVN7FZ(&vQ|8R;TTwV;zhik&B9&;K_bAr+m7=`9PDCYkG=a}LiKp#4ZOi_ z>>x;I-K(6>{nfYX)a9>=Rb*AM*h8_a@9%ei_ug~v_jm5O=f2Lbcc6Em_hN5v@AawP zE7KPC_FbHwB<#IBHCPh%_Fn4mALzX_H5Jl@XUYGPbe6-#`O8bX>CPCnJiVbjoxzLa zec}0TdKdfquMCY(U+%Z(mnZrsRLoxV29)rpzu5iS7eAY^e@~vveBytw-(Ri#li%KX zG4mv|ll{~G`}xeb+bsMm3wK@|d-CXSW`6y|Ur&5z=e@uC#}EF-@BQW5Z++)4AARc2 z{<7`s@BDh^uP49r=5v`}B0c$jV-=SRlgd+tM-$M0JF$1`I? zJ0Hp4TbfVU{WqTb#OL46WLBR(|M8BU=ReWWmdWH^uzcTmF7xG=Ek2WZwEX>)^Zbc# zpZHMbk6z4V{;!wce-`2kJbg3sM>{`|dGDFk``KqQPd;ktpIUt_Pe|0uk}M;|qM zr%Zm%Wu839{POan%-e75bXq$y?7%gImo0o`_X8F_urQl>@Wn#6^4zn(ASH}c_c+VkJC-#@T-X!34y@og~p zMUzc%e8=A9&YLE?kE~sA{VRzaXY$vXw=y4t#?HXllbwHOVb;RGu<*Am{BsMxY2kM* zw0tH*9Xqcl?=Q50wjX-@zn#c@>)F4^Jo(Rfr>~E_xAThWlz%a1ywgU0{IR{yCog?H zV@=EMe>AyoemwK>5NEQ7+=ckB zf9T^Gi?{MR2<`VVD{E+1x-a~AG5?2s{^xe*|7$iV^RMhZ zp+^m$r(C;tcFlCdH~$~>ckw-jcV_Rw%FV@C?|dg;mSO&sYxf>0>$`vTZ1vF(K3X3C zkI#N}2l;@m$xT64+7j6y?H~M~&sIPG?Aa&Z|JpwdZ9bH>^Fxm(P1Z7B{rTmKRz`?> z@WYR)lOgSYl}~%Z^uP6a-`aWc#FM8lUQg=z;FFJk$MXGCpYQD? z-?#Gle&1-E$UOSv!1p_!eEgqU8UL+Mzmuf@MWr`7zXY9AC!Xw_x*qzTpHFn}@;|mT zf6wwhwfIn8=2MUVj?w=OU*6cK0^e`t%X>MW_itL6-!&Y5AiK&o;cp?&ANW{Ze)+`jnl7+BuUY!f`}CO~3-uYxr@wBr#>NN#bf?Go>oFX@ z{@lk4`lRj09_I{?dp`ezB!6!{|I5#3R-ZRLebV&siOet9d-;Vw-ZYv!zi#^L*U=Lu z508HAv31}UXZLUaNYD`l8t?qr<4g98v~8BREpMmz=NhTS;1Nt&weqi*te$MEPnOwa8wZy)C z|7*V&XzYB_usWA{g5A3FN$Y=JwD3gcmorAobozVPVy096;%)2i%+7i5$ElmqH{Jg+ z(x1RSvk?7{9hRYA)V}#BicUm_^XCTu$6u@!RO6@=hze3g71GV zkDt{&*xpuG+ zufX3@a`~A@Pcr}h=f3mwn%$}MtJ9EOyns_c?6hhj;#EHj-#d|y7|L9}TqK>}<9wv{WU46^?*iRV0 z+|zc9PT|=*Hde5A7cjQ6ca05H#_wgm{M)=^-TztU%YXPElQBY|@h3KBQ#r!Xfq8tVG4>6W&ykNwJ6^4^}j zJ7GG-bosiyKl-mm(Rj&dTr(QujiND=)Z^b+U)P>SW4H>eT$&WDO#kNf-nqQqvwLLW zzc!ktTN2qb+!;#-`#3Kd*^++yv%Dn>(k9vneKCy(ivaB=%3qIddKr+&#m1( z`TO}af&R4&cEWrAv(Fdvna}rc@@cTO3w6yuql^!mO$a8b&p%@NG41&u1fIe?l=a_F zzH8}b^XUS%=oV`q&;B66*7R=X!)^8^?ceP$z5Ekjc-Z#V>uqm7e5>uvSKfH|@JnrP zJbd%@FMQ>#*Ixe;4=(mz>ie02{=uKQeCdVE3mdP0rR|lMzjW@cw$H!zg)g*y_A76^ z{1X2{X_?FmOP_07{MpwFF{j#+2cLWRg`eVT^>eSi*=GNJ<;{n0wEff@ufOu}%{O1* z;nlWX|8BnV+LzvHdy5>TX#1k2efhHwyI*+tGY?-$Nk3)LZOIg2_X|Ju+N&u^+EzaI z`d8cRS=;MB+4jm;-gx7oQOL8={lZVa{>JB1GEG}_+skdQeD1X`ysE^;*2|Xj3orld zn{6+D)$sb_!?vG(?bU~`cfSyDxo0%)mz0$Qt~{x>pZHmr=zihN*FO8Dm%p$bXGuxh z_SM(k`dnL*{`~bb+Ll9fK7HHgUjEXnUwHV2 z&-d!XFIr@jtF3J^M7RCa%b$JiOP}q2;fr5<`KPwyvfJ8-ZhPzDn{TyU%%}P4u9Avr zF7d`*duvyUwzgYedF`$4ARvZD2yfb}dF{=sZD(G!SyB7Pt0vUUFRzIEiR5MQl0#Am z5D$`s4p?q8f+^hC|6cjr!&fM1B9Vat!KA{O%*(I7YSljTGYJ=&jQ9!9Z2m z+HxON{Nh@6PR!+o&!48N7?N-N1e8MyM)Ek>h7%vR>+!lSpR>ev@_FdWP<2_fZQ=^_Cw*zO#2gFOO zVI{r>&n}PL-nu!`C>*LO7a678-8XnrKF4O}(zI=c4Vx_bzTU}Ss z<(1Nud*<8VVdErx6w)u1_IL*M1&<7@f=(p7`K@{-oel6X5TtVCbo*!k_M z-uwE}Snl$b(eva(UR1w0q%R{4Y2#<*?vYQ~3w^iOx~H$^hOf;oZ;8idVN&)wTv@7FycHl%n@3)SY(PskSS1Wf3sXt(GUepB<8L%HKaxh~R>mh!m9KGnTw z6!g(#N5BM|RL{Wh;#7aru@WxZ+pAL#9-N-_{V;Y@T7L(xV1e9`U+qI>?G;ikdFf9{ z3s%B`5IjQ}ll>v2&H3lpqN33(nG(HQT?04Q?%zB^9ePe*-D;}}5!y9rE=;yBi7sI*x3n{#CdLW*6UO9k23DS5 zUEkR3S(WaEANcZm0h@t3g8}VzbNl>NWU<;GvP&CZ>by4xP2@-KLLoMU`0;iwIurR* zn^zjbM&czp^d-m&?Fo8!dIs&CZ*20M_f0sowl#8lWMEruv|3!srMtU0dx>(PEqoNx z-o=}jr-`|hZpFu8GjO`MeRDx{!06IOUwg;YbV>VIUp(JguFm_3-&hFI;@2^q3$`I?X6LgPx0WWy_9IK= zL3U_s%bP1}wAs~>bNA4PlznCW)S&QDD0!l9LuXwR&*4C6_{~9xY4;Ld=!ES&(H;uA#^3W=`id~ z@!c`qbGm?!+&aIyl zJ_==D-(J~H`h6PZo7ch^mdkb+DEy1#_`}t zo5V)KUPTV$H2(hb?Zse6Udyen3k!wnW6O=lWe=CDQzPQRgTGGGN5YAANE~wG>sIa> z+45sD@=}*_>A{pV9aAUA#umCB2p@&A_0dy`^C2=t{zl+Yu1x3!o~O?iM>=*KF_6MCJr=%(?_v0!J?#)y;dL1u(Y95VJkJe-Wje81N* zJ<$Un^iP$r@z3b{RDbefbNT1GW}Fl1IN831ZkoAqKH!0#R^18Xai7P^r!Ch`8Wk@d zJ7-Q^>!iQ4dJqRz)!O1)+q2h^D=^ZyPj)6{U<+W6QLftD{Ef+V=8vz=OoutA3zJuZ zJXV?`l^sesjl!c`xx%U4<}*UyH?z4nd#MRO4Gqc7>n%bNacV_JO;;ENn@w5i+;J7|-JpUo(HF{Efn+Qn?9j zv!~34lASJ?y?Q&((En)#A)b|rIS*jY>6=aX+B;`T0)L zA}7L0G6ufr5!#^2>zEqNCF3JEmdwxJkfz*P*mC#63U)g`uG#lM`j}tcH!D=VG>@pU zgzV5nzn|Oo`X$CmWe{TDch1Z#75atz+)cO-a}!Bw(ev#L`C%TB{t>$rxngcla(fuAHt~H+FIanc6gB`tL zyg*zU|ILbnK7Ys&ywY!TUt%kSabQPS!&CY=WM6^i-pgUtbMDT%&qsgivBK{3&ygj@ zg<9v}S+j77>4-1!thGl!_Y!1+d8+*QMtKOaYh)LYm-4rI$84OP%)OU{g?5*$@5Jlt zvIBhiY1eTbnsF~aq*v9JQguw;29@nZAI}(%xn0Vk-xtp%_z1K7oM1BNmDmWPi(Gkm zq8#xShoaG}(9_r2nq-4Eva7E7{z^6iI5DruSkK$brSgRBl$}qonOlJ-How-w)X##G z=734lEDZLd<1ykIJq)j^Z^_)S$b8M+Vl6XV2`c8a}mWw7(cjn)1z*718_ z{95#0{5R{l>ZA~y3U-~%9qf`Nu(JN1^aY#@2gc6W+#OSEHjZW;Fp(LR%Y7KPFyCc3 zkFRCVt({&QSf5W+l#Bhqf)3j_G&Pq z-UZtBo~q4LPrN*RbWM8w(NQ*6%zTw$#vDLeI_7yRVS^ljf3Nz8 z$2cUPkK3!9gFF|Vvihk`xa^Y0SnutDm-yT(JO~zh<%KqL1H0Mq_ZrSZ>{z7b(UhxOt#yQqF~*E$CWmq%xp7~?R;)4VS8d%hj|de?g02z*qgcwr8k zdT8$*@BJXyk$-A&oX z&CFG?=FJ>1^=HnQwN9;%636;Xj0@#nojEzCaWD6~<^|LAqhT4#QN8NC-*SWz`^PxP zr2Be>+ACcw&*tsWL9F8kdw*srjHQvYFkfZ!5jLJIrr+Dv+Hc)!$tQl;YoYgEF2B;2 z3w=JN(cV_w*An{j4*Obs`+ZLJ;7R3b-jsWlt7qjxrE8V2k$k3=-7592g^#p)D6W=r z($cCNAEu={3UR&;@%2IYkIT~iLCQSrysCo_56Y7-%U>U~+z(oQkBzQBXmvcU&oKhW z2pl7DjKDDh#|We&@V(sktM2;^(-A$|vHQh>y$Ai%<3p2IJNu?PX0m;2XA9@&;xdma zLUBEGZ~K|fGIvScXLCJM?B`nC+&snp7WTlgFX#5w!brJuD$6&<+Q;V3ouWML#Z%cw z4J+|YX!CL_%-4d2-xuijobKmZc&>K$UKw4Vzwc?bI$oYv*3fdRI!t`D8dloBnrE{SQ< zTroe;#lWSd)H}kX*eO1*jLy^$eG$5b}8}#E()Q^9)8(l zYRBv?=GlBUTkv%lu*&=E6t9iOOLP`Hb5oo{@n;FS#+EGC2I;qu5$Z2LD2z$ypU~GT zyV?+4B%HkNCV#B=pdF`aBvz^e?H<2#+#~ae+$T>Ni%5pxcYH3_rM_DE)50rP*1BlN ztQp&x^LEa<-0bRHKz3Pgr=1hh=E)D%dMD6OnT%;fUm@whiZ-ltgpI<=)8LwSbpJu` z>Yc5dh4b6UIsEB7g7OU7S;Cq5&Th^`;qL)o5BT3fF6A4fns9kIw@R5_zjG}*v_~&b zYQK8!!$#x8J|>+bgjQ~3a9Zbd&@bSmJ(9Fh@TdlZYSJKM)Rp>6UciMolk@zUnf4X+ zr99JlBw^Gjd{nOJAiwt?jBUc_%);t8`>)u~C;rhJ=p1wwzEi5H|DI`j)~6oW58R=% zuy8rhhX>jearAApd#<64-N|!5PF7tS9l`^BuzVR6_NdLA3j6-h53+q|XM5JajIU9A zuYd`93Y~>cM2AT~jouq9ITNh@AI#MMsc-T6v(fmd`~;_PK5(>v5&PBhX93XJ*_pL) zei|P;@QQyc^pbRQHQ0HZLo~q)?71JFpX^t=Ba|+;^V9da7gowks5&$w6y3D_^TD4( zkT>&lJb8NyzdK6r!)o*uX}}k~O<#9^sW12i^f=vF8eS4s@&Pb0w|z-*u?}wrKAuKW z=OObepfhp#z2NyXyF8~pv>jxKwnAS|oNUyBOqtG+e9r+3&z30DK*9lH`)*!{tsBB{DT&cc#297F^5dB|C-h>l=pjNj}-@-OR zmgv{m4@(&uw}7E++Gb(n=@jZ^ep5Bq<5raUh3wIBaA1D7-!!oc?Vr`ny!0rgzkT-s!gil1ykl=M2`>~Rz7cHZ2UdrD9R*{%4~L6;Cr&;Y-~^Qj4>$l37#+Ntv-vtQdRv zF)M4o$dPgSp-0{5rHKU*i;yjjowDBn>tcHdV2#!;veG2XoYtt3tfV zny#@K7P~Ir*1Qb3@QisFaN?&q8Rh9PKPtk7>tM6xZGYOMaEU|YQDvlsUdEeoEglMb z#@YwAdJ;dklK5%uF~2E^3@APFqBcceCY)qLhx3L(@0qVQ^FKnqf*#C|yZtyN#)*68 z*G12V&A=t5A^O-b_)pb+2!q~oXMtxX7Lf_f>nSaEws5-Ae>Qx3q|?#{KSp_sNb7A7 z^c8WjO~CkAV`Ohj#C$jVUUk(RB6t=0CvW8>+;1HAaYN8|Uh{(1^_Y4Y6()gulmcjSCew{%_! z)_EPp7|yr3nHydBIJ^T^V0LwAwWRHN-kWjl>jba#!ICMB7fNkV*Zw49=9fWw3;pKp z0_@C=*h0>~vitPt>P~ll6c3Z&rvdwh~yeeqRZvX5g|HjRMa$M=kp|Z7#1^-#l)4pD5r0 zR+PgWXLe>h%uQiyfmLE(*m?#2f-Oz=<+Z`ic3KkUu}}!Jd{KKs@t$t9|2L{6se`JPaJFp($Qvb9#Fx6(hq*<27tX ze4~wB`rVWV#a)GJF>@xlj2)F6u->9 zG3H?2Y_99U1Z^a(-qpl`4g1n4OZBI0#>%4SL!}|~@m%|7hkXq{%)4pr0DkZ<$3Df> zc@n3`c+NWJ&F-!RaM4&;b-KOScZGLQGOug4y5?wvi_+^}q2gO16i<93jC#d&?QQy9D_!2-JQ93(}7`cUow^v4{@k6TP5`TF)m>YH#OhWM_ZwP z0zcOG(8J6NBy$73tH>bN#FHi&2Pg9cl$oq6B;Sx=--gx!3*#iSUCWITTLl}>hj3#5 zKyi$#*!_jc+81+B$$BUIG$d0c-?XH3QO*DBZIk-BJ4v*HdE@=dh-x73-l(tge` z_OUfFFif78&O5XUE@^y#2lC``N=sKwTsdt0++4Xdim!&wVWbg%%;oC(pnRyDy+Y{3 zX%0%eQTfGZaek@3_KV8*VOm{yo)&-Dah~t^x}LnnWw$CGSVt@; z)#6eq9e5q~S&UlI_W1Oy-rnM@m;A(3s_Q|Y(I)-g{#yBNW_phidy<=hkH;5!e$Bj@ zb+49|Frr^V*LwaBa*b|BmsMK^>w0nDSZy5|oz7#VZ@*VlFZSd6vkP$^o~i6=WRrc^ zv0hhx!ban;SNYyo{Rq2 z&~Cp}s&86|-X$;ZKkd2VbXIZY!h_&*NAYopEKy!qAI|S9S9{H6?;P4$4dE`F%+JCt z>b|%zaaU(d*=ex;CqX5^$a@{8)I_5vrje{dMWV2UOM}hI@jb? z9_{xJY3!N!Z&oO}$hqXcTG^6KU8zmccA!C@j~$MkDw>3n8OreS;4i;VU*As^U{*j=d3NTs?OI zzZv*8+TOl78T%LEerhgvj&i(y2OpIUzG{>3p?A^@jD!=|;0p#HSnx#~02iHw4*cia zgK(OjyVpVe*-tWdesqnHd*oz!Vd=K*UFxXC=ON`mM{)}mYG3dtyk@hV!9S(?1L7Nv zm1vvalL6kTd=U|ko~12uP20P*HM;`u;*U0yCKvmOL&hfNvZtYy?U*f`b)^jw$9qG^ z**Ap4xghKUy)T|O3n%1&`r$(dy84rD?Yon^ygIsh3!J2%@G-L=Oq2(CqaE^Y`un?s z?+oaI6WeQ^X%(qcKvO6HVI9$hrAB?&mwN%@lkMzCr z5xt|jR~wR7bmK74%D)qIH+B|jzzh1=C_YcKaT0C%ZoVm_1xh(XTdnvE&D~fm3~b5eVFFIj=p~{{N&FLoR${*ZVM-0Hg<;O zTy8(&=yyl&^$lDe8f;I_4;0TR;RkKze%D>} z1mgzj3v`ojOKI0SFWo<}vBK{{UI(MYFe&4a} zsSWS)QvcOuWUKeeR_J3`SCTDEz2dsY_u8v_D*$+fHD40Re#=qPxB9`dU> z0d#_7nNafxhlLZ^AWKDmJVLM->fI89-rdWN1P}G&U?h2>y$VzLJ4CNj?oj){J!F`< zc<#Z)e5QKGA$r}9>ybn7MR(Cp3J=jk zhUKdhTg_vn>%&@K5Rb{3I{fXJ@67PapGA~UCYuA1ja4A@;U#iNnLzQ5}=x*7i!z=O%jH+M_*#f9zt_hq}b_pl5r9^c|GN zS(jp&b1T>({MBl|zWmp6ST;gB5M2_>6J3KOeTSN!t#(G2h2BkLhuW`&*UONKDeo z7G3m!=Z|akOG*1EcNQPJ0)K|5u4#-&nXH%44t-lB9t=m$cV38nihz~$IsF^+6`Cv5 z8X)=8>d=fhXrnsd1G(7+4BJ`4Ul5~XTIy$DU53Gn!v99`F2iR-gRXy4OIPJ@nZGb#Oo4L(WT~_3>(b&Z07b%xs(HFyO(dXK3JJi>)xep4M6vN4OWihxuH5YCKhLteh%ad7P-X^mtJovAwV#vK`C?;*X9WbDyHA@G$FN zEp73dgnX;3g5Hjw<#F<56md$*VGe$+Z*4$+*N(FPJ}?b+wXsTVIIZ0F?JM!0T%5ZZ zonE;ld=%c8>@WCxs`g#BQo01E-QNn@6F0^+*b;=1yv4EvR>+p*ua)XwEidrSJaAms z`rMz}1~cS~F!4u|pj9n@t&(ov@)XHXHMnX{9-6IE|7!V2-fsT82>YmeHTV?L39$9 zClbwSWxiF?!8d#Un4j|g>BJv?>KNOD-E7zTIQVHzp1QNYiFn4n9%uPzV}AqhfbuB+ zDB~pF3HeSE^Dd10*?YjaJ`F$NSZ&C>6lIE5wfR~pop{$cM)y8sj-35wtRJyvr9alL zR_@=tz#KAj0ANeVegfu(Sr=gL)0f3{E7iYRUQ`G6@@Su~;_4YP_oBTVM-eMwF*GG1lj}SqjiueShd^bvUTtgVNOe)j{v|Nr%o*PrWv@~-KhoMacKi8uvuz#kw(qr^ zQkjIcbJiL;d>y#vo13@pm!4&+2A^_iz-{X8o-envRE8DLNsCR-HGj>zC-4hO+y*l9Y>#Qx$#EagE&({pRM2~&m$Tc#d zIKpaWN_*p#p86s`=px!?b+)d zm-u>f`}|etfhW2NnzU8kAwR{T!#sbD#)$Hv$DBxPa|1c`nX?g1wLRWZJf3MbPSU;b#vGgQyR^S(LKcL--Cxy+x2pXbCC^?5W-!Jvundx5J?pxKnm7P-$ocz8W z@d8HL_e6gny52T#7CxdQ-Ut~_pszJ2iycG!;6~@#?d}JKcBejVZDjTodKsCJT;YqS zmi7nM$kW{2rGBu%HyJvOa?s__#}1WD>C7_mszakgXz|CHNyFw)YqU>;=GhcpXYJHMxy_t-uz;lDaJ?lYJ0Rd(G<@LRhLGFqJ`}1n)fAnCk`DR z{2g8!E36No$9Q%lH!%qw$d%d-*m)a?eh`~OOiKBt9w| zTC_RprMh@uT|7rOAy2$d^@r$ro>fy{(vWuK_H;+?%A)xStDFy9!AEVFJ`TH1G|8_& z)uYiN^w?9&J1yrA6WxSNkyi61n(M$GEGG|&N7t)fjODnFecsX!V1rEzB|d(Yo^UGH zc^jL+&kqpaXlzuzc;VeqC)vQnYo3R9+HCx| zh>oUzM_1`byCc3l9*K_{Yz_4rfrrWVjnQnc`3RW^x)7a7yXP5yjmAgii=O<P8tnftZwzAM{flk1xX=$);b!`x%5sy?(cWLD+ScEKil zZakd#p#J0&*7(opurt>-x(m9DIXd+p(AC(I@*0g1<%@6n7wM9jtJyy0b-D-cZQ#p+ z_E+>#hm0jyVb4fsFu#Ev7@sAh?#KajG&bQJ6!ql1nCxoq)rP$vppL20;CEDV1V;Sm zL-anIfmIq#dOz25tLgrD%y)&}b3A6JeNyM;8AB8 zUgH!_*f}02wY|;W-n%{L7j~b$FW3x2OKE;U(&SLS!9>%C=rCwuQ^t9fjxjj)=JMjK zeY32%j;?pw$WS~mw)Z$C*9m3jQexg^FK{L^epc>Yeh<<0aeG5&K@AK_^Pdaf{vgj% zckgY+;^AjwP4&Cfp^+G=Y+>bXg9N8UPmyl%{(}X{Rbtmzu6&psSdV(ii~UPCb3w)7S~Sz_&H=?88Q4q_Ra1tai_z6|qA8 zNn7fRwY&^@S(DA^_bwsBjF~7Cy9<7T+@klLA3tn+tx1Vj@!rf(vD0H;KHDqP;w-!a;yD?^`A;Swc@iPPP^ry8Z0WMp)FrK zo9jic^b@^S#G(>U;+ypk+2@t&ez0f3?@E~CtHe_)J`+xwgJUd#pRj}BQNBOWI1;+8 zh(|e|gcEa;%<1}h1;#auW5KOnvXEqTt4u&11({ z*ZlomAf6xB{yFkV8m&h`D=xp)?}Za%em|GbT046+)h5&Gf&57Z)1EU26+idmy0kp4 z8Yi4sV`pAn_ddktW-f%aC-w%h7USD#THRQy0b|Cz%ngv&kC`byEnh3g2@}7^MR9wD ztVJOs`hjQKe3Z)Zt zzDno&i@ox++H=*xhw$j{X>$b|6gkR&|Bp1))W??P+_f#^tkV^HBBW_HarQMqtA^z3@$qrQtpOW%zxT@wI)&d>$;duUs?^ zr-lckD&7g%lX`pW=15%MgWj|E`7nGF91NKxx5tNT>d^>{JjTqEci3KE(XK~58dZjP zRLH#c%7q67zZkw=jku;Ainb3MRp0%T>-n-h+xMG^kH=iT5SZm$tnO-=>=eeq>kJ9X=yvjsZVK*Fh+Y?UM$Jol8mqvfrqQliLc<-ubT4;`> z!})A5h@XQ6Z5}*%hJ3;s*z%0`C|+xkgL?2P&;9eNg=MsyYs@-y5uew)TPQqFH1pI)B&Pi+C4gSS*rI3117V?;u4tW40 zo{MH2s(<4>Nv5Qi;DffxSkmXKww?z~2TjHz;!E$3vn;lP9sE3aKU!%R5JwxOEcW_v zPabfm&*EHzbc^apTbh{be!zJb&T(*d#LhxYW(T^1j|60ga^OooXyP&`>!9_oCck)Q zJfixmFV-_c>0Ee5r^dR4c(n=Is?MDIGB^ix-CUD#28ewYV6yvM+v!nj;6VFeY=KTf{?uN4nYNF~eDvgkf5Y{~ z^Bv`IiLoLr<$$&L;XQc$bp%SWmAZ5we{U^I??eVeigt$K2-E<;9Sq-4RiG` z4AnOyE1ap~{d<2#v3yjz2T$4=dRz4FZx4|Krh)f|%$T9PJ(o;%HxL*va&F5)x z&3q$RXsoWiJADH)y&fm^SMobj35QD0&{3U6H~vGndwmW+(tSQ{we_r5I?CXB`hjELvFG&c* z(nCY-1NVG?R|%)l^|MQxOQ(mx2Dw5 zLTo|C7VxA#Xf)e3TM4I;J8L;?$JiF2o+|rt-<1u1-0!8=kiFc!&cYnsrT+O1`Vr(^ z<<%R5YRVIBokvyTBs8cKl{(gMpWEjJauWW4cgBE(sr{Nk* ziO1H6$0pcs6J28keMuSB)T`cUgp>5N`ZL8VME1Siz&nrY8{boZKW;U@cD?9l+9Y-X z*hmM74!V;00_jKFPu&Gpo#u~CY3hwZHRXx6aFQ-3-rIGI>qsMgir)kJIezGF+8+8y zwkK!%u|c^u7`Ce*tylndSwQ zZ$BZn2V-Nz%7PBG;Rl-zJH(GS8-YPJWvZUSiI923!kFLA*2@n8HjL&N z$%pLGFEZDLoY4nJ9t#*)I_6ryTsHpH{N;Ym2+5a-_U3CpKDc;(WY zv8?hE27g2hrIM=bUnY-UYs)68{&Z^ZtP34~e}}!ie<=>^il1mECBZ zL`S-m@3kN=38o2l$QZID{iJWh1bl*jvdEuE-shp_G|_{i z9fys?$0p0?#_`D^4Dn>Id6os?_7*UWbr>CxvJ z190C+T;j4lzg#mvKpJ%LWLMWnjDgw#Y14FXoL={8r=|1~83Q9|u5O>crSv{jUee9q z=(Bwo8)1%f!d?ppYwQ{r(O^pO+loceBpZ!tTWX7d&J z@nh^Fo(~fz@qoVE?CrXn)SdR$aZ1lU9Q28I`5V#&VY6V zeVF(=Sm*;Uf1Z#0&A_WrccaI6m2nzz=v(MhZ^^#WmbDjLpXl*&{tgQ`G5^VUnK2*b zBENUGhl9_f3$v&0)0c!k)SmH|HpUY_&BlrOHO_fMpS~A)O7js~t8XLuF2vrKJZbE# z{sY|@`oTg!k)WV4jxdSCW?f#`|gGMaFSqJ~+R} zzBsN?sYkW#C40$P`!3x#Q1tO!tl|Ey_*NeKU$pi|DXl0!zINhIamhM@t&`Y18+&-P z7bUDM<=4FTQ!kZIh^(>)M*CRzQ=a&4WaxPok0H*+_t=e^w*w>1S0!=9HL3mbC)(^^ zL0)yg-|`xnPrSt;^OA{ujeV1}Gks6er#&cdDvNnxo!?NL!h_PNSAOy1!^9tb-Y=%} z%jeV7n?CK^m#^!3(K%>2;-}W|pmcrya{ao;~ZKBRpGY55z+ZSzZx>&Kae$@$K{8(rBA=Iz#d`U-n0wYM@3*@MpBC-Q+^ zTxRoYRX>WpF3bV*&B%C1xi^Qa(SfV+`Ya=__#3S#S8Pf9^J56Vf)cb$j98h%hTAKl`xQPsdJl3%ei3eGTjqOo<`S4 z*C}7;fW&*VLXQ#S4Syf=?DZop)kBlEy{b)0GU#{}#`b zuGttd{z8VtQ?mAytZCMwr-TzY2$Qr>>CjP<57k{E{T+FA&X#n#Z{|1h#1FbreGj}5 z&$pv>Zlad>~CY#Cyp{X4d98tIk<{&MUwJ<3{nNv&xJiDTDVa{s|i? zSE8f$M!n$6+bN_;(>3Hl{$ea>L$Z00nOt^d@%r4r*;r<>d(+! z($&J3HfFwkI?+jlUcYfIolbwsxJa~Bhh~JLDP1mGS~d&%X?$V0#4k*_IW(1poCyOk z!Os(NF*P)E7Fl7g?3G!hB zq`iM1C)vAorGH|2dOY}ozB+R<_!RT${53L&txh`e$JiRX;IQVP#D~TR=pn`$#G4P~ zIqavwjdRPgVR+6MjpyhRU%#|#$`RljcBp=f1va*R(J7^^^w=V1mxVUgzHT^`t?6VS7t< zcu)L1KfVslxEAer{6su`vBr9`^}tCwp88J@-RYpd=n?uWWCaY64RAznfraRl4{aZD z-lv3UiFTZ)8MwqW!~^og`V(ymKCz#$6{M&9TnV~fdPn(d4e1M(x+XR>K1}u$<3m3g z8=xySCXgQBSd z^HY)$+M{q{ej9&T*c-mi0Yf{->Cef^-w5`A_=2u@6|H85(54L_L*8GS`H)#F`Wh(u zg&{rf8Mz_kp1OOUZ!ZoGX#bAdC;htoigB$vo1cvv9;4(MdW)eyLFUxgdL8QNHTqh- z(zmG2?UUo(>As7MciKc=*D9|<&X3XVc<;#6x_MhwKSn5w2-P;p8))Gd!{(aJ58F!7 zry0Jo76YDzIVc<775KEg{52XQ%2yqwFE6c)uVQ~+m>oN{`yD4|f6d=VA9xk&7vB5s zvt{Ta)d`vKIGG>lIcOs@^354|3GIC4c7b-@_Z00^x|2RctZPJBIU^Ma}G1pF)bp`@H< zU<8erXYT2@v72~){oZO;Sb`5r27ooHJo#fm2)LP-3zUP%Z&Hg9) z*v#10l4>#bW``Cy z(T|01f8}ifcw(;NT5fe6e}~eIhlLe%`O|uv#`f6dcYD^?8F%pZ;c@-jCp z8=dmCj*?JL`dVER(l`3G@t!mN1Lpm(u%<|wX3G=wJde7@7EI=Q65FU~|5cKo(r4J( zl!q*-&8hryVc1ttVNH{Khk=o3mg8ITUQVjLHh-I8y;QQqePW+x=R3{Uco-MqQ#jaO zNq@>13Y$`6DDl^-q3{V|umwtGWpAvCzIRks@!Wc8Sv}|Ot>2iM&RxjQV=^xx`D;~t z#Fy%Z{?weu-q@7ZKe5l(?txF3UqXf=yJ7h3_MrLj8^HJ4@a4qkhPNNYPpgK)iMqyh ztLOd1^uSs9r(+IXbO~D(8_ySfVw*2?l^+w=3orVAMV#!r8{W=wb7kyb zR(gf#FxC-}HL%k>UtGuF0ecLT*hJCiv@}3aiPZG|H0}Dos7YwDJ{KkMf&QhWPbiz3KY0{dK+RG`c*`JJ*e%*9;ns z;QP4DV+4*7I7Z+Yfnx-|*AR&N?ETz-P%*271#?d9#b;hbKknmm{^iOz%9xd_la1q7 zu5S#S|Jh0QcQB6!wlR&PhF8o#_v}NZp4H$|4zD<# zJ)yQg^?G5iMuTkoM&R!;LU#D}jLrqb^{m%D<#!n^Xg8ux^)6EwUFq)+=YZ-dJ9}YD zI~IK(*1L`eEl<3$hJrrXt6q(GZu94bbFJb>;X&(Hul(?Xo@i7XTkF0#dh};LDP!nlYX8vLwXFQnVb7}VVV{$icIs)O z|5WBd>t0KK(L@i^7Q(%)b#_cmhqD&oCqA(ixTkL?j=js=?>b9o^Z`HWITxn$Rld%(T+{xLLGTtogv_-dgYe>H;%{6w0&Omqr~TA>KY2V~ zTx0Kof!ddBxxtRE9*+~x^{iUoO))n9p0=jG5gA(O>>Q$+ z#T=Mu?5BS9$|D}oQH&9!H|;#`I5^!|8eUR+B$QplH%6&1xagNw|G58#9`c)JLwT(9 zU0m!Bwat3fdB5cdD}_C0I{HVmz4L<`m)GO*KYEpP;NYw5BlIIkTbut{!zgNEr!ArT?cLY7S9jF5#u~&FG#=GQl(Ija~*< zC|sKzU5j-+cvBYX=zGPda7S{IY|BLkymwLo>2JsP%;(jVLB$ZjTwW9kNXdL zSC=-I!nmKdgg(a4FZL7pugxxR>1>Adw9?yt^$zy+k4tx;_*-_b=NAfuBnrpMQIy+m_ z!+Ey$$>hvAbH0Z;A1;gtsSEY+IviV4bxU}+GiLdDVDRzh7n6DPbloeQ6oRGXX%|jG zrp|6tHZ;itu3BT@-t*neYw?dxW<81i9+}cyWr^>K;Iqea*n2PFq%&un9h#Z2^JwM^ z#PFn^$-Hsm<41I8YseXRdA-m20rq6E+~DIU$Se9!{2Ufm;@^kT+sqe~oSmwOQ|Xz; zVtv6cJCE-1G~#R8De{4zC*{?84|DM71dSEQ+e}%4R?IK=n(sxQisulTyzqQKezKB& zELoROzd%{c31C|hM_*~Z;gV>|PZsMq$hh90=eb#Ud77oyL#BgH-J9wfytcZ1+SY|u z@8mYe&X9(FTXm@=l+Kafqo2bzm+gcd1s#>C^&ap+PpRMYd^QUwPsh`z&0W8@p5-}x zK6WK-Bj7ZhH9MzVJ1ZYwz{zY&%3(~*ct__#!HGGXPS(HtHjLw+jUR|^A9S^hrA19Hs~_WN?KaxPPNX?eY3FGi;m~}_Gn+f z=74?QRI9H;$)5C0@%tm#5~cm2r_UM&bA=i=wGvL?C|>Eqncw7|vAyPz_N||$%)6YG zRlr>K1vYE&VOR8f%RJ$w{`r!%!oA+{VLTUB3K^d>-uw<#OWez}c14<41NMx$0C1X)D%F zeEqAw4*rUY`lu34)xOJCOBZmmKB#I;%E}x54H?_u>#)>M0&~22AFWpZYWacxWE@l8 zJ~}vt=&+7c(5jZNR!XOLjDD#H7M0474r`_QSIbKQr+wPtm2iol$;LWrG9`=%v6Zv! z5B4=?iSa0RuerdZj1%+N$ROk5hT#?Z#N_Q%EANM$&dUI%gG+` z%t>*@ck~s7nYYD84vX-EADV0&2 zPiQTi#2=yFnd0Ixul(Ax9>;zGrK@KM{^J`b@2gDlbl9QzQ3yY}rk^g+zxg?GbO`%U zH1?0{p!}7>IFF~xen#y9q70=~dAe_ADB8Qj$cH9l{`~hvNXvdV_E~UUPkzOR-hu9Y zSWkMjmgV{2IvLM1R%PtUnq1Fmn|}=b9?w}T(OC=bYo%8%eauJNeYw2NicjOIQk-m^ zIL$%%jmz`*2Q9lE`8_{r*Pce&bH({|2f0>x3J+3NJ@bkm!oAA%Y2)j?^49WPW!I9Y z8ELD*NPMUc3Kf4G9wTs!z%c^H2pl8uy@G)HKp%du)V*9iJr>nomn-Xo6kiDo=Iz)| zXs!J#=q-lJ0P>ll@UK4z=9h8X4=jHh8b#-$Lad75Ngs3Oj9|DcA%*3-+ziTCk`l zEqITv&llz}q1)&8m^Q1g)MjK2xN&dfAyGg@9apn^`oMoks{HQ8<0 z@pQ^v3lDI`79ri_e9=#rXc3aum(xhBJRPp#4Lb%sf_!_vxG!f{B2WJ8S6aE*nf{51 zjccdpJC+7=_HDSE!<{$yaW-~nZEJ))k|*fOUl+E!=R?=)CR4FZ-zco$4O)C>tx&i8 z9!X>(<_WogKgHXb&ogQ>%Fj8UiJ^{d_MGd?emS2G@_n#&W5L!2Z4bVUfu!Tnlf+S; ze`h>L?s;cw$D-W`oK!Y@BvjYrtQ_CtEY%5i{w?rKUx*Dv=-(yshm3IkX)jEKjSo3% zef|7=&{4cIy$k7m-#>6I-hJ2zj3`qy=zGus;oiQ_ZKo@Ooq~Rm+(@s=KZf#V&vlHg zbeW4n+iT$KUClMv@Lk5$k#qMhPW7LnOzlAEJADC&} zkey%XdzSa@*H`(F|rwCihi0lM}LSP6=aFJ@&3`(+%GRI*%{x{v-S9SteD$^emwuu zOq{?2nSu}Ywt)j<1mgP#?p>L=-&Gjr$w$wfk@bQfXW^|7eG}sZuIM28K;(z~ahkMy z_Mzdgg|gMZ$yN}(W@1I3BK-qav_1GRUpX_upIFae7~iW8roA9L=n?9HE}t68olTP` z`ag~7R5$i4rs0wn2QB4G3mb`($`)O4l5Hzrj2fE3t zPo9a>?VGvV$@iJ7#R;3r&a#F4;?;+$M>9gvmHmWnLT`IruC|9h)mib_&s7>m#Ce>+ z3VPUC<#K=#l{=zEp7SBM@!2gnxJJQVrT>d=fh@$ARytQ#m^xh zNulHnKE-phL%m~-SA>s3jp^{ABff*5J>%KVaIA5jqvzb6g3qR68qV*dZzh(I!;a~* z=I`-junUkg`h9+WpAYW}d-lr4Y6({46`#$>PcOaFVT*_+?0Z7x=S4 zN&caLMJYzR{TzU`=%s~VMmuND%a`T-QHt+ohvFA~TD0lfCuCD<+!uWGnQmoHN_m)H zW3EK^O5^KTa*gjR+NDWiJb$e53Ts>Rn?38RXOKso_ajfUu@ODhFD;Zk5aXmdJU_l; zTuT|Wj}lz+eU^_?|D|_AAE9xv{NUc*9-C#X;^nB7Z~{MJCVizjM72BF2-r+oKhPWz z`qpETcCEfr^A6yIO#1l&$rik{iY+eL@*({3ZqZSiA4u%Ku9t3(_AY2Y7h_?`1$ksQ zq~W7D;l!9k?<6f`jxgJCzT=L~5qi7d^Lg0U;+r-mJ+3x2darK)JJR=42}Zm7b7A8{ zwL5UqxH0sl*cy4=#h55JvarrN2Ko@$7EgqSjgRPio{HDSGq7`;4@SYNI5u;BY*Tbn z2~PQO8#qaq%jTfnLJypl7iSCSMvFWoSK_l(!kE8cYX;x6b_RBGEz5I4jmJD5<*pN- z5v3)|wv?=4v(e^DQzdt;f=wD9Y5WpbD@I^f^fA4$iTorw&FoRL0W^P(oceKh8c(el zSArAk>Sk9bV^!+6+n%f#7knGy57*9SyS&)+>yvBd!#CN><7u`cCTTp0=h)|iuV+23 zZNc!Y=9)w^jh|MH6VKAO^}wWD8T6~7*Q$7w<4b%q<}Fvhdd2&(V>y0WHNJ?`KK(&D zJ+vpDdA}skY*jqU@deM!8BKQ$W-rW+)xkGpW!L^D*h;hMVyi=_5rdEbx_{HnR&Uj?%~13&1>t)e3va7 z+WM-ec~Cmd$}gT19a~&WVLqL?Dsbbx*j_*8YV4aqVGn3LHzOK^+KZ;S7uD0J;ac&n z5{f@;OiIOlc1qsyxE5rekMfe4MTiN~a$A#Y;&TzE5X1 zfUW<^X4aZI>FPn(mr+97%GaMy(+bz(OCfWSY4eeK9*6a)LnF$p2VZd+F`xdPwEjN6 zj?4NW-^X?5-q$znx#E1f?}cmCJH|+L_s?~$XWwgKIgGy7a5%2-F#^X393${SMnHXC zHQ@&thqSs?gGn`M(#k&SacTAL?z^(acT1+P&e&F*%Tw$R;I}Z`d7GcEdBz^cp_%T& z{ERQ}sAB{FzCK(t-!XMJJ9O*9So`|+@VxfERvWShls!D!Yp?Q;Dpum35V>LQ5^So) zW3O~zjJ)~z&7*{s$A@e7C8eEN*b9ehpM%%+xq*^1+O3Y4$H?ZtM`<6`*7u<4&~c*Q z$~cL~p4Ho1tZnW`_msnmvN#i3?z!S^?`mO9Sp4|#u<;WwtaH>VL+C8dG^nm=p}v`{ z{po3Gh@&j=LTLMnm%QH_;tmrl@y0&!a&<_Hr|%-KKl7264jX}V+Jl*vhB)4lcp>E5 z-EsV3;UvEJrdB!r%f)N0oBi|U(hx7dKX%Tc;NvDOJ^f$cXR;&c^@*XCZlxoycs&fP zL>pP6UEJQfxu>5;@lL3Iy;9o~p4b;YFKf$Q5611z`~72&gVsOcxmj2VpE%@OcV6dG zm+<|zGHp`dwWn=?2RKtF>PUZI_+GcwjX&a$ll&Q^rC7#vrj5N<9z)9JJ^Jz*ja7_I z;XW_#j78v!cTb&p?%M#*XiKycFf8QHV-eq@k9D>seul3C(Sly0^M-QBo^S&D-YX|h z5r@6v%V;E4qC;DQM~%B|AHk}gNr%d(0q>pkV{_*Mze?vrzVUtSd`CEU#=0(NsP8ZJ z75qZn+gk6(=YxLZ=hyC%-?uNYl6}BC3h&C^iKnCMMq)(S(BU2HJ*qzveL~5P`ZWKH z?@Lif&Y6J)_4as_^8*pbo8ORAl#85ry(pU#dG#_)+D2oe@>O5-13c)*yYse+aN@b% zFaAEj1-}<@o%ee$pEY13USuDr50*?f3nyVjNIymWB~$1EuOmH98rvf``^CfO+gv(5 zL|OP>;RiqHAMrxpL7a3H`dhr~eK#r;9Un4AfhXQ$-1e9s(EC*%v^<Q6h11~^QLRY6Yxaeg}x$Q{nyakwaq)%5}#t|Z=Ru( z^X!WXU^t5kEXX zdu8#$gH`D$=6Z>zy~Vird)koNu*wHFpC;{^c8UE(9{LdF^*c1(x8ju{GQiu1!xf<^#iWd#f*=?OsGLinmt6 z3EN0G$PV^=B44tTrK9NU&_mcy)~`)-joi?;V>gzc8z`16UC(<_AIrM|t759wktb{@ z;Uxc$o=>jvPlpX5oZ{!z-qQ!%?dhA^G$(G%FDV~$C5#Ppk8R+`n$2uyF)i`r=j0Nc zIG-_;Q~UG28I^~SeleH3v&i`rJCo5*9PJ6cL%ZZ2I}v+A{XAnh_|SdWOPu$Kz+5GL z2xCd+DAdL&C+5AG_t580ZAvnQeO{ECxfOheY2P^QNjeuywtD-_r}l#foa@n88U2GE zqHOdrXC2kgYt1WAwmHF2_RN6Ii4O%^T=Pxv0v`#7hmR9=g(r<)gq6nU%-eZCSJdCz zIkd$)TQ`Tni=XEER6k@6oFqTsB)!x=Jy7r;#x;53xgOalJZq*5d0Nm$N64PGlpHYDm+nf=DwrQXJIAPUd`P{)FP_s@n&1yGe@?i4YBa1# zF;5`5W-N7>`doba(Bq``W9Ot6ktya2=%;8uerla;kj!iCvZP%V^lhSxD#}two5&Lw zq0^wjoYd8s#GfX%X21zNLw}c?tEDY6k1BZ*kF634D{KPw&TwiR|Qc zv5#vHc2TnaXEzy>L=ngdSyjx;DT z`LVH);lmm2$^L=VGp?Qo@z`pi=aF&6e*8empPkA=S10~|@d1>`p>xz*Lh!u%6y z!9sZywi-U3AMu#9wc7oJ1bg1{NS^mu%x}7+d`iBX>IJNVijbeivF#%{`--=p2D8Pqa;W08ZZj-#F(}Ay4RAY zeWoXT2ka=yQ!{ZwziT{wbmgg3|JEWWwWLMQ>)jkBti*HDpEtJM1w4b#jfCn^#EE%u z{8;4{9t`!IUpQThj8vO8jO+6Io0`(^C|Ftw`YBw_0MYSpO)_8`OVXmfsZl9 z!YZ3NWQ}Kz5>D`{w#V8DYb&=G2M3rFLB6Qx)WYz{_4&=S`ikCX5sMPrK_bL$^-ta6YAcFwUl?5X~lEco08wl9M(yM5n+BEj=H_sI3-yavPnJcav_ncnk+mP(ZWqLwl*Fz6VW{>_IG2FVErOKM|MAnQ$%- z{c_Oy*OH&_z=#JQ9zHUq9KaiU1Z&YhoYzUy;W0j>L7&I*@qKn?t>pY&tKlVn;`73B zJ^VfAzmPrji;qvcCJo;-sq_w}=9BYj@WQ$(I#FjB#b4>0ZQh;eD`ej`eUbLur`1_; z^5vs*SBg&ywWjIMj`?)4e)8vW{kdxRY#urZC1FDtf4AJ^WThG%uD#)VwLSSo;M|JG zN7uzZFWJZM<(l_KpW^v#CRWg;EwHzqdKUIC+x};siC63b_*9*ID1GAF6FLjI0Tb$o zJdDmxhkerE!9DgVGKM`ydF1ytJo$*{U3q-`bu+LMJ?vx8Pgob2Ug_gGZGmU<-x2qJ zV0(Qd@e2VCV5#*5mA_Xg`p}VnqD=1jK~wbOvYLsL^hM#Ut9>V_ouA>PHlpuE&v)h) zzz+E;cTR`2tf^1TT|2{`fyLa)%+0RO1^lPrV~Zd6_-28IWEM=2A>!hG0lLk`$kQ7> zfAW^jPZE}nBZhJ}ySom#S_km#dSW;SwKCIbDM{+U*KoG?DHvtgDH$adC2!H@cf&_^7TGK5}NAua;W63*m z)RLUF&q{xYwrofC#vZSIc5T^?y?e6Rw2zV<+c{Zf*FIT|WS_HpP7?M={@ArQYe`O4 zz0tV$_p65sKBCb*-Ay*T+h;KIy6V-dk9%+3x^?T`s^Y>p?sxOfI#_Qyk#cpk8FddG z=^|&f$U{OWhMZHG|D@Yc2#?SymatbhwP=HUM))Wr?&Yq&ThWemX1&4KCWP8@ zS7;(~oBQr5rzr0^&&WRflcbZGR>hUAL+dw=1Hzwj>2A_V_=)#i+zRJ=O*dqIvRc{o z?g*V2(k?+5CjIxI=tTY|EvVnH&*a>4dZAw+od`GKrHr~)dQ2)uIVO9kGO6I9zaKD3 zZWD%+rjePS*mrUsT;#Q<dy=4FmM;>S?plV~t0ZOhkj@P0AMH-^+>g!94D*AC3(OpIoa$v&2GAUZe4j6Bp8IhM@& z67Lx!-z=^4+|)CfcM{DcO>_hDFXuekU1W@#`H64}%nu?II&qHU`bypzMz?IEIY@LG zrt|J6$`{f|@Rcw(XWSQRuIF~T1n=HtUY-Rm_q%=ei|`bAT-MkRf;Q$h1t01LlnL_A z(7f)Ib(i@&`FDPWml#s!m}NcZEc3WD=asm~@|>rubWN_MSU34f z}mZL4F(OH_0O*X=v7= zWXw@lAv_QIz8;~K(22Y*GMgd!i{FG^9GA2aFpYAF593?|3(gG5XJT7m+4R=Hbo6v}%^g$|KSW#{AZX58C)N7odHtt*#{a@f<_@HEz&}UL8@EP9#``B50 zo_Xb(#$49Co|SZtPodRe8>!?#h%-Y%FOETe5&sV7IgV4M|Kd(6=@%(2{dK=XX>UB_ z*dVP$4$B=VW_r2Hb#<4M@;40e8?T47A^%VZGwV~#M_wJ(k2`2sw;P@weiIv}jBBY^ z)-v+W@P5;1QvK4t=uaX$DLc$G;@vt%-t9i_M%m;y6++e<^qYL2pVZ&pZF<>0?KQ$n zs{UcUWqx1@t1n;H!W^gzrZj_4<4TLX^ig4TAI~H_>Jgu_-+GN z(OBDw?nB*@HUzdqxkXrTzj<8hAy4ufb*OwTs?lcmu&i0e=_a&dKa!s)pKp@U@axHV z6C5Xnl+mnDWE0mfVjCds*ml|LT^N-e@!(2>HelKg%(~V%tPk>C=p-Ta8S0&~W_RBK z9|_*%!6BWLZI^2}k=>N>#FO@|@%$`98!%}la6Cww+^%hbk0EV9vNpxtCq2RIjY63d zZ{kPPNm<^iFE@-j>^;)o+$QZ_zOpSWX}5#*L4FhXB$PQB=cR|Z9hOCtXeRT#j635V z9@AW?eDfTehJNdhBr9vB`O!IZY5PIa;f>lRjFLy-WyrBKi6#@%hI6CX4oD};HG_T! z^y2r$$jWA?Q}FZtHO8e)f#FdJ1@60}Q)(n%CeoPe7Cf8L%{b{JkC~?)75bRroQUf! zbOPZo>Rw9EQftKFns=;BaW+0%+gPfTpBVBTI)$>cnA?9;;)+hRgN)&MKi(+^g@+#% z`Usr&!cX^1LzCVw?LR8vN%9ld-lESxD)bRJ)i}Uhe$PB|m*bVX+M_u344Cn^H|`SO zd&!^gbyBhii|tBZJqn@pE$zSN^~Sx>;Z|k1E~c%3Hn5TH^AV-fmcNvwKY=#jLw1q7 ztbB?8ZbWI{-g9R zc+m$c`vN5GI7051l6oE`x=ezVc+jq7#z}B9)^qToz&>ey#P7s>x2luh#P@!ye3QyP ztZ70M@vF-_!(09R1hGfm3V*4C$J`2$+&1(^JJ~Qs-baULC=TVBAageycFYiXU(x9!J zds5z{(*b3KRtyhPZyht|H^+>D3BZ-s+=pA_Dz%$w;4eD)?SZchQ>tJ~*# z^Xr=wc#{HeQsDklKxC1G_qVl&vv$G#Uc-kItK)&{ZfO#mpAB;_Dj%NVo3wV5I*$j! z2V0BaA|dy%;0#rawn*;#Y58hC?qBBqZ}Zd59=<FK>P&GAsL`q)rJRET;F? zy1*_W_fL{GbnV92Wi__)NR~jXr|k}LHl4z32hkWR-AV7%-zu8Zu4@l@xgv6 zbL%(99}GoqZdD))Ic!#rtGmVdUh|v%n`RieSChOfX$)_M`eaiC7Sc%0yWA_@=5mxx zcQRg=Q#joTI?(?z-bZ|YSjMN&X&go~&Jw50<{r*T=XWFz!;L{LO}cYWtT}x=&ar1c z+s^#sv?W{*+J_}HlDn(M@fd%vc|B@>{2S$$@x(I*<8_$dIfoJkwGXy5ug;s1zsz|U z=bUNQF-~^G88#30)t!zv&Q-*V`q4Np=65+;K)Omg$02#c%rEA1uDF9r(Ft4jNB6&w zZ#g&eNmW{F(yu2;Cux%*^&>eGBzR2>iP8|Ov%P4Ra+jsNJ= zkux_eXFj7Kc_cguT1i{xkY^GEr(1=@fn}&SFc0_TGmU&k-XR}x+=$HKxMMocMF~GJ zkGXz1-_GyMXXb74liX=whV?n$HPMcxB(>UodUbnd{ z&!L&erpP+xISKl(4S|PeE=T7HOD@It)LG2%v!5wv<*cWaHHSRY$#d28>+pwZ`M4X%v!HfV!WKJU~ezZX}D)RTYD{)8{OFI4=L98v}J-;UwrJ_;KFg zSfQ*5mFMk}p4`sv2>j$7NoPpEEzduZ7Chs#Jy;A3wB@|{jQ$(N>z-Q*@~NO(!$X(@OCuPw9cpwGo5&+ zkZ$%4ELZjz01&y=>eqBREptoB3&+PI5-kydI*CCgo3pM$(3~X&!ST3*?*JJxn|) zvn5?Z-XS8ixLwHmRXFdF#+3WKPfP0K_^zxSzVDEI$2KUBqz}#fBsiQzD7Xrp%<`Id z?T`kNhrC06;++?~KPI1ObvgIn>TWvb?bW+6vpgE7qnS=i-oCmcOK2jxx_NCUa+5Hf z1bw6pp#kR>>d3MNO;=j0#ECpWdNJRf-a$uR;h2)T$%o_gk$3VI^ToQ(n%t4aIiHW{ z`P5UW(~^DOt=eSmi=!^vl?Bhub(^I`l}dIV|8?`ArQ{z&~&F~R;8-r#r>+TAV`x{^j|M@F5)-%599CzWA3+l_8j!#s=6 zac_o0;`G@l9viN?nSPS=8E;GAniNuZxYM~!?kSLZZpBZmk9kNZ-a*On#dp$$@|)v~ z^NQTH#PzV$IS%_tz6%Uom#VdXb*n)+!8pHheIxRG5`UP}$d8nBockr6>l%(V@*H(m zX;0`Ra{5+w3i6bcIZ3)qYKw4CU*Z_(2faJ3OsO7Bbg?hB7?88!%tIQGX2hFw+oX9- z^exhga?5Og6nq&{KJm^q+_z!pyIJRz`AS6j{{j@t!PyJH4R}oN!pm( z5;`y>{AM~G+*f4WVZl742j?R`d?)?n9x;Z{ht%D4vJN5rjWK<&2j94N&A9u)yq>!i zoyeOU!vd=r{*#JJ+eS#7+A-px=rz1khxefvW6-#}hrxL&>`)xL7+ z2iaRLYp6*yqK$>)o!`WN!u9N0g~NHx1^e=NA5b6XTsw(QvaVtql!@j#%{biexU@?iAe@w$d;=5u2#-h5||_$67Fj6pS8`IVtM}!c4j` z9cOz|W*#^cCr=H1H9{W=Ss(Rj(uw-(p>jk0O!NfqS1{9wHatGEu3??5=Ry1gA9E=7 z3`M8m+G>(sWyaZEw&hrd*%v8xEZP8w8}%r28Hw}k9?Me4GSi7`WUl{cqmp^yLC|Qt zO`#Rnp#rbigDB4huSuccYSy{AwhswbKFb5lcvk0_6Q5d zj>st4Z}Eowq}IzuS<%G>FNUN6*C)ffp<*&l`K>f#_@QMTF1&o8qaM^W3FZfpCJ=GF zus_9K{YG>WSxj6_PAQdH{+&Tn{>-B+DES96+iS1ad#+B%mzZmZBo?pj!%XrwDDU9p^tVixzeAsCueI&HHX>Ba@8HQZT zNL~raKW4g;PUidj+M9*7T5PGo2lvxC#a<`nB@|d5=1^e8d1#Lr=bPis0d)h)Bef<} zG&;OKG0HdxhTX<&H!yU3v9qvE(nP|CnLYyB0i6!>#?5rPc|CL2d4_AnM~OZUgiaX4 zW_>|mcof0|etM&EcMSYQSvR^r`r)4A#{2GoPGdICF*$zMW9&BN4gZ4C@;E#X>-zzn z-uRC8qtGhrNhG+g;ad4&^4HyIzX+XjbDH&5_M^L{k8e3==iW@-QOEs_Tptr2`W$#c zyxe=vw#{$~EatR_DNgvfHYQ9vfo_-mUiBrG$ODmN;^1!`jEyBTJ=S)+E8H7Pei_G& zYe}w;%r==@(P%tmlvACqc#?{&o!Lc;NdQZ_5nV!x$HM zWv`RGzfowcV*(Df-h+N*_BZnz%a7`$Uwx!U9p*b}=V7Fc876`APVaD({NxS#NU1}b zX>>r313!&gA7X82*pY9hlNp|eF@Ava;n*9&dN{Yd(SM3@r|ugw_87>QI|<*Y%?J7Y zR`A~`Ot&h3yL730JddP5jNv$}@_rOprH)DAQR;n=W$!00<8?nsJddkwGfu}{=W*5d zW<76G;7tm=Nr5*h@FoQw1O?1WOks zAs?PQV4CdxnN;Wfg8zQjJB|nUfe}}pXX3pA>$^2yd*D_3I%%(?4}j04zr!v2br^D= zMQt&#v6`x`aSy2c-C}9)e&Tf8bqmZ4VRM`%PI6w}jPr5DS--i>@%VA$chvgK@X>zF z{=T2|G1Hm;3Um9D;zz~rILe#h;@?~07&7B=KjXBco8=bvzi!F6FbvNvjKe_rXZFt=2VdMv9YQC{=t+2tr)~P18Oq`}lG*&*NSyP=%a6a) zmr5AqZ#A#le1$ZenNi! zC-?M7T?`4E`Ao=B@xI&g24s_AGs7uy!C&ps1?-YO9+Kx+H_teZe;a?7`A+u1PU1nz zF#ZiIfmg!2#rIzFOIr*l!8VQ$->EY(KV|Kt?~*3@IHn}+R-ue3&Uxf(b=DnpHs?3X zc{ALM-wW<{Q)aw9_L&*BNpa?3Ii8K0^j*?8CYg`)=a?ZMlE=t9Er+14Zio9SK1Vx6+r8p@ujLFn@l30629pFSw1s~pD!-sblO}f`W?tNfcwu?jOhj>NyhsoT?F{ko@Uxl6`?;a$bimurK=|C8` z-sQNEy%F2>g#UK93k~ih6wY}TK{l38xzmYcTez8sCelf{Uy4{Jq>eV|j z8PBYTWn{0@!iw%5r<0tKB3*<=47mmt9phecJxV#jn{vQh&vGiD&f60wjv?Yl{@7fr z*~wqGy4#8S;wa;8H%>VY*=}mJ79FRPtcA_GfY3|Ub!IqEDlT-w8JroyEqi$7o(js` zJCV=KCvt~%-cI(X;>I0NxPKDbym23^*p8{cvi!JiMOuk0I4RnUx1(r3$7CstoS~T!%4hL z+oQX5us>3C^V^LdGp#7wSx+ODSs|?$pF}6hD}LkIXwr%LljxUBH_K|;1!T-I6ng^m zodjLR+hDu=Pwk-`?v>|#F-)6;tC>C$r>vHG7*hVrH*-k&#_w@waWUUdXvAOEB4!#% zU1oVMYifQQ$Kj;j4Y+VW)9~&Sx$}hj6lJp+*IUIY-zk@DY}feBkhmQs+#U!;5V*ei9hkA-btKE3yves z_vVK(jeNs=9FOEJsb50s1XbU%x&vA4n3H6;nNEzG@5dR(;UwM#e##}`DatFu)^cz^ z)bd~wv(EdIgxW6>BMox^)+iV-+?nuA9;V!GKzg6n2(>qm-EeaZ)AfyDD6*N z%X9vb{^eSbYiB;94>He2JrUzERfi$DO2R0EWw?5i3jOK*<-HX9H%}ozD^PTnH0)6WgQQiPKs7#cZv60 zh|Vdvah%YGO}@$|3R_I4O;hMZnyEB=<2p$AOVz2)CA2r#57cdCzM%bb5=|zhQLm!? zRN#^DBx%MrIfi6CDljl~^W439kv(Sm*BwdL2ju~}0HKCK- z%koBk8`6vXD>RuDo-~~}Cz<{HZBf-lIqxe21(rMX=yTlFu1N|)=e{zo)>!SQ(Kd*T8;$iy8IeyZ~ zC_l;nYlh=N*~Z8DRQieY3GEuR`4CRgm(A-MGtMH5rTlnE{eWj(19P?ExD^`lz5?T( zAC}?VV5SS>T>nvTr>8=p!2jeyZ+FiI_=0jSEt^B0uGTzQ4IuR!JsrWc6WI`yAVj#^Y||${Ny1)(W^!E_w*h zp>2U_GWLW{wA*p*%XKm9q8-_wlfB1!4E;hd2Ja4SG2{Ay_|KV>^x`9>PLeLSYKySQ zTrK)9=kQz6NpyCzPAT{>q|RgL13{t@ms-ulIes) zeEYKIxb@u5wT*EHrmShzd2#AXD&0&QLtpjau5PaJ+OvZ--YvE{vl-{QjdYeZ4CfKy zPvUN-(@E0ec5Mkvoa^LHW6JAW^OJFI{6KHo?)#SQyUZVO_PUA}$&aXm>6O@Ecl_?P zbYxrE4cI36N&4qu;hjnJ5;`%Iu{5%`nBDR@Ds{S7^g|3Z8&VnaT@V`xn$hs zCuw*B%9+FYlMVAaPWWmPeI%_NEvUcqDs~gr_b}1pjbKsu z<1UZe(TU@U`nuAwAbTc_QI0ptY@v%eq0l6!RS6Rl`VDED(Y-m@isPx@#k(Mf0|;iNnd zB2D0-t(AVapB3#?Tq_Cw4SiS^l5Vi=DP8pDyT$|tGu#g% zE^u(4h3qqzw7U!8U*XyYb0_H`etFtJSr2V7hv{>$u2l3h{r$8DL5DYLQ)ofEx7jZA zM&-=kr4B_8-c_!AfZ(g)T%p1t4G(BVJ_?i#nRR&Vnd^R7;$|ErelM^|*;|FA2iMc; zQTHKEmgo1<_Wdq%E1Ztf?yc&)UHVblJBhNlg8e9M->S~>^rN(K(q+eCm-nNzjD}^`wAh_?sGrr-tDx|MIko{exln@-Pg>@n0wy4Ca%er82@` zB2+Fh3`WX{Lt!u&nvW(D;bbAH(u+moJBp}xlo*ENfvT5@AAauQN43l6FJ1Ouc;+LP z*I)W)zw-KN%U;W3`NFl+7B>L=yyX@9-X7kkEmvCmPgt(r2w1K@kN16q`+?lmCoGm1 zKJ`{hXCLME-)p&E#J4{}+5IPSSFc^N?0xgSx$ECJJ@uv6kaq3#_Zf9g&+L7Ibs&%B zG0S^cZ*Q#5++zoI`tPvLk09UsESARwmgzeww?DJDjeM5nA8YMTy?pWCPaTGfFh22a z%L~uEextL1d~ZYjXAr&y+z)8v*jq+g7|#>ar~lyfmwxw`UpcM);f|6k{> zzW&lzRsVeFT_5-^;JtqB?Uw7`IeqF&q&eYZ2)_Q-6$^Oq?MD18;ueg7b5oYbF$S)0 zBjh)WC6|2S3ziqGE+enyF~ETO%-^oeSvohiELYzR-nq7wySjgR%5Ay)ciI-q)Y~l| zf1o`>V)1<+bct|Kf*#{Ol>q^}h)?ZPS+beCPv~s~4S9ZjEYD-e z^P#uou1|j=_Y*mb<+Fg}ss(Y?SD@b%+Py~F26ES}KVbQOjDe(rZwSxdFw^hzQ!iY5 z=lzB0Mq9}%_UjA(7ij~yFed+31#f#OhmeQxzEc0kKW_PruY6ng?tdHf`7`2fPGgze zDagYH>TF!OdJW?=`_y!TW%vK&^nbtqd!PF@=<>6tzE}8(>F<5=Ckhs{1OBr7<=^|7 z#d7MimhXP@Yc{0iK$mNc+*Rvi=yTMCzJJdtq)DAN)JZt6q0VclbLtcMpS7Y+3+e=a z7_j3za58umbrHYc`%mBn;KaCP3b-O2e7SCh_rLzWD=k$&c#ZkiP9Y!TCCdwcjxv;U zlggcX%qW*9{sx~`i9^<6`RM2V>PCmOApC&uv-@_-_2*cRjFbJT7p!L{^z-5!@SZ8p z1m3&OKCw*b6VlHDnp)lgy8b)x;J?Foow2-dfjsb*D=o~&k6RF$`{5e$aBNQM3(NOP z29Hmm`>%ZubRVZ@?hWXPw%HF;cSz3#F z`ZL{u`s1B`{=&Iw$2mZW--j<;ymWc`$)_$neU9l1_~4y>^4ZHqVTJnS1udr=NCNESNXcZ|Xm9 zSswfN-gYX9-ZjV1_g$-guB58v{0-*>9@Z~x6Z@yg%hcoy+|{Qtdi zV;Ujyyn6{Bna&Qqg7i5feR_GA{xse{KOy}`kpA+7^#2O!zd2Sv;r+*W{wdN0cDDHy zrcbD2AL;)B=|6ywFqQ!eyrk4#Qpuid-1zBZv5W&;U)i0 z{U_dW`h}^ly;I>A#kW6y{l<-`QTE+c)ERjC!iNG+pYuI^;n^2I?mK(-;*(F!NBx(c z^M@>8IfE|L$}9B^OXm}Rdphu2@BH8PrvAy-p7}@b|DDrMf9B^{)$M-l26@KwO?~im zD)Co0ZoC5@e(5jKXNdphf4FhuGQ!8vhmf5&77_ju!gC0}jPP>^zmD+N5dJyBFC(eXM))88>ITFvM&H{Z#qlF~_)84m-(tL4ribqa*Bh|& z)7yvNNn`&0Gb0%N`*(&hqjrnsKix3e1MZSE%6mT|Um3!EtGW-Zp_aJLNrVbfhHtor z3WilS{PRX@sJvwS@P(((2mO~ne%aFNJaysHH2!DOba3}fZ~6SwPd_)k_1wj$&slfR znBW>Va~E*Mhwa@JTpg?{*q|BQd>jDO{fzjnr7=35B=oH=7T1RvL+cfR%v zh6FAN-*D~u;-&K!wdXHB_oP~TLK?kFxep%t`V)^^zV)k+*XZBJO)w>s^9D?}>C5?e zFkFr^-+VZ~B(O+$E0~P+GYb9ShcAT;aNhEmF;6`<48PO<=fA>rs%1a*2Y-pR+%&@P za7~Bx;g!E<`Pr%O6~DHB{pViQ|L&K+{qp6nef!G$zX=`im7j&a@U=^)ET3h5mizfr z@BOo1G|ffdY5$I~R(xyjt2a(tk~eN-lU%>5dFrh>wN6xRQ1mr_>-qBFPv54|4IvT0Bhx`FJYei zD(2O1oy8gg{m>f0G+dwF;JW{VmaFeUeyppmj;~+1w%`9C^kA%Q(GJ%F$sEN9)-t5o z{s)KpHR>48N8OX{l8&<86*~miW-{l~?tr|H@Baq$w^vTTkOvM*7vlT(re64M>bZfT zo{PMUv+h4LbeG?>SmySA_%Yfo4)Q=)J-#0R+|VZo_chc7{!6lr-#b0Z`yS|)S3k%1 z-!Q&CF=u(4*Kx7)Ovpk?OC8ASf=OpD&Geh zW&wNF=$rpV!G>>F=JtLBbR_TnP2{m$!P>%uv8E#g?Jbs1xAr5Js|xlw%KsvCO^hYf z{VMDF`>fZK?*j(b^BQ0> z*PX+6uJ=*??dV_kHK)OMw0GR-S+1T3Os7BtrW3Cc@VcQ{uGUC@yU|ycAF-?xo~a+O zyjP{6AJ_*f{S%M97mCw+QNNoZ*FF260nf6mIp5Pia8Ukj=JKa*F8`y$^5%T!K5$U} z9j5YJXN|Z2*a}r!Ip?V zhb{5b=x_AHmq?rcnPVArf^uxwi!{)hwnWhD8sqH4VV`C(ZchJ4tWD7`=5*2#?NrD6 zV!t=63w?5paT7nVu5Wz%M(4^quC!kIE7+6BKWrB~HR7c!2Jfi6e}1EL?#7Mxz5bFh z9@w9%zL#Bl+u+5iw++XK#l81Q;)L&?p2A#+Hm7p#y?x;FIi`Cc4-mhC_-IU_%*A1u z{i0>>)Z2#iLB9XeROS-m*F4}UJm9Za0oS)IFMs-HRGmnp-Hi5&*AR}{#XR#>;P(Xj z>K8`i)V=pJrz~HfJTP!@@BI|sRs0qAo`d*+f7Sc6XYVp$75s9Zy~+^Q4+(x(JPN;# z3D#wnkvdRjVOVAyzm};?3h}$bkL?1#FHXSkLu2?2M)-O5{%`f|%B!cTtDt{Q?RyM* zO*6dmYJsqu@O}Fb_EUnd#jEgrzX|qtu#5@czXA=(1LOGqEmIlj36yu&pP06M>lZM; zeS>{(ZsYXnFMa3roBPf)hMQAx%X#-^Bo18uHenJxu6XzU_aRIpzI?^Nyxxe0ysCJjBaBg}bV2$jiTvGKyEO`1UY{4(RZ*Z|}>)Hpl7kbyJ)F4DmbZch$ze zZ|{eJDHuP519@nqkXg>r>RBC<7op zG=87r?cq0rKiqqt7;E$6ct7CzAm-#Nt%A93jt!ICdU~wia9fy*1|j*r!_m&-ZTpv`Wi`_LfIwetTHv*AB{D z3GKmY^ac1k_R`>i*ATMY)XO2o7atwxi&sK>QRM$a$mN5)3o0*c0!oHYp>KbT{qe-q z)oV}WjXCI*g}r}@a$hl*v!qnH*09`fgNEQKCGTKC+4~99@nv)VX(RuVAheSrcVwC;Tu&hmDZRHAyKiCfdz5wX( ziBs=|PUBX5p)c-%*k3qjF8{Jo{@)MFpFM5qoPO-{EsUwwl;zW)#iw6Ak2d#z7W(MV zQb&Z|^UC600rl+j{pELocXG*58oxQD2)@IQd%#Q6X@&Fe4`KM! zO)y+}wL}ArIf&8@CWGd z#2@}GGt9aH^UFdv}9O~uqM0? zo9W}Pp?$0kzMuK0xRyo8{^y$2LLZO3qx~!7`{Db$=__TNYdo|I-P*99qkWFAJl5!h z5jF#r4{1r-;9q~~UkvGD>>W_LI%z@}ei3rAeDS;wcyOYq11KI-rhw)Yw7NxoCKiY32 zKly;Rh3U7w@&T;pAbX6m7SQ+x+Ti!skj6YYtPL^lRC%r;U;g43TUWk#_2Tp=UWUC$ z|C;3!r`v>&Yg)o}g>AxyGK!-f*jC;HJJL_HK7~JgPY1Lc@(=k_@FtJGoKbr;41Ue3 zepWQdqOD>5`1bvlU%Ilhk8&2!b3bLdI!9Wh&?fvTYAp<0re}aB*W$zV+$+Qr^(eWC zyu?rPTBl$6fKAl}+=uC^JmBM6ZiLs6-qYmE4_>)y`HLU^+O^MsKc3RRyC1*8I+bnd zJnB&gk1Ku&bc&6pc~0;`d4U z#Gfy9!k_=I;4>T5^L5y_q#nRIu`TiWPpTif)fLc`I@a&O&;A7bhC2MP3~PMXr(Sp& zGW`ko;jh4-_zdv72Ab|;?@ktU{Z+Ir`vb0Fj}K)i_XoTNdc1~w8uI-5SRUf~8sv$2 zf52-+$P|pZF8Z%`AKQRDX=Twy;eNGIG4S|PtR3K`={^8XC;PvQym*|q=Eu=l?H(!WwN9Q^-C?pGq* z7%()Zt0Fe#fo=I^WDK)&T+KFl3o zQgbZE$Bo||+vD|C%hjjM`G)dD?5YYk)c0ez%fq%ITd%Q6=J^=bk_R?6fI;`om}8^gCzy*oAYKpE5QIJazuUN1l>R z0~anoIZVEA>EcH|#2j$PSS)7>XD?lNayoS8@-xrVZMZPaRJ1#MH{L9k;p;RvYclQ9 zi%&jz{?aAOuvw`m%zDmUzz&6BLDs`4Lvx)*wo!GKXP$eJ8yr+SmyrJ%Y)p{0Sbhj+ zgmM1-fv2B)?xQb0A2MDo!?#fxzhnp-8I14Y(f7cxoL>QUP}eXvf`6=FJNWc=4>2Kl$Ex zYP$YI&y7;-)5eFV&OfdCM_kABicZrj3V6=&>WCFnPd7H&bRT6C2)bxjbh(P$y zT)Oa)XU{&ZjTf1aclu)&EU$M%*FE`xp3+7d34&LUrQwq^G`o@_Sth! zpTB4>ckcW%NE|CQJzY}C)6bv%$c1M=;y?4uGiRUI#_OJ*X0l@P>CiCG$8M_WAWztT z2K{nV2EdDCRSi4!0{HNz-};LeF8i^E=z_t4P3&K~fSP0v6Ip>A#*SlHH1B4D3$jw)a5Kq0}pC_L>|0F9a8k{j|$RLBoa`xOg5QDp+jGw@vzJJVO`MWO~a>yXA z#RB|P#`<%Yr_WCRAcQA2P(6p-&z@65ra5G$OP9}H9B$7tqh~n-C6vElC>)8#=HrRv z*$+K=?)-<1RC9X1P%M>~B%R`D22XsLFl!6N9^~UFxFV|kFm5XlScdV@H%Wh(L&7X@ z^H4ON5ng889%dW>8{sD175qb-4y8Th@Q-*%;3N)(WL!OuP(K{PV+gk+Z2ULkE5Y#* z2uJ+Hz8LbA^ojcR2;iXT4*1phpxhebF?uI%j|d)wnV>2i&GZk``0d2-2)iWj! zk(_t+(@vYSwC#>pR$8rW!l%1!D`A_};j@OU*4dUT?hMCbj)E1k*_CwQS`$3UW5cuH z3OmE;)U3^yblURC8SA=-eC;f(q#Xrc!fGu8c$d|dcUaTT@}S|hEp6>Kta`wn)BV*& zEz?fwT0Ey~fskI;{JLh3>i%{~(>zXHE9P2@3!PlT7O>^5bEwEV8(zWul1@9qxL&c~ z${iOTPFpBEYh6z`3!&_cb;C7VSVLa`e$pLJsFN(Md1iat17}dvD)R%)6V|mzMjvQ# zgdyON*6Y1_UGp#=10MM9DFLsrUf)U~Pgu)F<{Q2CjH|HbvaY+V?2lQSD>_?nB#sLY z_5pcJIepNp;7Q?$0JcS4bLO>ymIcgNEu%%W2I#M4 z^O|PQ3p z=4A9sIFw>P#LL?o{Xr$CXSO1GBLzAK2rFO$5Bb}OM?muwLJyw>;6^+_dnfq|{MHWY z4NnrVhmf8}8uHkKz*aB{FnX`v|-s8f<(JBXL!oJ{4OX1+grTVdcrkKz( zJs;Xn=z(}aYdFJNU32J-0Mb&W?X^^_QMKW3nAsQ5CoaGj(Fa=#fEoSe$!hg>w6-u? zt*-j3;J+o^--ziAXH?7d5`%0cR(35!F7Gt3i0nLl^z{{%zvh%^n zMmFvkICGUHU%y^S>Ww(cJC`)@W_xi}=h&MKyB3ZMk2&i`#A!>G>@7#wTU>XN{(v2P zZcl^9F%H20gDuiI1HMm`x|`mLt70ECn$4Og75CU&v9;CJt$xM>S>^OXjwQ4}s_e*z zY^}9;tLmvNB$r~H_1=6_A2dJ@yQ^1^$Iu`4nL;^yTzEJOzD1{XI|#|-h;O=D;En7+ zi;(v7fWM4(Ay-r2nRa+9UGauW$?e@iEw1Z}D|*hG?+y~)U@jysv`_J*-9U* z!R}FynZZ10FE~85_4I6QHPgVn2KiKkY}$(U>!|?vDGk}P(B1X8V&(GoAQ#MTc)K<| z=&fjtPDw)uTvmYFvaa81v;?|#);#oO-CEhTw9`nfcF^a^<<46~ns{Ti!P0nNGU)wcs4+KUdMSdQr>O z*0$1p58+u|p5KYu*DBq$nys(bR<$O^jMf3Z-ICUvfqV-ttgaRli_r0@uQYl~HI6rd z=UzkBvA8s_Yg%dvb1`@;9_2i)`L$fV=dbvS`CLC!u{V4Ejpglj1Xtk2)R@ld^O!%f zS`Ms-t!iv8%w;I_=x80x<=8bqB{ZP&>y914CrrGsX=KSq)rJHF6H+H+W z-M}1qrLJh*^j3DY+Je>$mipNl=mND0MpbE$&82t!dSb&@X|AN~fnaG}pIKkCFRkq4 zJBz*971wIXnui`AcFf&tKS()8q0G574VmF3UnDj|8>>5;)#Q9=WpQ>xTX4E|qos`+ z{;r?b+s-G0(K=}7@L_B^Dd)WQayuH`nF*DB{ZP!e6^^cV{T)ZkwjOg)p5ws~w7NNW zhoWidmrI>x*J{y*wmA3l`Cekj^(tv*A>sypnafcl!QremC1~0I3M7 znZ-PhHKD_0Uw7E;sM)q2vSQ8P!5TDmEOwPvGCNbS1|85N9IZU;gP{eip%;Nu0_$n$ z48Fo_*cVSM)yw!BK$Xs#?$Lv~4s6zSUGF14&>FSsykp>AXeCzz?Tz}D7R~K8b=beq+OKcEN7w|t9s{P}CF6%w>`Ia|J>gSvLhcXYj^6+)fq#Ee=G=CRgH6ZVL+ z6kz%ozCO@9c;yf8xvo}EwVQy{UUq3Qg(toMR~;*W zUb12<+45HKPdS7>aM=s7@N8iv<5=Gf!B&)Dp9r7dYY19+odwXxx{dX}3+qCM4}B7F zhG}PTWu1j2c+F+q(!7wj{T=A9I{0ea=#yMe5B3MUIek0k*w!m{*S2ka+qw;11UU5d zW*7Op{Z)@W$8n(6e-TH*VM~W-XK+ErKu?5S#&u-PD*VHcYyCh+ zZ}v4k*BuZW4KI4Iv&%Tr^iIa>3qnqGXWa3+eaBf|D7rAmY${YxuHWc4AYbj!YYqD% z+r)@r+tSXFL#Z2Z6Mlsg)9`RC5|6EV4fC3Ud7$u7FY-@c?+2QzF~`zO(Vp)4t$Fu) z8hX7>oY`Oa0T))N>Lw1fkHJ}o zr$96Onfn0SZDFDyA1RoHmkyz2$SdfAyF2<~$AF#v0F^Cwka2C%*}_n>!cLizeo#0K z;pVp^{lK?3m1i3I!ko^oSMN9Fhs_iSV}7v1zJ@%m83*E&4_0eZ{X6<+SSMJ@snW*U z80EW{h#4->e^iAT7jvFb28mGbz}z2#HE8&=s3L9?h+XoFL~co*^JcXv^a>X$w2K%E#o8i#`B1 z-aQD(Pkau_jc{fXf2xepXL-jQ+Q2%+g+znzj66sDH}AvPl=i^OYRqz+FioXX@kIpx z=NZKhJY=)Naat&I5zmO%jL!Jq)F2D7de+H8%dUH-A4Gq30 zUtw+l5O&x!S1K#@e5ba#y}hQ{b*-9%-50j_NKy|tVFQLen?4)(qx7sNv+IvXTD3a< z3i9r*B320fgL-V%6$HQ~?^8a*V?l*HuIQ!e1P+cF^aJQ`#emH##B$yFNGEOU!5;vh zNCb8SC+t%2LDjcl+tO$=fr=?L<4=md4X~tztD!Gx|4=aIa39_v!weX{I2wMG7kQaCpLFe zp;j&8gB=aNs|x(iRroVeX3&dj^y>yvnYF4PfBd_?p=FD}-$`FD=@HZY+F~hbgAVVr z+Va)_+dQV<9LIthcNiDzwRue&Y=M>$`i~Q!H*C;Z_*nr1?6Ez+)9;U3qruKvJMDDz zx@)ro!w*gSdmydGN`0&9kCdY`Hb<i-wyw)o%{|S!kC6XO&he)4;bTGWicP$3FW%0Sf3|W)?q~VmwdR7w;tOa z6rdxH(#q(N^l+2 z%G;SttM6ai+KpHsK9TFcW=92@1)kf&PLWb zsA8hFalY90!IrHrHnd!Du@^|h!=3H!TF-|45!K|j&#$BZmC|q=h$vl-@+xn&t}PUr z^aVnWMzy+=b3@i1>aKZ0E?daC)9@~I)BQQvLmKcu0mps~euP!SpF>|q5O&5H z_@(-3Eto^U&8<{ZPT$5_vEJUz?#|iLj)6Y~S_NX+gnMX*JqApatW7&%6Z7;3cKCBD zi`aAEgHN?kU(IAU7YkeT-B*(S6#SK*K{J@2-}HOhFarT*_ypkJfDcL!=xO)|3VODg zK?r{baH8)s(8;VWv

tF$rJcT4f=dE+&0g)Ta^~-pH}_2gWyaIIDFfxl_V^66^(` zjE%UP=oau0bDtqN&!J6aMp{AH0ZtS^dRaH?z_7`rBx4wb5H`LtY+P&$8v=^VryN z>RIeJqVFGi(;(o9hi1~1rJV}swcE%1k*qGP7M2$5e!v{>Ycr*tOf!rzQHGxx;~adX zd#m-`_|~$k=g%$=w)+A2pS4Z}xPd;+s@`ZSUm|et)K+`7ntK&CE!3$M^mJtvMz%uP%zZ$f! zfnEY$$oG~gZ-XXM`GSlYo;<=de#Y;iZSY~kW>Czb+wjoq}#oE(dmukU0d}8 zte`W?1FZ)CCVc10?;ouJH}s3X+6&Ar_Wg@Vt&uBjru&Zeny23K2G$D8{vCH~rIfC$ z^gD|My`Kpr>+Zt(4Ay5DFdw^hbHs zlUf?&W;S*j-O5gOrm|h{WLHw2j6c5-U2E5ao_sn`?|CpU(zXkSPrXz1MnW0*h0ur# z>p|#MpqJfB8O3%vg>X%EpMO9H>qEPzSYC$N94D zK?w0fe^B@EVb@!so!)e)K{d}AxHB)@bjpsQ06yWqV4E909eOI^ z>8tTT2$j5IM1DE!4``xa0I%|UlBf7B*ED?7h*nmssSz&;9unU7-Z+s4U|(H3;JFiN z^1d|kCLZ^NtoK~$oBeUmq`NN#-|Ub3Le_h(^mzJ1ttq*l!LuIXzE1kk=4|;8&x9a7 ztpLP2&<8&=Gh#W2^)z&JZ)7c3>b4fk$=MM6O`-D2Y&_>|c~e{N*+6uyVw9(kl>0TQ zU(q*>brY+l4^q`^Jsv!8UPD#KeEn4M&r?%F0rvQ4LpN zpB*TFhB`kLNe=v5ex8AX4Ft9d*twO@rsv$+jr(e=tu=4k6|}9>XUg>y5#c^m?u|Vr zJW!<#XU9-A>URNtu5}bHpdZdY#(f*jRBLN{Z7YC1*69J9PO#0wKf*I=4f+USe~iP1 zlFcX|4$h4zKZpijC;e+$0QzKK6E@uh(NVSsW7{^xvp`2J|yqZF!7{t$A-h!}Edg zhc$}x@Pzij zez4t-tMdhDi*^k(eN1>Ldx`REb8K6E#hATU_rT8zc;H{dc}>_F;b*3uk#NBWv+L6q z`n!ZT4&I5tZWTZXx}#5!hBLPn-}YK%u3ZaYue=@hNhi;Y#d#)g7e2aJdAkPq!BdKc z$I~C{s4)aNWp((mciUQ9Xu&?n^J(OB_*hBXfmTGE=kffcZy_-o3Pke0Rs13K9Usru zR)^;y;ZM{&%E!FAFj&I4v#ze%3K$}&3+MK^|}vz^6sVq-&J_ZI80H}gzOv0E={m6e9mUD#d7cWuEn zZ#ch`sm!IeLcNWCf3Dx~Mpjn?30JtBC?;(Q<%iGovam7kP`Kkat7X^AM)cnQMP1m7 zk>;9nuC#5#xb>vr3&cJJJH`Ue=NM;H7lB8<;R!Fr%PrfW(J#?I!}C$_XKceK(A>?I zO6#f0^5Ryw=!Cs^)|#Bz#a?nPHv_+0q6U0o(T)6OE45|gcxrg&>-Ie4)w;{0Y3tY< zf5e~it6@&cTW8yg3oY2%0e=c-Ww57$`(20&&iU@vv-xl*A8ggyoo#E0^* zwmhGfhYtZ`3H}Z}y0z7P=!E-I zTGxX!Fd#;8Q9vyVxZ#7E$)d0FT5}F(+0bWjNN49}Yqb>iL%>*(c4qR8svqZgvWZ5o z-m~Q$R=u&N>_SIF1!H5~I;YNhX^jG8Q&Phj^R3;AH@@lE!T@kFtrOVh@Wp!_*Q+A#+#~jBq@=F<~tCyVJ^exQ7m5e=gu4cx0x4Mbe&?Ro^h&Y5++q2r9Hp1~dy%=J2Ot5xcKPlJSAU4UMu2dg+^ z3%&r&4cdRt-%{&yC3i-cLv=sUyRqm@)q9oI%+jFa$iqCn)$(^1+pbnWg-Z>5UEBJK4Q}n_ zBjW-2O&Jayk!ui~DYIHjEAti1iSv2qZhvWKehD_{?3!n%M)q>VN)PnME( zz|;qg@qbgtdFK-B>xk2LrZ=~idc~wQ@37{!ZTP1A1wHr=c;0YO+OFc58k*sgw{qzd(?{2@0I%Iz=H6qr!M)mJ`^519`^KBK2KLDGA*)E|{w4zY5)fef3ETw1 znYFEId)_mHdmiAe${GFxeAAbAYt=^E26=)#*lN!m@j?HCPUI~I*6(W@MCd3#8}5Sw z?6Bj=IR@(R>2z6l8gn>D2bHP`Mj=n-pyvXKL5^oT7dPA_aVZ=q6qD`c zsxywx!w=IW{32~%7yL<`n#AH+BdljbE`x8;mL4eAk$7K!^nbwxt{8}r8E4cO8~(sU zolMZ32yG<0oy=m|9;+@T8+P)Zu0s`pfZJ_)+scPN4k`RNT=PI)ZH<4rAMa(iJv8!h z68u9xLhw#d@28hmQ*m1|A1m+7^n=UIL9U52c?SCQUoCD8)EH3s9P-oppzp39nXm2y z@6AjCYl$KJ;;S{`0_S0`TkogS@yyB&b$Rk#5Gt*bTigUu>#cesqiPpjZJ;xicY zTDGjt7T(nOaVCI=rMl4^GlWC=Eh!H|*aK`$QaCU#9-eK%0T(Ga3>6NNHmtYb*zIGE z9nUJcjxPkvBluCPIt$292~9*mPeT^~8ft#y`-;*xs1M3-G|mD4D2}>yEsZ;YB-i~9 z1^z=Vk*0(ppLg02Vh*+93?2f=RlX1R#f)%1RG8&lSTE$al{g;%cHHlTRrrW?^PLZW zOs9@Weo{2e5BHek+K4>)OBvf#R;goz)3A;~V7G&L*2r_De*uPqjdP)TjJaL$IbeZq zh;$e`lz)ND1Na<<-lB9%#Em&^_)UP}D{lLp801vA&e`(NFI6AlvvHQnVOw`O(RqNC^EF`OIX%E_YC(aLx+<8hxzZ ziNmmOK!5D(v)a~qzTueqL;O)}OJL<0&!K-x!Ho9op^(QOO8Nok0g^bMYMj?XQAJ;M zeiM9(EXJ8c(b2(2D7Vf&z#5EnFn$>4$Aky_U;WrN{VHlb!gg`q2oFQ9-GB?_kqv1q zfb~cqwY9R5Tb}o%afQyp(#i(yQpLGeY{ea3OK&aBdcxZ%hdvi_iJ^(z675{9rI@s7s7qC}4zM$@_pi8 z^9&WwtMLxVMkIxMs8TI#qb|&4=E+0&8T8>8;yF3=?XlrO1V-b+Wy3j6tUC?b+c7r7 z(Up~2%HQ6}R6V#C(N8~_mZ`#?9WNO^5E8 zfs2y;PK;;X@mYlbIh$|Qu%<#=oM4V^d_ZVmJaE3Xd5dM7S;W~{EeqOK-~+4BSBt*s z72p$}qkp_Sx05Wc*ljq2rtGwHt+i0CH@mU3TLqutPBz>x*N0toHt+Io`YM|>k0-e} zTkfx|4mNPklV^MKJN_aKK-SWBXmg0i5&MG0c~;Fh(;nZP1;4_tmWjY$j=c&ReQQ~a zi9lNOZv{4eMQe0s)6viLVQWuhV5eT@d78j$F-YI4=yD%DZ<{3-lGw z$3naC5ft0IPS}0ubDF`}?RR0ChqI@&j&EzddS?OWALn)(xh0&@gRIgE%d6SoMmn-f z+cnPR=5fAnK^p{;u}ug1x=dR;=f|V{06)p$kEAQTOu&UPzp4+V1+K@ks z92c!cPl5Jz;@#+{c7X$YY4C40g9SY}m*KfO`laZ*L6|r0Bh*(i-FkJE=kAaWADgr4 zu4B*2Rv7+4_zBB>0Dyf6NBxzRoT~0D;cO80EDYKyz>O0F?tssp&R2H|=np3@KHC^{ z*0LCv%~EvJ=BcKtIQQs98J-`UsSJYN(m;>0kKnh_m(=}_OxL~5%8t{usE!nHDP<9=I+_idV*H;|94DR&ic{MGS-Q4xq7M2Rh(t@p1acyGWaAsn$ z7|xXzVFc+mvUBql_(4|mMyE*LfzK9xoIcJz=HM$V!3UMV{i!+ls-i2vC)ez0&3ZMk z%Km~+YPGyFuQxpf-XEPlE<7-wd-Ki#{LDCuN<47q0_VYieWhFVR5SUx%^3Ct_!hTp zGp)7Arl!@_xBWr;t~P^xD0)L{^3KhU^8Gbx_T|zXd{|pc`F^&EJwCX*R-X&up>M6M z<)U$%i`=NLYD*AqFyIwaLp+W=&i{Y*&O^&_Bw4cGLahmEtw61{CIRsOzhbWilG)WW zZ|A-3WY_MV({YNGlt5_V=4KuaWMY&08P0!`If=Q+3(=3N-BHc0p+69-Ml(lVH|F*G zc;8Ol83)+1(j5<4zveB^+O{ai=n5t!UG`Z#dn<;V_4Vp>o2xoLmN(8_TW_S(?&O47|tUxdzT!~ z_V| zxzfpv?=x@&nPV7R*+G4pJ0m>1gn*{U~PpP+Wp*M>U~c3oVDS(RH_5C&i8wK;#_ z>vIQ#8rX~yrlQcXp{Dl{et5NKQP#V&%IeLE;IGfQT>sWHl(o7FW~J} zL!e!EdD}^Ueg0d^LA_nF!}_?PH-C`A z$lzznWNfjrQ-8>Q^<7c_`zK5G6@Tyr>G4V$8{(^hJMY`qTs9b~pGxE6CQOW+#D!kP z^4U8YT~aef-kj8bxy^4Y2laO8ObsX1KaujY;FXKfT-JH-<06@wc^yFk$9%_IdCaHdL3YF^FUK>n8zd^%A*U;j@^CHJ8cAkNN>zzL5uOw|;-6K!d z&H6c2nP~uAMl2Ku1%b=k$;X4VK)*Fs){BaF{cc+6Uw-& zOAR01K&x^Ol5aHaggeWZ#@B#+bypwoOH{t8EB&W7*p64t?IuK0!*_<4imu%7Mtb)_3dqOuXa ztkcJI0BC#iE4!qsU)eVrof4;wf*W=2nGhIE44V*K1f%m+oD<&*EkDKb+X#a~M-*H3 zCN#jtT^FYd-XI)8s|IC~a>B(xKMQV2Z_^wvtwVhr6n=+YzXt`1@V~@@w*p?SNcrBu@NQ+*9I-l&8v+qo%sqaPV0Jjb%*e|3>OOf zMCm}68y#1%9q|X@MpC+~)ax zJ~=!)H{NTGXF+S$=;Dt&oYgAXC_+wOz_Pnp+llR387C$R)Fa2T5OepLu^&4(*}xf!S@plK+MJuEzNG(RcF4*?c;? z^Lo*+WAo@WTgwSYZpSJmV#Z;+g6k#S!OaV786M#V?ZH>6%Xh#Wz;HHC><;1Pv@xmA z<`Z$ICU+}ciWd@@XJ`Cy*82+MYQnfw$Npi`7!O2=TS;4YbKq-DxaG0bewOcEvpd5p z%X+!-E!%~1H-F(<4QKMTUwU`?k@Prc1|I~|G%@4AIPs?jzZRFRq`qb!+Sc)!%@Kp{ zWy8N)_OFldW^rbmSJpEGK7+RQ6F*Iv06;cnAV#XuFBg};*v*Ab^;zT4XvdNX{4y%w zxzlknib*HEdAiTqqgx^$U^vzio)KlCJiF)NGOHgd-D~m+b+X6Y-1LYS$M?|Xyo$5h zly>bJ?ZRc!Wj(4)53Pgouls2!Sj)qU+Z+yLRXWu4p(4I4UVGC#A4{ioCL3x~E^Ejh z_t}X@*<)x-gb!Y?#(w1}+-W9VSDqvHzAMxs{ZwdIj-OT`m3a;~1pI7Dtf_F9n56W( zT5mD8I*U8_>88`(Eaofi8Go8|4aN1w*NXkB!8(~|@on40=JVUVQjN@Z`)A?saJ%_T zVMYGq;O4~N^o|gX;!{6w!kw>!<0^Cw+pAFKWM3Z}6Tfe0=3T}=V}5t5JY0z%#{6^R^yl zAQ5%Y7iFGmv4INXlYn4oueLz*k@gA?pKI7`n>bp*wd{G-Tp!b+t$j`2lEKrsSq+>I z%L$ypYUJUxU4w;vq#VBH3Vk7`!PYpB9P~xEwQ&SiWFx+SyA3A5{xsX}R?j8vhqc}$ zLy>xZINB9X`)GMI4pl~OJYP;c68Jy_ZN9@4WQA|1O4RLFqlw#eo-Ivp{q{Xm&Fq`| z)8M*W-m(#{Mq9`q^@mC8Ir~GM2gSAX{f58eq=*A%&RQwW^V#C6zkCe34{Q5)_Ts1e z`Z~CEUiR=&ZDj0rem=Mt<2$FgYKGtg8!nZL&(9u^u@w$x*u#yun%3QbHBIK}o9!Jo zcw)?8ga2U)+Byqz5%!42*Ve8}I|Kh4UhDj6%9e;J(w1H8KXV-)7%p_>nAM@V~&_nAxo7+F-V}(M}*9fUcW}z~@Z6maX%k2FK6mUH0snv$Pia zdFQe`rJao5sCk?91-(5Ble%o|Pq%m7`5K~v0EHWD-GduWDNe!;c!xJBrf?j6^m^9D zeXVuGHR7zPI#WII-0MXYCy#pM@#CcWF?h3lpy*flrQ7Htab}~j=?mBf$iuBe++g$t zy&mv@A5Rf1;RVJa9I*GCEn@9lzud}|?9-#yVjbt$;_IZIsDc&s5vL4B?}%2Tp9a#e zjqUo)p(goRk{yI=`psd+i2AC^ruGrcn&6y!uPa|)Qx-rzI|-rseSAm_21P(C_hR* zh$H$g!uQ|rvRq&A9Cz8nZE6?umlXD+Lss$Ik+9~=j1k&z_{tPd)V+L#seccu;{=cisPkb)yn@+At$xq+7;MZ%);LlmShWqFzm0_ruu#BlKz8lZiUpz>|DwKpJ{J%Qe5 z!a}o+oxR zw^^-%X8qOoep6DLe6@?(#N73JPlSF0dW7&~#jm0Nm^Bq027SxsyZo~aAA{HQFW!22 z&eiksmyedi=dq{{Ft;etx+g`8Rd$^X9O{6L(WQop%{bImDaubw5l#sAI~h zjez)_+BZ`trtkB6b8WNs@xBU2d)U~Qc4$lda$j?yAN;3!dzVA=hreex^9}hYYks|& zzdoOhoB8t(dLF8Gip^W^2W2wv`MkHU`AA%7+C#iZ4k<71v>-grlzV~gd?+dJirM&U zeGAjEl`-n;t1r-(l_$S^J7rdNX|NLZ;`kckH~HN!P1*g=d0#QRI131iQp(5OjQ*CU-=yMf|2)kz%jrA&f zm^CSv+B1TW=pKJp;@+A2>7E}*)W5CksT}nCK!z|;{uwIBI^2ofcI(u9b;)ev?gkCS zZVKBFc$7F>t|z=r*pxVfybpg+@mx&oK~LJ2__(7XX%($YyP7J5BLl9VepxH`WjSN| z+~?MFb8a&G4AqrlziQqAQ*QUSt-WLNq8Nz=8w4xM65Gz}qUra*hD|$k4OdXH22BhX z!wJ)KuPRMWR6!Ql6s4JG6|U_~l9=)3^?U~hu4D9eKF|>663R3472{mvf_BK~i|wdA zbJ5)dLXvG!m=wGg;tYBz*|s?7VXO5FKS*`nMWYZ*qf5NPW=dQ)euF(L2G{KYPN;U9 zfCVn#OjdiRbmKm&pJ*p%$c;@NKJuR~W#%iDBN5=7(0{I*;&}B82Xzx8?*?0=JhTTG znqv1ov$D$<;jvl5(i+4o6t*e+t?d$z@R})jr*!}E>K=p#b@BTr-kGqKSb5z{JRfdm z&iwJg0YW@Z&Ff~2X98daYjEX?(VY}e%HYeX0eDW9dZ+FeEjzZhtYW<)evs3C2;UT@ z3s*r}s>JN{n%LL(>;vts*QUXIW9FsPV;A4}3cmj6ctO#<{q+lLr^o_Kve z*Ngt8`AHZi8n#xgQFd+!cpY6hMPN{~Yj*G)-9za_|JLhO-SYO)Sw5UYsTWJePwmv} z;g#Bp#-^Ak1QMgETQR&S1R4+N#PVyN|4>P22ki-2x8dM`A2s_gbRfa-h|#HdoM7W- zjw+Tmi^{4R$)<=YI3Z>q*hh_1Yq%u4y0d<@HjhWQTPxT>8-EV=A=s*`e0Swo)4tQ4 zPRpa!e%m}dFE98!K4f;P< z?83WdTM6>Fepy@k{&hu}=J3_PaavR1P;NKgbiGms9A|=#>TEvuau+uq-Jw*NKaSRn zm6Vg+R|t;>@A)$+XlsqF2TGCpgT77w2FD>Lt(jLIh1I={P8xXBrrAFYYWs@=C>87H z>j!X4+JX61n3}M`(#YGG7=FBl|0p~P{Y2hxqlLa*H!iS)bAx7e-rl8Lc+YEl^+vnq zrkF3Y9ut#up*3$v>|CokNt|Z$!-RNZZT1$)BUMbSG<-H%t*2MA97}q;Px0=+*>YQ# zIB}hN^orL;qB7d2FWFLBdZ})Xa=o5QgMn^&?L9m9Y_|aB{Bo^oarf-FLH5KyPF#Z+ zbPn*p)?+NP2k_!1l&zo}w{JP-vFP2gN>A4+MhbcCgmKy=4A(iV*nO0t$5{d`QDUZA zCFfZW&y)Bvgl=8FL;O1oS&VBLhvP?l18B3>?2$Q)?yC-;7YCbV^!AZ*u>NHRtJb|^ zfmK$yb_|UEl49*{?o!z+m{fEI!JNHC4#B;~%~cH4^hB{ay_|HA)3&?0f*FQK>*Zyw z`EQaOWXLyI4qC~=-(F$j_-#j*PL0^;_x-eft2ynxc-2<65svV&cL zHMnv~dmJp#3)fx=ZRfKy2_y@npqm{;^T+yly^O7|*KoZ*vle#sbaF?REK?n{pZ>nQ+m(l~K~p#X<$eE-H`#v?AQUl! zKavYU)x5&~PGMf~hHBd1^kO`E&M? z|E}C>56WTqManZzO#bzsk0H2T?&%bVyZdO+zQ^FW-a6N=+JycGrtos1Cdu#Zt349I z*JgG^!*cc8+k+e4Hqx8-)0;4*SKe!Rb6&$!!p?_|!%E36-fq*zq3Po{Cbpb=gqLS* zdg@np9ly-c0s9rcSD(OX|GS3x<8!EgK~n-V9{jTW^1pk`98-m0y>UARYyJIfJx;`; zrc0@N(XYVWPNDoN;g64e*p$Q9M*XehV_3fs4Ch}kDaxdFVVu*iUaxwr(XQ|7-C`vf ze7u%u05HybFJk2R@&4+U%0S$0^)GM(GzD;q{mtzmj`KI4^BdpvTjWj1yP=-lj8)oh zFTK<_|LRxFT`$+&wr*%WOqsOIyruDhy+j(wzpXvk_OVWzT(MR9moaYonLzZfe7}wl z+5o~K&D0adF8$=Mk6WJO_bY##8_nI%_*ech0RGNrn(s^krvg)uMlIaOElVx7M6JL7 zpQL}v@&8ss{nH-*w8!631ON1^|Fc>JKhu8OoS}p<nk~+1;@LMOxKlq>e0KJBBvHEm@t+_WN!v^GXJ1g&^m!&`ubsIh$dp2ok@h zKK|PO{`@@qF0J;UZ#+})fp>m=q&))*mCYYN|E;QMH~apjJ@z=i53m#1Ugsbz06P`D zBcmf1LbLBM#Lf-gKj`hB=Sz2TRy_oQ*qHFg*s+!`u(jhG_rXLtg0{gllLjZmCz%xC zoyZ-yqd>;b>{5b3TzN!lN%J=89K!lx$_DUA}Vb0&nY<^%htv``Py zjKhusPSv>(7YGiTG*dU!zt^>e&!Qd4=UsFKQ+4=)!XA3)P*G02%(~EdR)_HMnY8w; zi2N=|>d&7_ivOtV@sO_x<*A;WGh8fUCtix!-0@ozcMcw)a9QDf1`nYhDfXK9U`9h# zpT*R_dh{zl?vXH14_!%dzi2b?6O}o;NS2G}%Hr?w$#WF`5~dsxF!My3fG^ei8e5$7 zEQQH#y2KqSmf_2Rdxx-X75leLvA9_TW!LUv6PAvp_^8;`9@z0xUE(U1mW}9QG0!gG z_JGGpA5&$F(Z`avWpX#9zP{#{&$Nd>s12{#_>$Ar7{-KMy1Uvlq-$AXeC!X;fe3YdewR6=584C!b@XQ`dswz zoTDH0_Fef*Im9a?Vb7??(t{oMo4_%h2xo3!cgL;??u-^8{Ym4YI*iW~llmeIN9C|g zHLIy$qP&{VFDAaAv}vu7;wX+H_}J`M)&1(xomWP;>!H~{ztD<(S&jR{?Y}uV^y$we z+9RrY30qsV9&KO9KU}&=)9XB>dq>|1F|R5<y>#b zHB6+Zw{`W>u6T~~Xhg7g?pCcNB0!s4r}-#gwgQ;KZjHHjeSg*~qa`<$J?K+sLJm5z zBW6P7Q34IbX2;zayCg3$g_&C_r;S!4T1r~Mhyb8B$ zDWMoyDuXb>al%XP;dCCC%kcVfT44W9Jl#n)f3zq5Qj0&)Pm_G}@QK17r~k}`;?z4a z4hLYiUI`zh^f6sv+@~7DS|zt_4GvFhS&`P&X5q~_goD?n;d)-NZPma-(&JYz*QC#N z!3XgndBWX1f?s)|c{9aa@a*2Q)#!EA0h>x?R?R4U1B!r8%TJ4;^+IE0aW6pH@ZiQ7 zADGejmaL>hqvkTXW^E3YI#D;ZUs(@#8y-|f=g49aqRn3DZ^A=(^)?d25^ihwgyK*2 z!c+KZ^r7c?G<&3nvks43*Qw0i?O4f2wwV1Ce=rDE5J8*I=~%3HRdfg*nOnQ# zG{@_Df7T67>Mr#cbCXQw=o?UF8#hv1FzP2@R=Oca((uQo|ukh@72n;H& z9sNx>=Wy3Tju^{e8Nzgf)!J z7K`SP_;k|zuC^!1#3{4EPJZm2+tcK;TY{r1-O%FAKZj^{@SB`!Zj?tQ_qH z_9>pN!PU~(-iSGBZLZ5^Vr5^(te-{3{ipbYk&qwL(rWn_A^QmTFzC-JjmU14s*Xos zYKPu5ai7BLVBUPS$Pe`8IQ0*9)_o1U-f|`Gu-2mav~n+nR+H;$8GOE$bMR-z2s}vd z+JooKo@QHKrV>Y%`Gho=KgJ*A-e7=9$CY-3;yA+v&OX>b#QN(;b|S9bbG-=fQ~mq2 zzQ|)6B$ncE%UlHyp`*LO#bIlumyn1lU;W*RttHMtUAa{EyI)@Io_tI+|2Sb(5wEk?zPsD>(OE|3$wvg<@pGLTE${7n zd%KK9X6SQ%jz4H58l?r0*1Fz^j_!-(oo!xw*{a-L^-17SD(x1hRWp-0?ArP8JsjQV zbIcF&cZxEn9ZIEpI6ulfr7c=0?XKBlWbeml$H&0;+cnsSRVrVu*9s*XnxT*q6A(SzM7x)~2*Y3~Oc05dU zBb9#J-VURMW`8v6CX)AO_G&xb>*kt$c330iizowWV)Izp+vaLW0d($3bC&uDe~@dD zX)Qxq4|%#H_I6(QCjPdRPxn&!YUlm9I~`9?ZYgK@DLKeq#DL?u>j4^~XPIp5>vQXH zT3@_U&)JGkG<`hL9S+&XhlO*0Iq)RLs~`6YzMpSP(ak@w$10Oq{IBw5>Ps9|wKHvy zH{3hUh6!^{Shixq123=M(D48+eceso0q5|L2wpc2X!S%wql8yhIRy@as|i1F>*w*n z_#AWQ!2g)Jw|-Lv>7T(sK7oVa3yhDbFmU-#2UKS|JDWP%W#pGZN(3%lw3$uJM6?7| z*W}e;HE=e;J8tF3?KKG{@UgfBZi-ji13cJX@8aFf=Z6v3)P9t;c0|EXieqVP4}M=z zll(Ms4gZX;u^tVIzoB|!9O@plOR!o^_DtQro`!oy84lDpn3Ld*qe3%?ml@a|8~H&f zb6%${e1X_{sjXfw=h8{zk8k=daRTb-AJoBgs4!DUDub!FpBCgl|DHa)dRj&&^vzc@ zc-kA6>Rn&QPCAq82a4Blvbql4W243Ze>wPVDhfQW=c`0N0(YjKz@p}EcLa~K%%t)g z6Xm$9rGcS5p<(%NSm*Qgw6^ndWE>uZ+K+6&PVU<5>%k5E_Ie7(dR3zHJoq`jWUKjW zGr|wf#E|-J_<0@Y9aDy1|5JHr4?i{}cqU`zoNbk&J109^T*kx~r3|H~-xuK&)BlFa zn0!2lDLQ(<$8qSqGzTaB-<0-FFK)2R-t^Dh)bDcn^A&qt=l*IPzs3=t;+EXgml#96 z<7@S-o}>xpZQ6V1JN~1_%)SsUyto@1gkK6oD5@j&;{a=0eyL@Ku<{M1X*rKUxVY4cWX@{U<2s2mVy^GVy z?Zqe97gj;$c%J^I^u}Sn^UQrs{8eSStcl3J2vV^ zNS~Yc6WDz|l}!KTy2P|oe*824S7u~)=RUfp-_LoXJW2~ecFltE4)Yjn=*YrOxbx&3g+u-E9zZbALTm|VPD1Ov8}b8_S0EGd(e+1`taL+ z|1O8Ft>>n$wU3uAUiVc0Q6AM9DO1AIe$0#u$`c9@NBwJ$Ng2I9od4ircAb+@{X zp)FM(CZc8dgT?;zjE`=kSgi#15u46sQ*L?^b%D>hbM!X5c>p_8kbNcTgX3J6<6fqd znEF*|pp{)+w8 z7fqY|EdTFczq!nIMt$C&KPX!=l*l4zHN0oKVe$sfccI?VKXo_Q-eu!btSmIx;EMSA zU&Wfy`BOYdY(Pp8fvpHB!)=f`mr?Ku66u;iAJMWDA_^&^AXx#d1N3;>m zOudc;A25bzeN+6cuHmnFMd3MJ&js(}FhtoD;|RVAu`T`hgWz$}(E>v=+O_Z@;oA9a z<~3cbGj_9wNMTr}EL59q=8_*5;Ohd+`LwU*eNz4uSrCs5ZWO#luWR_GhVvzEoh!an zwRU!z`TdeOO`8vFtQf)|W-LI4XsM5n`tXv17+taFf70vE74CpIT>+durbPTtVndzIKPkTqN+w zDqdxXKCV7wutDj@(GHApZ_=`>_k8aU@srpp*SG*S1z}Cc=5_|F&P3KEJwFaXaCHuE>01fF$_qsHW$6c zQ@a(gC!N)?HN%dIk&-@IALp?Xea$PMC<#+6b}P+Op<<~$r%(9fLgSS+0ZnGjQ&qJI z{xG3svj~RKI>KWqfqhKe&6d~c!*hLX?$WVMH|8$bU}3|is2kLRE-`pSuS1TOV#dpWo}#2;KP4i&WgaD=sjv-)iZW>muA zCIx?R@R?F@6*JeiV~JorMSMg0@1*5+nTtAJe?9MX&#nH&gXcV{XPfi;A_WJ~uAH-} zgD4Zy5EUi}1_fRNw+PMD?zZFOJCw;_pHnm|7cIpf^t=ZerHSkMjvj0FGFhhj%a4`A z=$gZ(so$APF5oTl+bJfuGz_t0ny{e}q2Qp3E`2ktgD&G0t1U)MyX-5%E*K?KBd+6`I3&ED|V(j~R=Y z+^@d3ZGDXw_^RCjcItsQn|CYi^Bq01=ICSmL2#(fwGd=UW}QRBTx&DyHa;=6WwJ0S zl>^sfE4gJ~gip+E3SLH=UB!VM5%aYRrbD^Zua<)YlI)@UEnYZ+ILSVrt5LqAaL)Ft zS7N+GU)RiH!qC{vZ!R$kL;26~2Lr_*a~Ard%WboB!C#6zp)bK4&pee~F6K+=i;6Fo zF4~F9x`q`rjQHCUd=uP7)Q#Ns*=MO91dS+YTq`l#}{ftP<8Qt)0Ki;41TchJR z5m-#_1=h>{5uMKY$M}Qh?5w>>Iix;TJLga6i|*>@1lyo{V0zz=!}&~Rd>hxh*Et&R z5%Dhri9x24FWGKo)Q=ZV=U^eq(QA~r#SeL66Y5N#=O~*&Y2R&B$Ccptp3L7e&f?Z? zuZsjq|rTgKKR^m!5^5b2&CYv!CNU7p6Usy=#uq5j@?| z1t!+xtL`X>LfSMzW|&{sihqS}Lk z7u>w8D;tW=I;J4z|KIVS?#E-A+^{z^i#U0Qm-EJPOvNwVQ|5?WB@);|E%z}uHOSQP zbLx}e(3HcwL8{8Kt%B3ym&0_g-%$+RPwjEdZiNq0_u_W>$vhVZ2!1ww#M=3NreFX@!hf>q+R=fDR^ z!rSya$_cjCz3#nJtB&6jd{oW1re9H>-;_?7SC&jMHlAiYD2IRI5$X-}h5h^*ekX6x zr_B3X)Jb0$r?1{L`RJUVJA6%vAI#a)*!nb1{=Z4&br-i(7={-*ZetmMz@%H*?0H zl>HFClIR6fROWoG$B_Vjm%ZVY(`r4MAEPfinnkN)ipZ zVUpx=6d&GB27S0oZ~i>tPiZdV@1ePeI23*?4c^!OC&`{J86*#dQoT2sjXSbE-7-iv zNW09c_N86tX3-@SW+SXnc5ZY>pP2`HtwD5=oG)+d{Bl^2pbyTOm-CiiNBGfvDzUbL z-|Kuv8Kf;O{+cNZ=Z;9AUCo@f&Hd%Jx>#Ts`0-0W&JsoluCo!=f&H6Pemp@kaAD4$cG;!|!xFTLhT)j}bl@I9-o2l4{ zx`l&xz-Jtc4V_SM+KOjc#79)!gU@)2zT+*!CxJXW=*UjW#}`x^|#_sidDs4v_~iOvR0p-#dRz+(+~{v*5B>a4O$- zyaLZo*e7{yN^g|*Qp}^2a5mYG;_%*Rn+|)dZrklPOR^htPk`(XHixm7n0nFJM$@Yt zGO_EFAMiE!n%Ek_nT_VAcv7L3lkpnFm?FRE6BAxlQ-;bpoSIRR_1tMAb-z*z@?1SL>rk@wFJyW-?hiy)H zCHybTvir4Y-YVLe`F%aTXT+^tG<-fJc%pPK!P(~x7n~*$n9mCvZ^Kxz#FH>Q+|KcN z=dRN4mWJ_Xk_MYU?=mOR&d22-NxVw*4MTN?F}BNUj{Ae>gOyv8?7lTe$8TOZyWu)| zf=+S}u_p6q^VykD-h<*>3VSFIujlM+ZZ*r%2z}xQ$N*C;VXA*B-@{iN=8Gm}U;r#X}+}yx&(`rOIok-GuB-sxYpO_Ca@pzT-AN6F&;w$J=YO-8$Xj zaMzqnTbIHhhP^l%sD~Xd-GT=O=ct7*!KG9`-?ECICr#_!GAJD{{D?lpA2hg{-^Pbl zV~?$!{KH3;PlfzlRF>?f?5w*saTas?<>7eCE-kF`@VL?oa9ixu((RL;;t`yqbaAp< zTR1N7WAlnn=gCd+zE0+jX|F;Y)Ae&biLpjD^Q99DA^Vn(=;Ih4wqW^GKQfn4Z`D3H zIJh$&NyNaqIs@j*VrTOR?(J)T1b()R1rxFT@&RsHS`+II17c}J+`%sS7H-p3JVI}) zSY)&rx|Z$9d4F{?;zaI;bt|%%&#?v}3eeb(jc=c+%fH&A-oIm?fNz1%^&)02Yaa5r zRO%#MJx4AK0OE{#_06Mjm?yoK%3*~AKM*q*4jKJw+=(R~_2@Z+ z3MAGNuSGcISuZ{(c29iKpZ2%gv;|(K*qc|zisIOzx!J`kP5eITal!>t98&fpFVrD> ziTip)`^AUy3mDA^&DM+_G!{R`A7q}&9Lm~H5W5e57R~jnWu0oqo!$?ni0z~(M^k#w zwaU6JOw--u+Qdnv@0aK+@jfx_RR6dBEEKAovfy!}*R_3&fOSsMAEn<-!Ee<+#kZY~ z#P_zRLB*5pevUsFh!cl8#Ci;-j}J+QwZdy=_N`(d*3VbzeJD6q12;DmiSFxg?s6lr zS$K5BwA?7>qcmT^2(9TLH(VX6qXyUse(V;Sqtf3s^BTSa-h#Cq-YWR*EV*d6t4Xjz zEAc7*plsi1{8%3AiS$L~-xH;t(EPTByG3EwiJngL*?EJU?ZPT1+P8HPtTVhLCMVq4 zR|g*x*7_G^TN0r*WpF0+wH1qV0cVhYCG3!IBWM5@q;kxp!`5Kb7k^Oe)W`UPhBFoj zWkQ+KfJlAU40va^IdrqkS=~Y7>>R9QKOeYuit$3Y4Za$)uj^j+l6hvu&3;2dj#EWW%udFf!ODVZL7LiJ*vd3UDsQ&@+N9W%F{-+yKmh$I?H^FKZvbQ z_CEHA1|y1KeI3p!6V}9v9dn4-UKwM9?ygeki*o+MOnugz&-dlC&eE=cra{6T{?%5JQ4;CGS@R_9%{k%^~}39a^nS+lZj zdEyMp6s@GZnle=`!CrQ^YL9E^a`QR1c80}K(4kux?w*%*;7Hq9)CJcQ9wn@nfBt{| zcJ=%Af8~j;#e;Kg&^DY)xw~S|*L!Vq#^v7eVV$s|Mt_g2gOz!?p}_+v3xBtl@ncZe z9=3N2@|o=OuLtrhMda-g@*Vo1mQhUQ)=F87owher_KjO!$I8`J09;>b8WB)IH z;(Wk;w#yAZGEe3z)${YrAM#3>cz`>x^sO$qS*60eb`Qg;& z2^AaiNr76YB=x)-7OeiDewZ#|RT_`PvX{HQPU~>w+NtljSAa(}xQnPgxV9=!<vnl`4?lC$t=rpzNBhNB+ql{BflOC~ zZ~B=x92m}Uzb~CTHO>-W`F~@zzmx?K@Np&Fe7oA2-L;ojzoS2C-lELl&-AaC6&NS; z1MSm;wzxb>w)y{e{1@40N>5^JlM%*-@6TYK>pzu6dEPFc;-C6sTW=`eU*$jr2fP+P zqDQG$4~%8o)BN|T@%=xpgEuFHAAGMdzjD7c2jvxyL@~P*Z&2e`+!hgzH9rMXu64Wc zT=B5X9)Q2RZ%cpR*ELIT|9y!(f9IdOu>Kl*u<~hcYR0VQ8@+tnqh{pK@Pa8LzRgy9 zC3-U!zHrd+^7P%h3jF)Z!5x*}`8O}#|EaB14%?1Vx2pR996bJLedD$E2sVBU)@;T{ zmf;-f`=-pA@BjY!R(CT=d42aIy`k6dzNYuJ&s2Xh`Ln-#%Ji$?R8{+$c z6;L*RPe}O!_?(z|n6G>w>Hc{=zWPO8c!%E5Yqh&<@OrMgQ@`Q4;lAj-_xt+$OR}~1 z&^7$ud~wtmABwrC?-@*mv7+yMEJbL0&Ewd>4NhbBDA+X3K8r#KZ!!9JTHnq4!Wi`M zV+`uK#;?97yS;v|A+Eydx|}uhEAq~3{Lf7}$iLz4@#)9XR~>Ud)3KEw?He?gm^}n# zQOqA9rI~R;d{pmDzhpm>PcXLq>xc3)ool|pD@QQz z&naA(`6o~8Nh%CI)9vH@dUVLQu~oy9GBMu360#feI2ah6L?8QuD@Yl;F}@>wAqK7^ zTn%0)v1zd3@w}0Dtx)`uIfNQj>|3_hk&Fi1C;Jt1Be;PXn}ICxWlGo91z$q)+AYGB zleQ@NH}NY&!j%;}QM^Fv-Q*d*j)@P4_81zFM(?$Vy*@-)Q?y?Q9jc0a*||=v>=J*j zILv@Q3lsiaQXkS@M`Jr^2Li_yTtK)*XtxRr0fQCZO1w&we=DcBgUkDPfhHk&?4rS| zc%1MZ5y_%Flx1Rbk@7n`J8%HZ^e9mo(64tsUKm``5~}9Ldx${DiQhVlxy+5+6}<^|D@T zG@aLLr*))MjvUdx#r_Fen8lCTQyUH%hgM-v8RGuD{-L6%PRw2uJ8rw1BtPJS)wHzL zcrNU?N;&8+&D!>Hf7H*(6ncq^le4*Gi>o4>ZHsXPpN;Pu%m>}Y*gd*jG+Vp2buN}p zW7i61iLtupbFkY-9!#jr{7q8*eJW{=qAk zd6KwlniEnz^sKQ<`V-`5N@Dzh&6(%XUc@N}^XH-kM_6lv_&Fso^z`z+KTL04{?!Ac z*`g`Vg5!cR!^4U;1e_4lfH+PvvyN;80 zd{0?~5sqJQ)!Ypze-4sfrw7I`ta_UkIL&cM(5cgNU5OKyrnzq&&c&lWC5~wZ?Agi@ z((fZh&_(<+MBv)C==Y3o&7p9M*7yUg=MA`l#r$^Be~s!L;;xitt!k$+o=F!fy#*Vr z!cSWXufaGc92)#!3+7LJ#aC^KIj(}#YR}0QBAZog;Py)PD1Ire=4-}MsI!1P_Nj7c zAKr>}(ATOm-+<%5mtQ73E9*EK461wP)>vnH&o?Me<5R-8RI$^7IdJnDMzI@?z6Sg+jIlZxwHN}u8nvVKI4 zY1mdB%{Q^K(}~66g+Lq*W~Ul0&uE+4C_%u}1;of)ZnRES2ctv-K12&V>c}_&TT={6 zZ#h6r3PXwf1He5s7i@D-heOWO?N@i{)EG_}WB$4r-DA;pvoq0r_$mG%nuzR`(2dq! zqH~~4s`GNW43G0MNDVX6na{5m1rH3o3_s0&W{;iAnj?kq@>gwv9x8pPwK%Lom(i@^ zcCOhOytN1I!n&t;if|0QvGh{Gr{GG87`>QG>}w|rr~YI7!N&OH(4V9c5vME@tpoeT zc*{YD^F<(l<^_Bw=>3g}xZ1**0dRX$<}G|4z%6Mb`q(H_oY})zWzmV8^Q(un4UT;i z*AIQzSGU95cib>ni&K1<-cyYh`}~(RD13@P$Xr>wujQx1{)g-GmvKJmY!~jSesWI7 zR>!+!I_KJ`&$u4lI+4 zeE#U>f&8x@O-JK=I)6ek-6Y}%Hmcdc;xSC97^LlSOdR5A!y&X?xi4_qbW^Jr{ zS+`gUCW%8H7N&Hr0?|Y)fY32Wt}=E{{$j8rwxu z`S5DCr9fyCxBY#|*S_6m^ZUc(+mqOr1jLO?gmwL(EnZ)pGXig83z6}o5I*%A)%j3( z8LcsTcBi+Cmn*MRhq={{)Rv)rb~I=NibMNy^;*40_X^k$KBbC*v9q2>;`T}#pmfld zPc8Q#o*eh&(x2lG{%ZF$>mqlMZG%51B?gIs7-);;1a7mRzPT*$itOp$DfH`;tUYTW z5%mJw0W(lKzS`3){yl8mLIj4?S&cRd>Hw-bGBy=+i;w;n+_hzI`g3Bv@7JqQKVSa; z-&l??1fY#W`xsTfFPHCeUIThu39Lrq^XVM@mFzqkFRX}p=VP0u-b^{vM4w5fZr+!A z+dHL^!gIggGC+Rupt5C>u!BG02V4C1s=3x6GR@nLbzVK;Q(eWmBlVsraHkx19E*=GaKiLqsC1 z7s$WCsMxl^EzG62Ph2b$edo)N!H_l>Ef;4F(EUG_-tE8z|Ful^EEQ7C{s~w6rA-{` z#W^AqI1Kx_?Xi$9jxyq?sZXhIozb*qojtds{ko5T_-Ch3$gb0eKiD3>l;K@3D$Bb( zQ0oNmeWzdJ5Ne!g{_5Qdt{n<+Fh4b?cl3*d>(aNtIiJR7z+1P<=OlBnZ|~#U#$No< zawzkDw!h66@A)fHjP$`;H>N+S5B+Ied=-tlzrE5+){SegoV+`>6fG5 z95;&a7qr(gSiu+0@X2#6SAT0Cy~l?B^4@TUO+?9`m;U{)`H+Har!E;jo3U-iH{+wH z54E)?dE?gd@mMg=Vy`lN>8l(c>{n`!zcHbiDF0ToZm_2MN!Wsxa35dz8}I(POaD`j z&(-B8uJliPe4-XVca4AA<8yWSi7WlC_IPWm>Ab|5N;oa+;@4Tu6oltH_NU zntOcUKeHxr9kZYQzBZWi8&hXbM7av1{CWxz=e)e26B@%;T=*IBrQE~P#|6O%U3^Jh zVh?6L@x<&?YrJ(_H`Tia!LliXd@QLGvj+O>;E&I<-!(wJnf;ZIf$%nd7gS!*js&9l zTL4|q$|cihqcK6@fL&7ue8(krqPTc2dqVkO>wV+jFW>m$J9Zr0g$uT^al^AxjrF2` zPxn`4w1TKC{>g7b_x@1A8G-YR_MtlS`)8ZncOl*v*waD2@A$aK z^4_MI11rOB63b#2Zt!S=sg>mG?RC2?xP#cRWXEcxeI3t1@4|7T6$OLVeo>ne6D#gR z1@X@VU_*gy(9Q>1mrmgB7U34jPMQKs!bS&PLA*7vDR_3`pBm0isE1xBF$ph}jW{%( ziMd!eT9_N+vw3jtTyPW*`8&@N*G)J?1`WMl?s%H1P1ssp2;b>SUDn*AbvXKQQ!bJi;YuQT1uQ>G>r$s{K3_l?WY$TK+76W?}I#t zBzx8DjuU;mF;8?_kF|wu7_Klp)d#p5*NgAdh^bZUH_f}vO5(U7Kp62Y*OaC8a3`ky z>02M`SF*{HlC{b{AZ(ky%mbVmj+E)w(xU}0-lXo&N(64HxK9?bqqgaTvxyg`$s)ca z&S-KQ*Y@f2^}4EN(}Ol+Y>9R-T992A?qIx-56>fuM-Ysv2#3&WG%EEM^A+i1{6T!! zBB9RYOn<_EL0YAG;658f;AxXFC%bHTH`=>-YdW zd#2=CEik3hED=0aZ!Wq}!U}TnuDiL?E;a1FIrb;$iVE9-8|8MVaHql}$DO^{;}A1P zehtfocu0lPsQ+j`k`6ci6n`+)cc#RM3;Szvs=?Y2DjrX6bFv;&Z!_sJH!8`GSt&4nMsi z*r17($Zxkj#`;2w< z4m`pP;d;H~6u9m(xi8>spHpGZIn&v=y<0XM;=PZt!7^W&wfHBq6~ASl7)az~+-+6M z*ZF-uE)GYn-sN7L%{zUt!w@pAr~L8O4cgLVfk1Gm+qsf`D4*O&p%M*Ky`l2a4J7ur zmbqNO4iqEnNPRNzIW8dz^WYwA;jB@hyKMINv)OtT$%~)hGW-r(5Sag%Q%cZo-w}Jd`f)>yue=O>0I%n^lb% zy)x=f2|653-#hj}wrOsHs9l2CaQMI4e`FZ^?j!LBRS2`sv9%r<{XCv%Kkdi6)OuSw z-OIQEjEFsG`B)Ci$`*q(e4^)OxGI&;=?GZgwBa>nn|5`hfP8Z?aDX}%$9>rHXNfHvC zqu~x6(u;?D>JHA)a3KBmfKQaWqKSM4n|J%vRnqTsbTM^h`8KNvAL9?Ij&xz=pXc)R zwvCNM?ZjE4oP2mg);nO1E!d2~1^BFYpo!a@*Xp`94a z>}!n{66e4jF@Wr{xOX4p4+_uZdZt}X+n8oH{R>WEIWd||BFZmmXUZUn#M~1fGVwT< zFUCnf23B%DMsdu|q(FP{Z~DS(#l7>!`{U}x{2YIa?}!W95d|1zxN4h3)K?lT&l=+%MsMu?nkv`M7N0chYd;+)ZJguls0P!yOzc z@5!L8n`r)$ok8}752iOB^~MUn%268Kt?x3B@9*a-#~1JJ=B4d);FRtb?Y%X~BdCgg z23=0^JFy1QX3>S(vr0(G|9%N_) zZN`dxpJ|^@r#D{yeO=}MU54*B|BEM-A!uyDGqa`zl{bICl*Vi-|8Jea1A36e%U8Rr zKQSNbtq-MN>-l|2<^Nxk-c!5%`hDK>=W5M6^0A=Hu>J&X{kV=l@abmeReySt%@WQa zJcFJ20^d!D5AwP6mA7B|ieC=pU5{V$uDkx}HI+*J(|?GcOurE))$}u!L;MI6>xDLX zW9RCJ-)s55*VkVxRZxB4-M%|%8)_Kxo|4IzUMqio9{F5P=o|3BRL>^Xo4)^bksVJ1 zZTX}nyzYuu{ys+^lWFlJg+tJOvRmoepG$tFn@)}Sowb}k%>$RwK!SRPGtT}5KSu6v zvKy4`U;W&sa7H)6lp`Fp6TzVN&E!33D`pTr0OUJp_JbM{^$UV@>)En6NZDye>aUhCGP;co0)s7C9^#jJ{*>Z*8h+T(!E0V*H;i#CV{ z?eFnNJ7uJU^qB+)Mfqg@RGl%uv&Jg6yWg*r=SXyC2W8)wqmgr3KEl}7;ZRw^Z(2s% z&qJ%v+ZcWnrV2O|G5hH@woZ240wZ|!{ z_Rk%h`mDZRpPqM@xIfso2Ivl=qvYG;g|mT+z_oK1*gfEk|I3dD!QrsV1OAqx!70w+o~D=RN(GmqG9 z_E;aBcWK*D9&J?3A9fwyUG~C##bLtsXYvQW-0b>zNOcN!hW|Twt#DfDMXH<#*%H%E zaoB_xQjTWT-Jol0jj>zBvgW;R5sr*SyQZ4CVPb-pY)Iw#STg;Jt1%5tlG!!&MjxTS zNCy&)HSE4%Ym5i55b+!?t5}+@Wn(X;4MK`7MO?)LxL*@pt`z#AR(3VNuLx-eccL?L zUE!nPwpn;@@Job)5}vdrn_Un)(nrfdTZs2?cPI3J?rG{AOwZ`%cKdKZz%`pCG~ynt z3t+md=RV!{zVKT0BY1kkubS=qdXU5B6}6|c`Z*JsqH$Tgui(L%c|jVoq1LX|as0i& z$4c>ap+ul}anaUIsUK68E}Vu#0UU~Pdg1lLcDu1uE4q&FozQLb>@Km%pW0^^F3;Qn z=clfV3voJ6PUBiBudBP(A?kRk)Z)Ie>XrOrhfE<_s+t>0*j=0c{AGMDKT;UhUNgro z?j6Qttmb7ODe}%d3XjMVb}2pJSYfk(137Ng!J39I>$>wc)9pUp-P9|UMy1?d%^@P) zGR@NN*~|caY`k6uPd+4^&-i=CLF+n~!&{?1CKtM4XX>+s( z#T}i{R~Q$Tu>06h7+XGE-tV2*`PECaZWyd)EdihH z#rTHMk?i=TR=dr039-BBict`lmiqkiw4S5E>1E;I(VYhyEYfZRD#68I|H{b{` zo8(*7dH>U^a;^n@MnO7MMry_MuV)68%-laW1T33&!Apc!*Yfd^^vz*23w`!oAMN zuob%9TxFXM?V6W6cuaUg?8FTi2l$7y$IyLMEJbi9o)g1a<=7@(mKSed`+IE`X2}o^ z{Na-@pZu^~dAQBaa~(>3ia$7*CF$=6*1ckp{X_5cY&g|(Ar#-Ay4Q3wDjo1Jx-VDf z8os)@QVBK}^-Vdz_~E01gJ1x~n6(uKJ*7?1t`&~MV#hek?OWYVdy?&L7LS3OLytE% zoet}j+YZ+T<`U~u{K0K%jDJF?3WmcTBh@-RtHJg)xa`)}k9{f&Href$Mv2uaeZfXp z+g`FY?4m4!!)(Px-*dm(f!;ok}qH5gW{4G!90 zExLWC^bk`Q^IOOL+C%=Ri(T6V#zyMRna>knv>}bx$i5yN&9ZQ~Q*HGAD~DxQ__+<% z3AXv%po0u93zr!U;bqGjD;8g+)FFD*q3Vhg{YppBK#rMMk?M!u3!H7r`|`DvV(;9Xvqcv+p{r=qaum_j$4S1p5&bZSYt+`-xw1L=%2ZxZv#l&bn8!y?C`3`Z(ag;iLu>VUF~B@oTjf1+S!}Z;6Xgv=O)+l z+^6lVYiNz;_`Cx3`dJv^wuneJlV@Jhv_o0O4j)~E~*>Ao{h>?a@O z5Bk1v?3=3N`hL=g4*QdHbR54|h%=h2MeE+OF?X~d&V`+u&VuIn!1>$QS^~0dYO~3C z61)VWZAu551a^nT9Y&b4!udHRWvBK_V> zv*s`VEt-!R;3e*HtKKaOkN$N2zn zoy6Ems3-mXCI5Q*1=lD$-x!pZy*H+_OK)D)L1NrI1V)4UByQjWmBYkGCN?o?hNFzR z?yuK=x5@VhAAIs|doF3(gnNw|v4S{v?|ds?--)-0BUfA$XYMhajm8SI%ENmeg%9HM zz!`m#)bCJP%zfAYulM++eLh%HQen7YaOfHY^ zQ@XHhuUf1%ih@*ay6IC-YQc)jAlxXNt}E z*ElENwzWx__Tzn%Bs#;o)E1vQ`$BPleZ_D6^-tf=Z!J>?f1dqRs%-eQ%iA8er$Vz{ z^eDP{-}Ub2f+WYVwMc(Hs_**sn|km!^{qes#((|<=OF)Ujl+*eM$X&IT5)duqF?7f zFVlbi34;xQeQ27)4kWO)Z#(4A{byW$|M;{AWv&E`9o|hmPG0{>GLg3D*(V;W&;8J4bTRzCUC>YJpAk33u@GbF zV}`^{kxP#HPV8sJPAnT3OvmYNbRDgaE1T9O;*GE8)T|jCwXezQWS$uAmlZHh+DI{1 zJ7PKg^Al|bUi9k>CGOgnt~YiXl&*_kf4b*r#JQDnt3o@IY7|Ukd0*j!Utj8A8t7b3 z;3be(O}W05~|*C(!?gx?3{_eiQ};55))EbnfTq}v11>XR#4nUa3|pg zJ<5j<1@7i12M)z!i(F-1NNq6o^R|%VE~i|OE%}c|K)0T^+2eo__wa)6YLEeYh+m$y zOglOcsh#}`W4?7MMsP>W1?^p`BqonFWy!_F&55i0u9XANk?turb?GRI2V|arm_aIn9u6iatWS95h!v`Vx`81)sUg zYC;|_gKdIA;mgV{IMbzQkCb?g>3il9+%2-F=NcVO)0fb9bv-zF;!_EeYPHu4^IZ#A z&?*+3Y-mQ`n)4oTQH$Ju59*~RS9Z zJVw{+d+wltf4pA^7cBc)Jv1WE^EFdr-7Znbw8i>D9|He`n_7#^+|?qQ-?bwP%@Ms= zH}&Y2z#63+8ygF&J1jTEIVm3G9eeT}Q!?TMKeGe)o5ED#ZW_FQf(|6}lF4^>X^n5) zTK_uVOD}QjwAP7YB{{zBcliDj;Iyqlz;9NealP@yrd9Cwc@ zQOV3{YS(qFK;2=ciIMv^t)T1s=P&$!1`G7NrOoT6dqx6`4mipWc(hiB{-e1_Z6b|S z#&@W7%`5`B&sqJQq&SHeNtJP1cTVZh*C(yeVu@9M->aY0CEP(EH72I2RMs%=~Tq6&cEC^WA8P zihphLB`U8dF$*UDU9LWy&Z}FTa7HV1bCoZh+;Fct+Hl+RGaa<*&1s~cNe4MOh4+c( z#U-ET<}$-KPd>aU@w;jGgYjsZ{Ab5y^FrHoHjD9D_4pt22hr;`R?DV8?83-MK-?SV z73NL2zE-H@f* zXAIw5?Lt2*B$LHe@xDgC8SO;siL&P!!|6DOF012htoF2Vudf%iHJHXM0UvYKf*1S} zPq4lrFP~+!1r7fZevWe9fdRg@HS(58FTi1Rb4;Y(8B==?tYnn10;}eDPE1FC1*enw zSN;1xv_pFW6NCTjbMwX>JPK`8^3j4xwZ@5VD|6^H=gDkaTF1TEIdkmfsLu4Nb6EqE zPw)}uE%BdB4!B;L_4#CdK5T z{g}DdaXN_KUyDbq?t&!H=Y=hy1v#yoHhGn8!|T|4+>9x46X{6U)-&0ltyW?+w&A^0EH*4|^1cGjt4W>9D@ zQ;%V5?1uTB=HPm-?3XR-IK2RSPCHh(0WQe%GF&?8hnDBt_TT`XxNcpe`%|`^@?J4q zK&>tsq{2h-9km%xaMldw9zHA|gIf18XU|Zo|J(dQwTCW+75Zm4?W35h$Oo6`&goNQ z)+oL+gbu+0iR|DqT(}XxFq*zLwdx|dw-4#k#bEz0!x;n{M9Zrj87@)&qCf7;4Y&gLWsDaqV-?oPD>9B6O^xZdf>AyW=!OQ*$j)@SX^75`KI z;2V4J+s4>NA7js+JtTU)$vW+1Cnlfqa}&z2&m9g)aH@U#bu}p@`hl4Ar7!Dxkhl!S zFPhH8U@-s8+M@mmqI;XSn8)t@;yFjl&ATv_YsBbCpUM-F_uz$7uY zj_FN!GVAtO%hXTQWB%vs(;k1U8U8u+GiKQD>daJz?Kew~hwWN0P$y4n_p;CBLaV{K zld40Ayq3Z@H&!GTk3JOKMWXTksLRjaa;IjfP~L}%$8jt*urHCqDKfpCP(3bi9>k@~ z`?-=@vx>)Odz-56XSek@XkHhGkpHF8@_)NbdHpwGyZn1<6SEfj=QF;;oLM4fE5aKta@>CS#P@! zZ^1ZEZJ!%we9Pq3cQD82hLQ`pLh~AN<1?%^uUNAHFSor(!F){QhP_ zjP+Q3PBC5;=Co$PZe)oaTf*lMt^se&_^a9W_0scJv|4W#GyP2QHaJU+uJAwW2K{n&2CN#b2UI;#m3j>N7T z=E~mnZ3kr(9&3;tUZR0I@#MY-7e5}TWG|NDu3pRmFJiB9?$g*my`$01K1%JbF}?EJ z+w@_|WST=w@;_hx7~nmhc~@`O*#BeP_}^>3&uENaV{SOGn14?eki8LnE;W}M*92n7<#t3zGMHrb%x z{lX<1KkfCKy~0^3lz$1od1K9bLHe9X@($y~>fet2)+%&*+3~)123+mnYlEzdkI23F zVNZ_f61KRzAsc5{qiTlVg7|t{ueubYnMx|+(?xo)}%S; zVl4Ul%(zK{1L#ZtPshq#H`=4I_<`aHn*}Blb-fDD+uvn_zL)QRZ}2rg{`d3wXTDQeKJCc79X9(4 z#w&A!w>iBWOBfD11FEa{rO+x!~Efk|9t9|ulzNq{NC<*{98Hx%P&*&rXg6Pd1DAEFV2RAU647} z%&RK@@88Go{ra8Xe*3?C@Bg0{e*c}{>s_z^>u-H*`t?5Mer#b~fYT<9n$2t*@U-Uf zT;Xr#`c-y4`~2SL-hazq`qyB3{Jwv|3H+?DX5U4X+S)Q|t1Wq<)Mfqw&pRcUUa~C*`RyU&guJub;n{KM0S-l-tbfg@pF&8W+la##l+j$>U0f-O~&1 z#0kBgFnM%@jYyAB{3Bsbie0vd_br0u;EOBbyKryhM!~bUi2o#i5F4m_za8-M2ZB3* z&f+P8A7Fla?w{a;;0d*kpR*4QOAnmD-GJqUz|G{B-+*m^w;8Tli9Ne?RK2><)cPU* zAijIG0Y=cD(cvkSZ@tC+yn49s&1U{2`uQFdV?lo$Vy^4bZvGT2ONX8fv~8va~j zv8^V#l|1I(oUjh@4P|fcZ|4shtel0I{xeP_jh~(J2sfh)x`k4%H=yq*|J|Zz+F=7X z0WCcKCVv;W54e=_EpB4?w3<8e4T9H7J2k}fAL0)(J{XVDUhJO6w@m*QHcQ#yH{zp{ zEkm&6(X;y?58U~3?MNeZ(u5C&)+Ssqmz-<9-X`x~bkFU1`PuEC?#~4}y;k7|`Gb*k zDMEg&5_!q!*TN3O9~4$5-BzRf8f)y*!9!w@Y3B~7)i@E%KG1UYa=F6OWjltoHA*2S*rv3ts>2yP>%ppe^O|;XT@$33b(iJO=na3VI zyRo|+5-0vc{6X4d+Hm2bz^8RL;Di>*#TJZfG&$V^NRAbZ_9N*_X34lf^KnDmI=Xh8 z`#86jhtExVylkcH`nic8G7w%kk)^kdp)m#Lr59fO6n{_~tILzPbc6So%8bj*v%A3; z4*%Nqy3=NI+`ZiAV3zY64n*n~u1y(^;|pw8+)lhzuQ1v-Va^@B^6M4i9JRP%Gk$!h z_fz~qIFMye<6ymEjw}&VQtCF&ff?}`S;ji*e6!y9S=(ORcr(-wkPi|KOW_9Im2-yl z2h&4oBZ?cyZ3>q#$=@oJbh^3yeUuM4M}4t;E>~rGBQ7J$-$>rgrDt4WuqF_z%KicvbKDY6*_X?vQemO8M!r&mZPk8l3{vi8l zvxoNg+-Cm~F+l{2R1%yB{c^Jg#NhjuB9+lOKDrG;kdv98QkD9-b3AplUAn?sE+>fE zVSK=OR2%fjdAD}TtK`F)Bx=E7V-bGkbF{^Q=eUEz9yyO`^J&T|6alYE)b9dk<_Trhn44kY5u3oM^ ztYPMR{6U?|aIh$sgwEfldr2$lSAR=Hc9E<-jmD<)=qNj|dxQ9%IvzJ=>zdHL(5_)H z7vW*K(DRTVo^IvQIZ+vPgZYS?%^z=zaNlm>TL^7aqxtetzz;`UXduG*RvqFS{6U?O z%o$JTJDpW|s+-RJoU8RWom*|`ekj&b+(drcMibOloZKxOE(WUmbvzB-`E+rI{fi4j z8_iAf#SXiDdp0jsyr_MO9I|otzSjBXUGC!Bp|idIG5(HCzz$?H~t;8!Y+H|r6!KuavL__LhqVn9!^VlP`J-e@dxoC_#BPj{f1g+bfZ~L z*|6cx$%a4WRs#&sYm@t>g_&h{8)v<23pZr%l8*@o0n;(>`4Rr0{7_~>dpF2$_7qOZ zzy~k*aMV6{fxsQvkw0b5rTwYfpB+*@ZsVW{TV|8+haEq}AJkG}uHf%{KH6iEQjE@@ z`_jiQy?*Rmv!!65xE}1IvB0x%_mo2w9e~~|Ps3p3_WEP|L4!A9#&7LljKYrV`pTZ; zeSzQnY7>K>JD#%kjYB8zHbDGhH!JU-=@|RSgqL3?eVkA@FKEtB@CWTT??FC7^)HPJ z9(U-}6v0%h%KyuTw^_P7t{hIbcBWg3Y^s%Umi;1JPA9{Dh4CS5YD-LjfBgV|F!ZPX zq{hGwH4h~)c6`cW<|?%Xm(lCwe(t1J?Rt0h*rrds2IzKWoDUf*W_mODn?Coq^9MEW z>iS?2+$+y31rllu*5{X7W&d^k={1h%!Z%+Wp$tCDx$!lOs{)8?FgELR|NHraX3xVv z!ajCq-QIgRt>>nS{u%$6eJ5>-9XWfi+uIKF+CRevmD02aYi0&+*X*d99BQ_N@r)VInQgHbu&1f zUi+unVK_p8(8Fzvb)zq_ClIdkljB_TChX4(cn=%FS{s` z`wqVmn2t-X39os;R}|wt_`AWf+zp@mG5#R!pg3VteAu19@_s)WeMfOxyaBqdF*KFX zAr!~RJy7>Ce4>`HK=Bb4+zc;_*K4j7?7ytF^V)3S3Ll7HA4pI2XZVBiHxSc{W^U%1 zndHHu(5?idbUoY4Ucmgo*~AZ#CaN@F$?xT^EwB(sla#i1fvk1lshCq4YbgmDyg*DhN zx}H>FN7wrr{u=qw9%)M6fxM;PrgPq;K_KW8y(6aJD8Xjw@hyK_Gj@JS1 zM4$Y2!Nbb>B7cxLL8Do&^;KN+N<2u})t8u`;__kdQr#__E;Q9baGJfj$zf@=;G(7q z($pi@(|j;}5PSF{_A=db)=qBKYQY$Ly7g+}q`B>!B`zaZW&BKuvCM;g7(Y82GhgBl zvL+~|2n>crLU4iBG%dK&hi)YE$Ho-Qm@=csto)jqD-Etso=~qg1B;5rcB=q*6j)SQ z7!jcZZ-4-3&afjGslhv99B<@dr)S(+I{6t=r1wM6Q~hbj;zat@H@3S`~&rgqOX zJ>}#ir`mefgm{odht^sur<%$R{t+K|uQL5CKZHMQzbwq(9O!$~HGI#7I7VOO4+gM- z{T^+hSUvrZEf|zsCGX5H%uB4zaIQ=1`Fd9$7t88*&#YA^*P;CH!P|OU+&b1`5MR^( z;mpE|GUFI5-Swnxm!5!2gXv7LEp{?Eq1uhM`Wk=G#|A09#yk5DVN<>xQNtlOYXy4@ zG;0s3^JSb^lq%I=25nmIKz&>b0WLVez;R z9iIW5K;q$)$rDMgOYzjc#UG?@X#>Uw73=4wp{|DY>Ai>;;IZk8x8z*E{5Lr zAlk1Kw#hSdajH>^2E%Am?tM+#Fg%qs{JV6I`3N3ec#B+Yp&Ch?GJ{k8*j^EjVPQv_ z@gq)4xc)W%;72p^!&_6w(tKq{$o;vfYkgoXXWclUVZJ$BpRwS07R=Sqr9@JpHM#Ap zo0Rq^T06i%^2%FTUU{3XFv8xWGtH&KnPnq-A3k#}{BL#6x68G=E%*2gINX=`gJw*a zHc`9if#xYg;*RfU@%AMeIi)w5ckCXz7n78m8+3}tMDO5??~`P3K;q!%rE|?+yYRwZ6t5G=8MF9a>8i%b@$7N=;;TVQTs4$1}E0F;M&)78v825gr@q9;y67RjZ>w<(#+kAFWOSExgniZ{C$DW zjg7#meIu{1J&z#!=hwt3{1b1=dKu?v@7+6hPZh5W8`PxVVHG!C+D58-+zH$Zw^ zs?STyLCfK5{6Wstl!meW$GJ7&w~Kk%Ur)5&>nv#WcEDIQE%P}$lju#|Yp)Jn$cM;; z4_^Go&TBYZ#IwOhtvJk_(MM%YUcgzsqKAxwo1MJwzs4UlIdx3AD5r8iYK*8q2%}Xy zsr&`4E#~su$hSGNA2so}!&Ad|4h8}iC0qt9V9T83JTKXDQ6DOlceiIR4X=>%NX|)1 zuMa!;9EN<6KM1~|f~k(pW%eaz9pUL`ZPZ%1OUN2{gxZ4@0^KQb8)^riQ^b<@2QDLf zCihLVSE`(=yJu_dw20k6i{_Qj8vLLqPSFxb;XC|6zdunrwTl@m^cQJ1@EBi?>|=~- z&!UHVuC~%R3ItY8>|#(5&7gi~l1)6hqNB)aSaq#UXm(j1yM@wd&OVpC^siyqfIq!0 zTQ6}~g-0z!&ryHeJK9 zoyr_zk}x5I+38Dl3GDj)-aPqx{>cqze_(>2vVUw6XN`+~)vopfjdY-rIC7$bGgu}k z0J#l-(rE|NmU<(f|J(V4s)l#{|6XTve&D&{c?awH%iyt`~v^ zjESVLlj<#15%Kg2aK4VjMeBP_a=6sn6x*K~NH2KmJaGN#vF|ohbq)!{` z-5>k)_;0yBW&6FnpC6JvzrFtFvNR08&h<_!-mZBr6RCMz>G{0^hN@DAJP zQ{i1Fg3e$B+SBgZ*`%LF2N4bxdVXjPf}Nq+DU8H@;1jLN$6a=_rTTsKh}=8w&)Yzi`__XOC3#e#vD9BXKw zN}sdT_BCl!@#|`lPZjN=eQmnd#ZBI`G5WtWX%~7Q9AUaVRl#%$o%208pHGHvZo5KvFrP1- z%FFwFtUPS)rUZsFAQxmexlV0}iF1a|CSJI%~bGp9GsUW2dOXd2S5I4e_W^y{IiX*FM{@TWl!G_7ET`_UO^n- z>_oV~$w}8ZXJe;MZENtf9C_0|xJ^F1*|e=&Ytrw~hXS{3HNNjaJU~sA_ki<)Sy@;3 zIN!}b_}+7yzQp)osnA}8E}WVR%jrt9*z0cE55*vO1KKCmJUWYTt2%~{1*q<+jWBIFE)<%y)z|ogpZ567yJoD&hv@4LnmNhm75BtQkJ8Y8N=Q4f&+8h570woQd@tULAP{y?h&Nz=1FJAX{F( zYxGlJ_V4dD| z^F98c**1lPJMx25b~8S}|Fef(%UKcIq8!FvD|K{QfzD;z?bY4sV%`Untyxif6~AYP z8ELpyA~O%o!{f^v3g3h;OyKvnE{q&q;UnV$UG!~_c0$iq?E!zv?G49Y;|~^8bZpT% z&zv2Ep+^G4S(N(Ho=Gu1xyrdS2vsWgR>mMgAbU+c1PZv}}=0ns*}sG?uCJ z6#1mlyg;K}`w`~gT(r=M^lN8$^c%~bHY2BJ?fKe(HG`GAy|Vo@TBqQDUeCUF%fz20 zqO17$@W|}Q>*Fx*rj_?`h|Vo@-WL4rOZ-8dMWtI)7)k4fbt4c9a<;K*ZU(IgVh$F4 z=Bgm`4LD~CEPB37?+e*yE|o&>cTHMa@@mF~{WC|YFVS~idGu$G%wxS}Cmvk}@n1bU zCv*l4mQLSe?gd8#4`qJ)4u6pNLz>|2E5HtX>C_=-4x2+>*m!lz1!B$8j<>8mvu*M) zIyu)$x1Z~2>1+H!Gqz<1HYk6@PW=ijeK$&Ai+l=!W;Nr^no+A-vB#ZS=Gm;C6ZNQl zK0iymZ-y>xlQY#UF5FML8o6*_Qy6xR<>Ty}J-Vq}q@TEE1Cw^GA$%?r+KqG$=12K} z-)TMueUGmwsUbe7cbm-z8s2)!(1(*P2iE;V zV4oO7CXQ!ure&`J*ABb@J7lk8?D!%6AmicBIG5SaPv_*PRK7$?XZjN5VvJ~<@Z5cL z+YOvM#Tzo=?fzfTnR0|Ose{mm z=ucag1>hRD2X_lQZf>|#Dn%BL@H#jm|L)yQOx?|}M;qK!ezgZSbI+rn;18-Fef;R} zz7@7_IrS-nH}$|~O&?LeqRW6qNxPPG2Mc0+7K7k(7b$cSH})lrbFeA!T=;h?{|9^5 z!yn)e`u*xNzPTrU!PKLEpG%L4O;`#mdyjY1PVQ!vLtn6fAp4RW$h?i5gR&W{kgJW+ z*besoBm6;?|6>Dfqw#)Pr^zqPB~0+;FkjKnH8y&BjpzOt);nDG@SCT!o;~7BU&NHs z=k$Ksh4G;|*uVbw^9K`X?auc8K7p;ApFiQfjB9WGPr1Nw{$z*tJzVTxu*rX{hyUv@ zVNt6C6|ZxqO8c7~@5le^ZBPMyJAU;m=~w77`#9e)^ZXz1&%0ll#-KleuLZ=#(Ae-_ z`v=&dBEG!QkwX7rhsK8A9{-^65n%0DksynWzJK}nzp>*V)g0Jyazgm0-}|)R?D)xf z*PIm@n+cua{Q1)4cvM|-wki5&HGi)kI-+(HZU7>Gz>$HO6iNJM% zla|6ik9MLL!w)CStx66W55Cu?`s{|f?mAR@u2aq1(u@8Sf6&aA@}u}yD9D+;bR6B6 z&F~8spT5RU!R@yc+6{HSUKe?{2~4z zn~(bKG+Dy^?s4Ka_tk6PP9O=jPzh$$tf3je6x4 z>XNTdzEiZvV(nA9=_)54e(gMXEI4ipY|!FfTB-Zm?HP*MwRPy6UOTr{D*7OKr_)Ud zzx@&ZV5L$yqk)RQS$Q293+sdWHaUkhj#KdPQl)vbyT~2wdAii8FPih?{YmaM;h(t_ zI3XP2O)h{ZrN?sswY>a@My4m%n#U&t&Alro14wfgVD_^c(1nowDR_4^~#$Q8?MkA?jHT4<WkMl-~S$e zP(JBG7CVUD>SRnP5||q?$Tak}#O;H5RHJY@MeVf<|2=?i~3{~-IEpyHDJ zHJgFKm-2tK&neC_U-mdW${TbpJ-ETN1$p9%FUSw_v2aGU^75#mvy_= zSl{oHetmw5_jilS$_hQZgG6K>!3UCFC|6(Uctg_zEJwJYX%EV&Hpu6}3!_7P>up|N zyz+|eCnx0Qg@&Rt_!@suSd6uG--2pcEI>_5rciE}k$L+~{d0ZCJ zCa6`T!AQdJx2)~p)~z#Vwdq&%8SBdY?2MnAa(l4|)t*+gCj8KhZQ0@RckG}&zQ-SA zuEJmF+hOKf^fAD4wD>X4f&*&ruwY%QwTh?Ju5yCr+gwxku}W*w44*n7_$c*-%1&F* zU+UoeYLoPQmyVfSyLY!)na)e-cNwlHdoE#u`IX-HHU1ziU^ql(%`j(YZO{W~V%LS! zviBqIh*){A9JIh>V4w2dv4-y1SE@(Z^IM&NA+oymFX zxNcB6YQ^s~eamxtT5Fh_dwj;{b^g`-gTx=ITPX&^j1R*f;@fThaJ-9e|*y3x( zQj0hZ_K)Shw0ghBAM|x%%vk?p9rxGv5a+dI&`ynS!Q8B|?`IE{`t-J6buZ^6IU5_q zo;dy-kpUNMVEb)~w&=Zd+Q&$;l90%8SCGK2d!!IqVjop=ZW)~iy;m+u+Ll*;JJ$##a>1+H!ipfO`gDH04!{wAMc7q&V>TlSxGr3_* ze-6Tpwc9A;PxC|Q!%gLu<3Q6*ode1v%1r5U;??yOk1^Oj^nqF@SJb) z2dU#7B{eZJX8h@iw5e3(T<|o=JL!*0Y3_;xoQSU+Vwv7$Hf1!JhKhK6J;ByCPHfld zR~FEl(PU{LQ4a=UG%OA9^R}0_=lR4>@dv?i1mCvK`~oc|~MLFu3B_svCp(qHK3 z++hng2|;s~PHI`(N9<1UHuBc| zQAHNN?%hp3xg9@k^L$;;)5Ig&zc!!5?h;4JJY~wyhw=_{FGhcGHD3DL`Gbs*-|^3v`R!yL25nq*CU+U_rdVdy$3UPFb2g_PXEJ=$dRrzaZg|kvW1}~xHOZWz)$YI7 z*QfpU&aYjcSO9(Dd#s!9_WPPyUi@i{AdN>)jsuI*ko;|J&T9B{FDq0{pnfkZqe-Cv4&U!f;mPel_zP^{u@D z^PXuNqp9xK%WuD-_Az6UcYfMR55ID$J$`S8_wV|B;j_+A-xSeI%;raDT7v@cACIQo ztfN7HKfpc#Z7R$+zJPZDf0bR&KX!fY-|zWrcZwrxy!VjWqI}j$-Rq|PfLSNGr@jqk z%Dhh|f#Hl!?8mSP%|-KGwTWpvVuYpl@H6~D`i*{=HJr-kfAypHO?$;ZID_;R`j_&q z={0nZG~VIcNr%&xt<;D5;4hy>hIme1-~AMSkl$iRe#%c-(EUg#zEAu4C^(PGLir;2 zj2Og)g5osaS0s%7vEQ%AVG$$-k-B)}=oK1;Hj>@CIKTXA8|H|w^9TLTpgv-{{;xBz zY_ruk%6ZUHzu}?kol7sX_s@lQ=+E@i%t5l%=X}CRRqXt`Px1lv%^%=RchPP~Scnema?m10<4Qn)O)=J@1SMQ@i z#CwC!sy>KK#%{H32A{`g%&DC+wZPXd^(pGw*V8cZ{2HJ1sX*o!=nkjn{H8VD$iHIz z@WOgb-ZJqMa`=LqsAhz?kAcDEviEK+?sQ{?N4J%{beh+n;}4p7-sCk=$LdV7g+;T! zI(LvhReUnM1Ih?KAgoEck6;Bx6SXvZbqDxNg79D96eZLK444VB{(Oqx7YRwze%2pb}=R0&STm-vIee_F-m zM!CuV$U2~yeKRf)Q4F3}%CU*Irmx4TI;0KYlu8%1>op(iRKn>_O5(2JyOUj2@MhX0 zM(&~}zSR(1uR+whtZt|DC3H>SiAeT}H_|tJjX$WlNcH~Nci5Ug%^a)72o36-9lV-w z9D|30ms5V>oGJAY?pw8KV&01PE4k6^JifWm4*;BHBYZ>hT~)y{Yo%rKJSZG*x8Tm- z@0z+|&-*?8;CtTJdSqhVOYXuV$?$es=fbCe|sd=WUi?HAgs(`QoCv z=;lNA$%^fsFE8?Vy0Ox11~IbH<@{J4;*-Z8k8bBS-Ns)^9J?cn%_1g@~gZ%yC(5`R#+ zb@BUQhYVtg(7XkA4Q-BHI(h>Ogd=`n4vH}z7#paHGWWMx(}wkPnGycKV6nC zneJ@b<~5onTbWhsGE&YybVT8zg)P~EZY|upHL)90aGpBOEAVpi`(Y3L%Nc@)PQJz; z)ci#KYi{!URRYX85x5b>z&g?4M*iJgnKfcGnO{1$w7qeXI3aW=tp=dz!ym$jX8Ez+OBKH(06t&2a&`)M=fzEcj&dWYBg ztA*9KV$G1WGKhqJy-3dX~UEiw!z57^+&T-`qGSX^{d$K76XrlAKV9P zswX!?akq^RNHy9sn!CO7k|d;Sc)7#{&A2dAu{Y zM>M&A2JCvUa#=+^w11heTHg+k4rqkUP(FJIJjX$U+Fn%`OYjbEWd}L-WHXAJ{ zD}hO(+U?iYh0*LzEJfoyPTULaS}>a)oR-mI18puoXFjfGWvsy~OdV!bCwq?<(S}Ww zG6T-z{Efe}hXd>KANwCF1pg|3&~OBG{^x7WO}`TXPc!>p@nd;l^pW92^B!Igin|Ke zRB@}rW)97_Ei&8jqhoD%k6!)^SG8N)J==$2KYu6ICtT>nZ&rQg3zj6cZQD8CtNB}?TWSJ1A62aQ2&az9wYpSXz^<#Pz}L!)E8$qyUFdv_gMEXeih zUk1N|t4dyE^TLniA2fSLv(Dq&*>x1lYwl~&Zk3YYLN|DfFa-EDOZZO?QxR#@I;Cee zv|>fSr=HdeZBbr_-u?Eo^EoczIb1)&A5_6VXA?bs`>f}w(nwrEak_+LQa;$-Td*@# z^zqfH_2+{!;V0{Ta@i`eJ_t78pZri9Djs9kYsvdxuOH(Ns{Fc)kI?U5z~ctNpxl06 zA$2fiGk}Khni!bDshljh-D;>YZi1OO4%p3Ezz>(PL-wdH^j*LF?C*Ng&wc#jdi<9! zjf>yPZ^j9)fkd&V6~~Shz;N$0M!?C?Bq1(in=N*#*KiU&rgefGoy7i--x*y|+2L;4 zqtN%vnBw1`;t!g-kS*`JLdueQ1&cBl{m8V8%H`Z&+wH~cA>T8-@9U(3es-(j{`3+O z{`u-T_c#9b9`8o4*L=(0%^x(ly5?hD?>TD)NzM#|9({cKawxaqa{A-e?_18Ryt5|j z(aRdwXbW=m!Y{;7+3fY|{&)v-|2h63<+ruA>E7Tmfh$ov)U7|H4d$v?4B7?$udxZe zWAJ@b?AI&Fyet!hNmFk9N#lZly`E!mXT9>jfIq0YSibiF}R#-OppiO4tN&W;6LWlzF0A6+LNno%-kkyx%{$r z|D5*l+kibWb`(TFGx?7~L0jYeMo!Ux$W;i`DXA&9=~v>>@nF12w4T`lIbMJ0QXI%9 zH@oIdosYm0-t|i%G?zB;&l%1ldlQ2Ts`Kbfk1sV6Nc30bPOO>jU8}`*ESYSKGtXfo zF}tmIn_1#+lOtr@pY9u_h+Wh8_s?j0pzp?ReDL%`zMGfy{hGJ+w}8o~!2Q2*neSD3 z^f}Wvgn`Sp0B0qm^}`=1w~4{ThZ+f?a~f#J0z@HqSLB{48o#fV!*ADuPvJGa?t`6t zAOBaEeF?tE4S0z+=z;CT+-%Nz68}&3g93s6;ji%rjekLQs6Mdc*WT8QSL18sZ)UwN zlt&!TyJI*YIZ|M>y)HNazFsgLd|e^RE+4A29~DoYJiojwJ|pp{#JLNBdxG<1(Iqo> zfj@ZStbL0=Xxc#Yrs+8Te1i=(IYt5*wMVE>UJZ}wON^Ly`K!4J%R%GcYqjBUsysuZ ze@ZSOqj!n_5vm}2r(low^f+OaUfl`4Vtiso3ln~o>*3!6gZLVM(DYH+AxxRe^e^J4 z3@0Q|t*oYC#rQUJ=+17ymSU>IiMt-4A!Rsh^4H0aodZkLsZi~ME?JVzuseR{N+s8m z7U`t!<={vXTTUIcupb-+{_5BGgQh(+#!Ou98}C$%NFY^w#;)xWlw1C5 z`V+YA^;t{oQq_&)wral4t9X&2F&dc6yK`*X&?YsD{6OJhZJ#~27h(Ct9I!zLNh#X$ zOZ-9l5Mwte?JIMsJp%Dap%DQm$A@0xmg{)ki+ED}ZjGFAA#^rlJ-Ab;V%WC(_3^wm z4y>vr(e$vwWtA2c!RW^M`ubzYLsntuvmaxq(Q z1}*xx#;?p@%xnadHx=JdQWN`i-Rq#TKvkff=ln#Tyx7zV%ftDowRuU z&Mp$>YZ!n6~SKm*%AKHwC8$Dc$2;D*Z6~4 z|4dtS80Uub5sDWJ(R())Gjk%`YS!V_WR~q8(%FO7i7C0S@U6A!6LzwAYb+nBj>(fK z-W@oT;X1yK;O(p#))C)Tc?f5RI1KUe)E4jzg&m;x`ZfNbiMci71HUufi@r6!jhQ>a zY0*riZ;>wbJY+1?mdPgCbg|Z8n(ZIc2NLy^``sxL!b$S(_P{s|*Xi2x`_~dX4rTh; z?v=YP$kn$}?mjr5=!=4_3A1{I``_aa`g8)DCJLKbx6Y>s{`_bpnf-`Sg?7489Y~Xd8+@fI9 zzE&!HV(`#yeDOX0pxS`g)gAMcoe0#UjT5@rjBVwWE}`3)Dy0vz%Is0^GzhP9ESK z>n(eX*}OT36n2B+u`wVe@ctbaJQ$AO}x~O6^3qhU)wg4 zo;|J>W{p~q_io+ImHCSCp}zGB55C49H1W0?>jAKvK&Ud>EuPs2dmyk{IKqr;9*3IS zbhKX#XI8h&AaHQ{Cp+F3cX{ekm$VCb|5Z6sspsv?I11{L5I~_mONhG zaq1Z^9yt`fqxixT(+{C#_<{O5~T$6`xkFGoDqO zt9f_z$kr0ceI==~T~`>#2dC##spdAve)Xv zir4O&Uen2L(bPzHjw@?DeWdca^2lL71co=Z(DDsWW+WXp`xrA1{g0hX`*r$LAZTMBTBLC+hF4GCT-AFC;tIt2t7<-c zbMmKvW5olnYiFNG4+Bez@=S&*w&r)e*PQu?Hx1e3o!IFG)-BFG#pAQRO;z_CB*#JX zdIJOa{}0^Ky!pTVhjS^qrHUbD-qqRKaHDvrxb=+Dj3L&W93MtUMqd#L7YOwp&ent3 zqfU-7$WY7sb8}oFC^#dwp!Cv0nA?e5)s5@+J1j-dRXUEs)ZAQ84gcrysjWe1l z3vT14cJAkg@dSJI+oM`2)K|{r{M<6b2}hKV{dEMBlJnYmeUCr*?t3P_&)CB_q5XHX zDMja|IUp1&*gmHN9?B}^F$N5Ff!3g3xI3thuP3;C?w|2sH`YOu_a5)fCShhXS`AzC zjtDti;u!gyy|3{HRaPGlpb^xkbYYusLm+4ul#fe12jWOg|Bm0XNA|d?Pso`s@#(h0 z2zjh_nL5qs`hvQ$^;|WR<6+{tT5QOBsdf-nFyws>lY>4dPT`mMgNh&1I;gVyH*E3G z<$j+toI&i;oJOCDj7zFl#)at@1_#kY!=dZF?%TGB%ReWcC#M^Xox;(4GrBGb?|?W( zo9O-s*Go@nChmWXKZphIHVX(_RY`uk(9S-h0||yqu`cel5!>03>*bt&(627XVyP5t z)Rj|I{Ym9E4Z{~;i!sjuq|>0(&zS3jb$;$Yum6?%HwIDnfXaY zpa$QU{{X2Lp8Jn`uZz{L^rn%eb+-06Kx9^A;wo$}XiO@yDJz?gWC0kdfRo%sj- zHId)uQrUkWk9ti!8`c+p&NF4kZ&kR!8+`IQ@w52zG$)$EYu;AAd+mexM}O0$-*}J1 zUvUlQ4`2M}w{iZSuqf)@w23%T;zF4?ZRS4gfpZwN zwSN#F%mA+lS_1ky;`W^H8BeUQeKZSqRk9fHg6R`~zr8S49F#BoV z=I;&kg_v&k)`}T6*RSu?vyWY$d;cwe>E9rIf*+MXKEhrR-P)=g(mbN;0Klsot%`3Hpw z`E}_VVr(#bNOQ*78UIA|%^OtQ99-1V{^+jH1coh5)7iIJ9Qs0InLXrIPa?fK;rRl=zx_Y9qZT6MwEA&0RPnYh+ z@wT;(3hxFH%54q;!Ub(%F0_H^YkxO?P-nynYs4RYt2i9ZW{Ei%RraBr zUHBV0$IGXP&R{MDcgh9Bsp891KDLm~_?*=T72a1cxJS2^M$cL0}(c?d4f`T~{%o+(Tu2R@b)jtRa-UM760U9<@C)0aZ8&3S1! zFFv0T?gY4ruugr>%gJWiN{{6$3z5$+mAhsJ$yRmc(cc32J$yfH;NQG71_Ps@=1bF0 z0~LdR&}lQ(QGrC+gN$^%C`ZlRY-k6tSNCF5pI~hRYzj&D6kBrAMuqQKf^X1@dsdP% zqKVq|@a5K2_7*Yn@{0*Sq|LC!XaIhVKZqUV5oL}K{yNG;;3_8uU>go`54Bl!M&3u z|KKL}$i}h&4%u(<2jBZL+M*K{pM^P6`z7=r_pb3LsvbA81z)s#8JOR-Qfar_sujbH zdA?FObZXhyv7NmU51{s-jo=V&vKug7VJO&wxLmSHriRKP61crJoHTDBqj?RMP|O6U z6Zf;l?}XaBcK2z{(WbBPwtw>q+FBdHAGv~P?P5oWe2ppE-^@eIL14}ojcfYM!WMtI zKMf{(_3R0^^>mlc*`-l2(yfnUk2RlhFZi>w8aL|yRcZ0g6Ygj>kEOgEaqV8*zGu@V z@&tKb;}5bvu?{dMWQX={Mu(NyDPd28wlEyZ0#-YKg9>l0`^X)ZlW=x$Ll-UH##fG0 zDn50x$LK268W*5`EFRI6;{}ViPV(ihOV!89OH3R6CjQQgG~wjaMi-JpF#Mu#@ds%; zV~5!nXde+t7Qz+A=Ah+vX#)$sqnBb_fOF=A_t!e|lg=M4@?3>&Hy<7=FC176`j1yI z^y$cPW94mow=w$woz!bf|B=|kdo!Nmjb1Y@9I(HGI}{1$)E=l5t1M6-jja(P-Q>;NCE^&W06o9y4x zz4~}PjL(_72G%IiOe`L`0%ht>=e67+Jvo7EP~Um-KH{LVoc+tY+__P1xQ`k)(&Ysx zr>z*@&cMeHh3#Iy#~-BZW)Dc)*3XqE8tcrLxOMH_h|fA@GElnr^G?0Hu1}iaSqpHu@>*@+zUmV< z9~WNB=f1`t1pDCVx+8buEvvPgIf?y*FlV^^Xg%(c+Rmj11=h4$@s!Rw?HIUiK2N>V z|GgJlqr>`hOaI?qFYq|$lY61$cE*|YEqdKgtyJ&aZ;xh=sJm5OLgoQ!A-|LhFKyb# z*u(tA_@NKR?~7)u(XC~Gh6lCHG79%zb^U+2jP{N>kB01e68&tm|0$w%p|Q?>)T_;s zBzlb$PWx1G`E*;URPYAxlKIBlihIg$!_C|r;ig~F>&j0aYj3|#GfItbI}u3kZ}odO z&7OV>7P`cKX?T)%5rsJ(%eFb6C)d|YtLAw$qgit~z&EdQ5Fcoe`D zb1$0tfyU`cdB==hw9UZNIhqR+z_N#{=!7p1*b zL^%W*EBooZ*sn*c(N5LAFI&|qo5?a73}rhW%mr;#Pa+U2b!M6HZHty@q!g**_QXols&|*zJ1T*5qJ((sETB zZrAb3dxe>JKb?Q@$EU zW4ACXt%Goe$o1+&oPZwSJ;#TOcBjGC_|%W`2kBRIDLCYRzI^@}+^(K;14F+g`@8mW zo56T7E*mP?banRv}J!VWot=pnld{gJaq z+Iz)L?6>r0Gf$ZhYCfPV@{j6*mo#7d*Z*_=pxHyI$qa8poGA7rX!P0UEbwton>PL5 z{*R9b_;LN-W_EmGi`fzw{f+JED#qPI4sY^K<_KV={*E@ zrSoI_L5)wsqXIb+`z^5c@+3k z#0|m!Eq401tlZGkiJ_aEaAQg*`w)j3^tuX#r?3$#R~vc9is#Jwor zVToIfn>0~NV0*bHc&GR};DR;V?GErmw$QwUc4TFV_i5>U;2%H49~A$?#G_!3X%EF6 z1OnDYc{MGxHo@<_n((}u>$bo_3=dNNM*Qz^D}3$|Wwy%nFF0Y~Y+e&w4L%YW=a2CR zKmAE#7n_2+N+MrQSobWxQHyft(B$+i^?!qX&`)gjA7>rQlRq$Pv^lL@!&{R_QEk(` z#IRdfmWl8GIsPDxARGJ(%s&uVFZP5MiqoZ>n<3rsr>91=L5&<`Y0_hL(Cs^B4)J3+DTjXni#B5dx5_=DOT`F3DWAP0sNI6Ws|<QBy9t}D zU2X_GvV;u=2VorN(9cBkjxmDvX}%oE9F91i@Ppc%wdc3YD=|(Wz!{1(H;?Dt$#&~E zaH~i95&ALyAoWjQV$Nlrf^RTwH1QkbbBC7={siWszNIm%c#B$hdGAk}RpO&_FX_Dv z(Il#K{#%OM=wz3LN4B|}C#74W7$mc9YCrt9^9O_C+A+s!t|hl_{MtePvHK8?Lpu=T zVl-Zf31RMebS^nWzDvhU&bzLc`8T%){w-L|t4Dk?xQ#bBgOB3-1Q$f>?#K9p22W*Q zLX2CZns7V|ezxJ4!>ML1Uf$RCxs%cw(%z(^%hAVbN=gMZ)z zsSB@SUxKsrC-{SA&P{~Mr^MC;S7wa!+lr&AbsOWtetLg&a>D>)zt-9~(Mx->);QSQ zt#sR2A4^_74z`Rgt>M(=yQifK7MRTe>Dukfef4AfLB(?tBW6#VtQpdgXRcZguqD@6 zx7L^FewAf2A9geDi*+TP9cCC0!@ZkNi`%TRLF|Kr=3TnS80l^vjs4Y`m-e?!YCpXs zevCgDV9(B3x=8j@C);A(CcaDirYzi8^epzR{lcn_Q;XypPyfNvRO)uOv`Kn}Lk+AP z4!O9Ho9#$it{#aA86e^)=ue*{6W@1<}6#BZQ@U9 zo7lc0F5+O^h~|6oU~JJmU*ml{wQcRu@JXwHVP; z*CAZn*-SaH&JCaU{B{1IawVGmx>?VeyU+sF3t*kfIj{Mc zwM8+};JQ4u$0((PacN84y& z7e9Huj^jBi)_qd5v76k+*U!y#^S%6o>`8w43e4U_g%$RxCt$gXZT7WN3#VwT*GN8h zoe-ffTs`3h@-+|d&)oE090wB%Co$POh2vn~*!4r1OBLPWm6O|(-|MN5aN(au_cAYE z_0s(we-M8SWu@NHb0zPSLdobR{(ehs#gm;mVd?YobIICmh4k@-zqU0Xjc-(&+V z8-7=H{HbRZ>;HJE+VweNE&V>v`A}U5pUqplC}{J2#FuT*=`iI14>0Ya@|Xs>!l`%8 z@la;DTioWiXM)p7u(c15Gm~M$UA8tVJ?$VKYRju+EFtWqzo6v!EONY50R5 z+@3@0l2JB3@j*S|P=Cj{Var|$)H2k^%{p{UtqQaFJhfO9jz1HBFkKAqKCwY1UUl-u z3SWelr#@)+8cR72DgMO_F8EpyMBwM(5593{nwO?T|9D>;Zdn|?5TDcG+Cy|2rVBGZ z#$b%S@?rK zhUq8Y)Q#%m2M*pxyby65BCkzA^}!s-TE<~KmkuD;)TMYltgHWF{-Cn)f70*Y3z@bf zUBWar(;V2~bZe0ZMmW;07a8s}Pcu*Pl>0gy+UVcF9~4&UFwx15rQg!en|aZ!4Govh zBK|Hnm5z^77>$Nx-mE@AA0ZD1c!P>-qxA%@nY9A%e_!+b@8S=deXY{Np?)i_uHXK( zR#ZFZ1+B9_(y}$$2RJ};f2$8^Jxq)s68~D4*pu(HUQ59rraWj*X07~DHYy*T=CdYG z`VRPTTI1<=Wb@La;YzAq{xY_3_YV(!uPHw+9DRolldpHV^QikDYexTf{5Sby5%w>z zDL&(QPkg_R(&GH6Q?2)T!PN2J%pY`qNtmC0lBD$^aVPZL*y*r0Qf7>=;)!tclb>qv zKa*+cxLn$~6?V~f-~)d{b3^gvR40^?d7Jq-Z?+BPm{Z03fEwTh8-9ue*T`Z=LON{6b@JU+xdgwu^i%+>%xpzsZO-@bcypu znjPwZv{oD+$FZevD*JDY_9HGJwjkln=$#97!GT(&j!GlNsRx53!+o;|0pSGf0G{6XpW1f&rWl*XOUc`am!JtnO?+7sTX z#C#-g?Pq2k?^N=|Wur4f%c_IkU=}?{G&t*HFlzEz-?H0SlXh@)PPF9IzrKS%Xl&w zIP_I?S(7zlCVH(inxon30DO?RE8rgMM;C4spiT8io|dnyohGI&@t0D$2b!YKb+P$< z{6T4Wq|t949>gJ{e_-DS!>4@<+qtEPH`u|c=j6uV!{T87>MHB|WuHAcc_FqN+{ZfC zaMJJtcm;3L=!E0BB(H|A^DX>Ad?OjBV%y{nwvu57#BH#2i%L zDxzH}jnT*C%lLy#9{5+FoeQ33=IZ1Kj`+1hz_f1F-7OQN4gI4?drx28F23Q#CTK_S zfOiIUA&ww+bLs=VzSnE+cyozTwE5Qbx`&wpL~!2ne9cFh&X&ct_( zQvT5x*liUp%U-5G#YZEUn6p6wexJY8kEANO!IUL zH_r70acVE8);TR+Av_g~&qpot6X9GqoGLu$cJUO=9UO1lO7ADL)+T>wAr>-Apbc5+eT{Aq4Erzg2j6>XzKgZH@l^-^5gCHt;3qUEGZsWr z{b7pu80CE{3s3g-x@D^i`o-v;8I0QJ)391_`p;(idYz^Z>yUF=6-U;#?*?0i_$AKT z?P^zh7qIF_HiQq&V)N`AwvTM;`}l*(2ezQ*__l6VPOGaepDT_}9?Ru*UJaV*{d0Y4 z1rEzvdgbf`r$MlEZ$UHsY50R5Hc%|=#+v?P9>g_+d$$sHFuFIohvu|1td+_}^U0yb z2Dd*Ie=wFmwx636oXiP0pm;;S;2^>Y(L{b_2I1>@F`Zlz;p6_0$Q}2i@Uggx{!IMA zK46r{c1r(`c$A(}7gtzQ<*ZZ7J{H5Hh(OY4?=c zJ)P4d*FPq5`$aLp_I~@C^_Q=og+Dlg;Oz5gNwUVMPdtr0shX{~cLjFeB}8 zu#f2?=r~{t%8J%bx-j<1e@8~PB-1ICyiRLj{DMBP57uTT_SC;46Qq(gq!yH~&J?{A z#js9O8Kxe<+Eh3Hj)QeL{h@|7>hMTkDU&bi$Jem^x3w#4yN$d$r3d;XW}Qz?Y_K;T z{!R5^(wcs@GnrvxS=W9=W3PEMdm7#Nj>EKNVdLU4n!Vab+wjL5;&*(OtMpy4b%k=d zNOhEUyVXcycySwp%Mrbg+Icz8#D_6AHHw#8_|H}*@l)yB_=9H8SM%{}?7WnvFezc5 z@+T3##zL_cEDW!g@hmerE_%fKs1T=aE#Glr3ix1yDZC=sCk%Eq!4?e9f_rwd_Feoz z(h069s-P-E^Ko4EWi+D60AZ{~(?kv-E5@UW?4=o_W7!^qHO*zqR=gHs&wwkeGm2d% z9FY4-a4PX%j6NREmA@d*|GxNxmSf6ZCI+>wm_^&p1gF{g>@>S&;M=XmjhcgLj(emL z8~mJm9c}?3f(hFv$wjw<_@WXXo z_B-;Lq%QX2OA3nu)57QVTjCGOHw7PX{1vXQ_$&7a<=c3*=fcA2r-r{tET>BDu(0l7 zxT}Ry{Mn7(V%H}$9Py`2T*VcFEMVr+yp)a^@%?y?M(20&2j#OHuuH@6g`%bGqUhA3 z3GCUl8En2vBb*|5Q}c2O*~WP=f9()v<%U6cH!Tx`uzPQV``9-)Z8m-a@b&CM$Jiwm z>*(9~gJx}-Z;a!vucKzeLt|V;FoN<_zBG0g7IUItMZjZCe79Gbp1pmpLxt(BU&$VF zoqM~rIxX}4>oaQITAkRX>1A%|{N?-jgN(IKAObH~98T#S)1J`l6L;BNqx0%D9_>md zU!1}Nxf9C=?v^kZVL0%j#QC~+Le=}~)NB%s4BM%2Z0dL@{~%+l=J9Xm4{9A`Z3BVB zV;`nHG5(`jj8-;d7QAx#V-$L;dv8}M?eH&o4bN^BEC)N*deN3vpV4jIG{H}9ucuwj zKipUL?uEt=uZfQ2gGfu?6n_vOuZnRXpJP>eYt$unO-2scSn+|G7-PY?k*wq!-#Ted6tmmo`PZUGFe|u1?2EJ>&GwuIpSz zt4_>Xx6Zxscku@|jT1ztK6oE}1D`5s;}2+8`Qa|ujohN%+Agl@Bf_|jDe3BNm0H znaoe(D<`oV+Qb`-?^E?i6F-@_l2gKB;BJQ0WdVd6-8W3bFh_UT2-!)qkpIrn1sb+8!=9Fq?_Ra1;X#@mh8 zc`$#Nn1kTr3;3KCvAmL7@dF9J-GozE#pBQUF8-iwXsmU!7VF+-#o5j3h-4I7-OhPb zoW$LlFu_Fw80z56%oYWVEWQuSa>e7lcw7bYk-)uNjzll5>&ZDEkNLxNo*9(x#liHE z9Xv1J#UK38E@9oyKt(&ic7q=^jl#jlmOO9`SFsiV&m3-=-W^`%jhJ53%j(eqW2>Q$ z{H*krTX(q%97e0anmlZZ_3$QC4lP4H>$~`aTCbDV7;6*aJ855N>;|$)vA2~Ebs$_S zCo;&Q&M)l;elV}|t1F(JIqu+=oBV$JxVBEoMfrLe6mo}AFud;<(hny;U40jS(8{&& zk5+n3`sKGy`njfVOnq>@SzIE(10>u)YVhWOrao-v;@zxT{rzQmbsJ}P_wZXShp)pp znl2od-^U+(#|1L$UTn+6Es^$;{4Z%!pY3K6ixLJq%jj?l6j+LW#t;@dxF*%X*hI2j~-i9lUL{>=g&MsI);12Ne)UIS~Fq zKEOPf!O!i-E{=A{W4W^*Ig@72mr=l4}U_!zD7m%%P^E!GpK!!CI`oa*1sAAEC#-g)7<;`Dvy zfpmXfD^njl!gKpFO>Bp;`)YXDMvlkDpd4NmEo&9L-e!f`>Rb7PA8CJc9!-5vCyV)= zIsD`J0T(oPKA&%1>t|teZe5SPONKdhG;m_G=k&I&&mO_WxA6zx<^N;5QrqJG1FpEi z1wYeF4s`u)TjtTkO})OnlZ(d8Sg||7J~bv#1{Ynx!PTKo_I>dOKkGz!QCm|!mB)9V z(S5GvbD~SehwyX##M+{3{g+OV8T*J0#hB;walS47;Agtt_49uGG5t#G|2e|gvaWEu zq)i}yA=$&UFOS2!fFG&($j1%Iq|Y_cU}8D^GjkP>@3P|ZGaX$2Plvwao#v0e{=46$ z_vrN>^W}dId)IQpZ(`SGO%o`IOGIW&d}ZZ9>69J(@8=J`)Ar8Kj|HK7@7Le=e|S!s z;d>0xs1K75AIAwfywOqHQvFa3nwMldVU4K^Zt$_M<`42a*rwGE%y0gn1Mu;j`zGF? z(x5UGrogp6XZiv4F$7}=(_s8_=E3ut2$9XHhtMNHerK| z|HRNZy1~iRoo<^E_y*$)`~yEe7I=u^N4+w#Yh#OyHi@;ywc`50&r_VS?}|UDHelL_ zIK7G;%S6x{g1erG6H$IW+BUWygI~&K+Qn|IQ*md+I}(qp>9ud!*J>?YJZxd&;*p;W zJW25ezmGqtIv_LR4u%7baVC0BgFzX6Q1RK_*&{oGj`<_PDCszJIiLqhs0i zF_C18*ir#PVP#((Fj?_V(I$jr2kz{GTfqfun>N?=WBUckKk+WVi$Cbky}?8Cj-FOlMJ{)#kgAp1`#LGO}`$XI-<%{9kc5`1{jc%=7h`PnBjT=?1ekF^|9t z*I{{({xl8Fw*|-v_kf^HHS5rQ3YIWMiT9nS}%=-TDZs|x)> z8hw`;G50#)YQonxu3fIV>(uZ8RZ=mpzyxz%C)R$hWBKpm5B9Ek`Lzf$7oJnYEhImT z?GoO~hTEB}4XdZ*s(v3|+Fi;y9C+AG;*mYz%w1|=2M_5D;#KJC&!h)7cxd8s1h0;M(PfUX*G+4c-Y-jAtZ3pz zI#}Lp@R!pM0>YQ`yys#x43xO3vk-z5?)=GzBDrN*S;eDAW0_8@^$m~ zX=ZPxJx?IeuSK-B%QMc?ACl-l&bx8T$xQ3>LVwaW`n9uqZ#ce*rx}}`-C~*;i16mn zu3W!_EBB$)m!96J;#|ZVoE_jyp9lwp8$*85KHm;s7JpFrAV#;J5A7#(!s}w+fWG5_ zaY=Iob6GM=tmewNwyP#~wRC=eozdr0`_$;#j}iawm7T%=b9h8kbORQ(5#O|XYhA3z zY8KhV?$&lPb2pdUbu;PR&$D1=JuSOm7JpFtefjB``p~uf4FfhBkD=Phxw>m{|IK=c z`~)5R-crlNYFr*1ulvWzyQJ5|s%;TV^U$H)5X%o+n+H(7zA!Fm946kT-7Che7BTSn z{;j^gg#Qo^#@_Qq@dwq<8E7owO@0^AJ|m+(9(Jbaqn0{MU;BF-&5O1C87iz*3q2%7 zPtEi4d22VC!q#r>Y82ieg2_#U87}SnI@`n#V{r9~@YUV+6+eudx4@sQ+BmIKC3xGF zyI1|f_=BcafC-X<{oKI&?blvsd@}!5Y-WmoWRH_@5dt>n|s+RI>L`d@sz1_`a|&ddTP^m zQ=5Sm7cRKp_hK7jk}VIJz_-O8eA^3nG;@kcH~&8F*9aKap489Rwc^flylvFjtMMo6 zr3%;S)6IFk{c=4n)J~IN?L6qWuDwEF+770d|0I9#N4w}d*-HN>XHEI}z(1;$M8|DM z5{Y20LGD$3jPK!CgmERgA1=Q${-EU$r$n~S5BsjF#N6Xi__C7y$%}ep2;@uLPSytT z$Euw;49alqPVrOl`PzqeiCr-hI2324Z{rXC(5^@}{q_S7;F@G!RSyP-`Y8X;c16}U z&9mFsO<9KoUZ+9ec`M$s!qv`$UFsZKg>S|7_r@RmOLlXt&RPCogM@3g=3Lmr?F z8>fa{I*G?sJ{aqlimBjrRXv^1{kcb`(|dNFvKQaVA5BSn!W%%|M*Qkd~!NX zzKD;QZL{a75~CeB5KR3eW+z-|eVni1p1}zJY5pK{_W!|h{4q8N_Hm@@c*BQ%SQTmZ z2wKbO$xm`PW_|YS#Hij39uvk+V)DVfK~~=B{v{v&a^TmW{%4-O`;UIzPrsI1p9lHa z^Mv%0-(T{?o3?n@u};9dWMeEhZ^^jzZtdHbbZz4Kw(*SkJ=@)I3@ z(6-2jbU4+|Kibt#n-5KopXK_VGgZpgwgpx@Bxs^+Zf3mFZRO`@tPiapg^~EjN8K=A zhN0NAwi*(fNIn22j-UUYeqI6V>{}!_*dd9Vi|u+`U5W)OU|)7iNw0+ z;|qD2SEKAk@9wNN#t=WK?ufaOC=O7&8PzgP;tysfHMjGf{6WSZl14mS2N{>j7(()msC z2Q9z+H7Ce6Bn_WXW3;p2g9MR075@x8rqhNeL_9C_)?|+to*-RIX~}gg_%Gr@V%uKJ zo`HFdDN6|hCa z!;}45dYhd>&b15JfJWj+iVs!w(8DvhVjE9tKTqW0oA`s^;udXxny}hx6WFpCgM=wn z2Coc&tyh76N4bi#=_#EBG^N0;gmVh3U5~=TZor~y_>&hrPp>7xMERUoD1RG&5TB67 zIDJ7wm-MdT%6SvYo7kFn^3VZ0zN1Hbu5Raf@3?5>UpBgxc2c}4+SZx(?7$rMID0Hr{ZIoc6IZxPWe(`-WccM>g=iy zcbqf4I{X396ivTYV{Gv7CJlD3*pcXss_lvE`Az)6VXYmcF5u3p?SR2D#(3)r@!{yx z;L5kQozD+S&10)_x!c)xFE)>qj`8)e**o$6hPUp4mlrx5zq>1fPhYz;QVQ(bU$=o*`eqzhgM>$f6X-0+z+3ga&xctp=qPDnN@5- z)`>mGkIOgN8XjA>I5Id1`5~>O`-}L4@;@~GVM@K)Yb}c2Lbws>$)ALAzESZq=iFje z?vCrhSm|UnkIi-P`kYe$fdDZDYw%0UpvM-H}`*8ahD|RJgmSWpIx}@&C?FwSDeR ztZln;T6`UU5FgTaJ`AQ2H@MAtSqajY3;w*F?28v%EG^HW?K84UJt_F871$LfVY#Laq+*@XStsghF{9{|4UAL3lV-wrm_tSA~gRIP#@dwpM zjK8*t385Gta&8XHZe`RV3iwj7wl=

%lV<&5f>gt5vbmPj8;>RhXcj6}Z}=k!LhT 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 0x14000 +#define ALIGN_UP(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1)) +// e.g. size=0x13200, alignment=0x1000 -> 0x13000 +#define ALIGN_DOWN(size, alignment) ((size) & ~((alignment) - 1)) + +#define IS_NOT_ALIGN(ptr, alignment) (((unsigned long)ptr & ((alignment) - 1)) != 0) + +#endif /*_RPI_MMU_H_ */ diff --git a/lab7/kernel/include/bcm2837/rpi_uart1.h b/lab7/kernel/include/bcm2837/rpi_uart1.h new file mode 100644 index 000000000..959130656 --- /dev/null +++ b/lab7/kernel/include/bcm2837/rpi_uart1.h @@ -0,0 +1,19 @@ +#ifndef _RPI_UART1_H_ +#define _RPI_UART1_H_ + +#include "bcm2837/rpi_base.h" + +#define AUX_ENABLES ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215004)) +#define AUX_MU_IO_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215040)) +#define AUX_MU_IER_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215044)) +#define AUX_MU_IIR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215048)) +#define AUX_MU_LCR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x0021504C)) +#define AUX_MU_MCR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215050)) +#define AUX_MU_LSR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215054)) +#define AUX_MU_MSR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215058)) +#define AUX_MU_SCRATCH ((volatile unsigned int*)(PERIPHERAL_BASE+0x0021505C)) +#define AUX_MU_CNTL_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215060)) +#define AUX_MU_STAT_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215064)) +#define AUX_MU_BAUD_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215068)) + +#endif /*_RPI_UART1_H_ */ diff --git a/lab7/kernel/include/cpio.h b/lab7/kernel/include/cpio.h new file mode 100644 index 000000000..bfe2c7044 --- /dev/null +++ b/lab7/kernel/include/cpio.h @@ -0,0 +1,47 @@ +#ifndef _CPIO_H_ +#define _CPIO_H_ + +/* + cpio format : https://manpages.ubuntu.com/manpages/bionic/en/man5/cpio.5.html + We are using "newc" format + header, file path, file data, header ...... + header + file path (padding 4 bytes) + file data (padding 4 bytes) (max size 4gb) +*/ + +#define CPIO_NEWC_HEADER_MAGIC "070701" // big endian constant, to check whether it is big endian or little endian + +// Using newc archive format +struct cpio_newc_header +{ + char c_magic[6]; // fixed, "070701". + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +}; + +/* write pathname, data, next header into corresponding parameter*/ +int cpio_newc_parse_header(struct cpio_newc_header *this_header_pointer, + char **pathname, unsigned int *filesize, char **data, + struct cpio_newc_header **next_header_pointer); + +unsigned int padding_4byte(unsigned int size); + +extern void *CPIO_DEFAULT_START; + +#define CPIO_for_each(c_filepath, c_filesize, c_filedata) \ + struct cpio_newc_header *header_ptr = CPIO_DEFAULT_START; \ + int err = cpio_newc_parse_header(header_ptr, c_filepath, c_filesize, c_filedata, &header_ptr); \ + for (; header_ptr&&!err; cpio_newc_parse_header(header_ptr, c_filepath, c_filesize, c_filedata, &header_ptr)) + +#endif /* _CPIO_H_ */ \ No newline at end of file diff --git a/lab7/kernel/include/debug.h b/lab7/kernel/include/debug.h new file mode 100644 index 000000000..2e7d97904 --- /dev/null +++ b/lab7/kernel/include/debug.h @@ -0,0 +1,19 @@ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "uart1.h" + +#define CYAN "\e[0;36m" // 青色 +#define HRED "\e[0;91m" +#define CRESET "\e[0m" + +#define WARING(fmt, ...) PRINT_MESSAGE(LEVEL_ERROR, "WARING", CYAN, fmt, ##__VA_ARGS__) +#define ERROR(fmt, ...) PRINT_MESSAGE(LEVEL_ERROR, "ERROR", HRED, fmt, ##__VA_ARGS__) +#define PRINT_MESSAGE(level, prefix, color, fmt, ...) \ + do \ + { \ + uart_sendlinek(color "[" prefix "] " CRESET fmt, ##__VA_ARGS__); \ + } while (0) + +#endif /* _DEBUG_H_ */ \ No newline at end of file diff --git a/lab7/kernel/include/dtb.h b/lab7/kernel/include/dtb.h new file mode 100644 index 000000000..7076d8683 --- /dev/null +++ b/lab7/kernel/include/dtb.h @@ -0,0 +1,26 @@ +#ifndef _DTB_H_ +#define _DTB_H_ + +#define uint32_t unsigned int +#define uint64_t unsigned long long + +// manipulate device tree with dtb file format +// linux kernel fdt.h +#define FDT_BEGIN_NODE 0x00000001 +#define FDT_END_NODE 0x00000002 +#define FDT_PROP 0x00000003 +#define FDT_NOP 0x00000004 +#define FDT_END 0x00000009 + +typedef void (*dtb_callback)(uint32_t node_type, char *name, void *value, uint32_t name_size); + +uint32_t uint32_endian_big2little(uint32_t data); +uint64_t uint64_endian_big2little(uint64_t data); + +void traverse_device_tree(void *base, dtb_callback callback); // traverse dtb tree +void dtb_callback_show_tree(uint32_t node_type, char *name, void *value, uint32_t name_size); +void dtb_callback_initramfs(uint32_t node_type, char *name, void *value, uint32_t name_size); + +void dtb_find_and_store_reserved_memory(); + +#endif \ No newline at end of file diff --git a/lab7/kernel/include/exception.h b/lab7/kernel/include/exception.h new file mode 100644 index 000000000..eb975a1aa --- /dev/null +++ b/lab7/kernel/include/exception.h @@ -0,0 +1,92 @@ +#ifndef _EXCEPTION_H_ +#define _EXCEPTION_H_ + +#include "u_list.h" +#include "bcm2837/rpi_mmu.h" + +#define SYSCALL(number, function) \ + case number: \ + function; \ + break; + +// https://github.com/Tekki/raspberrypi-documentation/blob/master/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf p16 +#define CORE0_INTERRUPT_SOURCE ((volatile unsigned int *)(PHYS_TO_KERNEL_VIRT(0x40000060))) +#define INTERRUPT_SOURCE_CNTPNSIRQ (1 << 1) +#define INTERRUPT_SOURCE_GPU (1 << 8) +#define IRQ_PENDING_1_AUX_INT (1 << 29) + +typedef struct trapframe +{ + unsigned long x0; + unsigned long x1; + unsigned long x2; + unsigned long x3; + unsigned long x4; + unsigned long x5; + unsigned long x6; + unsigned long x7; + unsigned long x8; + unsigned long x9; + unsigned long x10; + unsigned long x11; + unsigned long x12; + unsigned long x13; + unsigned long x14; + unsigned long x15; + unsigned long x16; + unsigned long x17; + unsigned long x18; + unsigned long x19; + unsigned long x20; + unsigned long x21; + unsigned long x22; + unsigned long x23; + unsigned long x24; + unsigned long x25; + unsigned long x26; + unsigned long x27; + unsigned long x28; + unsigned long x29; + unsigned long x30; + unsigned long spsr_el1; + unsigned long elr_el1; + unsigned long sp_el0; + +} trapframe_t; + +#define MEMFAIL_DATA_ABORT_LOWER 0b100100 // esr_el1 +#define MEMFAIL_INST_ABORT_LOWER 0b100000 // EC, bits [31:26] + +#define TF_LEVEL0 0b000100 // iss IFSC, bits [5:0] +#define TF_LEVEL1 0b000101 +#define TF_LEVEL2 0b000110 +#define TF_LEVEL3 0b000111 + +#define ESR_EL1_EC_SHIFT 26 +#define ESR_EL1_EC_MASK 0x3F +#define ESR_EL1_EC_SVC64 0x15 + +typedef struct +{ + unsigned int iss : 25, // Instruction specific syndrome + il : 1, // Instruction length bit + ec : 6; // Exception class +} esr_el1_t; + +void el1_interrupt_enable(); +void el1_interrupt_disable(); + +void lock(); +void unlock(); + +void el1h_sync_router(trapframe_t *tpf); +void el1h_irq_router(trapframe_t *tpf); +void el0_sync_router(trapframe_t *tpf); +void el0_irq_router(trapframe_t *tpf); + +void invalid_exception_router(unsigned long long x0); // exception_handler.S + +const char *get_exception_name(unsigned long esr_el1); + + +#endif /*_EXCEPTION_H_*/ diff --git a/lab7/kernel/include/irqtask.h b/lab7/kernel/include/irqtask.h new file mode 100644 index 000000000..52783e26b --- /dev/null +++ b/lab7/kernel/include/irqtask.h @@ -0,0 +1,22 @@ +#ifndef _IRQTASK_H_ +#define _IRQTASK_H_ + +#include "u_list.h" + +// smaller is more preemptive +#define UART_IRQ_PRIORITY 1 +#define TIMER_IRQ_PRIORITY 0 + +typedef struct irqtask +{ + struct list_head listhead; + unsigned long long priority; // store priority (smaller number is more preemptive) + void *task_function; // task function pointer +} irqtask_t; + +void irqtask_add(void *task_function, unsigned long long priority); +void irqtask_run(irqtask_t *the_task); +void irqtask_run_preemptive(); +void irqtask_list_init(); + +#endif diff --git a/lab7/kernel/include/mbox.h b/lab7/kernel/include/mbox.h new file mode 100644 index 000000000..25b712383 --- /dev/null +++ b/lab7/kernel/include/mbox.h @@ -0,0 +1,66 @@ +#ifndef _MBOX_H_ +#define _MBOX_H_ + +extern volatile unsigned int pt[36]; + +// Mailbox Register MMIO +// https://jsandler18.github.io/extra/mailbox.html +// include/bcm2837/rpi_mbox.h + +// Mailbox Channels +// https://github.com/raspberrypi/firmware/wiki/Mailboxes +typedef enum +{ + MBOX_POWER_MANAGEMENT = 0, + MBOX_FRAMEBUFFER, + MBOX_VIRTUAL_UART, + MBOX_VCHIQ, + MBOX_LEDS, + MBOX_BUTTONS, + MBOX_TOUCHSCREEN, + MBOX_UNUSED, + MBOX_TAGS_ARM_TO_VC, + MBOX_TAGS_VC_TO_ARM, +} mbox_channel_type; + +// Status Code from Broadcom Videocode Driver +// brcm_usrlib/dag/vmcsx/vcinclude/bcm2708_chip/arm_control.h +enum mbox_status_reg_bits +{ + BCM_ARM_VC_MS_FULL = 0x80000000, + BCM_ARM_VC_MS_EMPTY = 0x40000000, + BCM_ARM_VC_MS_LEVEL = 0x400000FF, +}; + +enum mbox_buffer_status_code +{ + MBOX_REQUEST_PROCESS = 0x00000000, + MBOX_REQUEST_SUCCEED = 0x80000000, + MBOX_REQUEST_FAILED = 0x80000001, +}; + +// Tag +// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface +// Included partition only +typedef enum +{ + /* Videocore */ + MBOX_TAG_GET_FIRMWARE_VERSION = 0x1, + + /* Hardware */ + MBOX_TAG_GET_BOARD_MODEL = 0x10001, + MBOX_TAG_GET_BOARD_REVISION, + MBOX_TAG_GET_BOARD_MAC_ADDRESS, + MBOX_TAG_GET_BOARD_SERIAL, + MBOX_TAG_GET_ARM_MEMORY, + MBOX_TAG_GET_VC_MEMORY, + MBOX_TAG_GET_CLOCKS, + +} mbox_tag_type; + +#define MBOX_TAG_REQUEST_CODE 0x00000000 +#define MBOX_TAG_LAST_BYTE 0x00000000 + +int mbox_call(mbox_channel_type, unsigned int); + +#endif /*_MBOX_H_*/ diff --git a/lab7/kernel/include/memory.h b/lab7/kernel/include/memory.h new file mode 100644 index 000000000..35f7ddb16 --- /dev/null +++ b/lab7/kernel/include/memory.h @@ -0,0 +1,80 @@ +#ifndef _MEMORY_H_ +#define _MEMORY_H_ + +#include "u_list.h" +#include "bcm2837/rpi_mmu.h" +/* Lab2 */ +void *allocator(unsigned int size); +// void free(void* ptr); + +/* Lab4 */ +#define BUDDY_MEMORY_BASE PHYS_TO_KERNEL_VIRT(0x0) // 0x10000000 - 0x20000000 (SPEC) -> Advanced #3 for all memory region +#define BUDDY_MEMORY_PAGE_COUNT 0x3C000 // let BUDDY_MEMORY use 0x0 ~ 0x3C000000 (SPEC) +#define PAGESIZE 0x1000 // 4KB + +#define CACHE_SEG 0x8 +#define CACHE_offset 3 +#define CACHE_record_num 8 + +// #define MAX_PAGES 0x10000 // 65536 (Entries), PAGESIZE * MAX_PAGES = 0x10000000 (SPEC) + +typedef enum +{ + FRAME_FREE = -2, + FRAME_ALLOCATED = -1, + FRAME_IDX_0 = 0, // 0x1000 + FRAME_IDX_8 = 8, + FRAME_IDX_FINAL = 17, // 0x20 000 000 + FRAME_MAX_IDX = 18 +} frame_value_type; + +typedef enum +{ + CACHE_IDX_0 = 0, // 0x20 + CACHE_IDX_FINAL = 6, // 0x800 + CACHE_MAX_IDX = 7 // 0x1000 +} cache_value_type; + +typedef struct frame +{ + struct list_head listhead; // store freelist + int val; // store order + int used; + unsigned int idx; +} frame_t; + +typedef struct cache +{ + struct list_head listhead; // store freelist + void *data_base; + int cache_order; + int max_available; + int available; + unsigned long long cache_record[CACHE_record_num]; +} cache_t; + +void allocator_init(); +frame_t *release_redundant(frame_t *frame); +frame_t *get_buddy(frame_t *frame); +int coalesce(frame_t *frame_ptr); + +void dump_page_info(); +void dump_cache_info(); + +// buddy system +void *page_malloc(unsigned int size); +void page_free(frame_t *ptr); +void page2caches(int order); +void *cache_malloc(unsigned int size); +void cache_free(void *ptr); + +void *kmalloc(unsigned int size); +void kfree(void *ptr); +void memory_reserve(unsigned long long start, unsigned long long end); + +void freelist_init(); +void page2caches(int c_val); +void *find_CACHE(cache_t *ptr); +frame_t *find_free_page(int val); + +#endif /* _MEMORY_H_ */ \ No newline at end of file diff --git a/lab7/kernel/include/mmu.h b/lab7/kernel/include/mmu.h new file mode 100644 index 000000000..bb58ee390 --- /dev/null +++ b/lab7/kernel/include/mmu.h @@ -0,0 +1,101 @@ +#ifndef _MMU_H_ +#define _MMU_H_ + +#include "stddef.h" +// tcr_el1: The control register for stage 1 of the EL1&0 translation regime. +#define TCR_CONFIG_REGION_48bit (((64 - 48) << 0) | ((64 - 48) << 16)) // T0SZ 和 T1SZ 設為 16 +#define TCR_CONFIG_4KB ((0b00 << 14) | (0b10 << 30)) // TG0 和 TG1 設為 4KB +#define TCR_CONFIG_DEFAULT (TCR_CONFIG_REGION_48bit | TCR_CONFIG_4KB) + +#define MAIR_DEVICE_nGnRnE 0b00000000 // 設備記憶體,無全局無讀取無寫入權限 +#define MAIR_NORMAL_NOCACHE 0b01000100 // 普通記憶體,不緩存 +#define MAIR_IDX_DEVICE_nGnRnE 0 // 設備記憶體索引 +#define MAIR_IDX_NORMAL_NOCACHE 1 // 普通記憶體索引 + +#define PD_TABLE 0b11L // Table Entry Armv8_a_address_translation p.14 +#define PD_BLOCK 0b01L // Block Entry +#define PD_UNX (1L << 54) // non-executable page frame for EL0 if set +#define PD_KNX (1L << 53) // non-executable page frame for EL1 if set +#define PD_ACCESS (1L << 10) // a page fault is generated if not set +#define PD_RDONLY (1L << 7) // 0 for read-write, 1 for read-only. +#define PD_UK_ACCESS (1L << 6) // 0 for only kernel access, 1 for user/kernel access. + +#define PERIPHERAL_START 0x3C000000L +#define PERIPHERAL_END 0x3F000000L +#define USER_DATA_BASE 0x00000000L +#define USER_STACK_BASE 0x0000fffffffff000L +#define USER_SIGNAL_WRAPPER_VA 0x0000FFFFFFFAF000L //<------------------------------------- +#define USER_EXEC_WRAPPER_VA 0x0000FFFFFFFBF000L //<------------------------------------- + +#define MMU_PGD_BASE 0x1000L +#define MMU_PGD_ADDR (MMU_PGD_BASE + 0x0000L) +#define MMU_PUD_ADDR (MMU_PGD_BASE + 0x1000L) +#define MMU_PTE_ADDR (MMU_PGD_BASE + 0x2000L) + +// Used for EL1 +#define BOOT_PGD_ATTR (PD_TABLE) +#define BOOT_PUD_ATTR (PD_TABLE | PD_ACCESS) +#define BOOT_PTE_ATTR_nGnRnE (PD_BLOCK | PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_UNX | PD_KNX | PD_UK_ACCESS) // p.17 +#define BOOT_PTE_ATTR_NOCACHE (PD_BLOCK | PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2)) + +#ifndef __ASSEMBLER__ + +#include "sched.h" +#include "exception.h" +#include "u_list.h" +#include "stddef.h" + + +#define PERMISSION_INVAILD(userId,VMA_Permission) (userId&~VMA_Permission) +#define DUMP_NAME(number, name) \ + case number: \ + uart_sendlinek(name); \ + uart_sendlinek("\n"); \ + break; + +typedef enum +{ + UNKNOW_AREA = -1, + USER_DATA, + USER_STACK, + PERIPHERAL, + USER_SIGNAL_WRAPPER, + USER_EXEC_WRAPPER +} vma_name_type; + +typedef enum +{ + PGD, + PUD, + PMD, + PTE, +} pagetable_type; + +typedef struct vm_area_struct +{ + list_head_t listhead; + unsigned long virt_addr; + unsigned long phys_addr; + unsigned long area_size; + unsigned long rwx; // 1, 2, 4 + int is_alloced; + vma_name_type name; +} vm_area_struct_t; + +void *set_2M_kernel_mmu(void *x0); +void map_one_page(size_t *pgd_p, size_t va, size_t pa, size_t flag); +void mmu_add_vma(struct thread *t, size_t va, size_t size, size_t pa, size_t rwx, int is_alloced, vma_name_type name); +void mmu_del_vma(struct thread *t); +void mmu_free_page_tables(size_t *page_table, int level); +// void mmu_set_PTE_readonly(size_t *page_table, int level); +// void mmu_pagetable_copy(unsigned long *dst_page_table, unsigned long *src_page_table, int level); +void mmu_memfail_abort_handle(esr_el1_t *esr_el1); + +vm_area_struct_t *check_vma_overlap(thread_t *t,unsigned long user_va, unsigned long size); +int check_permission(int userId, int requiredPermission); +void dump_vma(); +void dump_pagetable(unsigned long user_va, unsigned long pa); + +#endif //__ASSEMBLER__ + +#endif /* _MMU_H_ */ diff --git a/lab7/kernel/include/power.h b/lab7/kernel/include/power.h new file mode 100644 index 000000000..07da61847 --- /dev/null +++ b/lab7/kernel/include/power.h @@ -0,0 +1,9 @@ +#ifndef _POWER_H_ +#define _POWER_H_ + +#include "bcm2837/rpi_mmu.h" +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC PHYS_TO_KERNEL_VIRT(0x3F10001c) +#define PM_WDOG PHYS_TO_KERNEL_VIRT(0x3F100024) + +#endif /*_POWER_H_*/ diff --git a/lab7/kernel/include/sched.h b/lab7/kernel/include/sched.h new file mode 100644 index 000000000..475bc27e7 --- /dev/null +++ b/lab7/kernel/include/sched.h @@ -0,0 +1,79 @@ +#ifndef _SCHED_H_ +#define _SCHED_H_ + +#include "u_list.h" +#include "vfs.h" + +#define PIDMAX 32768 +#define USTACK_SIZE 0x10000 +#define KSTACK_SIZE 0x10000 +#define SIGNAL_MAX 64 +#define STACK_BASE_OFFSET 0x00 + +extern void switch_to(void *curr_context, void *next_context); +extern void *get_current(); +extern void store_context(void *curr_context); +extern void load_context(void *curr_context); + +// arch/arm64/include/asm/processor.h - cpu_context +typedef struct thread_context +{ + unsigned long x19; // callee saved registers: the called function will preserve them and restore them before returning + unsigned long x20; + unsigned long x21; + unsigned long x22; + unsigned long x23; + unsigned long x24; + unsigned long x25; + unsigned long x26; + unsigned long x27; + unsigned long x28; + unsigned long fp; // base pointer for local variable in stack + unsigned long lr; // store return address + unsigned long sp; // stack pointer, varys from function calls + void *pgd; // use for MMU mapping (user space) +} thread_context_t; + +typedef struct thread +{ + list_head_t listhead; // Freelist node + thread_context_t context; // Thread registers + char *data; // Process itself + unsigned int datasize; // Process size + int iszombie; // Process statement + int pid; // Process ID + int isused; // Freelist node statement + char *stack_alloced_ptr; // Process Stack (Process itself) + char *kernel_stack_alloced_ptr; // Process Stack (Kernel syscall) + void (*signal_handler[SIGNAL_MAX + 1])(); // Signal handlers for different signal + int sigcount[SIGNAL_MAX + 1]; // Signal Pending buffer + void (*curr_signal_handler)(); // Allow Signal handler overwritten by others + int signal_is_checking; // Signal Processing Lock + thread_context_t signal_savedContext; // Store registers before signal handler involving + list_head_t vma_list; + char curr_working_dir[MAX_PATH_NAME + 1]; + struct file *file_descriptors_table[MAX_FD + 1]; +} thread_t; + +typedef struct execfile +{ + struct vnode *vnode; + char * pathname; + char *data; + unsigned int filesize; +} execfile; + +void schedule_timer(char *notuse); +void thread_sched_init(); +void idle(); +void schedule(); +void kill_zombies(); +void thread_exit(); +thread_t *thread_create(void *start); +int exec_thread(); +void exec_proc(); +void exec_wrapper(); + +void foo(); + +#endif /* _SCHED_H_ */ diff --git a/lab7/kernel/include/shell.h b/lab7/kernel/include/shell.h new file mode 100644 index 000000000..276d085d9 --- /dev/null +++ b/lab7/kernel/include/shell.h @@ -0,0 +1,40 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ + +#define CLI_MAX_CMD 15 +#define CMD_MAX_LEN 32 +#define CMD_MAX_PARAM 10 +#define MSG_MAX_LEN 128 + +typedef struct CLI_CMDS +{ + char command[CMD_MAX_LEN]; + char help[MSG_MAX_LEN]; + int (*func)(int, char **); +} CLI_CMDS; + +int _parse_args(char *buffer, int *argc, char **argv); + +void start_shell(); + +void cli_flush_buffer(char *, int); +void cli_cmd_read(char *); +void cli_cmd_exec(char *); +void cli_print_banner(); + +int do_cmd_help(int argc, char **argv); +int do_cmd_hello(int argc, char **argv); +int do_cmd_info(int argc, char **argv); +int do_cmd_reboot(int argc, char **argv); +int do_cmd_ls(int argc, char **argv); +int do_cmd_cd(int argc, char **argv); +int do_cmd_cat(int argc, char **argv); +int do_cmd_malloc(int argc, char **argv); +int do_cmd_dtb(int argc, char **argv); +int do_cmd_exec(int argc, char **argv); +int do_cmd_setTimeout(int argc, char **argv); +int do_cmd_set2sAlert(int argc, char **argv); +int do_cmd_mtest(int argc, char **argv); +int do_cmd_ttest(int argc, char **argv); +int do_cmd_ftest(int argc, char **argv); +#endif /* _SHELL_H_ */ diff --git a/lab7/kernel/include/signal.h b/lab7/kernel/include/signal.h new file mode 100644 index 000000000..afe2c1617 --- /dev/null +++ b/lab7/kernel/include/signal.h @@ -0,0 +1,49 @@ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +#include "exception.h" +#include "memory.h" + +#define SIGHUP 1 /* Hangup (POSIX). */ +#define SIGINT 2 /* Interrupt (ANSI). */ +#define SIGQUIT 3 /* Quit (POSIX). */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ +#define SIGTRAP 5 /* Trace trap (POSIX). */ +#define SIGABRT 6 /* Abort (ANSI). */ +#define SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define SIGBUS 7 /* BUS error (4.2 BSD). */ +#define SIGFPE 8 /* Floating-point exception (ANSI). */ +#define SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ +#define SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ +#define SIGPIPE 13 /* Broken pipe (POSIX). */ +#define SIGALRM 14 /* Alarm clock (POSIX). */ +#define SIGTERM 15 /* Termination (ANSI). */ +#define SIGSTKFLT 16 /* Stack fault. */ +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGCHLD 17 /* Child status has changed (POSIX). */ +#define SIGCONT 18 /* Continue (POSIX). */ +#define SIGSTOP 19 /* Stop, unblockable (POSIX). */ +#define SIGTSTP 20 /* Keyboard stop (POSIX). */ +#define SIGTTIN 21 /* Background read from tty (POSIX). */ +#define SIGTTOU 22 /* Background write to tty (POSIX). */ +#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ +#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ +#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ +#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ +#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ +#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ +#define SIGPOLL SIGIO /* Pollable event occurred (System V). */ +#define SIGIO 29 /* I/O now possible (4.2 BSD). */ +#define SIGPWR 30 /* Power failure restart (System V). */ +#define SIGSYS 31 /* Bad system call. */ +#define SIGUNUSED 31 + +void signal_default_handler(); +void check_signal(trapframe_t *tpf); +void run_signal(trapframe_t *tpf, int signal); +//void __attribute__((aligned(PAGESIZE))) signal_handler_wrapper(); +void signal_handler_wrapper(); + +#endif diff --git a/lab7/kernel/include/stddef.h b/lab7/kernel/include/stddef.h new file mode 100644 index 000000000..61b71d842 --- /dev/null +++ b/lab7/kernel/include/stddef.h @@ -0,0 +1,12 @@ +#ifndef STDDEF_H +#define STDDEF_H + +#define size_t unsigned long +#define NULL ((void *)0) + +// typedef enum { +// false = 0, +// true = 1 +// } boolean; + +#endif \ No newline at end of file diff --git a/lab7/kernel/include/stdio.h b/lab7/kernel/include/stdio.h new file mode 100644 index 000000000..5ee646448 --- /dev/null +++ b/lab7/kernel/include/stdio.h @@ -0,0 +1,29 @@ +#include "sched.h" +#include "vfs.h" +extern thread_t *curr_thread; + +#define stdio_op(fd, c, len) \ + switch (fd) \ + { \ + case (stdin): \ + (vfs_read(curr_thread->file_descriptors_table[fd], c, len)); \ + break; \ + case (stdout): \ + (vfs_write(curr_thread->file_descriptors_table[fd], c, len)); \ + break; \ + case (stderr): \ + (vfs_write(curr_thread->file_descriptors_table[fd], c, len)); \ + break; \ + default: \ + break; \ + } + +char getchar(); +void putchar(char c); +void put_int(int num); +void puts(const char *s); +void put_hex(unsigned int num); +int atoi(char *str); +void Readfile(char *str, int size); +int fake_log2(unsigned long long n); +void delay(int s); \ No newline at end of file diff --git a/lab7/kernel/include/string.h b/lab7/kernel/include/string.h new file mode 100644 index 000000000..8c46ec5c0 --- /dev/null +++ b/lab7/kernel/include/string.h @@ -0,0 +1,12 @@ +#include "stddef.h" +#define VSPRINT_MAX_BUF_SIZE 0x100 + +size_t strlen(const char *str); +int strcmp(const char *p1, const char *p2); +char* strcat (char *dest, const char *src); +int strncmp(const char *s1, const char *s2, unsigned long long n); +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, unsigned long long n); +unsigned int vsprintf(char *dst, char *fmt, __builtin_va_list args); +void *memset(void *s, int c, size_t n); +char* memcpy(void *dest, const void *src, unsigned long long len); diff --git a/lab7/kernel/include/syscall.h b/lab7/kernel/include/syscall.h new file mode 100644 index 000000000..a1ba07a31 --- /dev/null +++ b/lab7/kernel/include/syscall.h @@ -0,0 +1,38 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ + +#include "exception.h" +#include + +int getpid(trapframe_t *tpf); +size_t uartread(trapframe_t *tpf, char buf[], size_t size); +size_t uartwrite(trapframe_t *tpf, const char buf[], size_t size); +int exec(trapframe_t *tpf, const char *name, char *const argv[]); +int fork(trapframe_t *tpf); +void exit(trapframe_t *tpf, int status); +int syscall_mbox_call(trapframe_t *tpf, unsigned char ch, unsigned int *mbox); +void kill(trapframe_t *tpf, int pid); + +void signal_register(int signal, void (*handler)()); +void signal_kill(int pid, int signal); +void sigreturn(trapframe_t *tpf); + +void *mmap(trapframe_t *tpf, void *addr, size_t len, int prot, int flags, int fd, int file_offset); + +int open(trapframe_t *tpf, const char *pathname, int flags); +int close(trapframe_t *tpf, int fd); +long write(trapframe_t *tpf, int fd, const void *buf, unsigned long count); +long read(trapframe_t *tpf, int fd, void *buf, unsigned long count); +int mkdir(trapframe_t *tpf, const char *pathname, unsigned mode); +int mount(trapframe_t *tpf, const char *src, const char *target, const char *filesystem, unsigned long flags, const void *data); +int chdir(trapframe_t *tpf, const char *path); +long lseek64(trapframe_t *tpf, int fd, long offset, int whence); +int ioctl(trapframe_t *tpf, int fd, unsigned long request, void *info); + +void syscall_lock(trapframe_t *tpf); +void syscall_unlock(trapframe_t *tpf); + +unsigned int get_file_size(char *thefilepath); +char *get_file_start(char *thefilepath); + +#endif /* _SYSCALL_H_*/ diff --git a/lab7/kernel/include/timer.h b/lab7/kernel/include/timer.h new file mode 100644 index 000000000..8b02b6b8d --- /dev/null +++ b/lab7/kernel/include/timer.h @@ -0,0 +1,36 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ + +#include "u_list.h" +#include "bcm2837/rpi_mmu.h" +#define CORE0_TIMER_IRQ_CTRL PHYS_TO_VIRT(0x40000040) //-------------------------------------------------------------------------- + +void core_timer_enable(); +void core_timer_disable(); +void core_timer_handler(); + +typedef struct timer_event +{ + struct list_head listhead; + unsigned long long interrupt_time; // store as tick time after cpu start + void *callback; // interrupt -> timer_callback -> callback(args) + char *args; // need to free the string by event callback function +} timer_event_t; + +typedef enum +{ + setSecond = 0, + setTick = 1 +} timer_type_t; + +// now the callback only support "funcion(char *)", char* in args +void timer_event_callback(timer_event_t *timer_event); +void add_timer(void *callback, unsigned long long timeout, char *args, int inTickFormat); +unsigned long long get_tick_plus_s(unsigned long long second); +void set_core_timer_interrupt(unsigned long long expired_time); +void set_core_timer_interrupt_by_tick(unsigned long long tick); +void timer_set2sAlert(char *str); +void timer_list_init(); +int timer_list_get_size(); + +#endif /* _TIMER_H_ */ diff --git a/lab7/kernel/include/u_list.h b/lab7/kernel/include/u_list.h new file mode 100644 index 000000000..79767f194 --- /dev/null +++ b/lab7/kernel/include/u_list.h @@ -0,0 +1,150 @@ +#ifndef _U_LIST_H_ +#define _U_LIST_H_ + +/* + * Circular doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + * + * https://github.com/torvalds/linux/blob/master/include/linux/list. + * https://elixir.bootlin.com/linux/latest/source/scripts/kconfig/list.h#L24 + */ + +typedef struct list_head +{ + struct list_head *next, *prev; +} list_head_t; + +#define LIST_HEAD_INIT(name) \ + { \ + &(name), &(name) \ + } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * INIT_LIST_HEAD - Initialize a list_head structure + * @list: list_head structure to be initialized. + * + * Initializes the list_head to point to itself. If it is a list header, + * the result is an empty list. + */ +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +static inline void list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_is_head - tests whether @list is the list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_head(const struct list_head *list, const struct list_head *head) +{ + return list == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; \ + !list_is_head(pos, (head)); \ + pos = n, n = pos->next) + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_size(const struct list_head *head) +{ + list_head_t *pos; + int i = 0; + list_for_each(pos, head) + { + i++; + } + return i; +} + +#endif /* _U_LIST_H_ */ diff --git a/lab7/kernel/include/uart1.h b/lab7/kernel/include/uart1.h new file mode 100644 index 000000000..7b6bd70ce --- /dev/null +++ b/lab7/kernel/include/uart1.h @@ -0,0 +1,18 @@ +#ifndef _UART1_H_ +#define _UART1_H_ + +void uart_init(); +void uart_flush_FIFO(); +char uart_recv(); +void uart_send(unsigned int c); + +void uart_r_irq_handler(); +void uart_w_irq_handler(); +char uart_async_recv(); +void uart_async_send(char c); + +int uart_sendlinek(char* fmt, ...); +void uart_interrupt_enable(); +void uart_interrupt_disable(); + +#endif /*_UART1_H_*/ diff --git a/lab7/kernel/include/vfs.h b/lab7/kernel/include/vfs.h new file mode 100644 index 000000000..c19162a8c --- /dev/null +++ b/lab7/kernel/include/vfs.h @@ -0,0 +1,103 @@ +#ifndef _VFS_H_ +#define _VFS_H_ + +#include "stddef.h" + +#define MAX_PATH_NAME 255 +#define MAX_FD 16 +#define O_CREAT 00000100 +#define SEEK_SET 0 +#define MAX_FS_REG 0x50 +#define MAX_DEV_REG 0x10 + +enum stdio_fd +{ + stdin, + stdout, + stderr +}; + +enum fsnode_type +{ + dir_t, + file_t +}; + +struct vnode +{ + struct mount *mount; // Superblock : represents mounted fs + struct vnode_operations *v_ops; // inode & dentry Ops: represents kernel methods for vnode + struct file_operations *f_ops; // file Ops : represents process methods for opened file + void *internal; // vnode itself : directly point to fs's vnode +}; + +struct mount +{ + struct vnode *root; + struct filesystem *fs; +}; + +struct filesystem +{ + const char *name; + int (*setup_mount)(struct filesystem *fs, struct mount *mount); +}; + +// file handle +struct file +{ + struct vnode *vnode; + size_t f_pos; // RW position of this file handle + struct file_operations *f_ops; + int flags; +}; + +struct file_operations +{ + int (*write)(struct file *file, const void *buf, size_t len); + int (*read)(struct file *file, void *buf, size_t len); + int (*open)(struct vnode *file_node, struct file **target); + int (*close)(struct file *file); + long (*lseek64)(struct file *file, long offset, int whence); + long (*getsize)(struct vnode *vd); +}; + +struct vnode_operations +{ + int (*lookup)(struct vnode *dir_node, struct vnode **target, + const char *component_name); + int (*create)(struct vnode *dir_node, struct vnode **target, + const char *component_name); + int (*mkdir)(struct vnode *dir_node, struct vnode **target, + const char *component_name); + void (*ls)(struct vnode *dir_node); + void (*dump)(struct vnode *dir_node, int level); +}; + +struct dir_path +{ + char *dir; + int size; +}; + +int register_filesystem(struct filesystem *fs); +int register_dev(struct file_operations *fo); +struct filesystem *find_filesystem(const char *fs_name); +int vfs_open(const char *pathname, int flags, struct file **target); +int vfs_close(struct file *file); +int vfs_write(struct file *file, const void *buf, size_t len); +int vfs_read(struct file *file, void *buf, size_t len); +int vfs_mkdir(const char *pathname); +int vfs_mount(const char *target, const char *filesystem); +int vfs_lookup(const char *pathname, struct vnode **target); +int vfs_mknod(char *pathname, int id); + +void rootfs_init(); +char *get_absolute_path(char *path, char *curr_working_dir); + +void vfs_cd(char *filepath); +void vfs_dump(struct vnode *_vnode, int level); +void vfs_ls(); +void displaylayer(int level); + +#endif /* _VFS_H_ */ diff --git a/lab7/kernel/include/vfs_dev_framebuffer.h b/lab7/kernel/include/vfs_dev_framebuffer.h new file mode 100644 index 000000000..b996ee8e3 --- /dev/null +++ b/lab7/kernel/include/vfs_dev_framebuffer.h @@ -0,0 +1,24 @@ +#ifndef _DEV_FRAMEBUFFER_H_ +#define _DEV_FRAMEBUFFER_H_ + +#include "stddef.h" +#include "vfs.h" + +struct framebuffer_info +{ + unsigned int width; + unsigned int height; + unsigned int pitch; + unsigned int isrgb; +}; + +int init_dev_framebuffer(); + +int dev_framebuffer_write(struct file *file, const void *buf, size_t len); +int dev_framebuffer_read(struct file *file, void *buf, size_t len); +int dev_framebuffer_open(struct vnode *file_node, struct file **target); +int dev_framebuffer_close(struct file *file); +long dev_framebuffer_lseek64(struct file *file, long offset, int whence); +int dev_framebuffer_op_deny(); + +#endif diff --git a/lab7/kernel/include/vfs_dev_uart.h b/lab7/kernel/include/vfs_dev_uart.h new file mode 100644 index 000000000..b46dceed4 --- /dev/null +++ b/lab7/kernel/include/vfs_dev_uart.h @@ -0,0 +1,15 @@ +#ifndef _DEV_UART_H_ +#define _DEV_UART_H_ + +#include "stddef.h" +#include "vfs.h" + +int init_dev_uart(); + +int dev_uart_write(struct file *file, const void *buf, size_t len); +int dev_uart_read(struct file *file, void *buf, size_t len); +int dev_uart_open(struct vnode *file_node, struct file **target); +int dev_uart_close(struct file *file); +int dev_uart_op_deny(); + +#endif diff --git a/lab7/kernel/include/vfs_initramfs.h b/lab7/kernel/include/vfs_initramfs.h new file mode 100644 index 000000000..824fbdff5 --- /dev/null +++ b/lab7/kernel/include/vfs_initramfs.h @@ -0,0 +1,39 @@ +#ifndef _INITRAMFS_H_ +#define _INITRAMFS_H_ + +#include "stddef.h" +#include "vfs.h" + +#define INITRAMFS_MAX_DIR_ENTRY 100 + +// initramfs basically is same as tmpfs, but it is read-only + +struct initramfs_inode +{ + enum fsnode_type type; + char* name; + struct vnode *entry[INITRAMFS_MAX_DIR_ENTRY]; + char *data; + size_t datasize; +}; + +int register_initramfs(); +int initramfs_setup_mount(struct filesystem *fs, struct mount *_mount); + +int initramfs_write(struct file *file, const void *buf, size_t len); +int initramfs_read(struct file *file, void *buf, size_t len); +int initramfs_open(struct vnode *file_node, struct file **target); +int initramfs_close(struct file *file); +long initramfs_lseek64(struct file *file, long offset, int whence); +long initramfs_getsize(struct vnode *vd); + +int initramfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); +int initramfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name); +int initramfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name); + +struct vnode *initramfs_create_vnode(struct mount *_mount, enum fsnode_type type); + +void initramfs_dump(struct vnode *dir_node , int level); +void initramfs_ls(struct vnode *dir_node); + +#endif /* _INITRAMFS_H_ */ diff --git a/lab7/kernel/include/vfs_tmpfs.h b/lab7/kernel/include/vfs_tmpfs.h new file mode 100644 index 000000000..1ff4c4864 --- /dev/null +++ b/lab7/kernel/include/vfs_tmpfs.h @@ -0,0 +1,41 @@ +#ifndef _TMPFS_H_ +#define _TMPFS_H_ + +#include "stddef.h" +#include "vfs.h" + +// SPEC basic Note #3 +#define MAX_FILE_NAME 15 +#define MAX_DIR_ENTRY 16 +#define MAX_FILE_SIZE 4096 + +struct tmpfs_inode +{ + enum fsnode_type type; + char name[MAX_FILE_NAME]; + struct vnode *entry[MAX_DIR_ENTRY]; + char *data; + size_t datasize; +}; + +int register_tmpfs(); +int tmpfs_setup_mount(struct filesystem *fs, struct mount *_mount); + +int tmpfs_write(struct file *file, const void *buf, size_t len); +int tmpfs_read(struct file *file, void *buf, size_t len); +int tmpfs_open(struct vnode *file_node, struct file **target); +int tmpfs_close(struct file *file); +long tmpfs_lseek64(struct file *file, long offset, int whence); +long tmpfs_getsize(struct vnode *vd); + +int tmpfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); +int tmpfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name); +int tmpfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name); + +void tmpfs_dump(struct vnode *dir_node , int level); +void tmpfs_ls(struct vnode *dir_node); + + +struct vnode *tmpfs_create_vnode(struct mount *_mount, enum fsnode_type type); + +#endif /* _TMPFS_H_ */ diff --git a/lab7/kernel/src/boot.S b/lab7/kernel/src/boot.S new file mode 100644 index 000000000..456dfeb7d --- /dev/null +++ b/lab7/kernel/src/boot.S @@ -0,0 +1,82 @@ +#include "mmu.h" + +.section ".text.boot" + +.global _kernel_start + +_kernel_start: + bl from_el2_to_el1 + +set_mmu_configuration: + // set paging configuration (up : 0xffff000000000000 low : 0x0000000000000000) + ldr x4, = TCR_CONFIG_DEFAULT + msr tcr_el1, x4 + + // Set Used Memory Attributes + ldr x4, =((MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8))) + msr mair_el1, x4 + + // set and enable MMU + ldr x4, = MMU_PGD_ADDR // PGD's page frame at 0x1000 + ldr x1, = MMU_PUD_ADDR // PUD's page frame at 0x2000 + + ldr x2, = BOOT_PGD_ATTR + orr x2, x1, x2 // combine the physical address of next level page with attribute. + str x2, [x4] // [MMU_PGD_ADDR] = MMU_PUD_ADDR | BOOT_PGD_ATTR + + ldr x2, = BOOT_PUD_ATTR + mov x3, 0x00000000 + orr x3, x2, x3 // [MMU_PUD_ADDR] = 0x00000000 | BOOT_PUD_ATTR + str x3, [x1] // 1st 1GB mapped by the 1st entry of PUD + mov x3, 0x40000000 + orr x3, x2, x3 // [MMU_PUD_ADDR + 8] = 0x40000000 | BOOT_PUD_ATTR + str x3, [x1, 8] // 2nd 1GB mapped by the 2nd entry of PUD + + msr ttbr0_el1, x4 // load PGD to the bottom translation-based register. + msr ttbr1_el1, x4 // also load PGD to the upper translation based register. + + mov sp, 0x3c000000 // temp stack + bl set_2M_kernel_mmu + + mrs x2, sctlr_el1 // sctlr_el1: Provides top level control of the system, including its memory system, at EL1 and EL0. + orr x2 , x2, 1 // sctlr_el1[0]: EL1&0 stage 1 address translation enabled/disabled. + msr sctlr_el1, x2 + + // indirect branch to the upper virtual address + ldr x2, =set_exception_vector_table + br x2 + +set_exception_vector_table: + adr x1, exception_vector_table // vbar_el1: Vector Base Address Register (EL1) + msr vbar_el1, x1 // Holds the exception base address for any exception that is taken to EL1. + +setup_stack: + ldr x1, =_stack_top + mov sp, x1 + +setup_bss: + ldr x1, =_bss_start + ldr w2, =_bss_size + +init_bss: + cbz w2, run_main + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, init_bss + +run_main: + ldr x1, =dtb_ptr + str x0, [x1], #8 + bl main + +proc_hang: + wfe + b proc_hang + +from_el2_to_el1: + mov x1, (1 << 31) // EL1 uses aarch64 + msr hcr_el2, x1 + mov x1, 0x3c5 // EL1h (SPSel = 1) with interrupt disabled + msr spsr_el2, x1 + msr elr_el2, lr + eret // return to EL1 \ No newline at end of file diff --git a/lab7/kernel/src/cpio.c b/lab7/kernel/src/cpio.c new file mode 100644 index 000000000..56fdfc4e8 --- /dev/null +++ b/lab7/kernel/src/cpio.c @@ -0,0 +1,82 @@ +#include "string.h" +#include "cpio.h" +#include "stdio.h" + +/* Parse an ASCII hex string into an integer. (big endian)*/ +static unsigned int parse_hex_str(char *s, unsigned int max_len) +{ + unsigned int r = 0; + + for (unsigned int i = 0; i < max_len; i++) + { + r *= 16; + if (s[i] >= '0' && s[i] <= '9') + { + r += s[i] - '0'; + } + else if (s[i] >= 'a' && s[i] <= 'f') + { + r += s[i] - 'a' + 10; + } + else if (s[i] >= 'A' && s[i] <= 'F') + { + r += s[i] - 'A' + 10; + } + else + { + return r; + } + } + return r; +} + +/* write pathname, data, next header into corresponding parameter */ +/* if no next header, next_header_pointer = 0 */ +/* return -1 if parse error*/ +int cpio_newc_parse_header(struct cpio_newc_header *this_header_pointer, char **pathname, unsigned int *filesize, char **data, struct cpio_newc_header **next_header_pointer) +{ + /* Ensure magic header exists. */ + if (strncmp(this_header_pointer->c_magic, CPIO_NEWC_HEADER_MAGIC, sizeof(this_header_pointer->c_magic)) != 0) + { + *next_header_pointer = 0; + puts("cpio parse error\r\n"); + return -1; + } + + // transfer big endian 8 byte hex string to unsigned int and store into *filesize + *filesize = parse_hex_str(this_header_pointer->c_filesize, 8); + + // end of header is the pathname + *pathname = ((char *)this_header_pointer) + sizeof(struct cpio_newc_header); + + // get file data, file data is just after pathname + unsigned int pathname_length = parse_hex_str(this_header_pointer->c_namesize, 8); + unsigned int offset = pathname_length + sizeof(struct cpio_newc_header); + // The file data is padded to a multiple of four bytes + offset = padding_4byte(offset); + *data = (char *)this_header_pointer + offset; + + // get next header pointer + if (*filesize == 0) + { + *next_header_pointer = (struct cpio_newc_header *)*data; + } + else + { + offset = *filesize; + *next_header_pointer = (struct cpio_newc_header *)(*data + padding_4byte(offset)); + } + + // if filepath is TRAILER!!! means there is no more files. + if (strncmp(*pathname, "TRAILER!!!", sizeof("TRAILER!!!")) == 0) + { + *next_header_pointer = 0; + } + + return 0; +} + +unsigned int padding_4byte(unsigned int size) +{ + return size + (4 - size % 4) % 4; +} \ No newline at end of file diff --git a/lab7/kernel/src/dtb.c b/lab7/kernel/src/dtb.c new file mode 100644 index 000000000..df97d64fc --- /dev/null +++ b/lab7/kernel/src/dtb.c @@ -0,0 +1,173 @@ +#include "dtb.h" +#include "uart1.h" +#include "cpio.h" +#include "string.h" +#include "stdio.h" +#include "memory.h" +#include "bcm2837/rpi_mmu.h" +#include "debug.h" + +void *CPIO_DEFAULT_START; +void *CPIO_DEFAULT_END; +char *dtb_ptr; + +// stored as big endian +struct fdt_header +{ + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +}; + +struct fdt_reserve_entry +{ + uint64_t address; + uint64_t size; +}; + +uint32_t uint32_endian_big2little(uint32_t data) +{ + char *r = (char *)&data; + return (r[3] << 0) | (r[2] << 8) | (r[1] << 16) | (r[0] << 24); +} + +uint64_t uint64_endian_big2little(uint64_t data) +{ + char *r = (char *)&data; + return ((unsigned long long)r[7] << 0) | ((unsigned long long)r[6] << 8) | ((unsigned long long)r[5] << 16) | ((unsigned long long)r[4] << 24) | ((unsigned long long)r[3] << 32) | ((unsigned long long)r[2] << 40) | ((unsigned long long)r[1] << 48) | ((unsigned long long)r[0] << 56); +} + +void traverse_device_tree(void *dtb_ptr, dtb_callback callback) +{ + struct fdt_header *header = dtb_ptr; + if (uint32_endian_big2little(header->magic) != 0xD00DFEED) + { + ERROR("traverse_device_tree : wrong magic in traverse_device_tree\n"); + return; + } + // https://abcamus.github.io/2016/12/28/uboot%E8%AE%BE%E5%A4%87%E6%A0%91-%E8%A7%A3%E6%9E%90%E8%BF%87%E7%A8%8B/ + // https://blog.csdn.net/wangdapao12138/article/details/82934127 + uint32_t struct_size = uint32_endian_big2little(header->size_dt_struct); + char *dt_struct_ptr = (char *)((char *)header + uint32_endian_big2little(header->off_dt_struct)); + char *dt_strings_ptr = (char *)((char *)header + uint32_endian_big2little(header->off_dt_strings)); + + char *end = (char *)dt_struct_ptr + struct_size; + char *pointer = dt_struct_ptr; + + while (pointer < end) + { + uint32_t token_type = uint32_endian_big2little(*(uint32_t *)pointer); + + pointer += 4; + if (token_type == FDT_BEGIN_NODE) + { + callback(token_type, pointer, 0, 0); + pointer += strlen(pointer); + pointer += 4 - (unsigned long long)pointer % 4; // alignment 4 byte + } + else if (token_type == FDT_END_NODE) + { + callback(token_type, 0, 0, 0); + } + else if (token_type == FDT_PROP) + { + uint32_t len = uint32_endian_big2little(*(uint32_t *)pointer); + pointer += 4; + char *name = (char *)dt_strings_ptr + uint32_endian_big2little(*(uint32_t *)pointer); + pointer += 4; + callback(token_type, name, pointer, len); + pointer += len; + if ((unsigned long long)pointer % 4 != 0) + pointer += 4 - (unsigned long long)pointer % 4; // alignment 4 byte + } + else if (token_type == FDT_NOP) + { + callback(token_type, 0, 0, 0); + } + else if (token_type == FDT_END) + { + callback(token_type, 0, 0, 0); + } + else + { + puts("error type:"); + put_hex(token_type); + puts("\n"); + return; + } + } +} + +void dtb_callback_show_tree(uint32_t node_type, char *name, void *data, uint32_t name_size) +{ + static int level = 0; + if (node_type == FDT_BEGIN_NODE) + { + for (int i = 0; i < level; i++) + puts(" "); + puts(name); + puts("{\n"); + level++; + } + else if (node_type == FDT_END_NODE) + { + level--; + for (int i = 0; i < level; i++) + puts(" "); + puts("}\n"); + } + else if (node_type == FDT_PROP) + { + for (int i = 0; i < level; i++) + puts(" "); + puts(name); + puts("\n"); + } +} + +void dtb_callback_initramfs(uint32_t node_type, char *name, void *value, uint32_t name_size) +{ + // https://github.com/stweil/raspberrypi-documentation/blob/master/configuration/device-tree.md + // linux,initrd-start will be assigned by start.elf based on config.txt + if (node_type == FDT_PROP && strcmp(name, "linux,initrd-start") == 0) + { + CPIO_DEFAULT_START = (void *)(unsigned long long)PHYS_TO_KERNEL_VIRT(uint32_endian_big2little(*(uint32_t *)value)); + } + if (node_type == FDT_PROP && strcmp(name, "linux,initrd-end") == 0) + { + CPIO_DEFAULT_END = (void *)(unsigned long long)PHYS_TO_KERNEL_VIRT(uint32_endian_big2little(*(uint32_t *)value)); + } +} + +void dtb_find_and_store_reserved_memory() +{ + struct fdt_header *header = (struct fdt_header *)dtb_ptr; + if (uint32_endian_big2little(header->magic) != 0xD00DFEED) + { + ERROR("traverse_device_tree : wrong magic in traverse_device_tree\n"); + return; + } + + // off_mem_rsvmap stores all of reserve memory map with address and size + char *dt_mem_rsvmap_ptr = (char *)((char *)header + uint32_endian_big2little(header->off_mem_rsvmap)); + struct fdt_reserve_entry *reverse_entry = (struct fdt_reserve_entry *)dt_mem_rsvmap_ptr; + + // reserve memory which is defined by dtb + while (reverse_entry->address != 0 || reverse_entry->size != 0) + { + unsigned long long start = PHYS_TO_KERNEL_VIRT(uint64_endian_big2little(reverse_entry->address)); + unsigned long long end = uint64_endian_big2little(reverse_entry->size) + start; + memory_reserve(start, end); + reverse_entry++; + } + + // reserve device tree itself + memory_reserve((unsigned long long)dtb_ptr, (unsigned long long)dtb_ptr + uint32_endian_big2little(header->totalsize)); +} \ No newline at end of file diff --git a/lab7/kernel/src/entry.S b/lab7/kernel/src/entry.S new file mode 100644 index 000000000..74e3bcb53 --- /dev/null +++ b/lab7/kernel/src/entry.S @@ -0,0 +1,199 @@ +// save general registers to stack +.macro save_all + sub sp, sp, 32 * 9 + stp x0, x1, [sp ,16 * 0] // store pair of registers + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + str x30, [sp, 16 * 15] + // information for nested interrupt + mrs x0, spsr_el1 + str x0, [sp, 16 * 15 + 8] + mrs x0, elr_el1 + str x0, [sp, 16 * 16] + mrs x0, sp_el0 + str x0, [sp, 16 * 16 + 8] + ldp x0, x1, [sp, 16 * 0] +.endm + +// load general registers from stack +.macro load_all + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + ldr x30, [sp, 16 * 15] + // information for nested interrupt + ldr x0, [sp, 16 * 15 + 8] + msr spsr_el1,x0 + ldr x0, [sp, 16 * 16] + msr elr_el1, x0 + ldr x0, [sp, 16 * 16 + 8] + msr sp_el0, x0 + ldp x0, x1, [sp ,16 * 0] // restore x0 instead of elr_el1 + add sp, sp, 32 * 9 +.endm + +.macro ventry label + .align 7 // entry should be aligned to 0x80 (2^7) + b \label +.endm + +.align 11 // vector table should be aligned to 0x800 (2^11) +.global exception_vector_table + +// exception_vector_table definition +// https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/entry.S#L367 +exception_vector_table: + //Exception from the current EL while using SP_EL0 + ventry el1t_sync_invalid // Synchronous EL1t + ventry el1t_irq_invalid // IRQ EL1t + ventry el1t_fiq_invalid // FIQ EL1t + ventry el1t_error_invalid // Error EL1t + + //Exception from the current EL while using SP_ELx + ventry el1h_sync // Synchronous EL1h + ventry el1h_irq // IRQ EL1h + ventry el1h_fiq_invalid // FIQ EL1h + ventry el1h_error_invalid // Error EL1h + + //Exception from a lower EL and at least one lower EL is AArch64 + ventry el0_sync_64 // Synchronous 64-bit EL0 + ventry el0_irq_64 // IRQ 64-bit EL0 + ventry el0_fiq_invalid_64 // FIQ 64-bit EL0 + ventry el0_error_invalid_64 // Error 64-bit EL0 + + //Exception from a lower EL and at least all lower EL are AArch32 + ventry el0_sync_invalid_32 // Synchronous 32-bit EL0 + ventry el0_irq_invalid_32 // IRQ 32-bit EL0 + ventry el0_fiq_invalid_32 // FIQ 32-bit EL0 + ventry el0_error_invalid_32 // Error 32-bit EL0 + + +el1t_sync_invalid: + save_all + mov x0,0 + bl invalid_exception_router + load_all + eret +el1t_irq_invalid: + save_all + mov x0,1 + bl invalid_exception_router + load_all + eret +el1t_fiq_invalid: + save_all + mov x0,2 + bl invalid_exception_router + load_all + eret +el1t_error_invalid: + save_all + mov x0,3 + bl invalid_exception_router + load_all + eret + + +el1h_sync: + save_all + mov x0, sp + bl el1h_sync_router + bl el1_interrupt_disable + load_all + eret +el1h_irq: + save_all + mov x0, sp + bl el1h_irq_router + bl el1_interrupt_disable + load_all + eret +el1h_fiq_invalid: + save_all + mov x0,6 + bl invalid_exception_router + load_all + eret +el1h_error_invalid: + save_all + mov x0,7 + bl invalid_exception_router + load_all + eret + +el0_sync_64: + save_all + mov x0, sp + bl el0_sync_router + bl el1_interrupt_disable + load_all + eret +el0_irq_64: + save_all + mov x0, sp + bl el0_irq_router // ----------------------------------- + bl el1_interrupt_disable + load_all + eret +el0_fiq_invalid_64: + save_all + mov x0,10 + bl invalid_exception_router + load_all + eret +el0_error_invalid_64: + save_all + mov x0,11 + bl invalid_exception_router + load_all + eret + + +el0_sync_invalid_32: + save_all + mov x0,12 + bl invalid_exception_router + load_all + eret +el0_irq_invalid_32: + save_all + mov x0,13 + bl invalid_exception_router + load_all + eret +el0_fiq_invalid_32: + save_all + mov x0,14 + bl invalid_exception_router + load_all + eret +el0_error_invalid_32: + save_all + mov x0,15 + bl invalid_exception_router + load_all + eret diff --git a/lab7/kernel/src/exception.c b/lab7/kernel/src/exception.c new file mode 100644 index 000000000..2224915ab --- /dev/null +++ b/lab7/kernel/src/exception.c @@ -0,0 +1,376 @@ +#include "bcm2837/rpi_irq.h" +#include "bcm2837/rpi_uart1.h" +#include "uart1.h" +#include "exception.h" +#include "timer.h" +#include "syscall.h" +#include "signal.h" +#include "sched.h" +#include "memory.h" +#include "irqtask.h" +#include "mmu.h" +#include "debug.h" + +// 讀取ESR_EL1暫存器的值 +static inline unsigned long read_esr_el1(void) +{ + unsigned long value; + asm volatile("mrs %0, esr_el1" : "=r"(value)); + return value; +} + +// 判斷異常是否由EL0觸發的syscall +static inline int is_el0_syscall() +{ + unsigned long esr_el1 = read_esr_el1(); + unsigned long ec = (esr_el1 >> ESR_EL1_EC_SHIFT) & ESR_EL1_EC_MASK; + if (ec == ESR_EL1_EC_SVC64) + { + return 1; + } + return 0; +} + +// 定義異常類型名稱 +const char *exception_type[] = { + "Unknown reason", + "Trapped WFI or WFE instruction execution", + "Trapped MCR or MRC access with (coproc==0b1111) (AArch32)", + "Trapped MCRR or MRRC access with (coproc==0b1111) (AArch32)", + "Trapped MCR or MRC access with (coproc==0b1110) (AArch32)", + "Trapped LDC or STC access (AArch32)", + "Trapped FP access", + "Trapped VMRS access", + "Trapped PSTATE (AArch32)", + "Instruction Abort from a lower Exception level", + "Instruction Abort taken without a change in Exception level", + "PC alignment fault", + "Data Abort from a lower Exception level", + "Data Abort taken without a change in Exception level", + "SP alignment fault", + "Trapped floating-point exception", + "SError interrupt", + "Breakpoint from a lower Exception level", + "Breakpoint taken without a change in Exception level", + "Software Step from a lower Exception level", + "Software Step taken without a change in Exception level", + "Watchpoint from a lower Exception level", + "Watchpoint taken without a change in Exception level", + "BKPT instruction execution (AArch32)", + "Vector Catch exception (AArch32)", + "BRK instruction execution (AArch64)"}; + +extern list_head_t *run_queue; + +// DAIF, Interrupt Mask Bits +void el1_interrupt_enable() +{ + __asm__ __volatile__("msr daifclr, 0xf"); // umask all DAIF +} + +void el1_interrupt_disable() +{ + __asm__ __volatile__("msr daifset, 0xf"); // mask all DAIF +} + +unsigned long long int lock_counter = 0; + +void lock() +{ + el1_interrupt_disable(); + lock_counter++; +} + +void unlock() +{ + // uart_sendlinek("This is unlock\n"); + lock_counter--; + if (lock_counter < 0) + { + while (1) + ; + } + else if (lock_counter == 0) + { + el1_interrupt_enable(); + } +} + +void el1h_sync_router(trapframe_t *tpf) +{ + uart_sendlinek("\n"); + uart_sendlinek("spsr_el1 : %x\n ", tpf->spsr_el1); + uart_sendlinek("elr_el1 : %x\n ", tpf->elr_el1); + uart_sendlinek("sp_el0 : %x\n ", tpf->sp_el0); + // dump_vma(); + while (1) + ; +} + +void el1h_irq_router(trapframe_t *tpf) +{ + lock(); + // decouple the handler into irqtask queue + // (1) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.113 + // (2) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.16 + if (*IRQ_PENDING_1 & IRQ_PENDING_1_AUX_INT && *CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_GPU) // from aux && from GPU0 -> uart exception + { + if (*AUX_MU_IER_REG & 2) + { + *AUX_MU_IER_REG &= ~(2); // disable write interrupt + irqtask_add(uart_w_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); // run the queued task before returning to the program. + } + else if (*AUX_MU_IER_REG & 1) + { + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + irqtask_add(uart_r_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + } + } + else if (*CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_CNTPNSIRQ) // from CNTPNS (core_timer) // A1 - setTimeout run in el1 + { + core_timer_disable(); + irqtask_add(core_timer_handler, TIMER_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + core_timer_enable(); + + if (list_size(run_queue) > 1) + { + // uart_sendlinek("el1h_irq_router\n"); + schedule(); + } + } + else + { + unlock(); + uart_sendlinek("Hello World el1 64 router other interrupt!\r\n"); + } + + // only do signal handler when return to user mode + if ((tpf->spsr_el1 & 0b1100) == 0) + { + check_signal(tpf); + } +} + +void el0_sync_router(trapframe_t *tpf) +{ + static int count = 0; + unsigned long long esr_el1 = read_esr_el1(); + + // esr_el1: Holds syndrome information for an exception taken to EL1. + esr_el1_t *esr = (esr_el1_t *)&esr_el1; + if (esr->ec == MEMFAIL_DATA_ABORT_LOWER || esr->ec == MEMFAIL_INST_ABORT_LOWER) + { + mmu_memfail_abort_handle(esr); + return; + } + + if (!is_el0_syscall()) + { + const char *exception_name = get_exception_name(esr_el1); + if (count == 0) + ERROR("el0_sync_router: exception occurred - %s\r\n", exception_name); + count++; + return; + } + + el1_interrupt_enable(); // Allow UART input during exception + unsigned long long syscall_no = tpf->x8; + if (syscall_no > 18) + { + uart_sendlinek("SYSCALL No: %d\n", syscall_no); + } + // uart_sendlinek("tpf->x8 : %d\n",tpf->x8); + switch (syscall_no) + { + SYSCALL(0, getpid(tpf)) + SYSCALL(1, uartread(tpf, (char *)tpf->x0, tpf->x1)) + SYSCALL(2, uartwrite(tpf, (char *)tpf->x0, tpf->x1)) + SYSCALL(3, exec(tpf, (char *)tpf->x0, (char **)tpf->x1)) + SYSCALL(4, fork(tpf)) + SYSCALL(5, exit(tpf, tpf->x0)) + SYSCALL(6, syscall_mbox_call(tpf, (unsigned char)tpf->x0, (unsigned int *)tpf->x1)) + SYSCALL(7, kill(tpf, (int)tpf->x0)) + SYSCALL(8, signal_register(tpf->x0, (void (*)())tpf->x1)) + SYSCALL(9, signal_kill(tpf->x0, tpf->x1)) + SYSCALL(10, mmap(tpf, (void *)tpf->x0, tpf->x1, tpf->x2, tpf->x3, tpf->x4, tpf->x5);) + SYSCALL(11, open(tpf, (char *)tpf->x0, tpf->x1);) + SYSCALL(12, close(tpf, tpf->x0);) + SYSCALL(13, write(tpf, tpf->x0, (char *)tpf->x1, tpf->x2);) + SYSCALL(14, read(tpf, tpf->x0, (char *)tpf->x1, tpf->x2);) + SYSCALL(15, mkdir(tpf, (char *)tpf->x0, tpf->x1);) + SYSCALL(16, mount(tpf, (char *)tpf->x0, (char *)tpf->x1, (char *)tpf->x2, tpf->x3, (void *)tpf->x4);) + SYSCALL(17, chdir(tpf, (char *)tpf->x0);) + SYSCALL(18, lseek64(tpf, tpf->x0, tpf->x1, tpf->x2);) + SYSCALL(19, ioctl(tpf, tpf->x0, tpf->x1, (void *)tpf->x2);) + SYSCALL(50, sigreturn(tpf)) + SYSCALL(114, syscall_lock(tpf)) + SYSCALL(514, syscall_unlock(tpf)) + default: + uart_sendlinek("el0_sync_router other syscall, syscall_no: %d\r\n", syscall_no); + break; + } +} + +void el0_irq_router(trapframe_t *tpf) +{ + lock(); + // decouple the handler into irqtask queue + // (1) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.113 + // (2) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.16 + if (*IRQ_PENDING_1 & IRQ_PENDING_1_AUX_INT && *CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_GPU) // from aux && from GPU0 -> uart exception + { + if (*AUX_MU_IER_REG & 2) + { + *AUX_MU_IER_REG &= ~(2); // disable write interrupt + irqtask_add(uart_w_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); // run the queued task before returning to the program. + } + else if (*AUX_MU_IER_REG & 1) + { + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + irqtask_add(uart_r_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + } + } + else if (*CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_CNTPNSIRQ) // from CNTPNS (core_timer) // A1 - setTimeout run in el1 + { + core_timer_disable(); + irqtask_add(core_timer_handler, TIMER_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + core_timer_enable(); + + if (list_size(run_queue) > 1) + { + // uart_sendlinek("el0_irq_router\n"); + schedule(); + } + } + else + { + unlock(); + uart_sendlinek("Hello World el0 64 router other interrupt!\r\n"); + } + + // only do signal handler when return to user mode + if ((tpf->spsr_el1 & 0b1100) == 0) + { + check_signal(tpf); + } +} + +void invalid_exception_router(unsigned long long x0) +{ + uart_sendlinek("\n invalid exception %x \n", x0); + while (1) + ; +} + +// 獲取異常類型名稱 +const char *get_exception_name(unsigned long esr_el1) +{ + unsigned long ec = (esr_el1 >> ESR_EL1_EC_SHIFT) & ESR_EL1_EC_MASK; + if (ec < sizeof(exception_type) / sizeof(exception_type[0])) + { + return exception_type[ec]; + } + return "Unknown exception"; +} + +// ------------------------------------------------------------------------------------------ + +/* +Preemption +Now, any interrupt handler can preempt the task’s execution, but the newly enqueued task still needs to wait for the currently running task’s completion. +It’d be better if the newly enqueued task with a higher priority can preempt the currently running task. +To achieve the preemption, the kernel can check the last executing task’s priority before returning to the previous interrupt handler. +If there are higher priority tasks, execute the highest priority task. +*/ + +int curr_task_priority = 9999; // Small number has higher priority + +struct list_head *task_list; +void irqtask_list_init() +{ + task_list = allocator(sizeof(list_head_t)); + INIT_LIST_HEAD(task_list); +} + +void irqtask_add(void *task_function, unsigned long long priority) +{ + irqtask_t *the_task = kmalloc(sizeof(irqtask_t)); // free by irq_tasl_run_preemptive() + + // store all the related information into irqtask node + // manually copy the device's buffer + the_task->priority = priority; + the_task->task_function = task_function; + INIT_LIST_HEAD(&(the_task->listhead)); + + // add the timer_event into timer_event_list (sorted) + // if the priorities are the same -> FIFO + struct list_head *curr; + + // mask the device's interrupt line + // el1_interrupt_disable(); + // enqueue the processing task to the event queue with sorting. + list_for_each(curr, task_list) + { + if (((irqtask_t *)curr)->priority > the_task->priority) + { + list_add(&(the_task->listhead), curr->prev); + break; + } + } + // if the priority is lowest + if (list_is_head(curr, task_list)) + { + list_add_tail(&(the_task->listhead), task_list); + } + // unmask the interrupt line + // el1_interrupt_enable(); +} + +void irqtask_run_preemptive() +{ + // el1_interrupt_enable(); + while (!list_empty(task_list)) + { + // critical section protects new coming node + + lock(); + irqtask_t *the_task = (irqtask_t *)task_list->next; + // Run new task (early return) if its priority is lower than the scheduled task. + if (curr_task_priority <= the_task->priority) + { + unlock(); + break; + } + // get the scheduled task and run it. + list_del_entry((struct list_head *)the_task); + int prev_task_priority = curr_task_priority; + curr_task_priority = the_task->priority; + // uart_sendlinek("preemptive curr_task_priority: %d\r\n", curr_task_priority); + unlock(); + + irqtask_run(the_task); + + lock(); + curr_task_priority = prev_task_priority; + unlock(); + // free(the_task); + } +} + +void irqtask_run(irqtask_t *the_task) +{ + ((void (*)())the_task->task_function)(); + kfree(the_task); +} diff --git a/lab7/kernel/src/linker.ld b/lab7/kernel/src/linker.ld new file mode 100644 index 000000000..45b64f607 --- /dev/null +++ b/lab7/kernel/src/linker.ld @@ -0,0 +1,44 @@ +_heap_stack_size = 50M; + +SECTIONS +{ + . = 0xffff000000000000; + . += 0x80000; + _kernel_start = .; + + .text : { + *(.text.boot) + *(.text) + } + + .rodata : { + *(.rodata) + } + + .data : { + *(.data) + } + + .bss : { + . = ALIGN(8); + _bss_start = .; + *(.bss) + *(COMMON) + } + _bss_end = .; + _bss_size = (_bss_end - _bss_start)>>3; + + .heap : { + . = ALIGN(8); + _heap_top = .; + . += _heap_stack_size; + _heap_end = .; + } + + _kernel_end = .; + + . = 0xffff00002c000000; + _stack_end = .; + . = 0xffff00003c000000; + _stack_top = .; +} \ No newline at end of file diff --git a/lab7/kernel/src/main.c b/lab7/kernel/src/main.c new file mode 100644 index 000000000..582faa2ff --- /dev/null +++ b/lab7/kernel/src/main.c @@ -0,0 +1,45 @@ +#include "uart1.h" +#include "shell.h" +#include "memory.h" +#include "dtb.h" +#include "exception.h" +#include "timer.h" +#include "sched.h" +#include "uart1.h" +#include "irqtask.h" +#include "vfs.h" +//#include "bcm2837/rpi_mmu.h" + +extern list_head_t *run_queue; +extern char *dtb_ptr; +int Set_dtb = 0; + +void main(char *arg) +{ + // uart_sendlinek("in main\n"); + dtb_ptr = (char *)PHYS_TO_KERNEL_VIRT(arg); + if (!Set_dtb) + { + traverse_device_tree(dtb_ptr, dtb_callback_initramfs); + Set_dtb = 1; + } + uart_init(); + allocator_init(); + rootfs_init(); + irqtask_list_init(); + timer_list_init(); + thread_sched_init(); + //uart_sendlinek("in main\n"); + + core_timer_enable(); + uart_interrupt_enable(); + uart_flush_FIFO(); + + el1_interrupt_enable(); // enable interrupt in EL1 -> EL1 + + //start_shell(); + // uart_sendlinek("RQ size : %d \n",list_size(run_queue)); + + //schedule(); + load_context(&((((thread_t*)run_queue->next))->context)); +} diff --git a/lab7/kernel/src/mbox.c b/lab7/kernel/src/mbox.c new file mode 100644 index 000000000..530412d28 --- /dev/null +++ b/lab7/kernel/src/mbox.c @@ -0,0 +1,23 @@ +#include "bcm2837/rpi_mbox.h" +#include "mbox.h" + +/* Aligned to 16-byte boundary while we have 28-bits for VC */ +volatile unsigned int __attribute__((aligned(16))) pt[36]; + +int mbox_call( mbox_channel_type channel, unsigned int value ) +{ + // Add channel to lower 4 bit + value &= ~(0xF); + value |= channel; + while ( (*MBOX_STATUS & BCM_ARM_VC_MS_FULL) != 0 ) {} + // Write to Register + *MBOX_WRITE = value; + while(1) { + while ( *MBOX_STATUS & BCM_ARM_VC_MS_EMPTY ) {} + // Read from Register + if (value == *MBOX_READ) + return pt[1] == MBOX_REQUEST_SUCCEED; + } + return 0; +} + diff --git a/lab7/kernel/src/memory.c b/lab7/kernel/src/memory.c new file mode 100644 index 000000000..a80a1219a --- /dev/null +++ b/lab7/kernel/src/memory.c @@ -0,0 +1,491 @@ +#include "memory.h" +#include "u_list.h" +#include "uart1.h" +#include "exception.h" +#include "dtb.h" +#include "stdio.h" +#include "mmu.h" +#include "bcm2837/rpi_mmu.h" + +extern char _heap_top; +static char *htop_ptr = &_heap_top; + +extern char _kernel_start; +extern char _kernel_end; +extern char *CPIO_DEFAULT_START; +extern char *CPIO_DEFAULT_END; +extern char _stack_end; +extern char _stack_top; + +void *allocator(unsigned int size) +{ + lock(); + // -> htop_ptr + // htop_ptr + 0x02: heap_block size + // htop_ptr + 0x10 ~ htop_ptr + 0x10 * k: + // { heap_block } + // -> htop_ptr + // header 0x10 bytes block + // |--------------------------------------------------------------| + // | fill zero 0x8 bytes | size 0x8 bytes | size padding to 0x16 | + // |--------------------------------------------------------------| + + // 0x10 for heap_block header + char *r = htop_ptr + 0x10; + // size paddling to multiple of 0x10 + size = 0x10 + size - size % 0x10; + *(unsigned int *)(r - 0x8) = size; + htop_ptr += size; + unlock(); + return r; +} + +// void free(void* ptr) { +// // TBD +// } + +// ------------------------------------------------------------ + +static frame_t *frame_array; // store memory's statement and page's corresponding index +static list_head_t frame_freelist[FRAME_MAX_IDX]; // store available block for page +static list_head_t cache_list[CACHE_MAX_IDX]; // store available block for cache + +void allocator_init() +{ + frame_array = allocator(BUDDY_MEMORY_PAGE_COUNT * sizeof(frame_t)); + + // init frame freelist + for (int i = FRAME_IDX_0; i <= FRAME_IDX_FINAL; i++) + { + INIT_LIST_HEAD(&frame_freelist[i]); + } + + // init cache list + for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + { + INIT_LIST_HEAD(&cache_list[i]); + } + + for (int i = 0; i < BUDDY_MEMORY_PAGE_COUNT; i++) + { + // init listhead for each frame + INIT_LIST_HEAD(&(frame_array[i].listhead)); + frame_array[i].idx = i; + } + freelist_init(); + dump_page_info(); + + /* Startup reserving the following region: + Spin tables for multicore boot (0x0000 - 0x1000) + Devicetree (Optional, if you have implement it) + Kernel image in the physical memory + Your simple allocator (startup allocator) (Stack + Heap in my case) + Initramfs + */ + uart_sendlinek("\r\n* Startup Allocation *\r\n"); + uart_sendlinek("buddy system: usable memory region: 0x%x ~ 0x%x\n", BUDDY_MEMORY_BASE, BUDDY_MEMORY_BASE + BUDDY_MEMORY_PAGE_COUNT * PAGESIZE); + dtb_find_and_store_reserved_memory(); // find spin tables in dtb + memory_reserve(PHYS_TO_KERNEL_VIRT(MMU_PGD_ADDR), PHYS_TO_KERNEL_VIRT(MMU_PTE_ADDR + 0x2000)); // // PGD's page frame at 0x1000 // PUD's page frame at 0x2000 PMD 0x3000-0x5000 + memory_reserve((unsigned long long)&_kernel_start, (unsigned long long)&_kernel_end); // kernel + memory_reserve((unsigned long long)&_stack_end, (unsigned long long)&_stack_top); + memory_reserve((unsigned long long)CPIO_DEFAULT_START, (unsigned long long)CPIO_DEFAULT_END); +} + +void freelist_init() +{ + int PAGE_COUNT = BUDDY_MEMORY_PAGE_COUNT; + for (int i = 0; i <= FRAME_IDX_FINAL; i++) + { + // uart_sendlinek("\n %ld,%ld \n",PAGE_COUNT,(1 << i)); + if ((PAGE_COUNT & (1 << i))) + { + PAGE_COUNT -= (1 << i); + frame_array[PAGE_COUNT].val = i; + frame_array[PAGE_COUNT].used = FRAME_FREE; + list_add(&(frame_array[PAGE_COUNT].listhead), &frame_freelist[i]); + } + if (i == FRAME_IDX_FINAL && PAGE_COUNT) + { + while (PAGE_COUNT) + { + PAGE_COUNT -= (1 << i); + frame_array[PAGE_COUNT].val = FRAME_IDX_FINAL; + frame_array[PAGE_COUNT].used = FRAME_FREE; + list_add(&(frame_array[PAGE_COUNT].listhead), &frame_freelist[FRAME_IDX_FINAL]); + } + } + } +} + +frame_t *release_redundant(frame_t *frame) +{ + // order -1 -> add its buddy to free list (frame itself will be used in master function) + frame->val -= 1; + frame_t *buddyptr = get_buddy(frame); + buddyptr->val = frame->val; + buddyptr->used = FRAME_FREE; + list_add(&(buddyptr->listhead), &frame_freelist[buddyptr->val]); + return frame; +} + +frame_t *get_buddy(frame_t *frame) +{ + // XOR(idx, order) + if ((frame->idx ^ (1 << frame->val)) > BUDDY_MEMORY_PAGE_COUNT) + { + uart_sendlinek("[!] BUDDY of Page: 0x%x at level: %d Does not exit", frame->idx, frame->val); + // return -1; + } + return &frame_array[frame->idx ^ (1 << frame->val)]; +} + +void dump_page_info() +{ + // unsigned int exp2 = 1; + // uart_sendlinek(" ┌───────────────────── [ Number of Available Page Blocks ] ─────────────────────┐\r\n │ "); + // for (int i = FRAME_IDX_0; i < FRAME_IDX_8; i++) + // { + // uart_sendlinek("%4dKB(%1d) ", 4 * exp2, i); + // exp2 *= 2; + // } + // uart_sendlinek("│\r\n │ "); + // for (int i = FRAME_IDX_0; i < FRAME_IDX_8; i++) + // uart_sendlinek(" %4d ", list_size(&frame_freelist[i])); + // uart_sendlinek("│\r\n "); + // uart_sendlinek("└────────────────────────────────────────"); + // uart_sendlinek("─────────────────────────────────────────┘\r\n"); + + // exp2 = 1; + // uart_sendlinek(" ┌──────────────────────────────────── "); + // uart_sendlinek("[ Number of Available Page Blocks ]"); + // uart_sendlinek(" ───────────────────────────────────┐\r\n │"); + // for (int i = FRAME_IDX_8; i < FRAME_MAX_IDX; i++) + // { + // uart_sendlinek("%4dMB(%2d) ", exp2, i); + // exp2 *= 2; + // } + // uart_sendlinek("│\r\n │"); + // for (int i = FRAME_IDX_8; i < FRAME_MAX_IDX; i++) + // uart_sendlinek(" %4d ", list_size(&frame_freelist[i])); + // uart_sendlinek("│\r\n "); + // uart_sendlinek("└──────────────────────────────────────────────────────"); + // uart_sendlinek("────────────────────────────────────────────────────────┘\r\n"); +} + +void dump_cache_info() +{ + // unsigned int exp2 = 1; + // uart_sendlinek(" ┌──────────────── [ Number of Available Cache Blocks ] ────────────────┐\r\n │ "); + // for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + // { + // uart_sendlinek("%4dB(%1d) ", CACHE_SEG * exp2, i); + // exp2 *= 2; + // } + // uart_sendlinek("│\r\n │ "); + // ; + // for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + // { + // if (!list_empty(&cache_list[i])) + // { + // // uart_sendlinek("I free !!!!!!!!!!!!"); + // int num = 0; + // list_head_t *pos; + // list_for_each(pos, &cache_list[i]) + // { + // num += ((cache_t *)pos)->available; + // } + // uart_sendlinek("%5d ", num); + // } + // else + // { + // uart_sendlinek("%5d ", 0); + // } + // } + + // uart_sendlinek("│\r\n "); + // uart_sendlinek("└───────────────────────────────────"); + // uart_sendlinek("────────────────────────────────────┘\r\n"); +} + +void memory_reserve(unsigned long long start, unsigned long long end) +{ + start -= start % PAGESIZE; // floor (align 0x1000) + end = end % PAGESIZE ? end + PAGESIZE - (end % PAGESIZE) : end; // ceiling (align 0x1000) + + // uart_sendlinek("Reserved Memory: "); + // uart_sendlinek("start 0x%x ~ ", start); + // uart_sendlinek("end 0x%x\r\n", end); + + // delete page from free list + for (int order = FRAME_IDX_FINAL; order >= 0; order--) + { + list_head_t *pos; + // uart_sendlinek("\n use %d level page to match \n",order); + list_for_each(pos, &frame_freelist[order]) + { + unsigned long long pagestart = ((frame_t *)pos)->idx * PAGESIZE + BUDDY_MEMORY_BASE; + unsigned long long pageend = pagestart + (PAGESIZE << order); + // uart_sendlinek("\n from 0x%x to 0x%x\n",pagestart,pageend); + + if (start <= pagestart && end >= pageend) // if page all in reserved memory -> delete it from freelist + { + ((frame_t *)pos)->used = FRAME_ALLOCATED; + // uart_sendlinek(" [!] Reserved page in 0x%x - 0x%x\n", pagestart, pageend); + // uart_sendlinek(" Before\n"); + // dump_page_info(); + list_del_entry(pos); + // uart_sendlinek(" Remove usable block for reserved memory: order %d\r\n", order); + // uart_sendlinek(" After\n"); + // dump_page_info(); + } + else if (start >= pageend || end <= pagestart) // no intersection + { + continue; + } + else // partial intersection, separate the page into smaller size. + { + // dump_page_info(); + list_del_entry(pos); + list_head_t *temppos = pos->prev; + list_add(&release_redundant((frame_t *)pos)->listhead, &frame_freelist[order - 1]); + pos = temppos; + // dump_page_info(); + } + } + } +} + +void *kmalloc(unsigned int size) +{ + lock(); + + // uart_sendlinek("\n\n"); + // uart_sendlinek("================================\r\n"); + // uart_sendlinek("[+] Request kmalloc size: %d\r\n", size); + // uart_sendlinek("================================\r\n"); + // if size is larger than cache size, go for page + if (size > (CACHE_SEG << CACHE_IDX_FINAL)) + { + void *r = page_malloc(size); + unlock(); + return r; + } + // go for cache + void *r = cache_malloc(size); + unlock(); + return r; +}; + +void *page_malloc(unsigned int size) +{ + // uart_sendlinek("this is page_malloc \r\n"); + int val; + int find_PageSize = 0; + frame_t *target_frame_ptr; + // turn size into minimum 4KB * 2**val + for (int i = FRAME_IDX_0; i <= FRAME_IDX_FINAL; i++) + { + + if (size <= (PAGESIZE << i) && !find_PageSize) + { + val = i; + // uart_sendlinek(" block size = 0x%x\n", PAGESIZE << i); + find_PageSize = 1; + } + + if (find_PageSize && !list_empty(&frame_freelist[i])) + { + // uart_sendlinek(" free page at level : %d\n", i); + target_frame_ptr = (frame_t *)(frame_freelist[i].next); + for (int min_FreePageLevel = i; min_FreePageLevel > val; min_FreePageLevel--) // ex: 10000 -> 01111 + { + target_frame_ptr = release_redundant(target_frame_ptr); + } + break; + } + + if (i == FRAME_IDX_FINAL) + { + // uart_sendlinek("[!] request size exceeded for page_malloc!!!!\r\n"); + return (void *)0; + } + } + // get the available frame from freelist + target_frame_ptr->used = FRAME_ALLOCATED; + + // uart_sendlinek(" [+] Allocate page - size : %d(0x%x)\r\n", size, size); + // uart_sendlinek(" Before\r\n"); + // dump_page_info(); + list_del_entry((struct list_head *)target_frame_ptr); + // uart_sendlinek(" physical address : 0x%x\n", BUDDY_MEMORY_BASE + (PAGESIZE * (target_frame_ptr->idx))); + // uart_sendlinek(" After\r\n"); + // dump_page_info(); + + return (void *)BUDDY_MEMORY_BASE + (PAGESIZE * (target_frame_ptr->idx)); +}; + +void *cache_malloc(unsigned int size) +{ + int c_val; + // uart_sendlinek("this is cache_malloc \r\n"); + for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + { + if (size <= (CACHE_SEG << i)) + { + c_val = i; + break; + } + } + + if (list_empty(&cache_list[c_val])) + { + // uart_sendlinek("[!] No free size for cache \r\n"); //--------------------------------------------------- + page2caches(c_val); + } + + // cache_t *ptr = (cache_t *)(cache_list[c_val].prev); + + // uart_sendlinek("this is cache_malloc \r\n"); + // uart_sendlinek("[+] Allocate cache - size : %d(0x%x)\r\n", size, size); + // uart_sendlinek(" Before\r\n"); + // dump_cache_info(); + + void *ptr = find_CACHE((cache_t *)cache_list[c_val].next); + // uart_sendlinek("ptr : %x\n",ptr); + // uart_sendlinek(" After\r\n"); + // dump_cache_info(); + + return ptr; +}; + +void *find_CACHE(cache_t *ptr) +{ + // uart_sendlinek("ptr : %x\n",ptr); + unsigned long long num; + int record_num; + for (record_num = 0; ptr->cache_record[record_num] + 1 == 0 && record_num < CACHE_record_num; record_num++) + ; + + num = ptr->cache_record[record_num] + 1; + num = ((~num) & (ptr->cache_record[record_num])) + 1; + + // uart_sendlinek("before cache_record[%d] : %x\n", record_num, ptr->cache_record[record_num]); + ptr->cache_record[record_num] += num; + ptr->available--; + // uart_sendlinek("after cache_record[%d] : %x\n", record_num, ptr->cache_record[record_num]); + + int val = fake_log2(num) + record_num * 64; + void *target = ptr->data_base + val * (CACHE_SEG << (ptr->cache_order)); + // uart_sendlinek("data_base addr : 0x%x\n", ptr->data_base); + // uart_sendlinek("target addr : 0x%x\n", target); + + if (!(ptr->available)) + { + list_del_entry((list_head_t *)ptr); + } + + return target; +} + +void page2caches(int c_val) +{ + // uart_sendlinek("[!] Split Page for cache\r\n"); + void *ptr = page_malloc(PAGESIZE); + // uart_sendlinek("ptr : %x\n",ptr); + cache_t *Pageinfo = (cache_t *)ptr; + Pageinfo->data_base = ptr; + Pageinfo->cache_order = c_val; + Pageinfo->max_available = (PAGESIZE >> (CACHE_offset + c_val)); + + while (sizeof(*Pageinfo) >= Pageinfo->data_base - ptr) + { + Pageinfo->data_base += (CACHE_SEG << c_val); + (Pageinfo->max_available)--; + } + Pageinfo->available = Pageinfo->max_available; + + for (int i = 0; i < CACHE_record_num; i++) + Pageinfo->cache_record[i] = 0; + + // uart_sendlinek(" max_available : %d\n", Pageinfo->max_available); + // uart_sendlinek(" Pageinfo size : 0x%x\n", sizeof(*Pageinfo)); + // uart_sendlinek(" offset size : 0x%x\n", (CACHE_SEG << c_val)); + + list_add(&(Pageinfo->listhead), &cache_list[c_val]); + // return Pageinfo; +} + +//------------------------------------------------------------------------------------------------------------------------------- kfree + +void kfree(void *ptr) +{ + // uart_sendlinek("\r\n"); + // uart_sendlinek("==========================\r\n"); + //uart_sendlinek("[+] Request kfree 0x%x\r\n", ptr); + // uart_sendlinek("==========================\r\n"); + + // If no cache assigned, go for page + lock(); + frame_t *target_frame_ptr = &frame_array[((unsigned long long)ptr - BUDDY_MEMORY_BASE) >> 12]; + if ((unsigned long long)ptr % PAGESIZE == 0) + { + page_free(target_frame_ptr); + unlock(); + return; + } + // go for cache + cache_free(ptr); + unlock(); +}; + +void page_free(frame_t *target_frame_ptr) +{ + frame_t *buddyptr = get_buddy(target_frame_ptr); + target_frame_ptr->used = FRAME_FREE; + while (buddyptr->used == FRAME_FREE && buddyptr->val == target_frame_ptr->val) + { + list_del_entry((list_head_t *)buddyptr); + target_frame_ptr = &frame_array[(target_frame_ptr->idx) & (buddyptr->idx)]; + target_frame_ptr->val++; + buddyptr = get_buddy(target_frame_ptr); + if (buddyptr < 0) + break; + } + + // uart_sendlinek(" Before\r\n"); + // dump_page_info(); + list_add(&(target_frame_ptr->listhead), &frame_freelist[target_frame_ptr->val]); + // uart_sendlinek(" After\r\n"); + // dump_page_info(); +} + +void cache_free(void *ptr) +{ + // uart_sendlinek("ptr : %x\n",ptr); + int idx = ((unsigned long long)ptr - BUDDY_MEMORY_BASE) >> 12; + frame_t *target_frame_ptr = &frame_array[idx]; + cache_t *cache_ptr = (cache_t *)((unsigned long long)(idx * PAGESIZE) + BUDDY_MEMORY_BASE); //<------- + // uart_sendlinek("target_frame_ptr : %x\n",target_frame_ptr); + //uart_sendlinek("cache_ptr : %x\n",cache_ptr); + int num = (ptr - cache_ptr->data_base) / (CACHE_SEG << cache_ptr->cache_order); + //uart_sendlinek("num : %d\n",num); + int record_num = (num >> 6); + num = num - (record_num << 6); + cache_ptr->cache_record[record_num] -= (1 << num); + + // uart_sendlinek("[+] Free cache: 0x%x, val = %d\r\n", ptr, cache_ptr->cache_order); + // uart_sendlinek(" Before\r\n"); + // dump_cache_info(); + if (cache_ptr->available == 0) + { + list_add(&(cache_ptr->listhead), &cache_list[cache_ptr->cache_order]); + } + cache_ptr->available++; + if (cache_ptr->available == cache_ptr->max_available) + { + list_del_entry((list_head_t *)cache_ptr); + page_free(target_frame_ptr); + } + // uart_sendlinek(" After\r\n"); + // dump_cache_info(); +} \ No newline at end of file diff --git a/lab7/kernel/src/mmu.c b/lab7/kernel/src/mmu.c new file mode 100644 index 000000000..95e3bde7f --- /dev/null +++ b/lab7/kernel/src/mmu.c @@ -0,0 +1,380 @@ +#include "bcm2837/rpi_mmu.h" +#include "mmu.h" +#include "memory.h" +#include "string.h" +#include "uart1.h" +#include "debug.h" + +extern thread_t *curr_thread; + +void *set_2M_kernel_mmu(void *x0) +{ + // Turn + // Two-level Translation (1GB) - in boot.S + // to + // Three-level Translation (2MB) - set PUD point to new table + unsigned long *pud_table = (unsigned long *)MMU_PUD_ADDR; + + unsigned long *pte_table1 = (unsigned long *)MMU_PTE_ADDR; + unsigned long *pte_table2 = (unsigned long *)(MMU_PTE_ADDR + 0x1000L); + for (int i = 0; i < 512; i++) + { + unsigned long addr = 0x200000L * i; + if (addr >= PERIPHERAL_END) + { + pte_table1[i] = (0x00000000 + addr) + BOOT_PTE_ATTR_nGnRnE; + continue; + } + pte_table1[i] = (0x00000000 + addr) | BOOT_PTE_ATTR_NOCACHE; // 0 * 2MB // No definition for 3-level attribute, use nocache. + pte_table2[i] = (0x40000000 + addr) | BOOT_PTE_ATTR_NOCACHE; // 512 * 2MB + } + + // set PUD + pud_table[0] = (unsigned long)pte_table1 | BOOT_PUD_ATTR; + pud_table[1] = (unsigned long)pte_table2 | BOOT_PUD_ATTR; + + return x0; +} + +void map_one_page(size_t *virt_pgd_p, size_t user_va, size_t pa, size_t flag) +{ + size_t *table_p = virt_pgd_p; + for (int level = 0; level < 4; level++) + { + unsigned int idx = (user_va >> (39 - level * 9)) & 0x1ff; // p.14, 9-bit only + + if (level == 3) + { + table_p[idx] = pa; + table_p[idx] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_KNX | flag; // el0 only + return; + } + + if (!table_p[idx]) + { + size_t *newtable_p = kmalloc(0x1000); // create a table + memset(newtable_p, 0, 0x1000); + table_p[idx] = KERNEL_VIRT_TO_PHYS((size_t)newtable_p); // point to that table + table_p[idx] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2); + } + + table_p = (size_t *)PHYS_TO_KERNEL_VIRT((size_t)(table_p[idx] & ENTRY_ADDR_MASK)); // PAGE_SIZE + } +} + +void mmu_add_vma(struct thread *t, size_t va, size_t size, size_t pa, size_t rwx, int is_alloced, vma_name_type name) +{ + if (IS_NOT_ALIGN(pa, PAGESIZE) || IS_NOT_ALIGN(va, PAGESIZE)) + { + // ERROR("CHECK_ALIGN : 0x%x\n",CHECK_ALIGN(pa,PAGESIZE)); + uart_sendlinek("\n\n"); + ERROR("Input User Vitural Address or Physical Address Should be Aliged to PAGESIZE\n"); + ERROR("Input User Vitural Address : 0x%x\n", va); + ERROR("Input Physical Address : 0x%x\n", pa); + return; + } + vm_area_struct_t *the_area_ptr = check_vma_overlap(t, va, (unsigned long)size); + if (the_area_ptr != 0) + { + uart_sendlinek("\n\n"); + ERROR("check_vma_overlap : 0x%x\n", the_area_ptr); + ERROR("Vitural Memory Area is Overlap !!\n"); + // dump_vma(); + return; + } + + size = ALIGN_UP(size, PAGESIZE); + vm_area_struct_t *new_area = kmalloc(sizeof(vm_area_struct_t)); + new_area->rwx = rwx; + new_area->area_size = size; + new_area->virt_addr = va; + new_area->phys_addr = pa; + new_area->is_alloced = is_alloced; + new_area->name = name; + list_add_tail((list_head_t *)new_area, &t->vma_list); +} + +void mmu_del_vma(struct thread *t) +{ + list_head_t *curr = &t->vma_list; + list_head_t *n; + list_for_each_safe(curr, n, &t->vma_list) + { + vm_area_struct_t *vma = (vm_area_struct_t *)curr; + if (vma->is_alloced) + { + kfree((void *)PHYS_TO_KERNEL_VIRT(vma->phys_addr)); + } + list_del_entry(curr); + kfree(curr); + } +} + +void mmu_free_page_tables(size_t *page_table, int level) +{ + size_t *table_virt = (size_t *)PHYS_TO_KERNEL_VIRT(page_table); + for (int i = 0; i < 512; i++) + { + if (table_virt[i] != 0) + { + size_t *next_table = (size_t *)(table_virt[i] & ENTRY_ADDR_MASK); + if ((table_virt[i] & PD_TABLE) == PD_TABLE) + { + if (level < PMD) + mmu_free_page_tables(next_table, level + 1); + table_virt[i] = 0L; + kfree((void *)PHYS_TO_KERNEL_VIRT(next_table)); + } + } + } +} + +// void mmu_set_PTE_readonly(size_t *page_table, int level) +// { +// size_t *table_virt = (size_t *)PHYS_TO_KERNEL_VIRT(page_table); +// for (int i = 0; i < 512; i++) +// { +// if (table_virt[i] != 0) +// { +// size_t *next_table = (size_t)(table_virt[i] & ENTRY_ADDR_MASK); +// if (table_virt[i] & PD_TABLE == PD_TABLE) +// { +// if (level < PMD) +// { +// mmu_set_PTE_readonly(next_table, level + 1); +// } +// else +// { +// table_virt[i] &= PD_RDONLY; +// } +// } +// } +// } +// } + +// void mmu_pagetable_copy(size_t *dst_page_table, size_t *src_page_table, int level) +// { +// size_t *dst_page_table_va = (size_t *)PHYS_TO_KERNEL_VIRT(dst_page_table); +// size_t *src_page_table_va = (size_t *)PHYS_TO_KERNEL_VIRT(src_page_table); +// for (int i = 0; i < 512; i++) +// { +// if (src_page_table_va[i] != 0) +// { +// size_t *next_src_table = (size_t)(src_page_table_va[i] & ENTRY_ADDR_MASK); +// size_t *next_dst_table = kmalloc(PAGESIZE); +// memset(next_dst_table, 0, 0x1000); +// dst_page_table_va[i] = KERNEL_VIRT_TO_PHYS((size_t)next_dst_table); // point to that table +// dst_page_table_va[i] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2); +// // size_t *next_dst_table = (size_t)(dst_page_table_va[i] & ENTRY_ADDR_MASK); +// if (src_page_table_va[i] & PD_TABLE == PD_TABLE) +// { +// if (level < PTE) +// { +// mmu_pagetable_copy(next_dst_table,next_src_table,level); +// } +// else +// { +// //-------- +// } +// } +// } +// } +// } + +void mmu_memfail_abort_handle(esr_el1_t *esr_el1) +{ + lock(); + unsigned long long far_el1; + __asm__ __volatile__("mrs %0, FAR_EL1\n\t" : "=r"(far_el1)); + + list_head_t *pos; + vm_area_struct_t *vma; + vm_area_struct_t *the_area_ptr = 0; + list_for_each(pos, &curr_thread->vma_list) + { + vma = (vm_area_struct_t *)pos; + if (vma->virt_addr <= far_el1 && vma->virt_addr + vma->area_size >= far_el1) + { + the_area_ptr = vma; + break; + } + } + // area is not part of process's address space + if (!the_area_ptr) + { + uart_sendlinek("\n\n"); + ERROR("[Segmentation fault]: Kill Process\r\n"); + ERROR("Invilad Vitural Address Access: %x\n", far_el1); + thread_exit(); + // dump_vma(); + unlock(); + while (1) + schedule(); + + return; + } + + // For translation fault, only map one page frame for the fault address + if ((esr_el1->iss & 0x3f) == TF_LEVEL0 || + (esr_el1->iss & 0x3f) == TF_LEVEL1 || + (esr_el1->iss & 0x3f) == TF_LEVEL2 || + (esr_el1->iss & 0x3f) == TF_LEVEL3) + { + // uart_sendlinek("\n"); + // WARING("[Translation fault]: 0x%x\r\n", far_el1); // far_el1: Fault address register. + // Holds the faulting Virtual Address for all synchronous Instruction or Data Abort, PC alignment fault and Watchpoint exceptions that are taken to EL1. + + size_t addr_offset = (far_el1 - the_area_ptr->virt_addr); + // addr_offset = (addr_offset % 0x1000) == 0 ? addr_offset : addr_offset - (addr_offset % 0x1000); + addr_offset = ALIGN_DOWN(addr_offset, 0x1000); + + size_t flag = 0; + if (!(the_area_ptr->rwx & (0b1 << 2))) + flag |= PD_UNX; // 4: executable + if (!(the_area_ptr->rwx & (0b1 << 1))) + flag |= PD_RDONLY; // 2: writable + if (the_area_ptr->rwx & (0b1 << 0)) + flag |= PD_UK_ACCESS; // 1: readable / accessible + map_one_page((size_t *)PHYS_TO_KERNEL_VIRT(curr_thread->context.pgd), the_area_ptr->virt_addr + addr_offset, the_area_ptr->phys_addr + addr_offset, flag); + // dump_pagetable(the_area_ptr->virt_addr + addr_offset,the_area_ptr->phys_addr + addr_offset); + } + else + { + // For other Fault (permisson ...etc) + // uart_sendlinek("[Other Fault]: Kill Process\r\n"); + // uart_sendlinek("esr_el1: 0x%x\r\n", esr_el1); + uart_sendlinek("\n\n"); + if ((unsigned long)esr_el1 & (1 << 10)) + { + ERROR("[Permission Fault] due to a write of an Allocation Tag to Canonically Tagged memory.\r\n"); + } + if ((unsigned long)esr_el1 & (1 << 9)) + { + ERROR("[Permission Fault] due to the NoTagAccess memory attribute..\r\n"); + } + // check_permission(,the_area_ptr->rwx); + thread_exit(); + // dump_vma(); + unlock(); + while (1) + schedule(); + } + unlock(); +} + +vm_area_struct_t *check_vma_overlap(thread_t *t, unsigned long user_va, unsigned long size) +{ + list_head_t *pos; + vm_area_struct_t *vma; + list_for_each(pos, &t->vma_list) + { + vma = (vm_area_struct_t *)pos; + // Detect existing vma overlapped + if (!(vma->virt_addr >= (unsigned long)(user_va + size) || vma->virt_addr + vma->area_size <= (unsigned long)user_va)) + { + return vma; + } + } + return 0; +} + +int check_permission(int userId, int VMA_Permission) +{ + switch (PERMISSION_INVAILD(userId, VMA_Permission)) + { + DUMP_NAME(1, "Read is Invaild in This Vitural Memory Area") + DUMP_NAME(2, "Write is Invaild in This Vitural Memory Area") + DUMP_NAME(3, "Write & Read is Invaild in This Vitural Memory Area") + DUMP_NAME(4, "Exec is Invaild in This Vitural Memory Area") + DUMP_NAME(5, "Exec & Read is Invaild in This Vitural Memory Area") + DUMP_NAME(6, "Exec & Write is Invaild in This Vitural Memory Area") + DUMP_NAME(7, "Exec & Write & Read is Invaild in This Vitural Memory Area") + default: + uart_sendlinek("[other Fault]: UNKNOW FAULT"); + break; + } + return PERMISSION_INVAILD(userId, VMA_Permission); +} + +void dump_vma() +{ + uart_sendlinek(" +--------------------------+\n"); + uart_sendlinek(" | DUMP Vitural Memory Area |\n"); + uart_sendlinek(" +--------------------------+\n"); + list_head_t *pos; + list_for_each(pos, &curr_thread->vma_list) + { + uart_sendlinek("===============================================\n"); + vm_area_struct_t *vma_ptr = (vm_area_struct_t *)pos; + + uart_sendlinek("Vitural Memory Area Name : "); + switch (vma_ptr->name) + { + DUMP_NAME(UNKNOW_AREA, "UNKNOW_AREA") + DUMP_NAME(USER_DATA, "USER_DATA") + DUMP_NAME(USER_STACK, "USER_STACK") + DUMP_NAME(PERIPHERAL, "PERIPHERAL") + DUMP_NAME(USER_SIGNAL_WRAPPER, "USER_SIGNAL_WRAPPER") + DUMP_NAME(USER_EXEC_WRAPPER, "USER_EXEC_WRAPPER") + default: + uart_sendlinek("unnamed: %d\n", vma_ptr->name); + break; + } + uart_sendlinek("Base Vitural Address : 0x%x\n", ((vm_area_struct_t *)pos)->virt_addr); + uart_sendlinek("Base Physical Address : 0x%x\n", ((vm_area_struct_t *)pos)->phys_addr); + uart_sendlinek("Area Size : 0x%x\n", ((vm_area_struct_t *)pos)->area_size); + uart_sendlinek("Exec, Write, Read : 0x%x\n", ((vm_area_struct_t *)pos)->rwx); + uart_sendlinek("===============================================\n\n"); + } +} + +void dump_pagetable(unsigned long user_va, unsigned long pa) +{ + uart_sendlinek(" +---------------------------+\n"); + uart_sendlinek(" | DUMP PAGE TABLE & ADDRESS |\n"); + uart_sendlinek(" +---------------------------+\n"); + unsigned long *pagetable_pa = curr_thread->context.pgd; + unsigned long *pagetable_kernel_va = (unsigned long *)PHYS_TO_KERNEL_VIRT(pagetable_pa); + + uart_sendlinek("===============================================\n"); + uart_sendlinek("User Physical Address : 0x%x\n", pa); + uart_sendlinek("User Vitural Address : 0x%x\n", user_va); + unsigned long offset = user_va & 0xFFF; + uart_sendlinek("Vitural Address offset: 0x%x\n", offset); + for (int level = 0; level < 4; level++) + { + uart_sendlinek("-----------------------------------------------\n"); + uart_sendlinek("PAGE TABLE : "); + switch (level) + { + DUMP_NAME(PGD, "PGD") + DUMP_NAME(PUD, "PUD") + DUMP_NAME(PMD, "PMD") + DUMP_NAME(PTE, "PTE") + + default: + uart_sendlinek("unnamed: %d\n", level); + break; + } + uart_sendlinek("Pagetable Physical Address: 0x%x\n", pagetable_pa); + uart_sendlinek("Pagetable Vitural Address: 0x%x\n", pagetable_kernel_va); + + unsigned int idx = (user_va >> (39 - level * 9)) & 0x1FF; + uart_sendlinek("Index of Pagetable: 0x%x\n", idx); + uart_sendlinek("Entry %x of Pagetable: 0x%x\n", idx, pagetable_kernel_va[idx]); + if (level == PTE) + { + pagetable_pa = (unsigned long *)(pagetable_kernel_va[idx] & ENTRY_ADDR_MASK); + uart_sendlinek("The Page Base Physical Address: 0x%x\n", pagetable_pa); + uart_sendlinek("The Physical Address: 0x%x\n", (unsigned long)pagetable_pa | offset); + } + else + { + pagetable_pa = (unsigned long *)(pagetable_kernel_va[idx] & ENTRY_ADDR_MASK); + uart_sendlinek("next Pagetable Physical Address: 0x%x\n", pagetable_pa); + pagetable_kernel_va = (unsigned long *)PHYS_TO_KERNEL_VIRT(pagetable_pa); + uart_sendlinek("next Pagetable Vitural Address: 0x%x\n", pagetable_kernel_va); + } + uart_sendlinek("-----------------------------------------------\n"); + } +} \ No newline at end of file diff --git a/lab7/kernel/src/sched.S b/lab7/kernel/src/sched.S new file mode 100644 index 000000000..7d0f93cd2 --- /dev/null +++ b/lab7/kernel/src/sched.S @@ -0,0 +1,57 @@ +.global switch_to +switch_to: // (prev, next) = (x0, x1) + stp x19, x20, [x0, 16 * 0] // store callee saved register + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] // store sp, fp, lr + mov x9, sp + str x9, [x0, 16 * 6] + + ldp x19, x20, [x1, 16 * 0] // load callee saved register + ldp x21, x22, [x1, 16 * 1] + ldp x23, x24, [x1, 16 * 2] + ldp x25, x26, [x1, 16 * 3] + ldp x27, x28, [x1, 16 * 4] + ldp fp, lr, [x1, 16 * 5] // load sp, fp, lr + ldp x9, x0, [x1, 16 * 6] + mov sp, x9 + msr tpidr_el1, x1 // update current thread id + + dsb ish // ensure write has completed, lock for context switch + msr ttbr0_el1, x0 // switch translation based address. + tlbi vmalle1is // invalidate all TLB entries in stage 1, el1 and inner shareable + dsb ish // ensure completion of TLB invalidatation + isb // clear pipeline + + ret + +.global get_current +get_current: + mrs x0, tpidr_el1 // get the current thread id + ret + +.global store_context +store_context: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + ret + +.global load_context +load_context: + ldp x19, x20, [x0, 16 * 0] + ldp x21, x22, [x0, 16 * 1] + ldp x23, x24, [x0, 16 * 2] + ldp x25, x26, [x0, 16 * 3] + ldp x27, x28, [x0, 16 * 4] + ldp fp, lr, [x0, 16 * 5] + ldr x9, [x0, 16 * 6] + mov sp, x9 + ret diff --git a/lab7/kernel/src/sched.c b/lab7/kernel/src/sched.c new file mode 100644 index 000000000..09bbbcd17 --- /dev/null +++ b/lab7/kernel/src/sched.c @@ -0,0 +1,270 @@ +#include "sched.h" +#include "uart1.h" +#include "exception.h" +#include "memory.h" +#include "timer.h" +#include "shell.h" +#include "signal.h" +#include "stdio.h" +#include "mmu.h" +#include "string.h" + +list_head_t *run_queue; +execfile c_execfile; + +thread_t threads[PIDMAX + 1]; +thread_t *curr_thread; + +int pid_history = 0; +int timer_sched_flag = 0; +int shell_flag = 0; + +void thread_sched_init() +{ + lock(); + // init thread freelist and run_queue + run_queue = kmalloc(sizeof(list_head_t)); + INIT_LIST_HEAD(run_queue); + + // init pids + for (int i = 0; i <= PIDMAX; i++) + { + threads[i].isused = 0; + threads[i].pid = i; + threads[i].iszombie = 0; + } + + thread_t *idlethread = thread_create(start_shell); + curr_thread = idlethread; + asm volatile("msr tpidr_el1, %0" ::"r"(&curr_thread->context)); // Don't let thread structure NULL as we enable the functionality + + // thread_create(idle); + unlock(); +} + +thread_t *thread_create(void *start) +{ + lock(); + thread_t *r; + // find usable PID, don't use the previous one + if (pid_history > PIDMAX) + { + unlock(); + return 0; + } + + if (!threads[pid_history].isused) + { + r = &threads[pid_history]; + pid_history += 1; + } + else + { + unlock(); + return 0; + } + + INIT_LIST_HEAD(&r->vma_list); + r->iszombie = 0; + r->isused = 1; + r->stack_alloced_ptr = kmalloc(USTACK_SIZE); + r->kernel_stack_alloced_ptr = kmalloc(KSTACK_SIZE); + r->context.lr = (unsigned long long)start; + r->context.sp = (unsigned long long)r->kernel_stack_alloced_ptr + KSTACK_SIZE - STACK_BASE_OFFSET; + r->context.fp = r->context.sp; // frame pointer for local variable, which is also in stack. + + strcpy(r->curr_working_dir, "/"); // new <----------------------------------------------------------------------- + vfs_open("/dev/uart", 0, &r->file_descriptors_table[stdin]); + vfs_open("/dev/uart", 0, &r->file_descriptors_table[stdout]); + vfs_open("/dev/uart", 0, &r->file_descriptors_table[stderr]); + + r->context.pgd = kmalloc(0x1000); + memset(r->context.pgd, 0, 0x1000); + r->context.pgd = (void *)KERNEL_VIRT_TO_PHYS(r->context.pgd); + + r->signal_is_checking = 0; + // initial all signal handler with signal_default_handler (kill thread) + + // uart_sendlinek("signal_default_handler : 0x%x\n", signal_default_handler); + for (int i = 0; i < SIGNAL_MAX; i++) + { + r->signal_handler[i] = signal_default_handler; + r->sigcount[i] = 0; + } + + list_add_tail(&r->listhead, run_queue); + unlock(); + return r; +} + +void schedule() +{ + lock(); + // uart_sendlinek("Run queue size :%d \n", list_size(run_queue)); + do + { + // uart_sendlinek("Run queue size :%d \n", list_size(run_queue)); + curr_thread = (thread_t *)curr_thread->listhead.next; + } while (list_is_head(&curr_thread->listhead, run_queue)); // find a runnable thread + unlock(); + // uart_sendlinek("curr_thread :%d \n",curr_thread->pid); + // uart_sendlinek("curr_thread->context.lr :0x%x \n",curr_thread->context.lr); + switch_to(get_current(), &curr_thread->context); +} + +void idle() +{ + // uart_sendlinek("This is idle\n"); + while (shell_flag > 0) + // while (list_size(run_queue) > 1) + { + // uart_sendlinek("This is idle\n"); + kill_zombies(); // reclaim threads marked as DEAD + schedule(); // switch to next thread in run queue + // delay(10000); + } + kill_zombies(); +} + +void thread_exit() +{ + // thread cannot deallocate the stack while still using it, wait for someone to recycle it. + // In this lab, idle thread handles this task, instead of parent thread. + lock(); + curr_thread->iszombie = 1; + shell_flag--; + unlock(); + // delay(10000); + // schedule(); +} + +void kill_zombies() +{ + lock(); + list_head_t *curr; + thread_t *t; + list_for_each(curr, run_queue) + { + t = (thread_t *)curr; + if (t->iszombie) + { + list_del_entry(curr); + mmu_free_page_tables(t->context.pgd, 0); + mmu_del_vma(t); + for (int i = 0; i < MAX_FD; i++) + { + if (t->file_descriptors_table[i]) + vfs_close(t->file_descriptors_table[i]); + } + kfree(t->kernel_stack_alloced_ptr); + kfree((void *)PHYS_TO_KERNEL_VIRT(t->context.pgd)); + t->iszombie = 0; + t->isused = 0; + } + } + unlock(); +} + +void foo() +{ + // Lab5 Basic 1 Test function + for (int i = 0; i < 10; ++i) + { + uart_sendlinek("Thread id: %d %d\n", curr_thread->pid, i); + int r = 1000000; + while (r--) + { + asm volatile("nop"); + } + schedule(); + } + // uart_sendlinek("exit\n"); + thread_exit(); +} + +int exec_thread() +{ + lock(); + shell_flag++; + thread_t *t = thread_create(exec_proc); + curr_thread = t; + // uart_sendlinek("timer_sched_flag : %d\n", timer_sched_flag); + if (!timer_sched_flag) + { + timer_sched_flag = 1; + add_timer(schedule_timer, 1, "", setSecond); // start scheduler --------------------------------------------------------- + } + + unlock(); + schedule(); + + return 0; +} + +void exec_proc() +{ + el1_interrupt_disable(); // daif 會在 eret 時更改。 + // char *data = c_execfile.data; + // unsigned int filesize = c_execfile.filesize; + thread_t *t = curr_thread; + + // char *data = target_file->f_ops; + unsigned int filesize = (c_execfile.vnode)->f_ops->getsize(c_execfile.vnode); + + t->data = kmalloc(filesize); + t->datasize = filesize; + + // copy file into data + struct file *f; + vfs_open(c_execfile.pathname, 0, &f); + vfs_read(f, t->data, t->datasize); + vfs_close(f); + + //memcpy(t->data, data, t->datasize); + + mmu_add_vma(t, USER_DATA_BASE, t->datasize, (size_t)KERNEL_VIRT_TO_PHYS(t->data), 0b111, 1, USER_DATA); + mmu_add_vma(t, USER_STACK_BASE - USTACK_SIZE, USTACK_SIZE, (size_t)KERNEL_VIRT_TO_PHYS(t->stack_alloced_ptr), 0b111, 1, USER_STACK); + mmu_add_vma(t, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0, PERIPHERAL); + mmu_add_vma(t, USER_SIGNAL_WRAPPER_VA, 0x1000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(signal_handler_wrapper), PAGESIZE), 0b101, 0, USER_SIGNAL_WRAPPER); + mmu_add_vma(t, USER_EXEC_WRAPPER_VA, 0x2000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(exec_wrapper), PAGESIZE), 0b101, 0, USER_EXEC_WRAPPER); + + t->context.sp = USER_STACK_BASE - STACK_BASE_OFFSET; + t->context.fp = USER_STACK_BASE - STACK_BASE_OFFSET; + t->context.lr = USER_DATA_BASE; + + // for (int i = 0; i < filesize; i++) + // { + // t->data[i] = data[i]; + // } + // dump_vma(); + + // vfs_open("/dev/uart", 0, &curr_thread->file_descriptors_table[0]); // stdin + // vfs_open("/dev/uart", 0, &curr_thread->file_descriptors_table[1]); // stdout + // vfs_open("/dev/uart", 0, &curr_thread->file_descriptors_table[2]); // stderr + + asm("msr tpidr_el1, %0\n\t" // Hold the "kernel(el1)" thread structure information + "msr elr_el1, %1\n\t" // When el0 -> el1, store return address for el1 -> el0 + "msr spsr_el1, xzr\n\t" // EL1h (SPSel = 1) with interrupt disabled + "msr sp_el0, %2\n\t" // el0 stack pointer for el1 process + "mov sp, %3\n\t" // sp is reference for the same el process. For example, el2 cannot use sp_el2, it has to use sp to find its own stack. + "mov x0, %4\n\t" ::"r"(&t->context), + "r"(exec_wrapper), "r"(t->context.sp), "r"(t->kernel_stack_alloced_ptr + KSTACK_SIZE - STACK_BASE_OFFSET), "r"(t->context.lr)); + + asm("eret\n\t"); +} + +void exec_wrapper() +{ + asm("blr x0\n\t" + "mov x8,50\n\t" + "svc 0\n\t"); +} + +void schedule_timer(char *notuse) +{ + unsigned long long cntfrq_el0; + __asm__ __volatile__("mrs %0, cntfrq_el0\n\t" : "=r"(cntfrq_el0)); + add_timer(schedule_timer, cntfrq_el0 >> 5, "", setTick); + // schedule(); + // 32 * default timer -> trigger next schedule timer +} diff --git a/lab7/kernel/src/shell.c b/lab7/kernel/src/shell.c new file mode 100644 index 000000000..a373a9868 --- /dev/null +++ b/lab7/kernel/src/shell.c @@ -0,0 +1,588 @@ +#include "shell.h" +#include "mbox.h" +#include "power.h" +#include "stdio.h" +#include "string.h" +#include "cpio.h" +#include "memory.h" +#include "dtb.h" +#include "timer.h" +#include "sched.h" +#include "signal.h" +#include "syscall.h" +#include "vfs.h" +#include "vfs_tmpfs.h" +#include "debug.h" + +#include "uart1.h" + +#define USTACK_SIZE 0x10000 + +extern unsigned long long int lock_counter; +extern list_head_t *run_queue; +extern execfile c_execfile; +extern struct mount *rootfs; + +struct CLI_CMDS cmd_list[CLI_MAX_CMD] = { + {.command = "cat", .help = "concatenate files and print on the standard output", .func = do_cmd_cat}, + {.command = "dtb", .help = "show device tree", .func = do_cmd_dtb}, + {.command = "hello", .help = "print Hello World!", .func = do_cmd_hello}, + {.command = "help", .help = "print all available commands", .func = do_cmd_help}, + {.command = "info", .help = "get device information via mailbox", .func = do_cmd_info}, + {.command = "malloc", .help = "test malloc", .func = do_cmd_malloc}, + {.command = "reboot", .help = "reboot the device", .func = do_cmd_reboot}, + {.command = "exec", .help = "execute user programs ", .func = do_cmd_exec}, + {.command = "setTime", .help = "setTime [MESSAGE] [SECONDS] ", .func = do_cmd_setTimeout}, + {.command = "2sAlert", .help = "set core timer interrupt every 2 second ", .func = do_cmd_set2sAlert}, + {.command = "mtest", .help = "memory testcase generator, allocate and free", .func = do_cmd_mtest}, + {.command = "ttest", .help = "thread tester with dummy function - foo()", .func = do_cmd_ttest}, + {.command = "ls", .help = "list directory contents", .func = do_cmd_ls}, + {.command = "cd", .help = "change directory", .func = do_cmd_cd}, + {.command = "ftest", .help = "get run_queue size", .func = do_cmd_ftest}}; + +extern char *dtb_ptr; +extern thread_t *curr_thread; +extern void *CPIO_DEFAULT_START; + +void start_shell() +{ + // uart_sendlinek("In start_shell\n"); + char input_buffer[CMD_MAX_LEN]; + + cli_print_banner(); + while (1) + { + cli_flush_buffer(input_buffer, CMD_MAX_LEN); + // uart_sendlinek("lock_counter : %d\n",lock_counter); + puts("【 Ciallo~(∠・ω< )⌒★ 】 # "); + cli_cmd_read(input_buffer); + cli_cmd_exec(input_buffer); + idle(); + // uart_sendlinek("idle finish\n"); + } + // return 0; +} + +void cli_flush_buffer(char *buffer, int length) +{ + for (int i = 0; i < length; i++) + { + buffer[i] = '\0'; + } +}; + +void cli_cmd_read(char *buffer) +{ + char c = '\0'; + int idx = 0; + + while (idx < CMD_MAX_LEN - 1) + { + c = getchar(); + // vfs_read(uart, c, 0); + + if (c == 127) // backspace + { + if (idx != 0) + { + puts("\b \b"); + // vfs_write("/dev/uart","\b \b",0); + idx--; + } + } + else if (c == '\n') + { + break; + } + else if (c <= 16 || c >= 32 || c < 127) + { + putchar(c); + // vfs_write("/dev/uart","\b \b",0); + buffer[idx++] = c; + } + } + buffer[idx] = '\0'; + puts("\r\n"); + // vfs_write("/dev/uart","\r\n",0); +} + +int _parse_args(char *buffer, int *argc, char **argv) +{ + char get_cmd = 0; + for (int i = 0; buffer[i] != '\0'; i++) + { + if (!get_cmd) + { + if (buffer[i] == ' ') + { + buffer[i] = '\0'; + get_cmd = 1; + } + } + else + { + if (buffer[i - 1] == '\0' && buffer[i] != ' ' && buffer[i] != '\0') + { + if (*argc >= CMD_MAX_PARAM) + { + return -1; + } + argv[*argc] = buffer + i; + (*argc)++; + } + else if (buffer[i] == ' ') + { + buffer[i] = '\0'; + } + } + } + return 0; +} + +void print_args(int argc, char **argv) +{ + puts("argc: "); + put_int(argc); + puts("\r\n"); + for (int i = 0; i < argc; i++) + { + puts("argv["); + put_int(i); + puts("]: "); + puts(argv[i]); + puts("\r\n"); + } +} + +void cli_cmd_exec(char *buffer) +{ + char *cmd = buffer; + int argc = 0; + char *argv[CMD_MAX_PARAM]; + if (_parse_args(buffer, &argc, argv) == -1) + { + puts("Too many arguments\r\n"); + return; + } + // print_args(argc, argv); + + for (int i = 0; i < CLI_MAX_CMD; i++) + { + if (strcmp(cmd, cmd_list[i].command) == 0) + { + cmd_list[i].func(argc, argv); + return; + } + } + if (*buffer) + { + puts(buffer); + puts(": command not found\r\n"); + } +} + +void cli_print_banner() +{ + // uart_sendlinek("In cli_print_banner\n"); + puts("\r\n"); + puts("============================================================================================\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@-@@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ *@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@# =@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= :@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@- %@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% *@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#%@@@@@@@@@@@@@@@@@@@* -@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@% *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:=@@@@@@@@@@@@@@@@@@@: %@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@- :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@* #@@@@@@@@@@@@@@@@@* -@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@#- :#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+ +%@@@@@@@@@@@@@@+ -%@@@@@@@@@@@@\r\n"); + puts("@@@@*=: :=#@@@@@@@@#=: =*@@@@@@@@@@\r\n"); + puts("@@@@@#= =*%@@@@@@@@@@*+- :=*%@@@@@@@@@@\r\n"); + puts("@@@@@@@- @@@@@@@@@@@# -@@@@@@@@@@@@@@@@@@%: -%@%@@@@@@@@@@@@@@%= :#@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@= @%++*%@@@@@%: +@@@@#==#@@@@@@@@@@@% %* -%@@#-=+%@@@@@@@- %@@@@@+::=*%@@@@\r\n"); + puts("@@@@@@@= @% =%@+ #@+ =%@@\r\n"); + puts("@@@@@@@= @% ************- =@ #+ :%@@\r\n"); + puts("@@@@@@@= @% @@@@@@@@@@@@+ @@% #= += %@@@* =@@@@- :@@@@\r\n"); + puts("@@@@@@@= @% ##########%@+ :@@% #= +@@@@@@= %@#= -#@@= -@@@@\r\n"); + puts("@@@@@@@= @% :::::::::::@+ :@@% #= +#+=++@= -: -: -@@@@\r\n"); + puts("@@@@@@@= @% @@@@@@@@@@@@+ :@@% #= ++ @= - : -@@@@\r\n"); + puts("@@@@@@@= :@% @@@@@@@@@@@@+ :@@% #= ++ @= %@#- :*%@- -@@@@\r\n"); + puts("@@@@@@@= =@% :@@% #= ++ @= %@@@+ -@@@@- -@@@@\r\n"); + puts("@@@@@@@- #@% ****: +**= +@@% #= ++ @= *####: #####: -@@@@\r\n"); + puts("@@@@@@@ :@@%-=*%@@@@@- #@@#+*#%@@@@% #= ++ =@+ -@@@@\r\n"); + puts("@@@@@@* %@@@@#*=--@@@- #@@#-=+*%@@@% %= *+ =@@+ +@@@@@= :@@@@@# -@@@@\r\n"); + puts("@@@@@@: *@%+- =@@- #@#: :=*+ :@= +*=%@@@+ =%@@@@@* -@@@@@@+: -@@@@\r\n"); + puts("@@@@@= *#- *- #- *@= +@@@@@@#+*@@@@@@*- :+%@@@@@#+*@@@@\r\n"); + puts("@@@@+ -%@: -=**%@@@- #@@%#*+=: *@@= *@@@@@@@@@@@@=: :-%@@@@@@@@@\r\n"); + puts("@@@+ -#@@@%- =@@@@@@@@@- #@@@@@@@@% =%@@@= *@@@@@@@@@@@@@#- :*%@@@@@@@@@@\r\n"); + puts("@@=:+%@@@@@@@%+--=*%@@@@@- :@@@@@@#*=-=*@@@@@@= #@@@@@@@@@@@@@@@* =@@@@@@@@@@@@@\r\n"); + puts("@%%@@@@@@@@@@@@@@@%##@@@@- #@@@@%#%@@@@@@@@@@@= +@@@@@@@@@@@@@@@@@* -@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@- =%@@@@@@@@@@@@@@@@@@@= *@@@@@@@@@@@@@@@@@@@: %@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@++%@@@@@@@@@@@@@@@@@@@@@*+%@@@@@@@@@@@@@@@@@@@@+ -@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% +@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= %@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= :@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@* =@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% =@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ *@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@-%@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@=@@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@@@@@@@@@@@@@@@\r\n"); + puts("============================================================================================\r\n"); +} + +int do_cmd_help(int argc, char **argv) +{ + for (int i = 0; i < CLI_MAX_CMD; i++) + { + puts(cmd_list[i].command); + puts("\t\t\t: "); + puts(cmd_list[i].help); + puts("\r\n"); + } + return 0; +} + +int do_cmd_hello(int argc, char **argv) +{ + puts("Hello World!\r\n"); + return 0; +} + +int do_cmd_info(int argc, char **argv) +{ + // print hw revision + pt[0] = 8 * 4; + pt[1] = MBOX_REQUEST_PROCESS; + pt[2] = MBOX_TAG_GET_BOARD_REVISION; + pt[3] = 4; + pt[4] = MBOX_TAG_REQUEST_CODE; + pt[5] = 0; + pt[6] = 0; + pt[7] = MBOX_TAG_LAST_BYTE; + + if (mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt))) + { + puts("Hardware Revision\t: 0x"); + // put_hex(pt[6]); + put_hex(pt[5]); + puts("\r\n"); + } + // print arm memory + pt[0] = 8 * 4; + pt[1] = MBOX_REQUEST_PROCESS; + pt[2] = MBOX_TAG_GET_ARM_MEMORY; + pt[3] = 8; + pt[4] = MBOX_TAG_REQUEST_CODE; + pt[5] = 0; + pt[6] = 0; + pt[7] = MBOX_TAG_LAST_BYTE; + + if (mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt))) + { + puts("ARM Memory Base Address\t: 0x"); + put_hex(pt[5]); + puts("\r\n"); + puts("ARM Memory Size\t\t: 0x"); + put_hex(pt[6]); + puts("\r\n"); + } + return 0; +} + +int do_cmd_reboot(int argc, char **argv) +{ + if (argc == 0) + { + + puts("Reboot in 10 seconds ...\r\n\r\n"); + volatile unsigned int *rst_addr = (unsigned int *)PM_RSTC; + *rst_addr = PM_PASSWORD | 0x20; + volatile unsigned int *wdg_addr = (unsigned int *)PM_WDOG; + *wdg_addr = PM_PASSWORD | 0x70000; + } + else if (argc == 1 && strcmp(argv[0], "-c") == 0) + { + puts("Cancel reboot...\r\n"); + volatile unsigned int *rst_addr = (unsigned int *)PM_RSTC; + *rst_addr = PM_PASSWORD | 0x0; + volatile unsigned int *wdg_addr = (unsigned int *)PM_WDOG; + *wdg_addr = PM_PASSWORD | 0x0; + } + return 0; +} + +int do_cmd_ls(int argc, char **argv) +{ + // char *c_filepath; + // char *c_filedata; + // unsigned int c_filesize; + + // CPIO_for_each(&c_filepath, &c_filesize, &c_filedata) + // { + // if (header_ptr != 0) + // { + // puts(c_filepath); + // puts("\r\n"); + // } + // } + vfs_ls(); + return 0; +} + +int do_cmd_cat(int argc, char **argv) +{ + int FLAG_getfile = 0; + char *filepath; + char *c_filepath; + char *c_filedata; + unsigned int c_filesize; + + if (argc == 1) + { + filepath = argv[0]; + } + else + { + puts("Too many arguments\r\n"); + return -1; + } + + CPIO_for_each(&c_filepath, &c_filesize, &c_filedata) + { + if (strcmp(c_filepath, filepath) == 0) + { + FLAG_getfile = 1; + Readfile(c_filedata, c_filesize); + break; + } + } + + if (!FLAG_getfile) + { + puts("cat: "); + puts(filepath); + puts(": No such file or directory\r\n"); + } + return 0; +} + +int do_cmd_malloc(int argc, char **argv) +{ + // test malloc + char *test1 = allocator(0x18); + strcpy(test1, "test malloc1"); + puts(test1); + puts("\r\n"); + + char *test2 = allocator(0x20); + strcpy(test2, "test malloc2"); + puts(test2); + puts("\r\n"); + + char *test3 = allocator(0x28); + strcpy(test3, "test malloc3"); + puts(test3); + puts("\r\n"); + return 0; +} + +int do_cmd_dtb(int argc, char **argv) +{ + traverse_device_tree(dtb_ptr, dtb_callback_show_tree); + return 0; +} + +int do_cmd_exec(int argc, char **argv) +{ + char *filepath; + + if (argc == 1) + { + filepath = argv[0]; + } + else + { + puts("Too many arguments\r\n"); + return -1; + } + + char abs_path[MAX_PATH_NAME]; + struct vnode *target_file; + strcpy(abs_path, filepath); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + + strcpy(abs_path,"/initramfs/vfs1.img");// + if (vfs_lookup(abs_path, &target_file) != 0) + { + WARING("File : %s Does not Exit!!\n", abs_path); + return 0; + }; + + c_execfile.vnode = target_file; + c_execfile.pathname = abs_path; + exec_thread(); + + // c_execfile.data = target_file->f_ops; + // c_execfile.filesize = target_file->f_ops->getsize(target_file);; + + // CPIO_for_each(&c_filepath, &c_filesize, &c_filedata) + // { + // if (strcmp(c_filepath, filepath) == 0) + // { + // // exec c_filedata + // FLAG_getfile = 1; + // c_execfile.data = c_filedata; + // c_execfile.filesize = c_filesize; + // exec_thread(); + // } + // } + + // if (!FLAG_getfile) // header_ptr + // { + // puts("cat: "); + // puts(filepath); + // puts(": No such file or directory\r\n"); + // } + return 0; +} + +int do_cmd_setTimeout(int argc, char **argv) +{ + char *msg; + int sec; + if (argc == 2) + { + msg = argv[0]; + sec = atoi(argv[1]); + } + else + { + puts("setTimeout [MESSAGE] [SECONDS]\r\n"); + return -1; + } + add_timer(puts, sec, msg, setSecond); + return 0; +} + +int do_cmd_set2sAlert(int argc, char **argv) +{ + add_timer(timer_set2sAlert, 2, "2sAlert", setSecond); + return 0; +} + +int do_cmd_mtest(int argc, char **argv) +{ + // char *a = kmalloc(513); + // uart_sendlinek("a : %x\n", a); + // //kfree(a); + + // char *b = kmalloc(512); + // uart_sendlinek("b : %x\n", b); + // //kfree(b); + + // char *c = kmalloc(8); + // //kfree(c); + + return 0; +} + +int do_cmd_ttest(int argc, char **argv) +{ + uart_sendlinek("run_queue size : %d\n", list_size(run_queue)); + list_head_t *pos; + list_for_each(pos, run_queue) + { + uart_sendlinek("pid : %d\n", ((thread_t *)pos)->pid); + for (int i = 0; i < SIGNAL_MAX; i++) + { + uart_sendlinek("signal_handler : 0x%x\n", ((thread_t *)pos)->signal_handler[i]); + } + } + return 0; +} + +int do_cmd_ftest(int argc, char **argv) +{ + // ============================== test for file operation start================================== + uart_sendlinek("\n\n"); + uart_sendlinek("+-----------------------------+\n"); + uart_sendlinek("| mkdir,mount test |\n"); + uart_sendlinek("+-----------------------------+\n"); + + vfs_mkdir("/lll"); + vfs_mkdir("/aaa"); + vfs_mkdir("/bbb"); + vfs_mkdir("/lll/ddd"); + vfs_mount("/lll/ddd", "tmpfs"); + vfs_mkdir("/lll/ddd/fff"); + vfs_dump(rootfs->root, 0); + + uart_sendlinek("\n\n"); + uart_sendlinek("+-----------------------------+\n"); + uart_sendlinek("| open,write,read test |\n"); + uart_sendlinek("+-----------------------------+\n"); + + struct file *testfilew; + struct file *testfiler; + char testbufw[0x30] = "ABCDEABBBBBBDDDDDDDDDDD\n"; + char testbufr[0x30] = {}; + + vfs_open("/lll/ddd/ggg.file", O_CREAT, &testfilew); + vfs_open("/lll/ddd/ggg.file", O_CREAT, &testfiler); + vfs_write(testfilew, testbufw, 25); + vfs_read(testfiler, testbufr, 25); + + uart_sendlinek("%s", testbufr); + vfs_dump(rootfs->root, 0); + // ============================== test for file operation end ================================== + + // ============================== test for get_absolute_path start================================== + // char *currt_path = "/root"; + // uart_sendlinek("currt_path : %s\n", currt_path); + // char *path1 = "/"; + // uart_sendlinek("path1 rel_path : %s\n", path1); + // get_absolute_path(path1, currt_path); + // // uart_sendlinek("path1 abs_path : %s\n", path1); + // uart_sendlinek("---------------------------------------\n"); + // char *path2 = "desktop"; + // uart_sendlinek("path2 rel_path : %s\n", path2); + // get_absolute_path(path2, currt_path); + // // uart_sendlinek("path2 abs_path : %s\n", path2); + // uart_sendlinek("---------------------------------------\n"); + // char *path3 = ".///////"; + // uart_sendlinek("path3 rel_path : %s\n", path3); + // get_absolute_path(path3, currt_path); + // // uart_sendlinek("path3 abs_path : %s\n", path3); + // ============================== test for get_absolute_path end================================== + + // char test[11] = "abcdefghijk"; + // char *t2 = &test[3]; + // uart_sendlinek("abs_path : %s\n", test); + // uart_sendlinek("abs_path : %s\n", t2); + // t2 = &test[5]; + // uart_sendlinek("abs_path : %s\n", t2); + + return 0; +} + +int do_cmd_cd(int argc, char **argv) +{ + char *filepath; + if (argc == 1) + { + filepath = argv[0]; + } + else + { + puts("Too many arguments\r\n"); + return -1; + } + vfs_cd(filepath); + return 0; +} \ No newline at end of file diff --git a/lab7/kernel/src/signal.c b/lab7/kernel/src/signal.c new file mode 100644 index 000000000..454315f6e --- /dev/null +++ b/lab7/kernel/src/signal.c @@ -0,0 +1,90 @@ +#include "signal.h" +#include "syscall.h" +#include "sched.h" +#include "memory.h" +#include "mmu.h" + +extern thread_t *curr_thread; + +/** + ( ) + [Signal] [UserProcess] ( [ Registered Signal Handler ] ) [UserProcess] + | \ ( / \ ) / + | \ ( / \ ) / +-------|--------------------[SystemCall]-------------------------------------(-----------------/---------------------------------\----------------------)--/--------------- + | \ [Signal Check] (-> \ ) / + V \ / ^ ( \ \ )/ + [Job Pending] [Exception Handler] | ( \ [ Default Signal Handler ]-------- [Exception Handler]) + | | ( ) + --------------------- ( CONTENT SWITCHING FOR SIGNAL HANDLER ) + +**/ + +void check_signal(trapframe_t *tpf) +{ + if (curr_thread->signal_is_checking) + return; + lock(); + // Prevent nested running signal handler. No need to handle + curr_thread->signal_is_checking = 1; + unlock(); + for (int i = 0; i <= SIGNAL_MAX; i++) + { + store_context(&curr_thread->signal_savedContext); + if (curr_thread->sigcount[i] > 0) + { + lock(); + curr_thread->sigcount[i]--; + unlock(); + run_signal(tpf, i); + } + } + lock(); + curr_thread->signal_is_checking = 0; + unlock(); +} + +void run_signal(trapframe_t *tpf, int signal) +{ + curr_thread->curr_signal_handler = curr_thread->signal_handler[signal]; + + // run default handler in kernel + if (curr_thread->curr_signal_handler == signal_default_handler) + { + signal_default_handler(); + return; + } + + // run registered handler in userspace + // char *temp_signal_userstack = kmalloc(USTACK_SIZE); + // asm("msr elr_el1, %0\n\t" + // "msr sp_el0, %1\n\t" + // "msr spsr_el1, %2\n\t" + // "eret\n\t" ::"r"(signal_handler_wrapper), + // "r"(temp_signal_userstack + USTACK_SIZE), + // "r"(tpf->spsr_el1)); + + asm("msr elr_el1, %0\n\t" + "msr sp_el0, %1\n\t" + "msr spsr_el1, %2\n\t" + "mov x0, %3\n\t" + "eret\n\t" ::"r"(USER_SIGNAL_WRAPPER_VA + ((size_t)signal_handler_wrapper % 0x1000)), + "r"(tpf->sp_el0), + "r"(tpf->spsr_el1), + "r"(curr_thread->curr_signal_handler)); +} + +void signal_handler_wrapper() +{ + //(curr_thread->curr_signal_handler)(); + // system call sigreturn + // uart_sendlinek("signal_handler_wrapper\n"); + asm("blr x0\n\t" + "mov x8,50\n\t" + "svc 0\n\t"); +} + +void signal_default_handler() +{ + kill(0, curr_thread->pid); +} diff --git a/lab7/kernel/src/stdio.c b/lab7/kernel/src/stdio.c new file mode 100644 index 000000000..a1909d4b7 --- /dev/null +++ b/lab7/kernel/src/stdio.c @@ -0,0 +1,121 @@ +#include "stdio.h" +#include "uart1.h" +#include "vfs.h" +#include "sched.h" + +extern thread_t *curr_thread; + +char getchar() +{ + char c[1]; + stdio_op(stdin, c, 1); + return c[0] == '\r' ? '\n' : c[0]; +} + +void putchar(char c) +{ + char cp[2] = {c,'\0'}; + stdio_op(stdout, cp, 1); +} + +void puts(const char *s) +{ + while (*s) + putchar(*s++); +} + +void Readfile(char *str, int size) +{ + while (size--) + { + putchar(*str++); + } +} + +// Function to print an integer to the UART +void put_int(int num) +{ + // Handle the case when the number is 0 + if (num == 0) + { + putchar('0'); + return; + } + + // Temporary array to store the reversed digits as characters + char temp[12]; // Assuming int can have at most 10 digits + int idx = 0; + + // Handle negative numbers + if (num < 0) + { + putchar('-'); + num = -num; + } + + // Convert the number to characters and store in the temporary array in reverse order + while (num > 0) + { + temp[idx++] = (char)(num % 10 + '0'); + num /= 10; + } + + // Reverse output the character digits + while (idx > 0) + { + putchar(temp[--idx]); + } +} + +void put_hex(unsigned int num) +{ + unsigned int hex; + int index = 28; + puts("0x"); + while (index >= 0) + { + hex = (num >> index) & 0xF; + hex += hex > 9 ? 0x37 : 0x30; + putchar(hex); + index -= 4; + } +} + +// A simple atoi() function +int atoi(char *str) +{ + // Initialize result + int res = 0; + + // Iterate through all characters + // of input string and update result + // take ASCII character of corresponding digit and + // subtract the code from '0' to get numerical + // value and multiply res by 10 to shuffle + // digits left to update running total + for (int i = 0; str[i] != '\0'; ++i) + { + if (str[i] > '9' || str[i] < '0') + return res; + res = res * 10 + str[i] - '0'; + } + + // return result. + return res; +} + +int fake_log2(unsigned long long n) +{ + int val = 0; + while (n >>= 1) + val++; + return val; +} + +void delay(int r) +{ + while (r--) + { + asm volatile("nop"); + } +} diff --git a/lab7/kernel/src/string.c b/lab7/kernel/src/string.c new file mode 100644 index 000000000..0118ebf28 --- /dev/null +++ b/lab7/kernel/src/string.c @@ -0,0 +1,242 @@ +#include "string.h" + +size_t strlen(const char *str) +{ + size_t count = 0; + while ((unsigned char)*str++) + count++; + return count; +} + +int strcmp(const char *p1, const char *p2) +{ + const unsigned char *s1 = (const unsigned char *)p1; + const unsigned char *s2 = (const unsigned char *)p2; + unsigned char c1, c2; + + do + { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0') + return c1 - c2; + } while (c1 == c2); + return c1 - c2; +} + +int strncmp(const char *s1, const char *s2, unsigned long long n) +{ + unsigned char c1 = '\0'; + unsigned char c2 = '\0'; + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + } while (--n4 > 0); + n &= 3; + } + while (n > 0) + { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + n--; + } + return c1 - c2; +} + +char *strcpy(char *dest, const char *src) +{ + while ((*dest++ = *src++)) + ; + return dest; +} + +char *strncpy(char *dest, const char *src, unsigned long long n) +{ + // for (int i = 0; i < n ; i++) { + // dest[i] = src[i]; + // } + + while (n-- && (*dest++ = *src++) ) + ; + return dest; +} + +char *strcat(char *dest, const char *src) +{ + strcpy(dest + strlen(dest), src); + return dest; +} + +unsigned int vsprintf(char *dst, char *fmt, __builtin_va_list args) +{ + long int arg; + int len, sign, i; + char *p, *orig = dst, tmpstr[19]; + + // failsafes + if (dst == (void *)0 || fmt == (void *)0) + { + return 0; + } + + // main loop + arg = 0; + while (*fmt) + { + if (dst - orig > VSPRINT_MAX_BUF_SIZE - 0x10) + { + return -1; + } + // argument access + if (*fmt == '%') + { + fmt++; + // literal % + if (*fmt == '%') + { + goto put; + } + len = 0; + // size modifier + while (*fmt >= '0' && *fmt <= '9') + { + len *= 10; + len += *fmt - '0'; + fmt++; + } + // skip long modifier + if (*fmt == 'l') + { + fmt++; + } + // character + if (*fmt == 'c') + { + arg = __builtin_va_arg(args, int); + *dst++ = (char)arg; + fmt++; + continue; + } + else + // decimal number + if (*fmt == 'd') + { + arg = __builtin_va_arg(args, int); + // check input + sign = 0; + if ((int)arg < 0) + { + arg *= -1; + sign++; + } + if (arg > 99999999999999999L) + { + arg = 99999999999999999L; + } + // convert to string + i = 18; + tmpstr[i] = 0; + do + { + tmpstr[--i] = '0' + (arg % 10); + arg /= 10; + } while (arg != 0 && i > 0); + if (sign) + { + tmpstr[--i] = '-'; + } + if (len > 0 && len < 18) + { + while (i > 18 - len) + { + tmpstr[--i] = ' '; + } + } + p = &tmpstr[i]; + goto copystring; + } + else if (*fmt == 'x') + { + arg = __builtin_va_arg(args, long int); + i = 16; + tmpstr[i] = 0; + do + { + char n = arg & 0xf; + tmpstr[--i] = n + (n > 9 ? 0x37 : 0x30); + arg >>= 4; + } while (arg != 0 && i > 0); + if (len > 0 && len <= 16) + { + while (i > 16 - len) + { + tmpstr[--i] = '0'; + } + } + p = &tmpstr[i]; + goto copystring; + } + else if (*fmt == 's') + { + p = __builtin_va_arg(args, char *); + copystring: + if (p == (void *)0) + { + p = "(null)"; + } + while (*p) + { + *dst++ = *p++; + } + } + } + else + { + put: + *dst++ = *fmt; + } + fmt++; + } + *dst = 0; + return dst - orig; +} + +void *memset(void *s, int c, size_t n) +{ + char *start = s; + for (size_t i = 0; i < n; i++) + { + start[i] = c; + } + + return s; +} + +char *memcpy(void *dest, const void *src, unsigned long long len) +{ + char *d = dest; + const char *s = src; + while (len--) + *d++ = *s++; + return dest; +} \ No newline at end of file diff --git a/lab7/kernel/src/syscall.c b/lab7/kernel/src/syscall.c new file mode 100644 index 000000000..71f4d67a6 --- /dev/null +++ b/lab7/kernel/src/syscall.c @@ -0,0 +1,352 @@ +#include "bcm2837/rpi_mbox.h" +#include "syscall.h" +#include "sched.h" +#include "uart1.h" +#include "stdio.h" +#include "exception.h" +#include "memory.h" +#include "mbox.h" +#include "signal.h" +#include "string.h" + +#include "debug.h" +#include "cpio.h" +#include "dtb.h" +#include "mmu.h" + +extern void *CPIO_DEFAULT_START; +extern thread_t *curr_thread; +extern thread_t threads[PIDMAX + 1]; + +// trap is like a shared buffer for user space and kernel space +// Because general-purpose registers are used for both arguments and return value, +// We may receive the arguments we need, and overwrite them with return value. + +int getpid(trapframe_t *tpf) +{ + // uart_sendlinek("this is getpid"); + tpf->x0 = curr_thread->pid; + return curr_thread->pid; +} + +size_t uartread(trapframe_t *tpf, char buf[], size_t size) +{ + int i = 0; + stdio_op(stdin, buf, size); + tpf->x0 = i; + return i; +} + +size_t uartwrite(trapframe_t *tpf, const char buf[], size_t size) +{ + int i = 0; + char *cptr = buf; + stdio_op(stdout, buf, size); + tpf->x0 = i; + return i; +} + +// In this lab, you won’t have to deal with argument passing +int exec(trapframe_t *tpf, const char *name, char *const argv[]) +{ + lock(); + mmu_del_vma(curr_thread); + INIT_LIST_HEAD(&curr_thread->vma_list); + + // use virtual file system + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, name); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + + // uart_sendlinek("file name : %s\n", name); + // uart_sendlinek("curr_working_dir : %s\n", curr_thread->curr_working_dir); + // uart_sendlinek("abs_path : %s\n", abs_path); + + struct vnode *target_file; + if (vfs_lookup(abs_path, &target_file) != 0) + { + WARING("File : %s Does not Exit!!", abs_path); + return 0; + }; + curr_thread->datasize = target_file->f_ops->getsize(target_file); + uart_sendlinek("datasize : %d\n", curr_thread->datasize); + + // curr_thread->data = kmalloc(curr_thread->datasize > PAGESIZE ? curr_thread->datasize : PAGESIZE); + curr_thread->data = kmalloc(curr_thread->datasize); + curr_thread->stack_alloced_ptr = kmalloc(USTACK_SIZE); + + // data copy + memcpy(curr_thread->signal_handler, curr_thread->signal_handler, SIGNAL_MAX * 8); + struct file *f; + vfs_open(abs_path, 0, &f); + vfs_read(f, curr_thread->data, curr_thread->datasize); + vfs_close(f); + + // clean vma & page_tables + asm("dsb ish\n\t"); // ensure write has completed + mmu_free_page_tables(curr_thread->context.pgd, 0); + memset((void *)PHYS_TO_KERNEL_VIRT(curr_thread->context.pgd), 0, 0x1000); + asm("tlbi vmalle1is\n\t" // invalidate all TLB entries + "dsb ish\n\t" // ensure completion of TLB invalidatation + "isb\n\t"); // clear pipeline + mmu_del_vma(curr_thread); + + // new vma + mmu_add_vma(curr_thread, USER_DATA_BASE, curr_thread->datasize, (size_t)KERNEL_VIRT_TO_PHYS(curr_thread->data), 0b111, 1, USER_DATA); + mmu_add_vma(curr_thread, USER_STACK_BASE - USTACK_SIZE, USTACK_SIZE, (size_t)KERNEL_VIRT_TO_PHYS(curr_thread->stack_alloced_ptr), 0b011, 1, USER_STACK); + mmu_add_vma(curr_thread, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0, PERIPHERAL); + mmu_add_vma(curr_thread, USER_SIGNAL_WRAPPER_VA, 0x1000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(signal_handler_wrapper), 0x1000), 0b101, 0, USER_SIGNAL_WRAPPER); + mmu_add_vma(curr_thread, USER_EXEC_WRAPPER_VA, 0x2000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(exec_wrapper), PAGESIZE), 0b101, 0, USER_EXEC_WRAPPER); + + tpf->elr_el1 = USER_DATA_BASE; + tpf->sp_el0 = USER_STACK_BASE - STACK_BASE_OFFSET; + tpf->x0 = 0; + unlock(); + return 0; +} + +// extern unsigned long long int lock_counter; +int fork(trapframe_t *tpf) +{ + lock(); + thread_t *newt = thread_create(curr_thread->data); + // mmu_set_PTE_readonly(curr_thread->context.pgd,0); + // mmu_pagetable_copy(newt->context.pgd,curr_thread->context.pgd,0); + // uart_sendlinek("fork\n"); + memcpy(newt->signal_handler, curr_thread->signal_handler, SIGNAL_MAX * 8); + memcpy(newt->stack_alloced_ptr, curr_thread->kernel_stack_alloced_ptr, USTACK_SIZE); + memcpy(newt->kernel_stack_alloced_ptr, curr_thread->kernel_stack_alloced_ptr, KSTACK_SIZE); + memcpy(newt->curr_working_dir, curr_thread->curr_working_dir,MAX_PATH_NAME+1); + + newt->datasize = curr_thread->datasize; + newt->data = kmalloc(newt->datasize); + memcpy(newt->data,curr_thread->data,newt->datasize); + //newt->curr_working_dir = curr_thread->curr_working_dir; + // memcpy(newt->file_descriptors_table, curr_thread->file_descriptors_table, MAX_FD * 8); // <------------------------------------------------ + mmu_add_vma(newt, USER_DATA_BASE, newt->datasize, (size_t)KERNEL_VIRT_TO_PHYS(newt->data), 0b111, 1, USER_DATA); + mmu_add_vma(newt, USER_STACK_BASE - USTACK_SIZE, USTACK_SIZE, (size_t)KERNEL_VIRT_TO_PHYS(newt->stack_alloced_ptr), 0b011, 1, USER_STACK); + mmu_add_vma(newt, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0, PERIPHERAL); + mmu_add_vma(newt, USER_SIGNAL_WRAPPER_VA, 0x1000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(signal_handler_wrapper), 0x1000), 0b101, 0, USER_SIGNAL_WRAPPER); + mmu_add_vma(newt, USER_EXEC_WRAPPER_VA, 0x2000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(exec_wrapper), PAGESIZE), 0b101, 0, USER_EXEC_WRAPPER); + + int parent_pid = curr_thread->pid; + + store_context(get_current()); + // for child + if (parent_pid != curr_thread->pid) + { + goto child; + } + + // 除了PGD以外的context都複製。 + void *temp_pgd = newt->context.pgd; + newt->context = curr_thread->context; + newt->context.pgd = temp_pgd; + //memcpy(newt->context.pgd,curr_thread->context.pgd,PAGESIZE); + + newt->context.fp += newt->kernel_stack_alloced_ptr - curr_thread->kernel_stack_alloced_ptr; // move fp + newt->context.sp += newt->kernel_stack_alloced_ptr - curr_thread->kernel_stack_alloced_ptr; // move kernel sp + + unlock(); + + tpf->x0 = newt->pid; + return newt->pid; + +child: + tpf->x0 = 0; + return 0; +} + +void exit(trapframe_t *tpf, int status) +{ + thread_exit(); + while (1) + schedule(); +} + +int syscall_mbox_call(trapframe_t *tpf, unsigned char ch, unsigned int *mbox) +{ + lock(); + + unsigned int size_of_mbox = mbox[0]; + memcpy((char *)pt, mbox, size_of_mbox); + mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt)); + memcpy(mbox, (char *)pt, size_of_mbox); + + // tpf->x0 = 8; + unlock(); + return 0; +} + +// only need to implement the anonymous page mapping in this Lab. +void *mmap(trapframe_t *tpf, void *addr, size_t len, int prot, int flags, int fd, int file_offset) +{ + len = ALIGN_UP(len, PAGESIZE); + unsigned long base_user_va = ALIGN_DOWN((unsigned long)addr, PAGESIZE); + uart_sendlinek("+\n"); + uart_sendlinek("| User request new vma base vitural address: 0x%x\n", (unsigned long)addr); + uart_sendlinek("| Aligned to PAGESIZE: 0x%x\n", base_user_va); + uart_sendlinek("| User request new vma size: 0x%x\n", len); + uart_sendlinek("| Exec, Write, Read : 0x%d\n", prot); + uart_sendlinek("+\n"); + + // Req #2 check if overlap + vm_area_struct_t *the_area_ptr = check_vma_overlap(curr_thread, base_user_va, (unsigned long)len); + // take as a hint to decide new region's start address + if (the_area_ptr) + { + WARING("Vitural Memory Area Overlap\n"); + WARING("Find another vma base vitural address\n"); + tpf->x0 = (unsigned long)mmap(tpf, (void *)(the_area_ptr->virt_addr + the_area_ptr->area_size), len, prot, flags, fd, file_offset); + return (void *)tpf->x0; + } + // create new valid region, map and set the page attributes (prot) + mmu_add_vma(curr_thread, base_user_va, len, KERNEL_VIRT_TO_PHYS((unsigned long)kmalloc(len)), prot, 1, UNKNOW_AREA); + tpf->x0 = base_user_va; + return (void *)tpf->x0; +} + +void kill(trapframe_t *tpf, int pid) +{ + if (pid < 0 || pid >= PIDMAX || !threads[pid].isused) + return; + + lock(); + + if (pid == curr_thread->pid) + { + uart_sendlinek("[!] you kill youself !! \n"); + thread_exit(); + unlock(); + while (1) + schedule(); + } + else + { + threads[pid].iszombie = 1; + unlock(); + } + schedule(); +} + +void signal_register(int signal, void (*handler)()) +{ + if (signal > SIGNAL_MAX || signal < 0) + return; + // uart_sendlinek("handler : 0x%x\n", handler); + curr_thread->signal_handler[signal] = handler; +} + +void signal_kill(int pid, int signal) +{ + if (pid > PIDMAX || pid < 0 || !threads[pid].isused) + return; + lock(); + threads[pid].sigcount[signal]++; + unlock(); +} + +void sigreturn(trapframe_t *tpf) +{ + // unsigned long signal_ustack = tpf->sp_el0 % USTACK_SIZE == 0 ? tpf->sp_el0 - USTACK_SIZE : tpf->sp_el0 & (~(USTACK_SIZE - 1)); + // kfree((char *)signal_ustack); + load_context(&curr_thread->signal_savedContext); +} + +void syscall_unlock(trapframe_t *tpf) +{ + unlock(); +} + +void syscall_lock(trapframe_t *tpf) +{ + lock(); +} + +char *get_file_start(char *thefilepath) +{ + int FLAG_getfile = 0; + char *filepath; + char *filedata; + unsigned int filesize; + // struct cpio_newc_header *header_pointer = CPIO_DEFAULT_START; + + CPIO_for_each(&filepath, &filesize, &filedata) + { + if (strcmp(thefilepath, filepath) == 0) + { + FLAG_getfile = 1; + return filedata; + } + } + + if (!FLAG_getfile) + { + uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + } + + // while (header_pointer != 0) + // { + // int error = cpio_newc_parse_header(header_pointer, &filepath, &filesize, &filedata, &header_pointer); + // //if parse header error + // if (error) + // { + // uart_sendlinek("error"); + // break; + // } + + // if (strcmp(thefilepath, filepath) == 0) + // { + // return filedata; + // } + + // //if this is TRAILER!!! (last of file) + // if (header_pointer == 0) + // uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + // } + + return 0; +} + +unsigned int get_file_size(char *thefilepath) +{ + int FLAG_getfile = 0; + char *filepath; + char *filedata; + unsigned int filesize; + + CPIO_for_each(&filepath, &filesize, &filedata) + { + if (strcmp(thefilepath, filepath) == 0) + { + FLAG_getfile = 1; + return filesize; + } + } + + if (!FLAG_getfile) + { + uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + } + + // while (header_pointer != 0) + // { + // int error = cpio_newc_parse_header(header_pointer, &filepath, &filesize, &filedata, &header_pointer); + // // if parse header error + // if (error) + // { + // uart_sendlinek("error"); + // break; + // } + + // if (strcmp(thefilepath, filepath) == 0) + // { + // return filesize; + // } + + // // if this is TRAILER!!! (last of file) + // if (header_pointer == 0) + // uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + // } + return 0; +} diff --git a/lab7/kernel/src/syscall_fs.c b/lab7/kernel/src/syscall_fs.c new file mode 100644 index 000000000..ea8a4e34e --- /dev/null +++ b/lab7/kernel/src/syscall_fs.c @@ -0,0 +1,146 @@ +#include "bcm2837/rpi_mbox.h" +#include "vfs.h" +#include "string.h" +#include "sched.h" +#include "exception.h" +#include "uart1.h" +#include "vfs_dev_framebuffer.h" +#include "stdio.h" + +extern void *CPIO_DEFAULT_START; +extern thread_t *curr_thread; +extern thread_t threads[PIDMAX + 1]; + +int open(trapframe_t *tpf, const char *pathname, int flags) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, pathname); + + uart_sendlinek("file name : %s\n", pathname); + uart_sendlinek("curr_working_dir : %s\n", curr_thread->curr_working_dir); + uart_sendlinek("abs_path : %s\n", abs_path); + + // update abs_path + get_absolute_path(abs_path, curr_thread->curr_working_dir); + for (int i = 0; i < MAX_FD; i++) + { + // find a usable fd + if (!curr_thread->file_descriptors_table[i]) + { + // uart_sendlinek("i : %d\n", i); + // while (1) + // ; + + if (vfs_open(abs_path, flags, &curr_thread->file_descriptors_table[i]) != 0) + { + break; + } + + tpf->x0 = i; + return i; + } + } + + tpf->x0 = -1; + return -1; +} + +int close(trapframe_t *tpf, int fd) +{ + // find an opened fd + if (curr_thread->file_descriptors_table[fd]) + { + vfs_close(curr_thread->file_descriptors_table[fd]); + curr_thread->file_descriptors_table[fd] = 0; + tpf->x0 = 0; + return 0; + } + + tpf->x0 = -1; + return -1; +} + +long write(trapframe_t *tpf, int fd, const void *buf, unsigned long count) +{ + // uart_sendlinek("fd : %d\n", fd); + if (curr_thread->file_descriptors_table[fd]) + { + tpf->x0 = vfs_write(curr_thread->file_descriptors_table[fd], buf, count); + return tpf->x0; + } + tpf->x0 = -1; + return tpf->x0; +} + +long read(trapframe_t *tpf, int fd, void *buf, unsigned long count) +{ + if (curr_thread->file_descriptors_table[fd]) + { + tpf->x0 = vfs_read(curr_thread->file_descriptors_table[fd], buf, count); + return tpf->x0; + } + tpf->x0 = -1; + return tpf->x0; +} + +int mkdir(trapframe_t *tpf, const char *pathname, unsigned mode) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, pathname); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + tpf->x0 = vfs_mkdir(abs_path); + return tpf->x0; +} + +int mount(trapframe_t *tpf, const char *src, const char *target, const char *filesystem, unsigned long flags, const void *data) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, target); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + + tpf->x0 = vfs_mount(abs_path, filesystem); + return tpf->x0; +} + +int chdir(trapframe_t *tpf, const char *path) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, path); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + strcpy(curr_thread->curr_working_dir, abs_path); + + return 0; +} + +long lseek64(trapframe_t *tpf, int fd, long offset, int whence) +{ + if (whence == SEEK_SET) // used for dev_framebuffer + { + curr_thread->file_descriptors_table[fd]->f_pos = offset; + tpf->x0 = offset; + } + else // other is not supported + { + tpf->x0 = -1; + } + + return tpf->x0; +} +extern unsigned int height; +extern unsigned int isrgb; +extern unsigned int pitch; +extern unsigned int width; +int ioctl(trapframe_t *tpf, int fb, unsigned long request, void *info) +{ + if (request == 0) // used for get info (SPEC) + { + struct framebuffer_info *fb_info = info; + fb_info->height = height; + fb_info->isrgb = isrgb; + fb_info->pitch = pitch; + fb_info->width = width; + } + + tpf->x0 = 0; + return tpf->x0; +} \ No newline at end of file diff --git a/lab7/kernel/src/timer.c b/lab7/kernel/src/timer.c new file mode 100644 index 000000000..061bbb05d --- /dev/null +++ b/lab7/kernel/src/timer.c @@ -0,0 +1,177 @@ +#include "timer.h" +#include "uart1.h" +#include "memory.h" +#include "string.h" +#include "exception.h" +#include + +#define STR(x) #x +#define XSTR(s) STR(s) + +struct list_head *timer_event_list; // first head has nothing, store timer_event_t after it + +void timer_list_init() +{ + uint64_t tmp; + asm volatile("mrs %0, cntkctl_el1" : "=r"(tmp)); + tmp |= 1; + asm volatile("msr cntkctl_el1, %0" ::"r"(tmp)); + + timer_event_list = allocator(sizeof(list_head_t)); + INIT_LIST_HEAD(timer_event_list); +} + +void core_timer_enable() +{ + __asm__ __volatile__( + "mov x1, 1\n\t" + "msr cntp_ctl_el0, x1\n\t" // cntp_ctl_el0[0]: enable, Control register for the EL1 physical timer. + // cntp_tval_el0: Holds the timer value for the EL1 physical timer + "mov x2, 2\n\t" + "ldr x1, =" XSTR(CORE0_TIMER_IRQ_CTRL) "\n\t" + "str w2, [x1]\n\t" // QA7_rev3.4.pdf: Core0 Timer IRQ allows Non-secure physical timer(nCNTPNSIRQ) + ); +} + +void core_timer_disable() +{ + __asm__ __volatile__( + "mov x2, 0\n\t" + "ldr x1, =" XSTR(CORE0_TIMER_IRQ_CTRL) "\n\t" + "str w2, [x1]\n\t" // QA7_rev3.4.pdf: Mask all timer interrupt + ); +} + +void core_timer_handler() +{ + lock(); + //uart_sendlinek("\nThis is core_timer_handler\n"); + if (list_empty(timer_event_list)) + { + uart_sendlinek("\ntimer_event_list is empty\n"); + set_core_timer_interrupt(10000); // disable timer interrupt (set a very big value) + unlock(); + return; + } + timer_event_callback((timer_event_t *)timer_event_list->next); // do callback and set new interrupt + unlock(); +} + +void timer_event_callback(timer_event_t *timer_event) +{ + list_del_entry((struct list_head *)timer_event); // delete the event in queue + // free(timer_event->args); // free the event's space + // free(timer_event); + ((void (*)(char *))timer_event->callback)(timer_event->args); // call the event + + kfree(timer_event->args); + kfree(timer_event); + + // set queue linked list to next time event if it exists + if (!list_empty(timer_event_list)) + { + set_core_timer_interrupt_by_tick(((timer_event_t *)timer_event_list->next)->interrupt_time); + } + else + { + set_core_timer_interrupt(10000); // disable timer interrupt (set a very big value) + } +} + +void timer_set2sAlert(char *str) +{ + unsigned long long cntpct_el0; + __asm__ __volatile__("mrs %0, cntpct_el0\n\t" : "=r"(cntpct_el0)); // tick auchor + unsigned long long cntfrq_el0; + __asm__ __volatile__("mrs %0, cntfrq_el0\n\t" : "=r"(cntfrq_el0)); // tick frequency + + uart_sendlinek("\n"); + uart_sendlinek("[Interrupt start]\n"); + for (int i = 0; i < 1000000000; i++) + ; + uart_sendlinek("[Interrupt finish]\n"); + + // uart_sendlinek("[Interrupt][el1_irq][%s] %d seconds after booting\n", str, cntpct_el0 / cntfrq_el0); + + add_timer(timer_set2sAlert, 2, "2sAlert",setSecond); +} + +void add_timer(void *callback, unsigned long long timeout, char *args, int inTickFormat) +{ + timer_event_t *the_timer_event = kmalloc(sizeof(timer_event_t)); // free by timer_event_callback + // store all the related information in timer_event + the_timer_event->args = kmalloc(strlen(args) + 1); + strcpy(the_timer_event->args, args); + + if (inTickFormat == 0) + { + the_timer_event->interrupt_time = get_tick_plus_s(timeout); // store interrupt time into timer_event + } + else + { + the_timer_event->interrupt_time = get_tick_plus_s(0) + timeout; + } + + the_timer_event->callback = callback; + INIT_LIST_HEAD(&the_timer_event->listhead); + + // add the timer_event into timer_event_list (sorted) + struct list_head *curr; + lock(); + list_for_each(curr, timer_event_list) + { + if (((timer_event_t *)curr)->interrupt_time > the_timer_event->interrupt_time) + { + list_add(&the_timer_event->listhead, curr->prev); // add this timer at the place just before the bigger one (sorted) + break; + } + } + // if the timer_event is the biggest, run this code block + if (list_is_head(curr, timer_event_list)) + { + list_add_tail(&the_timer_event->listhead, timer_event_list); + } + // set interrupt to first event + set_core_timer_interrupt_by_tick(((timer_event_t *)timer_event_list->next)->interrupt_time); + unlock(); +} + +// get cpu tick add some second +unsigned long long get_tick_plus_s(unsigned long long second) +{ + unsigned long long cntpct_el0 = 0; + __asm__ __volatile__("mrs %0, cntpct_el0\n\t" : "=r"(cntpct_el0)); // tick auchor + unsigned long long cntfrq_el0 = 0; + __asm__ __volatile__("mrs %0, cntfrq_el0\n\t" : "=r"(cntfrq_el0)); // tick frequency + return (cntpct_el0 + cntfrq_el0 * second); +} + +// set timer interrupt time to [expired_time] seconds after now (relatively) +void set_core_timer_interrupt(unsigned long long expired_time) +{ + __asm__ __volatile__( + "mrs x1, cntfrq_el0\n\t" // cntfrq_el0 -> frequency of the timer + "mul x1, x1, %0\n\t" // cntpct_el0 = cntfrq_el0 * seconds: relative timer to cntfrq_el0 + "msr cntp_tval_el0, x1\n\t" // Set expired time to cntp_tval_el0, which stores time value of EL1 physical timer. + : "=r"(expired_time)); +} + +// directly set timer interrupt time to a cpu tick (directly) +void set_core_timer_interrupt_by_tick(unsigned long long tick) +{ + __asm__ __volatile__( + "msr cntp_cval_el0, %0\n\t" // cntp_cval_el0 -> absolute timer + : "=r"(tick)); +} + +// get timer pending queue size +int timer_list_get_size() +{ + int r = 0; + struct list_head *curr; + list_for_each(curr, timer_event_list) + { + r++; + } + return r; +} diff --git a/lab7/kernel/src/uart1.c b/lab7/kernel/src/uart1.c new file mode 100644 index 000000000..30e7bae36 --- /dev/null +++ b/lab7/kernel/src/uart1.c @@ -0,0 +1,177 @@ +#include "bcm2837/rpi_gpio.h" +#include "bcm2837/rpi_uart1.h" +#include "bcm2837/rpi_irq.h" +#include "uart1.h" +#include "string.h" +#include "exception.h" +#include "vfs.h" + +// implement first in first out buffer with a read index and a write index +static char uart_tx_buffer[VSPRINT_MAX_BUF_SIZE]; +unsigned int uart_tx_buffer_widx = 0; // write index +unsigned int uart_tx_buffer_ridx = 0; // read index +static char uart_rx_buffer[VSPRINT_MAX_BUF_SIZE]; +unsigned int uart_rx_buffer_widx = 0; +unsigned int uart_rx_buffer_ridx = 0; + +void uart_init() +{ + register unsigned int selector; + + /* initialize UART */ + *AUX_ENABLES = 1; // enable UART1 + *AUX_MU_CNTL_REG = 0; // disable TX/RX + + /* configure UART */ + *AUX_MU_IER_REG = 0; // disable interrupt + *AUX_MU_LCR_REG = 3; // 8 bit data size + *AUX_MU_MCR_REG = 0; // disable flow control + *AUX_MU_BAUD_REG = 270; // 115200 baud rate + + /* map UART1 to GPIO pins */ + selector = *GPFSEL1; + selector &= ~(7 << 12); // clean gpio14, and (11 111 111 111 111 111 000 111 111 111 111)2 + selector |= 2 << 12; // set gpio14 to alt5 + selector &= ~(7 << 15); // clean gpio15, and (11 111 111 111 111 000 111 111 111 111 111)2 + selector |= 2 << 15; // set gpio15 to alt5 + *GPFSEL1 = selector; + + /* enable pin 14, 15 - ref: Page 101 */ + *GPPUD = 0; + selector = 150; + while (selector--) + { + asm volatile("nop"); + } + *GPPUDCLK0 = (1 << 14) | (1 << 15); + selector = 150; + while (selector--) + { + asm volatile("nop"); + } + *GPPUDCLK0 = 0; + + *AUX_MU_CNTL_REG = 3; +} + +void uart_flush_FIFO() +{ + // On write: + // Writing with bit 1 set will clear the receive FIFO + // Writing with bit 2 set will clear the transmit FIFOF + *AUX_MU_IIR_REG |= 6; +} + +char uart_recv() +{ + char r; + while (!(*AUX_MU_LSR_REG & 0x01)) + ; + r = (char)(*AUX_MU_IO_REG); + return r; +} + +void uart_send(unsigned int c) +{ + while (!(*AUX_MU_LSR_REG & 0x20)) + ; + *AUX_MU_IO_REG = c; +} + +// AUX_MU_IER_REG -> BCM2837-ARM-Peripherals.pdf - Pg.12 +void uart_interrupt_enable() +{ + *AUX_MU_IER_REG |= 1; // enable read interrupt + *AUX_MU_IER_REG |= 2; // enable write interrupt + *ENABLE_IRQS_1 |= 1 << 29; // Pg.112 +} + +void uart_interrupt_disable() +{ + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + *AUX_MU_IER_REG &= ~(2); // disable write interrupt +} + +// scanf +void uart_r_irq_handler() +{ + if ((uart_rx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_rx_buffer_ridx) + { + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + return; + } + uart_rx_buffer[uart_rx_buffer_widx++] = uart_recv(); + if (uart_rx_buffer_widx >= VSPRINT_MAX_BUF_SIZE) + uart_rx_buffer_widx = 0; + *AUX_MU_IER_REG |= 1; +} + +// printf +void uart_w_irq_handler() +{ + if (uart_tx_buffer_ridx == uart_tx_buffer_widx) + { + *AUX_MU_IER_REG &= ~(2); // disable write interrupt + return; // buffer empty + } + uart_send(uart_tx_buffer[uart_tx_buffer_ridx++]); + if (uart_tx_buffer_ridx >= VSPRINT_MAX_BUF_SIZE) + uart_tx_buffer_ridx = 0; + *AUX_MU_IER_REG |= 2; // enable write interrupt +} + +// uart_async_getc read from buffer +// uart_r_irq_handler write to buffer then output +char uart_async_recv() +{ + *AUX_MU_IER_REG |= 1; // enable read interrupt + // do while if buffer empty + while (uart_rx_buffer_ridx == uart_rx_buffer_widx) + { + *AUX_MU_IER_REG |= 1; // enable read interrupt + } + lock(); + char r = uart_rx_buffer[uart_rx_buffer_ridx++]; + + if (uart_rx_buffer_ridx >= VSPRINT_MAX_BUF_SIZE) + uart_rx_buffer_ridx = 0; + unlock(); + return r; +} + +// uart_async_putc writes to buffer +// uart_w_irq_handler read from buffer then output +void uart_async_send(char c) +{ + // if buffer full, wait for uart_w_irq_handler + while ((uart_tx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_tx_buffer_ridx) + { + // uart_puts("buffer full\r\n"); + *AUX_MU_IER_REG |= 2; // enable write interrupt + } + lock(); + uart_tx_buffer[uart_tx_buffer_widx++] = c; + if (uart_tx_buffer_widx >= VSPRINT_MAX_BUF_SIZE) + uart_tx_buffer_widx = 0; // cycle pointer + unlock(); + *AUX_MU_IER_REG |= 2; // enable write interrupt +} + +int uart_sendlinek(char *fmt, ...) +{ + __builtin_va_list args; + __builtin_va_start(args, fmt); + char buf[VSPRINT_MAX_BUF_SIZE]; + + char *str = (char *)buf; + int count = vsprintf(str, fmt, args); + + while (*str) + { + if (*str == '\n') + uart_send('\r'); + uart_send(*str++); + } + __builtin_va_end(args); + return count; +} \ No newline at end of file diff --git a/lab7/kernel/src/vfs.c b/lab7/kernel/src/vfs.c new file mode 100644 index 000000000..832a88ab3 --- /dev/null +++ b/lab7/kernel/src/vfs.c @@ -0,0 +1,433 @@ +#include "vfs.h" +#include "vfs_tmpfs.h" +#include "vfs_initramfs.h" +#include "vfs_dev_uart.h" +#include "memory.h" +#include "string.h" +#include "uart1.h" +#include "sched.h" +#include "debug.h" +// #include "dev_framebuffer.h" + +struct mount *rootfs; +struct filesystem reg_fs[MAX_FS_REG]; +struct file_operations reg_dev[MAX_DEV_REG]; +extern thread_t *curr_thread; + +void rootfs_init() +{ + // tmpfs + int idx = register_tmpfs(); + rootfs = kmalloc(sizeof(struct mount)); + reg_fs[idx].setup_mount(®_fs[idx], rootfs); + + // initramfs + vfs_mkdir("/initramfs"); + register_initramfs(); + vfs_mount("/initramfs", "initramfs"); + + // // dev_fs + vfs_mkdir("/dev"); + int uart_id = init_dev_uart(); + vfs_mknod("/dev/uart", uart_id); + int framebuffer_id = init_dev_framebuffer(); + vfs_mknod("/dev/framebuffer", framebuffer_id); +} + +int register_filesystem(struct filesystem *fs) +{ + for (int i = 0; i < MAX_FS_REG; i++) + { + if (!reg_fs[i].name) + { + reg_fs[i].name = fs->name; + reg_fs[i].setup_mount = fs->setup_mount; + return i; + } + } + return -1; +} + +int vfs_lookup(const char *pathname, struct vnode **target) +{ + // if no path input, return root + if (strlen(pathname) == 0 || (!strcmp(&pathname[0], "/") && strlen(pathname) == 1)) + { + *target = rootfs->root; + // uart_sendlinek("path : %s is root \n", pathname); + return 0; + } + struct vnode *dirnode = rootfs->root; + char component_name[MAX_FILE_NAME + 1] = {}; + int c_idx = 0; + // deal with directory + for (int i = 1; i < strlen(pathname); i++) + { + if (pathname[i] == '/') + { + component_name[c_idx++] = 0; + // if fs's v_ops error, return -1 + if (dirnode->v_ops->lookup(dirnode, &dirnode, component_name) != 0) + return -1; + // redirect to mounted filesystem + while (dirnode->mount) + { + dirnode = dirnode->mount->root; + } + c_idx = 0; + } + else + { + component_name[c_idx++] = pathname[i]; + } + } + + // deal with file + component_name[c_idx++] = 0; + // if fs's v_ops error, return -1 + if (dirnode->v_ops->lookup(dirnode, &dirnode, component_name) != 0) + return -1; + // redirect to mounted filesystem + while (dirnode->mount) + { + dirnode = dirnode->mount->root; + } + // return file's vnode + *target = dirnode; + + return 0; +} + +int register_dev(struct file_operations *fo) +{ + for (int i = 0; i < MAX_FS_REG; i++) + { + if (!reg_dev[i].open) + { + // return unique id for the assigned device + reg_dev[i] = *fo; + return i; + } + } + return -1; +} + +struct filesystem *find_filesystem(const char *fs_name) +{ + for (int i = 0; i < MAX_FS_REG; i++) + { + if (strcmp(reg_fs[i].name, fs_name) == 0) + { + return ®_fs[i]; + } + } + return 0; +} + +int vfs_mount(const char *target, const char *filesystem) +{ + struct vnode *dirnode; + // search for the target filesystem + struct filesystem *fs = find_filesystem(filesystem); + if (!fs) + { + uart_sendlinek("vfs_mount cannot find filesystem\r\n"); + return -1; + } + + if (vfs_lookup(target, &dirnode) == -1) + { + uart_sendlinek("vfs_mount cannot find dir\r\n"); + return -1; + } + else + { + // mount fs on dirnode + dirnode->mount = kmalloc(sizeof(struct mount)); + fs->setup_mount(fs, dirnode->mount); + } + return 0; +} + +// file ops +int vfs_mkdir(const char *pathname) +{ + struct vnode *node; + if (vfs_lookup(pathname, &node) == 0) + { + WARING("Directory Exit!! : %s\n", pathname); + return 0; + } + + char dirname[MAX_PATH_NAME] = {}; // before add folder + char newdirname[MAX_PATH_NAME] = {}; // after add folder + + // search for last directory + int last_slash_idx = 0; + for (int i = 0; i < strlen(pathname); i++) + { + if (pathname[i] == '/') + { + last_slash_idx = i; + } + } + + memcpy(dirname, pathname, last_slash_idx); + strcpy(newdirname, pathname + last_slash_idx + 1); + + // create new directory if upper directory is found + // struct vnode *node; + if (vfs_lookup(dirname, &node) == 0) + { + // node is the old dir, &node is new dir + node->v_ops->mkdir(node, &node, newdirname); + return 0; + } + + uart_sendlinek("vfs_mkdir cannot find pathname"); + return -1; +} +// file ops +int vfs_open(const char *pathname, int flags, struct file **target) +{ + // 1. Lookup pathname + // 3. Create a new file if O_CREAT is specified in flags and vnode not found + // uart_sendlinek("\nhere!!!!!\n"); + struct vnode *node; + if (vfs_lookup(pathname, &node) != 0 && (flags & O_CREAT)) + { + // grep all of the directory path + int last_slash_idx = 0; + for (int i = 0; i < strlen(pathname); i++) + { + if (pathname[i] == '/') + { + last_slash_idx = i; + } + } + + char dirname[MAX_PATH_NAME + 1]; + strcpy(dirname, pathname); + dirname[last_slash_idx] = 0; + // update dirname to node + if (vfs_lookup(dirname, &node) != 0) + { + uart_sendlinek("cannot ocreate no dir name\r\n"); + return -1; + } + // create a new file node on node, &node is new file, 3rd arg is filename + node->v_ops->create(node, &node, pathname + last_slash_idx + 1); + *target = kmalloc(sizeof(struct file)); + // attach opened file on the new node + node->f_ops->open(node, target); + (*target)->flags = flags; + return 0; + } + else // 2. Create a new file handle for this vnode if found. + { + // attach opened file on the node + + *target = kmalloc(sizeof(struct file)); + node->f_ops->open(node, target); + (*target)->flags = flags; + return 0; + } + + // lookup error code shows if file exist or not or other error occurs + // 4. Return error code if fails + return -1; +} + +// file ops +int vfs_close(struct file *file) +{ + // 1. release the file handle + // 2. Return error code if fails + file->f_ops->close(file); + return 0; +} + +// file ops +int vfs_write(struct file *file, const void *buf, size_t len) +{ + // 1. write len byte from buf to the opened file. + // 2. return written size or error code if an error occurs. + return file->f_ops->write(file, buf, len); +} + +// file ops +int vfs_read(struct file *file, void *buf, size_t len) +{ + // 1. read min(len, readable size) byte to buf from the opened file. + // 2. block if nothing to read for FIFO type + // 2. return read size or error code if an error occurs. + return file->f_ops->read(file, buf, len); +} + +// for device operations only +int vfs_mknod(char* pathname, int id) +{ + struct file* f; + // create leaf and its file operations + vfs_open(pathname, O_CREAT, &f); + f->vnode->f_ops = ®_dev[id]; + vfs_close(f); + return 0; +} + +// void vfs_test() +// { +// // test read/write +// vfs_mkdir("/lll"); +// vfs_mkdir("/lll/ddd"); +// // test mount +// vfs_mount("/lll/ddd", "tmpfs"); + +// struct file* testfilew; +// struct file *testfiler; +// char testbufw[0x30] = "ABCDEABBBBBBDDDDDDDDDDD"; +// char testbufr[0x30] = {}; +// vfs_open("/lll/ddd/ggg", O_CREAT, &testfilew); +// vfs_open("/lll/ddd/ggg", O_CREAT, &testfiler); +// vfs_write(testfilew, testbufw, 10); +// vfs_read(testfiler, testbufr, 10); +// uart_sendline("%s",testbufr); + +// struct file *testfile_initramfs; +// vfs_open("/initramfs/get_simpleexec.sh", O_CREAT, &testfile_initramfs); +// vfs_read(testfile_initramfs, testbufr, 30); +// uart_sendline("%s", testbufr); +// } + +char *get_absolute_path(char *path, char *curr_working_dir) +{ + char absolute_path[MAX_PATH_NAME + 1] = {}; + int max_pathdeep = 10; + struct dir_path *ctmp = kmalloc(sizeof(struct dir_path) * max_pathdeep); + int deep = 0; + + if (path[0] == '/') + { + // uart_sendlinek("Input path is absolute_path: %s\n", path); + strcpy(absolute_path, path); + } + else + { + // uart_sendlinek("Input path is relative_path: %s\n", path); + strcpy(absolute_path, curr_working_dir); + if (strcmp(curr_working_dir, "/") != 0) + { + strcat(absolute_path, "/"); + } + strcat(absolute_path, path); + } + // uart_sendlinek("absolute_path: %s\n", absolute_path); + // uart_sendlinek("strlen of bsolute_path: %d\n", strlen(absolute_path)); + + int dir_namesize = 0; + for (int i = 0; i < strlen(absolute_path); i++) + { + dir_namesize++; + if (absolute_path[i + 1] == '/' || i + 1 == strlen(absolute_path)) + { + ctmp[deep].size = dir_namesize; + ctmp[deep].dir = &absolute_path[i + 1 - dir_namesize]; + dir_namesize = 0; + // deep ++; + // uart_sendlinek("ctmp[%d].dir : %s\n", deep, ctmp[deep].dir); + // uart_sendlinek("size : %d\n", ctmp[deep].size); + + if (!strncmp(ctmp[deep].dir, "/..", 3)) + { + // uart_sendlinek("Go back!!\n"); + deep > 0 ? deep-- : deep; + } + else if (!strncmp(ctmp[deep].dir, "/.", 2) || ctmp[deep].size <= 1) + { + // uart_sendlinek("Do Nothing!!\n"); + } + else + { + deep++; + } + } + } + + // uart_sendlinek("deep : %d\n", deep); + int n = 0; + char *cpath = &path[n]; + if (deep == 0) + { + // memset(path,0,MAX_PATH_NAME + 1); + strncpy(cpath, "/\0", 2); + kfree(ctmp); + // uart_sendlinek("absolute_path: %s\n", path); + return path; + } + + for (int i = 0; i < deep; i++) + { + strncpy(cpath, ctmp[i].dir, ctmp[i].size); + n += ctmp[i].size; + cpath = &path[n]; + strncpy(cpath, "\0", 1); + } + + // uart_sendlinek("absolute_path: %s\n", path); + kfree(ctmp); + return path; +} + +void vfs_dump(struct vnode *_vnode, int level) +{ + // uart_sendlinek("In vfs_dump\n"); + displaylayer(level); + if (_vnode->mount != 0) + { + // tmpfs_dump(_vnode->internal, level); + _vnode->v_ops->dump(_vnode, level); + while (_vnode->mount) + { + displaylayer(level); + uart_sendlinek(" !!mount!!\n"); + _vnode = _vnode->mount->root; + } + vfs_dump(_vnode, level); + } + else + { + // tmpfs_dump(_vnode->internal, level); + _vnode->v_ops->dump(_vnode, level); + } +} + +void vfs_ls() +{ + struct vnode *node; + uart_sendlinek("In directory : %s\n",curr_thread->curr_working_dir); + if (vfs_lookup(curr_thread->curr_working_dir, &node) == 0) + { + node->v_ops->ls(node); + } +} + +void vfs_cd(char *filepath) +{ + uart_sendlinek("Before change directory : %s\n",curr_thread->curr_working_dir); + + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, filepath); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + // uart_sendlinek("abs_path : %s\n",abs_path); + strcpy(curr_thread->curr_working_dir, abs_path); + + uart_sendlinek("In directory : %s\n",curr_thread->curr_working_dir); +} + +void displaylayer(int level) +{ + for (int i = 0; i < level; i++) + { + uart_sendlinek(" "); + } +} \ No newline at end of file diff --git a/lab7/kernel/src/vfs_dev_framebuffer.c b/lab7/kernel/src/vfs_dev_framebuffer.c new file mode 100644 index 000000000..3ddff0935 --- /dev/null +++ b/lab7/kernel/src/vfs_dev_framebuffer.c @@ -0,0 +1,131 @@ +#include "vfs.h" +#include "vfs_dev_framebuffer.h" +#include "uart1.h" +#include "memory.h" +#include "stdio.h" +#include "mbox.h" +#include "string.h" +#include "exception.h" +#include "debug.h" + +// #define MBOX_CH_PROP 8 + +// //The following code is for mailbox initialize used in lab7. +unsigned int width, height, pitch, isrgb; /* dimensions and channel order */ +unsigned char *lfb; /* raw frame buffer address */ + +struct file_operations dev_framebuffer_operations = {dev_framebuffer_write, (void *)dev_framebuffer_op_deny, dev_framebuffer_open, dev_framebuffer_close, dev_framebuffer_lseek64, (void *)dev_framebuffer_op_deny}; + +// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface +int init_dev_framebuffer() +{ + // The following code is for mailbox initialize used in lab7. + pt[0] = 35 * 4; + pt[1] = MBOX_TAG_REQUEST_CODE; + + pt[2] = 0x48003; // set phy wh + pt[3] = 8; + pt[4] = 8; + pt[5] = 1024; // FrameBufferInfo.width + pt[6] = 768; // FrameBufferInfo.height + + pt[7] = 0x48004; // set virt wh + pt[8] = 8; + pt[9] = 8; + pt[10] = 1024; // FrameBufferInfo.virtual_width + pt[11] = 768; // FrameBufferInfo.virtual_height + + pt[12] = 0x48009; // set virt offset + pt[13] = 8; + pt[14] = 8; + pt[15] = 0; // FrameBufferInfo.x_offset + pt[16] = 0; // FrameBufferInfo.y.offset + + pt[17] = 0x48005; // set depth + pt[18] = 4; + pt[19] = 4; + pt[20] = 32; // FrameBufferInfo.depth + + pt[21] = 0x48006; // set pixel order + pt[22] = 4; + pt[23] = 4; + pt[24] = 1; // RGB, not BGR preferably + + pt[25] = 0x40001; // get framebuffer, gets alignment on request + pt[26] = 8; + pt[27] = 8; + pt[28] = 4096; // FrameBufferInfo.pointer + pt[29] = 0; // FrameBufferInfo.size + + pt[30] = 0x40008; // get pitch + pt[31] = 4; + pt[32] = 4; + pt[33] = 0; // FrameBufferInfo.pitch + + pt[34] = MBOX_TAG_LAST_BYTE; + + // this might not return exactly what we asked for, could be + // the closest supported resolution instead + if (mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt)) && pt[20] == 32 && pt[28] != 0) + { + pt[28] &= 0x3FFFFFFF; // convert GPU address to ARM address + width = pt[5]; // get actual physical width + height = pt[6]; // get actual physical height + pitch = pt[33]; // get number of bytes per line + isrgb = pt[24]; // get the actual channel order + lfb = (void *)PHYS_TO_KERNEL_VIRT(((unsigned long)pt[28])); // raw frame buffer address + } + else + { + ERROR("Unable to set screen resolution to 1024x768x32\n"); + } + + return register_dev(&dev_framebuffer_operations); +} + +int dev_framebuffer_write(struct file *file, const void *buf, size_t len) +{ + lock(); + // uart_sendlinek + if (len + file->f_pos > pitch * height) + { + ERROR("How come? dev_framebuffer_write to no where!\r\n"); + len = pitch * height - file->f_pos; + } + memcpy(lfb + file->f_pos, buf, len); + file->f_pos += len; + unlock(); + return len; +} + +int dev_framebuffer_open(struct vnode *file_node, struct file **target) +{ + (*target)->f_pos = 0; + (*target)->vnode = file_node; + (*target)->f_ops = &dev_framebuffer_operations; + return 0; +} + +int dev_framebuffer_close(struct file *file) +{ + kfree(file); + return 0; +} + +long dev_framebuffer_lseek64(struct file *file, long offset, int whence) +{ + lock(); + if (whence == SEEK_SET) + { + file->f_pos = offset; + unlock(); + return file->f_pos; + } + unlock(); + return -1; +} + +int dev_framebuffer_op_deny() +{ + return -1; +} diff --git a/lab7/kernel/src/vfs_dev_uart.c b/lab7/kernel/src/vfs_dev_uart.c new file mode 100644 index 000000000..459c9444c --- /dev/null +++ b/lab7/kernel/src/vfs_dev_uart.c @@ -0,0 +1,53 @@ +#include "vfs.h" +#include "vfs_dev_uart.h" +#include "uart1.h" +#include "memory.h" +#include "string.h" + +struct file_operations dev_file_operations = {dev_uart_write, dev_uart_read, dev_uart_open, dev_uart_close, (void *)dev_uart_op_deny, (void *)dev_uart_op_deny}; + +int init_dev_uart() +{ + return register_dev(&dev_file_operations); +} + +int dev_uart_write(struct file *file, const void *buf, size_t len) +{ + char *cbuf = buf; + int i = len; + while (i--) + { + uart_async_send(*(cbuf++)); + } + return len; +} + +int dev_uart_read(struct file *file, void *buf, size_t len) +{ + char *cbuf = buf; + int i = len; + while (i--) + { + *cbuf = uart_async_recv(); + cbuf++; + } + return len; +} + +int dev_uart_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_ops = &dev_file_operations; + return 0; +} + +int dev_uart_close(struct file *file) +{ + kfree(file); + return 0; +} + +int dev_uart_op_deny() +{ + return -1; +} diff --git a/lab7/kernel/src/vfs_initramfs.c b/lab7/kernel/src/vfs_initramfs.c new file mode 100644 index 000000000..2915c2b0d --- /dev/null +++ b/lab7/kernel/src/vfs_initramfs.c @@ -0,0 +1,190 @@ +#include "vfs_initramfs.h" +#include "vfs.h" +#include "string.h" +#include "memory.h" +#include "cpio.h" +#include "uart1.h" +#include "debug.h" + +struct file_operations initramfs_file_operations = {initramfs_write, initramfs_read, initramfs_open, initramfs_close, initramfs_lseek64, initramfs_getsize}; +struct vnode_operations initramfs_vnode_operations = {initramfs_lookup, initramfs_create, initramfs_mkdir, initramfs_ls, initramfs_dump}; + +int register_initramfs() +{ + struct filesystem fs; + fs.name = "initramfs"; + fs.setup_mount = initramfs_setup_mount; + return register_filesystem(&fs); +} + +int initramfs_setup_mount(struct filesystem *fs, struct mount *_mount) +{ + _mount->fs = fs; + _mount->root = initramfs_create_vnode(0, dir_t); + // create entry under _mount, cpio files should be attached on it + struct initramfs_inode *ramdir_inode = _mount->root->internal; + + // add all file in initramfs to filesystem + char *filepath; + char *filedata; + unsigned int filesize; + // struct cpio_newc_header *header_pointer = CPIO_DEFAULT_START; + int idx = 0; + + CPIO_for_each(&filepath, &filesize, &filedata) + { + struct vnode *filevnode = initramfs_create_vnode(0, file_t); + struct initramfs_inode *fileinode = filevnode->internal; + fileinode->data = filedata; + fileinode->datasize = filesize; + fileinode->name = filepath; + // uart_sendlinek("file name: %s\n",filepath); + ramdir_inode->entry[idx++] = filevnode; + } + + return 0; +} + +struct vnode *initramfs_create_vnode(struct mount *_mount, enum fsnode_type type) +{ + struct vnode *v = kmalloc(sizeof(struct vnode)); + v->f_ops = &initramfs_file_operations; + v->v_ops = &initramfs_vnode_operations; + v->mount = _mount; + struct initramfs_inode *inode = kmalloc(sizeof(struct initramfs_inode)); + memset(inode, 0, sizeof(struct initramfs_inode)); + inode->type = type; + inode->data = kmalloc(0x1000); + v->internal = inode; + return v; +} + +// file operations +int initramfs_write(struct file *file, const void *buf, size_t len) +{ + // read-only + return -1; +} + +int initramfs_read(struct file *file, void *buf, size_t len) +{ + struct initramfs_inode *inode = file->vnode->internal; + // overflow, shrink size + if (len + file->f_pos > inode->datasize) + { + memcpy(buf, inode->data + file->f_pos, inode->datasize - file->f_pos); + file->f_pos += inode->datasize - file->f_pos; + return inode->datasize - file->f_pos; + } + else + { + memcpy(buf, inode->data + file->f_pos, len); + file->f_pos += len; + return len; + } + return -1; +} + +int initramfs_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_ops = file_node->f_ops; + (*target)->f_pos = 0; + return 0; +} + +int initramfs_close(struct file *file) +{ + kfree(file); + return 0; +} + +long initramfs_lseek64(struct file *file, long offset, int whence) +{ + if (whence == SEEK_SET) + { + file->f_pos = offset; + return file->f_pos; + } + return -1; +} + +// vnode operations +int initramfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct initramfs_inode *dir_inode = dir_node->internal; + int child_idx = 0; + for (; child_idx < INITRAMFS_MAX_DIR_ENTRY; child_idx++) + { + struct vnode *vnode = dir_inode->entry[child_idx]; + if (!vnode) + break; + struct initramfs_inode *inode = vnode->internal; + if (strcmp(component_name, inode->name) == 0) + { + *target = vnode; + return 0; + } + } + return -1; +} + +int initramfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + // read-only + return -1; +} + +int initramfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + // read-only + return -1; +} + +long initramfs_getsize(struct vnode *vd) +{ + struct initramfs_inode *inode = vd->internal; + return inode->datasize; +} + +void initramfs_dump(struct vnode *vnode, int level) +{ + struct initramfs_inode *inode = (struct initramfs_inode *)vnode->internal; + int child_idx = 0; + + uart_sendlinek("+----------------+\n"); + + for (; child_idx <= INITRAMFS_MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + // uart_sendlinek("0x%x\n",inode->entry[child_idx]); + displaylayer(level+1); + vnode = inode->entry[child_idx]; + uart_sendlinek("%s\n", ((struct initramfs_inode *)vnode->internal)->name); + + // displaylayer(level+2); + // uart_sendlinek("datasize size : %d\n", ((struct initramfs_inode *)vnode->internal)->datasize); + displaylayer(level+2); + uart_sendlinek("datasize size : %d\n", initramfs_getsize(vnode)); + } + displaylayer(level); + uart_sendlinek("+----------------+\n"); +} + +void initramfs_ls(struct vnode *vnode) +{ + struct initramfs_inode *inode = (struct initramfs_inode *)vnode->internal; + int child_idx = 0; + for (; child_idx <= INITRAMFS_MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + vnode = inode->entry[child_idx]; + uart_sendlinek("%s\n", ((struct initramfs_inode *)vnode->internal)->name); + } +} diff --git a/lab7/kernel/src/vfs_tmpfs.c b/lab7/kernel/src/vfs_tmpfs.c new file mode 100644 index 000000000..11e939243 --- /dev/null +++ b/lab7/kernel/src/vfs_tmpfs.c @@ -0,0 +1,253 @@ +#include "vfs_tmpfs.h" +#include "vfs.h" +#include "string.h" +#include "memory.h" +#include "uart1.h" + +struct file_operations tmpfs_file_operations = {tmpfs_write, tmpfs_read, tmpfs_open, tmpfs_close, tmpfs_lseek64, tmpfs_getsize}; +struct vnode_operations tmpfs_vnode_operations = {tmpfs_lookup, tmpfs_create, tmpfs_mkdir, tmpfs_ls, tmpfs_dump}; + +int register_tmpfs() +{ + struct filesystem fs; + fs.name = "tmpfs"; + fs.setup_mount = tmpfs_setup_mount; + return register_filesystem(&fs); +} + +int tmpfs_setup_mount(struct filesystem *fs, struct mount *_mount) +{ + _mount->fs = fs; + _mount->root = tmpfs_create_vnode(0, dir_t); + return 0; +} + +struct vnode *tmpfs_create_vnode(struct mount *_mount, enum fsnode_type type) +{ + struct vnode *v = kmalloc(sizeof(struct vnode)); + v->f_ops = &tmpfs_file_operations; + v->v_ops = &tmpfs_vnode_operations; + v->mount = 0; + struct tmpfs_inode *inode = kmalloc(sizeof(struct tmpfs_inode)); + memset(inode, 0, sizeof(struct tmpfs_inode)); + inode->type = type; + inode->data = kmalloc(0x1000); + v->internal = inode; + return v; +} + +// vnode operations +int tmpfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct tmpfs_inode *dir_inode = dir_node->internal; + int child_idx = 0; + // BFS search tree + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + struct vnode *vnode = dir_inode->entry[child_idx]; + if (!vnode) + break; + struct tmpfs_inode *inode = vnode->internal; + if (strcmp(component_name, inode->name) == 0) + { + *target = vnode; + return 0; + } + } + return -1; +} + +// dir ops +int tmpfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct tmpfs_inode *inode = dir_node->internal; + + if (inode->type != dir_t) + { + uart_sendlinek("tmpfs mkdir not dir_t\r\n"); + return -1; + } + + int child_idx = 0; + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + } + + if (child_idx > MAX_DIR_ENTRY) + { + uart_sendlinek("DIR ENTRY FULL\r\n"); + return -1; + } + + if (strlen(component_name) > MAX_FILE_NAME) + { + uart_sendlinek("FILE NAME TOO LONG\r\n"); + return -1; + } + + struct vnode *_vnode = tmpfs_create_vnode(0, dir_t); + inode->entry[child_idx] = _vnode; + + struct tmpfs_inode *newinode = _vnode->internal; + strcpy(newinode->name, component_name); + + *target = _vnode; + return 0; +} + +// file operations +int tmpfs_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_ops = file_node->f_ops; + (*target)->f_pos = 0; + return 0; +} + +// file operations +int tmpfs_write(struct file *file, const void *buf, size_t len) +{ + struct tmpfs_inode *inode = file->vnode->internal; + // write from f_pos + memcpy(inode->data + file->f_pos, buf, len); + // update f_pos and size + file->f_pos += len; + if (inode->datasize < file->f_pos) + inode->datasize = file->f_pos; + return len; +} + +int tmpfs_read(struct file *file, void *buf, size_t len) +{ + struct tmpfs_inode *inode = file->vnode->internal; + // if buffer overflow, shrink the request read length + // read from f_pos + if (len + file->f_pos > inode->datasize) + { + len = inode->datasize - file->f_pos; + memcpy(buf, inode->data + file->f_pos, len); + file->f_pos += inode->datasize - file->f_pos; + return len; + } + else + { + memcpy(buf, inode->data + file->f_pos, len); + file->f_pos += len; + return len; + } + return -1; +} + +int tmpfs_close(struct file *file) +{ + kfree(file); + return 0; +} + +long tmpfs_lseek64(struct file *file, long offset, int whence) +{ + if (whence == SEEK_SET) + { + file->f_pos = offset; + return file->f_pos; + } + return -1; +} + +// file ops +int tmpfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct tmpfs_inode *inode = dir_node->internal; + if (inode->type != dir_t) + { + uart_sendlinek("tmpfs create not dir_t\r\n"); + return -1; + } + + int child_idx = 0; + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + break; + struct tmpfs_inode *child_inode = inode->entry[child_idx]->internal; + if (strcmp(child_inode->name, component_name) == 0) + { + uart_sendlinek("tmpfs create file exists\r\n"); + return -1; + } + } + + if (child_idx > MAX_DIR_ENTRY) + { + uart_sendlinek("DIR ENTRY FULL\r\n"); + return -1; + } + + if (strlen(component_name) > MAX_FILE_NAME) + { + uart_sendlinek("FILE NAME TOO LONG\r\n"); + return -1; + } + + struct vnode *_vnode = tmpfs_create_vnode(0, file_t); + inode->entry[child_idx] = _vnode; + + struct tmpfs_inode *newinode = _vnode->internal; + strcpy(newinode->name, component_name); + + *target = _vnode; + return 0; +} + +long tmpfs_getsize(struct vnode *vd) +{ + struct tmpfs_inode *inode = vd->internal; + return inode->datasize; +} + +void tmpfs_dump(struct vnode *vnode, int level) +{ + struct tmpfs_inode *inode = (struct tmpfs_inode *)vnode->internal; + + uart_sendlinek("+-%s", inode->name); + switch (inode->type) + { + case dir_t: + uart_sendlinek("(dir)\n"); + break; + case file_t: + uart_sendlinek("(file)\n"); + break; + + default: + break; + } + int child_idx = 0; + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + vfs_dump(inode->entry[child_idx], level + 1); + } +} + +void tmpfs_ls(struct vnode *vnode) +{ + struct tmpfs_inode *inode = (struct tmpfs_inode *)vnode->internal; + int child_idx = 0; + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + vnode = inode->entry[child_idx]; + uart_sendlinek("%s\n", ((struct tmpfs_inode *)vnode->internal)->name); + } +} diff --git a/lab7/send_img_to_bootloader.py b/lab7/send_img_to_bootloader.py new file mode 100644 index 000000000..29d43b781 --- /dev/null +++ b/lab7/send_img_to_bootloader.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 + +from serial import Serial +from pwn import * +import argparse +from sys import platform + +if platform == "linux" or platform == "linux2": + parser = argparse.ArgumentParser(description='NYCU OSDI kernel sender') + parser.add_argument('--filename', metavar='PATH', default='kernel8.img', type=str, help='path to kernel8.img') + parser.add_argument('--device', metavar='TTY',default='/dev/ttyUSB0', type=str, help='path to UART device') + parser.add_argument('--baud', metavar='Hz',default=115200, type=int, help='baud rate') + args = parser.parse_args() + + with open(args.filename,'rb') as fd: + with Serial(args.device, args.baud) as ser: + + kernel_raw = fd.read() + length = len(kernel_raw) + + print("Kernel image size : ", hex(length)) + for i in range(8): + ser.write(p64(length)[i:i+1]) + ser.flush() + + print("Start sending kernel image by uart1...") + for i in range(length): + # Use kernel_raw[i: i+1] is byte type. Instead of using kernel_raw[i] it will retrieve int type then cause error + ser.write(kernel_raw[i: i+1]) + ser.flush() + if i % 100 == 0: + print("{:>6}/{:>6} bytes".format(i, length)) + print("{:>6}/{:>6} bytes".format(length, length)) + print("Transfer finished!") + +else: + parser = argparse.ArgumentParser(description='NYCU OSDI kernel sender') + parser.add_argument('--filename', metavar='PATH', default='kernel8.img', type=str, help='path to kernel8.img') + parser.add_argument('--device', metavar='COM',default='COM3', type=str, help='COM# to UART device') + parser.add_argument('--baud', metavar='Hz',default=115200, type=int, help='baud rate') + args = parser.parse_args() + + with open(args.filename,'rb') as fd: + with Serial(args.device, args.baud) as ser: + + kernel_raw = fd.read() + length = len(kernel_raw) + + print("Kernel image size : ", hex(length)) + for i in range(8): + ser.write(p64(length)[i:i+1]) + ser.flush() + + print("Start sending kernel image by uart1...") + for i in range(length): + # Use kernel_raw[i: i+1] is byte type. Instead of using kernel_raw[i] it will retrieve int type then cause error + ser.write(kernel_raw[i: i+1]) + ser.flush() + if i % 100 == 0: + print("{:>6}/{:>6} bytes".format(i, length)) + print("{:>6}/{:>6} bytes".format(length, length)) + print("Transfer finished!") \ No newline at end of file From e6a5b753ca1070f2fb8838e58ea1db1667af53b3 Mon Sep 17 00:00:00 2001 From: SianGx0102 Date: Thu, 20 Jun 2024 16:35:50 +0800 Subject: [PATCH 3/5] lab 7 --- lab7/kernel/src/syscall_fs.c | 6 +- lab8/bcm2710-rpi-3-b-plus.dtb | Bin 0 -> 32761 bytes lab8/config.txt | 3 + lab8/create_diskimg/create_img.sh | 42 + lab8/create_diskimg/create_sfn_img.sh | 45 + lab8/create_diskimg/initramfs.cpio | Bin 0 -> 1057792 bytes lab8/create_diskimg/sdcard/FAT_R.TXT | 1 + .../sdcard/bcm2710-rpi-3-b-plus.dtb | Bin 0 -> 32761 bytes lab8/create_diskimg/sdcard/bootcode.bin | 1652 ++++++++++++++++ lab8/create_diskimg/sdcard/config.txt | 3 + lab8/create_diskimg/sdcard/fixup.dat | Bin 0 -> 6745 bytes lab8/create_fs/FromTA/initramfs.cpio | Bin 0 -> 247296 bytes lab8/create_fs/create_cpio.sh | 11 + lab8/create_fs/lab3_user_proc/linker.ld | 5 + lab8/create_fs/lab3_user_proc/makefile | 23 + lab8/create_fs/lab3_user_proc/user_proc.S | 12 + lab8/create_fs/lab5_user_fork/fork_test.S | 28 + .../initramfs_providedbyTA.cpio | Bin 0 -> 247296 bytes lab8/create_fs/lab5_user_fork/makefile | 23 + lab8/create_fs/rootfs/file0.txt | 2 + lab8/create_fs/rootfs/file1.txt | 11 + lab8/initramfs.cpio | Bin 0 -> 1061376 bytes lab8/kernel/Makefile | 93 + lab8/kernel/include/bcm2837/rpi_base.h | 7 + lab8/kernel/include/bcm2837/rpi_gpio.h | 25 + lab8/kernel/include/bcm2837/rpi_irq.h | 24 + lab8/kernel/include/bcm2837/rpi_mbox.h | 17 + lab8/kernel/include/bcm2837/rpi_mmu.h | 18 + lab8/kernel/include/bcm2837/rpi_uart1.h | 19 + lab8/kernel/include/cpio.h | 47 + lab8/kernel/include/debug.h | 19 + lab8/kernel/include/dtb.h | 26 + lab8/kernel/include/exception.h | 92 + lab8/kernel/include/irqtask.h | 22 + lab8/kernel/include/mbox.h | 66 + lab8/kernel/include/memory.h | 80 + lab8/kernel/include/mmu.h | 101 + lab8/kernel/include/power.h | 9 + lab8/kernel/include/sched.h | 79 + lab8/kernel/include/sdhost.h | 69 + lab8/kernel/include/shell.h | 40 + lab8/kernel/include/signal.h | 49 + lab8/kernel/include/stddef.h | 12 + lab8/kernel/include/stdio.h | 29 + lab8/kernel/include/string.h | 15 + lab8/kernel/include/syscall.h | 39 + lab8/kernel/include/timer.h | 36 + lab8/kernel/include/u_list.h | 213 +++ lab8/kernel/include/uart1.h | 18 + lab8/kernel/include/vfs.h | 110 ++ lab8/kernel/include/vfs_dev_framebuffer.h | 24 + lab8/kernel/include/vfs_dev_uart.h | 15 + lab8/kernel/include/vfs_fat32.h | 252 +++ lab8/kernel/include/vfs_initramfs.h | 41 + lab8/kernel/include/vfs_tmpfs.h | 42 + lab8/kernel/initramfs.cpio | Bin 0 -> 1057792 bytes lab8/kernel/src/boot.S | 82 + lab8/kernel/src/cpio.c | 82 + lab8/kernel/src/dtb.c | 173 ++ lab8/kernel/src/entry.S | 199 ++ lab8/kernel/src/exception.c | 377 ++++ lab8/kernel/src/linker.ld | 44 + lab8/kernel/src/main.c | 45 + lab8/kernel/src/mbox.c | 23 + lab8/kernel/src/memory.c | 491 +++++ lab8/kernel/src/mmu.c | 380 ++++ lab8/kernel/src/sched.S | 57 + lab8/kernel/src/sched.c | 270 +++ lab8/kernel/src/sdhost.c | 179 ++ lab8/kernel/src/shell.c | 572 ++++++ lab8/kernel/src/signal.c | 90 + lab8/kernel/src/stdio.c | 121 ++ lab8/kernel/src/string.c | 292 +++ lab8/kernel/src/syscall.c | 352 ++++ lab8/kernel/src/syscall_fs.c | 157 ++ lab8/kernel/src/timer.c | 177 ++ lab8/kernel/src/uart1.c | 177 ++ lab8/kernel/src/vfs.c | 464 +++++ lab8/kernel/src/vfs_dev_framebuffer.c | 133 ++ lab8/kernel/src/vfs_dev_uart.c | 55 + lab8/kernel/src/vfs_fat32.c | 242 +++ lab8/kernel/src/vfs_initramfs.c | 206 ++ lab8/kernel/src/vfs_tmpfs.c | 270 +++ lab8/send_img_to_bootloader.py | 62 + vfs_fat32.c | 1689 +++++++++++++++++ 85 files changed, 11073 insertions(+), 3 deletions(-) create mode 100644 lab8/bcm2710-rpi-3-b-plus.dtb create mode 100644 lab8/config.txt create mode 100755 lab8/create_diskimg/create_img.sh create mode 100755 lab8/create_diskimg/create_sfn_img.sh create mode 100644 lab8/create_diskimg/initramfs.cpio create mode 100644 lab8/create_diskimg/sdcard/FAT_R.TXT create mode 100644 lab8/create_diskimg/sdcard/bcm2710-rpi-3-b-plus.dtb create mode 100644 lab8/create_diskimg/sdcard/bootcode.bin create mode 100644 lab8/create_diskimg/sdcard/config.txt create mode 100644 lab8/create_diskimg/sdcard/fixup.dat create mode 100644 lab8/create_fs/FromTA/initramfs.cpio create mode 100755 lab8/create_fs/create_cpio.sh create mode 100644 lab8/create_fs/lab3_user_proc/linker.ld create mode 100644 lab8/create_fs/lab3_user_proc/makefile create mode 100644 lab8/create_fs/lab3_user_proc/user_proc.S create mode 100644 lab8/create_fs/lab5_user_fork/fork_test.S create mode 100644 lab8/create_fs/lab5_user_fork/initramfs_providedbyTA.cpio create mode 100644 lab8/create_fs/lab5_user_fork/makefile create mode 100644 lab8/create_fs/rootfs/file0.txt create mode 100644 lab8/create_fs/rootfs/file1.txt create mode 100644 lab8/initramfs.cpio create mode 100644 lab8/kernel/Makefile create mode 100644 lab8/kernel/include/bcm2837/rpi_base.h create mode 100644 lab8/kernel/include/bcm2837/rpi_gpio.h create mode 100644 lab8/kernel/include/bcm2837/rpi_irq.h create mode 100644 lab8/kernel/include/bcm2837/rpi_mbox.h create mode 100644 lab8/kernel/include/bcm2837/rpi_mmu.h create mode 100644 lab8/kernel/include/bcm2837/rpi_uart1.h create mode 100644 lab8/kernel/include/cpio.h create mode 100644 lab8/kernel/include/debug.h create mode 100644 lab8/kernel/include/dtb.h create mode 100644 lab8/kernel/include/exception.h create mode 100644 lab8/kernel/include/irqtask.h create mode 100644 lab8/kernel/include/mbox.h create mode 100644 lab8/kernel/include/memory.h create mode 100644 lab8/kernel/include/mmu.h create mode 100644 lab8/kernel/include/power.h create mode 100644 lab8/kernel/include/sched.h create mode 100644 lab8/kernel/include/sdhost.h create mode 100644 lab8/kernel/include/shell.h create mode 100644 lab8/kernel/include/signal.h create mode 100644 lab8/kernel/include/stddef.h create mode 100644 lab8/kernel/include/stdio.h create mode 100644 lab8/kernel/include/string.h create mode 100644 lab8/kernel/include/syscall.h create mode 100644 lab8/kernel/include/timer.h create mode 100644 lab8/kernel/include/u_list.h create mode 100644 lab8/kernel/include/uart1.h create mode 100644 lab8/kernel/include/vfs.h create mode 100644 lab8/kernel/include/vfs_dev_framebuffer.h create mode 100644 lab8/kernel/include/vfs_dev_uart.h create mode 100644 lab8/kernel/include/vfs_fat32.h create mode 100644 lab8/kernel/include/vfs_initramfs.h create mode 100644 lab8/kernel/include/vfs_tmpfs.h create mode 100644 lab8/kernel/initramfs.cpio create mode 100644 lab8/kernel/src/boot.S create mode 100644 lab8/kernel/src/cpio.c create mode 100644 lab8/kernel/src/dtb.c create mode 100644 lab8/kernel/src/entry.S create mode 100644 lab8/kernel/src/exception.c create mode 100644 lab8/kernel/src/linker.ld create mode 100644 lab8/kernel/src/main.c create mode 100644 lab8/kernel/src/mbox.c create mode 100644 lab8/kernel/src/memory.c create mode 100644 lab8/kernel/src/mmu.c create mode 100644 lab8/kernel/src/sched.S create mode 100644 lab8/kernel/src/sched.c create mode 100644 lab8/kernel/src/sdhost.c create mode 100644 lab8/kernel/src/shell.c create mode 100644 lab8/kernel/src/signal.c create mode 100644 lab8/kernel/src/stdio.c create mode 100644 lab8/kernel/src/string.c create mode 100644 lab8/kernel/src/syscall.c create mode 100644 lab8/kernel/src/syscall_fs.c create mode 100644 lab8/kernel/src/timer.c create mode 100644 lab8/kernel/src/uart1.c create mode 100644 lab8/kernel/src/vfs.c create mode 100644 lab8/kernel/src/vfs_dev_framebuffer.c create mode 100644 lab8/kernel/src/vfs_dev_uart.c create mode 100644 lab8/kernel/src/vfs_fat32.c create mode 100644 lab8/kernel/src/vfs_initramfs.c create mode 100644 lab8/kernel/src/vfs_tmpfs.c create mode 100644 lab8/send_img_to_bootloader.py create mode 100644 vfs_fat32.c diff --git a/lab7/kernel/src/syscall_fs.c b/lab7/kernel/src/syscall_fs.c index ea8a4e34e..0bce29aa0 100644 --- a/lab7/kernel/src/syscall_fs.c +++ b/lab7/kernel/src/syscall_fs.c @@ -16,9 +16,9 @@ int open(trapframe_t *tpf, const char *pathname, int flags) char abs_path[MAX_PATH_NAME]; strcpy(abs_path, pathname); - uart_sendlinek("file name : %s\n", pathname); - uart_sendlinek("curr_working_dir : %s\n", curr_thread->curr_working_dir); - uart_sendlinek("abs_path : %s\n", abs_path); + // uart_sendlinek("file name : %s\n", pathname); + // uart_sendlinek("curr_working_dir : %s\n", curr_thread->curr_working_dir); + // uart_sendlinek("abs_path : %s\n", abs_path); // update abs_path get_absolute_path(abs_path, curr_thread->curr_working_dir); diff --git a/lab8/bcm2710-rpi-3-b-plus.dtb b/lab8/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 0000000000000000000000000000000000000000..38395a23fc90767680815c7f43bbfb3a290c2af0 GIT binary patch literal 32761 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�D&OoC_~4g9tivONVZxf$G+%wkS(-3$L@6`g_7TDCjX zZ0wGe1kn#$y$N03GHt`At5nL~a;sv6?tVfLDtBzZfvLbSPPlEX)KP=ol3y$FuZ?K# zXq{r6RCi!U&_G1m5U=65R9h>Z>G;rAvqX;HRd$z~6%TKR)pAgjR>?KEc2EoOFI}HT z(Zk+nZg2C&R%k#PL<|DCfDac}0}-x51h)~K?qcnF74kM)Fxcu&T_b z;N~L)VOxvMMmg|KwHr9ZRqhdz%wl+uLlI??rK2!lgi~v-g%I6`f&Mc>*Fc1>5Jg9` z^17#s*d9?dyRD%lOrK+iLQh^iVS_5lE(U?YdK6{9i&rZx;GjZX*QY@bZ2zJ#%`RG- zkJK}Q(H=>QUv1*wgAN>)c8|B*&27)R8E*hT~6VH+RLhvRq~;)h{3J~sayp*djcq?x^z z*=bP$8ODfDCznO<1T0!-efE&~Xu4M?b4?Ws7QJ>Z)|qMrada*+YQ<9qvbpLa3nJ%q zqJM5wVdWq~YHPXb@qjovoJ|L>VpsV3h4W*g84}b?cxp=Ca`=_C$B&co(w^hZu*X+ysto}0S)*bX?FdxfaP>9TytA4wwD77_a_A9Hp#OVEWA!Fl_#JplwLCf-}ERJi*| MwhYsc7a#HeA5G>kdjJ3c literal 0 HcmV?d00001 diff --git a/lab8/config.txt b/lab8/config.txt new file mode 100644 index 000000000..e82fa85fa --- /dev/null +++ b/lab8/config.txt @@ -0,0 +1,3 @@ +kernel=bootloader.img +arm_64bit=1 +initramfs initramfs.cpio 0x8000000 \ No newline at end of file diff --git a/lab8/create_diskimg/create_img.sh b/lab8/create_diskimg/create_img.sh new file mode 100755 index 000000000..73514bd63 --- /dev/null +++ b/lab8/create_diskimg/create_img.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +IMG_NAME=sdcard.img + +truncate -s 64M $IMG_NAME + +( +echo o # Create a new empty DOS partition table +echo n # Add a new partition +echo p # Primary partition +echo 1 # Partition number +echo # First sector (Accept default: 1) +echo # Last sector (Accept default: varies) +echo t # Change partition type +echo c # Master Boot Record primary partitions type:LBA +echo w # Write changes +) | sudo fdisk $IMG_NAME + +LOOPBACK=`sudo losetup --partscan --show --find $IMG_NAME` + +echo ${LOOPBACK} | grep --quiet "/dev/loop" + +if [ $? = 1 ] +then + echo "[!] losetup failed!" + exit 1 +fi + +sudo mkfs.vfat -F 32 ${LOOPBACK}p1 + +mkdir -p mnt + +sudo mount -t vfat ${LOOPBACK}p1 mnt + +sudo cp -r sdcard/* mnt +sudo cp ./bootloader.img mnt/bootloader.img +sudo cp ./initramfs.cpio mnt/initramfs.cpio + +sudo umount mnt + +sudo losetup -d ${LOOPBACK} +# dd if=./sdcard.img of=/dev/ diff --git a/lab8/create_diskimg/create_sfn_img.sh b/lab8/create_diskimg/create_sfn_img.sh new file mode 100755 index 000000000..c4c7a9991 --- /dev/null +++ b/lab8/create_diskimg/create_sfn_img.sh @@ -0,0 +1,45 @@ +IMG_NAME=sdcard.img + +truncate -s 64M $IMG_NAME + +( +echo o # Create a new empty DOS partition table +echo n # Add a new partition +echo p # Primary partition +echo 1 # Partition number +echo # First sector (Accept default: 1) +echo # Last sector (Accept default: varies) +echo a # Toggle bootable flag +echo t # Change partition type +echo b # W95 FAT32 +echo w # Write changes +) | sudo fdisk $IMG_NAME + +LOOPBACK=$(sudo losetup --partscan --show --find $IMG_NAME) + +echo ${LOOPBACK} | grep --quiet "/dev/loop" + +if [ $? = 1 ]; then + echo "[!] losetup failed!" + exit 1 +fi + +sudo mkfs.msdos -F 32 ${LOOPBACK}p1 + +mkdir -p mnt + +sudo mount -t msdos ${LOOPBACK}p1 mnt + +sudo cp ../kernel/kernel8.img mnt/KERNEL8.IMG +sudo cp ../initramfs.cpio mnt/INITRAMFS.CPIO +sudo cp ../bcm2710-rpi-3-b-plus.dtb mnt/BCM2710-RPI-3-B-PLUS.DTB +sudo bash -c "echo "Hello" > mnt/HELLO" +sudo bash -c "echo "W\no\nr\nl\nd" > mnt/WORLD" + +sudo umount -l mnt +sudo losetup -d ${LOOPBACK} +sudo rm -rf mnt + +mv sdcard.img ../ # 1fc400 + +#dd if=./sdcard.img of=/dev/ diff --git a/lab8/create_diskimg/initramfs.cpio b/lab8/create_diskimg/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..08fa914524bd41a9ecc4d0eb44983850986ebc91 GIT binary patch literal 1057792 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

-e!a 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 UK7Zw1jl*ekMO}WXtLW$dAG(TTm;e9( literal 0 HcmV?d00001 diff --git a/lab8/create_diskimg/sdcard/FAT_R.TXT b/lab8/create_diskimg/sdcard/FAT_R.TXT new file mode 100644 index 000000000..5d2252cd1 --- /dev/null +++ b/lab8/create_diskimg/sdcard/FAT_R.TXT @@ -0,0 +1 @@ +fat_r test \ No newline at end of file diff --git a/lab8/create_diskimg/sdcard/bcm2710-rpi-3-b-plus.dtb b/lab8/create_diskimg/sdcard/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 0000000000000000000000000000000000000000..38395a23fc90767680815c7f43bbfb3a290c2af0 GIT binary patch literal 32761 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�D&OoC_~4g9tivONVZxf$G+%wkS(-3$L@6`g_7TDCjX zZ0wGe1kn#$y$N03GHt`At5nL~a;sv6?tVfLDtBzZfvLbSPPlEX)KP=ol3y$FuZ?K# zXq{r6RCi!U&_G1m5U=65R9h>Z>G;rAvqX;HRd$z~6%TKR)pAgjR>?KEc2EoOFI}HT z(Zk+nZg2C&R%k#PL<|DCfDac}0}-x51h)~K?qcnF74kM)Fxcu&T_b z;N~L)VOxvMMmg|KwHr9ZRqhdz%wl+uLlI??rK2!lgi~v-g%I6`f&Mc>*Fc1>5Jg9` z^17#s*d9?dyRD%lOrK+iLQh^iVS_5lE(U?YdK6{9i&rZx;GjZX*QY@bZ2zJ#%`RG- zkJK}Q(H=>QUv1*wgAN>)c8|B*&27)R8E*hT~6VH+RLhvRq~;)h{3J~sayp*djcq?x^z z*=bP$8ODfDCznO<1T0!-efE&~Xu4M?b4?Ws7QJ>Z)|qMrada*+YQ<9qvbpLa3nJ%q zqJM5wVdWq~YHPXb@qjovoJ|L>VpsV3h4W*g84}b?cxp=Ca`=_C$B&co(w^hZu*X+ysto}0S)*bX?FdxfaP>9TytA4wwD77_a_A9Hp#OVEWA!Fl_#JplwLCf-}ERJi*| MwhYsc7a#HeA5G>kdjJ3c literal 0 HcmV?d00001 diff --git a/lab8/create_diskimg/sdcard/bootcode.bin b/lab8/create_diskimg/sdcard/bootcode.bin new file mode 100644 index 000000000..23429a14d --- /dev/null +++ b/lab8/create_diskimg/sdcard/bootcode.bin @@ -0,0 +1,1652 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + firmware/bootcode.bin at master · raspberrypi/firmware · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + +
+ Skip to content + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + + + + + +
+ + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +
+ + + + + + + +Permalink + +
+ +
+
+ + + master + + + + +
+
+
+ Switch branches/tags + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+ + +
+ +
+
+
+

Name already in use

+
+
+ +
+
+
+
+ +
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch? +
+ +
+
+ + +
+
+ + + + Go to file + +
+ + + + +
+
+
+ + + + + + + + + +
+ +
+
+ + @popcornmix + + +
+ + Latest commit + bfbd42e + Oct 14, 2022 + + + + + + History + + +
+
+
firmware: arm_dt: Export the bootloader EEPROM RSA public key via device-tree
+
+firmware: Add tryboot A_B mode
+ +
+ +
+
+ + + 1 + + contributor + + +
+ +

+ Users who have contributed to this file +

+
+ + + + + + +
+
+
+
+ + + + + + + + + +
+ +
+ + +
+ + 51.2 KB +
+ +
+ + + + +
+
+ +
+
+ +
+ +
+
+ + + +
+ +
+ View raw +
+
+ +
+ + + + +
+ + +
+ + +
+
+ + + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + diff --git a/lab8/create_diskimg/sdcard/config.txt b/lab8/create_diskimg/sdcard/config.txt new file mode 100644 index 000000000..15654a481 --- /dev/null +++ b/lab8/create_diskimg/sdcard/config.txt @@ -0,0 +1,3 @@ +kernel=bootloader.img +arm_64bit=1 +initramfs initramfs.cpio 0x8000000 diff --git a/lab8/create_diskimg/sdcard/fixup.dat b/lab8/create_diskimg/sdcard/fixup.dat new file mode 100644 index 0000000000000000000000000000000000000000..e928ee3fc1bf00e638365cfa0bc4c9d94940bd7f GIT binary patch literal 6745 zcmeHLUx*cD6#str?009!>v+4adf8pK)wXTjmZ(iCMAXDAO{y1Dq)f6R5wZ}(h$7A2 z3L+mQ^(6?QKza-8B^0E`q=!K8t)d`&i0DBmsdK*h&dfLC+`Zo2G=t9EnRCAL_q*pi z-=CT005yBOa32hHf%RSF-NcVMg$1}o1|P%J=ieUVWou3xT-MD}<*mqK+Zb#TVcw)+ zlmf0UH8_x@4D7$nOK|xP&$_r&m2t%?>5aP}9BTAtP~i`o=I+C}#iM;)JA)_Zch#xr zW5~kk1#@+gyTiNn9-ZN*S*8o$_!`Kg_d;P|uRV=0H0y|1p>^6zA5&dioV~5{fb;Lj zbjQY)dDUz_ZOot682*_C-&>g=#+UkyIlPM;UFY_P7kG_e{6SwT7v68nYB*#fYjNjp z)2ae2vW6O~u&*X4)~PJf_ts4Gv-IZ_7Qw8u3{7l;vCRfivprz#6tz=>?nK5;APKic4au-bzMeXz{oSe#O;k}m`j$lvS;Mk(B zt2gKS*Oir8c)YOomS-F@T!tRII>!v@p_0t)Yaq6=&M*YA-F!122qYmhP>dEX@6327gxr8Lue# zy-uvHP^W=loD-Vo4A z;`6aAg?ygCKAw<#L}6HO#~W=*;sFlJfvdu(lSZrY)J$+bZ+3X8pcZeT z@i-Hc9IOc1mLMs_5}d)uSA|IGr~rc``|AYXTr3VoD4W1xAn!?3q|;Mz&`oFOA1yv| z?~^0p>PVvX)&LaxSEUX`WFZWhM-vLU0+JK3$!ow@&Q+{JH#0R$r&a66M#r}IoZ zYUt)eyjf*XssYrxznQ45b<WRw*eNqS&qc7S3W4(J zkh1+@pr8{pQcwJ$%S}G6Y-Zr{c>b28{VLLkf(J-E?N{|a=lZKqk zXN2HXo_20@@MggB8x>@@yw2n)KR$CJaz&+LYD>xU@VdKXj=T9Ih=8i!NL-5DEmW+q zeWYZ0%QoZkT#&cPQfjlIVDdK6Dp_lD zz?D({-j`iCOW}$Xu~YVRL~?^6f3DW|qtG+Xz{HbbwnM3-s|MHeY=njRd(SnN-5JL_ zs-V_&d^*~aoj92bu>wZUL^FUU-KqF`s{WSYonS4Qbc4qEnpu3E@F0fH5ni+gyY>)H TT!2(M{@_o%dmo8$>KOh8=fLZL literal 0 HcmV?d00001 diff --git a/lab8/create_fs/FromTA/initramfs.cpio b/lab8/create_fs/FromTA/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..0676fb1584617bc4d73624b3b212a12133e97d8e GIT binary patch literal 247296 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 ../initramfs.cpio +cd .. diff --git a/lab8/create_fs/lab3_user_proc/linker.ld b/lab8/create_fs/lab3_user_proc/linker.ld new file mode 100644 index 000000000..faee5d7b1 --- /dev/null +++ b/lab8/create_fs/lab3_user_proc/linker.ld @@ -0,0 +1,5 @@ +SECTIONS +{ + . = 0x80000; + .text : { *(.text) } +} diff --git a/lab8/create_fs/lab3_user_proc/makefile b/lab8/create_fs/lab3_user_proc/makefile new file mode 100644 index 000000000..590bdf420 --- /dev/null +++ b/lab8/create_fs/lab3_user_proc/makefile @@ -0,0 +1,23 @@ +ARMGNU ?= aarch64-linux-gnu + +BUILD_DIR = build +#--------------------------------------------------------------------------------------- + +ASM_FILES = $(wildcard *.S) +OBJ_FILES += $(ASM_FILES:%.S=$(BUILD_DIR)/%_s.o) + +DEP_FILES = $(OBJ_FILES:%.o=%.d) +-include $(DEP_FILES) + +$(BUILD_DIR)/%_s.o: %.S + @mkdir -p $(@D) + $(ARMGNU)-gcc -c $< -o $@ + +user_proc.img: linker.ld $(OBJ_FILES) + $(ARMGNU)-ld -T linker.ld -o $(BUILD_DIR)/user_proc.elf $(OBJ_FILES) + $(ARMGNU)-objcopy $(BUILD_DIR)/user_proc.elf -O binary user_proc.img + +all: user_proc.img + +clean: + rm -rf $(BUILD_DIR) *.img diff --git a/lab8/create_fs/lab3_user_proc/user_proc.S b/lab8/create_fs/lab3_user_proc/user_proc.S new file mode 100644 index 000000000..2d9837651 --- /dev/null +++ b/lab8/create_fs/lab3_user_proc/user_proc.S @@ -0,0 +1,12 @@ +// Run `svc 0` 5 times; svc (el0 -> el1) system calls +.section ".text" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b diff --git a/lab8/create_fs/lab5_user_fork/fork_test.S b/lab8/create_fs/lab5_user_fork/fork_test.S new file mode 100644 index 000000000..463d19529 --- /dev/null +++ b/lab8/create_fs/lab5_user_fork/fork_test.S @@ -0,0 +1,28 @@ +void fork_test(){ + printf("\nFork Test, pid %d\n", get_pid()); + int cnt = 1; + int ret = 0; + if ((ret = fork()) == 0) { // child + long long cur_sp; + asm volatile("mov %0, sp" : "=r"(cur_sp)); + printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + ++cnt; + + if ((ret = fork()) != 0){ + asm volatile("mov %0, sp" : "=r"(cur_sp)); + printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + } + else{ + while (cnt < 5) { + asm volatile("mov %0, sp" : "=r"(cur_sp)); + printf("second child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + delay(1000000); + ++cnt; + } + } + exit(); + } + else { + printf("parent here, pid %d, child %d\n", get_pid(), ret); + } +} diff --git a/lab8/create_fs/lab5_user_fork/initramfs_providedbyTA.cpio b/lab8/create_fs/lab5_user_fork/initramfs_providedbyTA.cpio new file mode 100644 index 0000000000000000000000000000000000000000..0676fb1584617bc4d73624b3b212a12133e97d8e GIT binary patch literal 247296 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

fMH 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

muRr>~-~v|+M97RYYK#qk z;Gs??=uU(-lHE>bF>Q}kmy!)Tc~94&ia@~aHoa}-Lm!6}ejKiOAg{K@Ki!Y_vfCaS z`8WywAs-=lC#d(+ORK54Et!v%cV_y*<>nyQ#F;z;efqB!w+3nqD0~k2X?@Ul*N@Cs zcY^n3CV{oY5PtF1ns9;hu-C2k)9H9-Wrw;v`7Q{RR>>`Hf~fUYJ(2REw&;Uae)JId zYW*1W-9xqC^ulwA{cN|c@DN|KdKuzHn47gee1S^FazLnYK|d$(kROY(a^&+i&dl zF~^Q)m0ZUc0_G9?s8yW>WT=EDBA}oj{W7 z{)Ynpp_WKf!jR89Z3r=kT5$#s0pu#*hx=kiI3Fs^axSbF^4m%rkAFMvcfu-s#Jc&; zhd-uMMj2+6qK;{8_4nuEIx+UVqoHqO>!0?qga^6D_QvF3dp(pda9mfP@uC_woxj`3} zxYyqS$w+4<3`b;C-$*OtfnE%9DqQDmdFYp_5AfMIOXaYwyPW7ez{>d=u<@K8;I{E> zn!pb6ZO#LDLD7GcA@{H%uKc!$sd-hPsV-F?$fb#%JoKH2*YoVy3 zuR6a8K1CMeOrq%M;3JemB#_!#*~l%=d(yZ zb>o7vD;-}@_f_(YR|7r{ z+Om0uis#jM2V^6X!aY=}7Pe6r<}&l-A^Z&ba18OB9QyXy@E`)CapAJz94FSD2JP(_ zo8jonN-gDY?_{bT+>7X^pG?bCVb6}23?GS|_8Ztm?C=*j@z{+sd4nF)3$P=3=~rB@ z*$7AEVUJ(s+1O1K-4`cmmRBh16&JKu`*W1ln)erk3{cH3$0Y2`1SGMbvN+;a| zxU-XIBO5r67J$7c8-Ohj=kJ(~zEXH;cGyHcfv&IUPR*~W{p^r^*vor-au@v#cBfwm z@&j_vmbZo$mVB!NKlX(OB7QA^^IJTZsm=lNj@Kg2Z_^*FM#_voj5xP4+8GK)aymqg>g40`cK0h zoy)FFvbM9+Htv)}zmUgxPbSWOmbMpgx1NK868GvUJP5-Pe(;q`{ADm zg5DSdZJZgR@3@FD5LoQhQ$fGI94&Nrb{1#Xd)vE(o#8o2&>Hvc;*uQX%SL9B8=-P} zC!4@U$$lrsGw=8;!vCDjw`y2Zp)F1@$2LA7G%y}G-`c#zGR`dG?5vgrZ7cABRp_fl z-}DObiOxP zT%0ZU*H#A`IOoZ;J^3Afkp>`ZX*;wz#N&v4!QwotW}In{Z_a{W;aAH<;4jBs1&zM7 zEXG72t@*bCo4%qoI0V+sHg~Li6*A;(Earl(I)VrHGAlm__91BY2*v>S z0Tgh*rFY#M-+|8qeuBA0;If2~oJUx0*NPh%=R$?|jk#=VvvZ;CLccK+g@3Aw?@jE7 zb$W^}+*cid9bB7jRWl9P=V1?Dp)cyl4oLhY;YqT z*`@6o=W_En-?yL*0?F8>1ASelt)27Z(SCrR@cE$ zR(d=fO=E0vf0LH%)mJFHjzR8Py|e2pj$Q_Ldh@)RmdbAKdTa|zg=A^L)~UEQF>g3C zu~-b}N{cXpbQ{^Z`3n3XD|(|-B=5jy3qMXDXCHI$6_((GO5py~9DG&L72uO=_Oxcb z8dzn2!6&s^UYXaMo&xWWP9GN@n9sd==Ky|YoJA!bxO0K?V8Fi8t$M1N{M=>?`vQE6 zTeg|jT4YnxYU|tnpnX@H!9Endp*4BuW=Hw{8a4ZJX%0TDt)+ZF+r%Cp++C~Bh49d~ zR@QRSIL<|GR9Cen2saq;im4$UM;_<@KYQn)9oN1hrP6)>@MQ`2SzA*8<7x z>Y2Cm-gdHUchBiK#Y##bv~Y7X4+k=_N&O7xzsa1$+~kGmN7e4A=GM?3h*hJRBd;6t z`hC1_r|ygcY+31!2d!W8mS=5Slw))Slaem`ES|j;L(cNFZZU^bK5vRmTO7Q2g*B%^ zS^A6lq18U0qxk=nA6a`%zxr`G7+s-y<#cm4V1v@|a5vO*sD!q22F(0v4OV3*8>(#= z!PPjiNWQi``j9kgOFa)i2Fir6ZhXo_HX0=Qp7zf5=otSR#=05r@ddsB;0K5kGCr8M zxA}pyoX#3tr`mjUMyt<^j|^wMHV2Md*q+>z&kkjgk59MBcu&=P7dO3K^e;DO5zmDq z>+?DnxUIw1-3wz=N6W4&EcVLd$m6+iHaYemQ?T_HTd<)Gr!9MMs`qK5n=TCJk(j+p zj%R!P$@bUTY>fu%$?Q>nI$LQyC&^DV8N&WjJ!e*nW^h_7JF7MV?9x!lmv-%QyO~WN zMx9*g1Sf9XHcI^c6!t-Uy z9gOeM9(MLvA?%<_Uq2emj_>{`$(|uh1$lcO+QaMiyhmr>aeTFn)@eK)N+eT*dJC&F zV8HSD=#?gDZccCA+@N>2619GPv>(h1?fq=ko32k#yXb4f9SFNFuEVU#EiDLxuk+fR zKk)UrgF*80Hze#KQX=fu#`jYvUI0@QhJ#5Oo)>@I?sQokonzHOvKJF4{9xB*tdn3Ou^j_2Uzy^1^1)SWJ_oSnG1p|G( zW{cF|ySCmo)~|N?o#jxV7Uk!SL;VSx!l%mZmF}{wpG$+wCHsm$_=5C!C5;X7)xe$i?Q1R@jMPu1ad8tSMo!{F zuVVS^9gQxj86$5_>c8CPx0Qo>yL6_8lWOwMf4{Z|W0|?DcCMZ(iGFBzOXlmrgUejd z)3^P8rDx@FvdA2amL4|LueQ+h-&Kxgb&UQ3Nn`qZZ2$6FW16}@x-Iw#x8OD%Li6DG zdTf_I&dKl8Zj;8O@!g-^ZSot-K^9c~{zK(?CzZ)0VX{N<1fP#r9B`1W{P+7THD75# zdS~DK{TlDTt3Cd7@4xcG*pFG~eEYWklFYX7J;wjaRe%3){wc@ruk-(O$A8-6Kh@6f z|LmXk`2BVMpYHhE+C!Ky^EvxGcntDI6kbHqdpcXOt+T;JWXt9|LEo}-vu`_ia(t`D#G{NTFp^lF7l^=z*VCZXS;;i7A3@!)xpV--8kK*04*pYvCeHm>fG zC+lW?BLBA0pEHXU_ax7CVkiQ?m1cwk3APV-!#>w0&e+I5$A_>Ri3e3h6OWiv2HOc` z+|{Lq4{xAVxd+KNns&mS$q|J^7VgQq`~Q8;wqh(?-FKI`>Qn3?_z62rh!r`6|wd?}e71V)<=^L7^jx zEqfChVB@Zf(*y03tq>=)YfOP}4-Y zexOmw-_Ta;p@BM(jfuQsf2ZH5&vY)>o2$}tZNLWudyc6;iQlC*;JIQ@3Ex!A#b(iS z2iR4y?J1U_w^&@AZZJ$AnJo0+YTJ~M?FC147_^Au!pXYoZ9BbWJU$#xQ{JM^pYQb5p!|{xJn`*{j zTJaU-{GgvG{giQlEvAjORUoiW$MC0}*xq^qP6nRrrNH~d9VCwEW)QutLss@sCnncw z-GugZA?%6zlNmGF4Y*9R=z5buW-zM|?=vuKWCyPBXyVU_2ZwJ!@zio({cD*GetE?$ zKazrsWs(L4yaW7nUGY$LUxWuO@Ysz7ujoNJQd8=)(nq+gKkYowd2}|d=F|!iKw>uf9$k9;(dDKM>Z8}$Ld+Hd;8eD%b3H@ z*qF-XV-)b~w%Ktk%{`AX_#imNg!=Bbe)v*|pXBREvY8BXt&V#ztKl6QVPXg}S~`QFJa3HiiY`-w!qGGjduT{RlQQ}M5m zHZ${(HK4D+D_>8lxAubgOo{m2i^D5@rr_8J6NGDn7U$;G#+J@}g%+oEJ-oU@_*{ky zg?*xQpv#SptJseCgKi>dr=^+4I0~Pf_SDRkZ=L#|6^FGW6Tru)>9|GO0bX{O^#X45 z{63!?o}C--HOI4{HEVS7M;^{jJ{G|d_gcN+9?hPOtD*f(n|$96vp-( z&63R;(Z1R)XtJLK?U=Cn7nf}uT&iRLFlmejqQtGFt-Cq!wI7&Ri=m5!T8txv=pr6;l*tZ2eK+1YWh$SUly;uX`YXz(>jw4wJDc1 zWRLso#G~vnG$z6auUBKgaun_~lddbzk$c}2YLR{_v@6F?tB}e(hZ_QZHYL_nxJyh@ z`dzKJm|LC29sG3DX>S(umG+E3O}d8SdgE)we$`-|%(M8mZDRBJ?Ov%yX1o2faCo@g ze5SA>|8a10;%|CKh(__LpEu#o*THcWx`yplD08x}kBy1nH#GAuOR6I_QfsPqo-Uh4D#1Ftk@&p!rC9g@?~IY_?4tt>9YrylSqG>Co1`CU42$Y22&^ z&WGg$&R{k2aN4fH!ah(| zZ<3)%JwF`n3a5RvJQ{~8BR8HeCmsoWAc8jEVG6Rsw^JqR_N&pvZ931Erni3ko~dT` z&HZU`-7Rm~2v?&md z(|vs%+&V9N_^38Ab~`^G+>7y@Q(QGe@PQ4N%Ejkr56IXG2Q%#9MqEwnZorx*^YqR3 z4jVi%X0XBkFa>R$1-S@&MB{5~*QK3-{|&Eo{xoGv#1v`EuJxb0*5fQpz}TXNITo_Ox{B8rnoJ@WW*QvDdbSw2woEBw-Jbdfl-(b)6_Yy;%s)*)^% z`hs2$c)*XR2$t{y;}8zmd(IZIcCKG;DR_~{pL`U{4B{1!ZrQoFk?i0Rb^BA2xd)i&b`-_FS4tO2J=(i$?BH&;Lja@hInz* zITp{2QlV^{Jqx;#ZjaCT%`uy1??aXBGQ^S5wc89xaScXbA}WL4`b*Y9W*# zB_G5QeHY>T?{`_QFL;i-?BO=Gi}_0m`_Un*`0Yqo^JT^e?Kga7iYMw`zQWYMjV1)X zAYS+P=|3Xm%sv%NA1w2YpPRD0d4%{aNE+kNex=*ddFRl6CVajf<6Q0W_2^E|Gc$*a zAIzAeU!~#InoLrC;()z9PT+h{(@{I%aD7(h&&Ez9vxlHrv`8kj$Py z?=xYc*+x&IKXJxfX|DSEzP|T=C%w6he!0kw>FLV2{GMi7fAl;Mr2m+)Z3-2U19}Kk z*xB2xRzb7=>U+N_sZGAxMQvj4`n@MYzX3f$c(UTx(0|ODiVlOmW%FJB*@ln7Yx);& zy*%gYdHKsn%i;4_)CZW`nd4QZdieSFH4b;mUq<7D{?5b1uq1!@BmdE-zCQE6!}}_( z#zjC~Pkl;l2G>jc|Mrf4^-z0#E-631T#x*lI`?^V*y4%1DW1-|45l37&H1_?CLh!> z<`ObeC4RZDxzG>(Q@y>*q4~q#vzz&b{F61m zUd>;h&&JLC`3F4@)jP%Jt@nd6nfH9&+t+*~E;Q{SUL=Qqa9%stEz;-^Aly}8! z{I$M?>DbB`_4U;k=*!BJU%s6(tGYB;343vT4e^`&?w6+Q{^z`}m|dI&gheUk<8H^< zQx=EcX>a8uF4ud6~d7L*H6E!mHV=s zF@5fH>$y2MnSF-pO0i!x?|><{``gyuF?mspM1u{2m1T)-=XKHadtk$+9lC}qs91w0 zhKu2Z>A6>xCMT*O3v7zg%(DvD_9jWp`0{$bg9FzwdOIIz2y+SLnfZ!wu5m#-o)v@Z_5deT zyG_6X7jP!4y;HhzpVd#alQZPTCJ!I^PnReLQiYI08<wETrc3?73Qnpx^{HvY7wW{4`r*XNp?HzOa2lzx^t%;@*eT&B6 zA8jK&JMINvS=h0(Xp1e%fK8fwGA{Pd%C&LMmhYWmemLvT5<#aqnVr|fAJX?VcU7@T z_J{F)34OH$(fg9iWMz)tC$Sh)@Ocxs;;9;_AAht3I+z%iX==9m7o`c;*foSJhq=XQH{7c=#7 z1~+!$U9+tO`CGrNEq(vGqD*u6YT!7nscw@M*ul9$vpR3@QZBsbwY_>I zKWO*C*2X?+dOOpnjDBJp?dgs<@AY&3h@TGYUTCmR-naAnWdgR;O%HCjbEX!8d)9`# z#qZ#I^>S!&f~|RQBfaO^+ltSIzAdpK(HnkDG0?xd%gND+6PNC`e03{#XKjTG$9j{x z)E@7LDT2*7kh``QIrwAv2Ez*`_HOfhLihMwszfs<#z=Pi*dIFaj@qDa(=Nor+wh#R z-olqgM$luIx}QCz^(u^$wt_#U_u12I(ZrpAU7@E6emlPtWXh}9)DL*we(&2QepU>| zWH?jImsyXA$+^&)Hzanh)tn?wv-x2{Jh3)=i{z0iCRQ3g8?DyUD_M>uz1^pHci?Qf ztxKG^PCa_XYa>w^?bDZRDJ{KJH%GZ%&!xdYx4ibAoqM)h0CRr1R<*c$cHAI);vXlj zK@2(v_+RTW7TE)MaTCf`(2d)-9P?Q8?pUR#YZW7fJa)o3Z4!p-99HZ;%FyF1ftDyS zQ>~KotcT}Gd>KNwF5e;k9fmB%wT#2@BfbH&S!?#l97gw5htG?H%`$rXNI6*lGJ{p? z-m$=jHZI)h-&-Xe$KUgPE}25Neu*qmNYI>>3;-CV&8!=v@` zvex`JNe(jP8!QK{WZ`eGFme30qf4hoZ1nqnTEEqt_FlYdt8;M`KTk{74-@tS&QjUI zuD}{xxuiV~7U+d*uY|Vq*_i~Ag;CJW4x;&EeY{@A*4J#WbZKwXj`bWoyREkTW}MEl z_(aS0=1db#W}3MyH}|y@+HRNK?JCvnb|!O)yhJ;fd-k?kZ=CFWFrFuegjCl${PX>Z z(HrC(z!^Qr*)+C~B>Gb~IhdYH_B8RD&I`jdaS8CxIc7p5{CalSIlk5$`lR|0^+1~O z(EDxlMV(x=vToY5Vz_@B1d8Rv4*!@H>*z(kC6^^5sFm;fzvCzNrxrxrUvU$(zA95D zW1QRZ@znV|P}ZKswEem{*kVI}-o|R_Wt|G!PIBI`@&C!ZxFPc`=l)OH8_4~CnT$Oo5=<9Q>jA_wAOzu2eiFY0 zT(g`jF)VSlGEFL*;W?QiN)F;$CcHVs1oYx2ek6+V>IidVH zd&z%SZnX#HF#ICrnI|Uy`p?G@Trc-@io@M~G-%&ra9nSlYgcVT{{vHaxlohj_x9Bu ziQsE9JECE^`t9w(4R0Ii&HL$1n9?inwY)j6;VEI~L&ssIWEXF@Y2(oJ@f#Cc&OO4* zGd4Z-E4z+g=IDU^3g4?w;I#i;L;UeM)W4u9ff)~eS$_H7J!X!nLa^Sr9fP(0ezqPb zVo}qj)V=6e;BKc-ewFaYM?P%I;cKJ**6}f{UkHZtFPIc%QoAtD=~u5;J=SQ~_w{bE zk_uy^&v>v8RT4vtT_`qHw4dma}9&Gzqr%kTdD*ekCH~mZ?`d7YR z#|Lcy;gDwP31gRj^4G^L&++?}KhBNj?q~cf{}=#&=QGWBCV^9dDM+Ih?&FrF7F(j$ z-~Uh2Kjrv;tD*jBkAK?Z@2G))`qlqgt%9FvzirM?!kF>L3EJ<89ZgOhsqkH65x|$t z;F?;Lqp482+M4X{*nlFfYBEwsmaiQ{o8gwMPGOcNk*l2JavA_RsUBJ2|T!0zqs{_+#u?%NN+%@s0anq8vfnV46vT6XKIh zig3>$bs506FkCIN&OM9$-CBSNh+9$Z`n)x8Gx1%7m&iUZEX@mnF`$#@5#Mi(o+7ql zxLsBJ%*O?)t; zp{mbf>R&zjl^^#=7^sJ?q_|(S8Tg6HoLwZ#MRaBH_xR*F3V#VxjtH1}B2B=T>V1tZ zPI{KYWH(*n4i(Gr<-ol|*tUxOTc%jtEP}FYcd-de$5MP$>}n6}c&RRN6-&!Tbg`Ic z7jS#PpHO=h*^5W8SAdXHW^A@oui3uvR#W);enMqad%E1vMgcVoTkJacn5jCtXuu_=8n zdU(#!k9zyAe5M@Ym65P#)MM$vj{8mEm`;QrUr^e#R!DIaM-hB%_N(fC_2|wkquce+?4Ms~#lEb@{o(fC931-e zXAOU59>F_T?#LoNk{PN*3$LL zJe3+I($m|zdTCcY$9Xg&*gJQtRuU1Q&8^dX6fj!>Okuai+`GO%>y^=xo5~*asWTx5 z9oZ2xq4Fq!24b`0Zj9cp)&=?#8k%dx1Ai-unVCv7vG?bFXt zcQPkdK_r$eL`uni*>c?@^YL>k4aG}mSjrR=twRgIz^g`4xZF{P_#J$VKgi{T+2%v5 z#(eMVI1d<;srr5Opr3&~Z&D3-V2Sc*gty>jbW{l+qMRWr?sp|>uR&`<{ZMoYtwK&uh_O~;34VptCwri z=epp7_>er|ZXUs}ywJRvVlH@gZ`o?}y6S*Ur828#6utpPz^CP>#n5`8F|xQ9AZ>VX zX|dP1QceAH*NAJ6Yo+!rCXTZ{q$w-B`jJ zMrMmeb4YwTX?|DRlVswQ*_Rj5T^4TrHQI&4!afU%oxY~5x>aP0N{4!A9JMyrWizp|FJsovBIEv3{J}`bk7;SOe2kENgnJnDXO%`|H%e8< zBQUi?Z<@GI;dL-?zFOo5`f{B52RrM&23~Ku5_ec@(R^CDmqM$_b+rsWU&}f8Gh+lE zq<8JX^JY)8EiY4vBg=e3n#&*K4{~oXz@+0!J3?`s;R0tL>>pzN^&>kG*Y3Gqg!ifb zeOh1Su?-SSakyo!f`?F2oYWD04Ltd}9Mm6hwgQ1>bk10hFNhr}Oc#DP?ZtRu9L=7t z`&u_vcsA}k9$F!v;}1%wKN13LEcI*I^dloZk0Sm@=ty{>nLV9X*Z4JDR^6yoT;bVM zN?bZQbeoBdx_PbXJMih#6UT$myv+@tUBiEzFsg{x*=yh3ZTjdeBlF}V0`K^_PK}oL z_PxDb#v(KHIX}lAG!l){0!V9JZ$wA;Me@!zuf1$lZm;?z@F@l+UW3=OA;QQ?w?87RRFV}3azI!;QkPQzZ zpv08>3H~5?580e)oXKOni zCc2SIzin@a(L%F7nspP&`!jpBo$hsW%|1J<5%NWpfi$sstn6)bHKYJK_oO*XeS|;A zwaB!VA+3iz-4S~`FMJb!Tgs<jE32FW2f@{ZAGr1N zcwl^vIdkBD%-mbQse<&+U?88sLGT5}M^qTN{HFt|Go77H9qlsm%OE8JmoD1OCT1d9 zf~srsYOoqOo8TR{a^&`!gcA5z+yXbntL*_EY_E6m?&kBuh-+#;%33?3;3vhgG`0u7 zFQ`d=nz)94M%P%62F2e{Juwb-585SIttNY>ZeLHsJ);Z<>Kn{S@WxT08N|yBY>$on zAe1?;(-yu!Y`xT0ua|S_r18f${gyZZb@UJFU^-NosUwxa)Z0%B@}GZCA6`8zqZ9h( zs~J4)jZ5{euVW{j$@K%pYdBe5hwiaaV}QRL{5BN@p4anLq91`fQ%_(~bGJK!$601l z`HhKkT-MUSP@d4R{5P!g`FdL0c{wr;4?^unHee@rZT9uxhJJfJg=4)c(Rm*H9AC24 z{Iwb32WMhP{Wko(j`NNw!>|9TJhX=&8xlN|v2xC~O3|H@oh>e7;)_y-($nvYaEj@F z!(>c89>f$KJ>cUwbY7Z+lm2f?d#4vSSY~hfXKw0ux%~Nxy{>bAwT@roh);1#?&(X6 zq2BSedR9-;1oJlSz4IOaQDf%!rfE!m}6YLACAaguVe^YwnFyDFRz9xU#E-5A8`J4U(FG)#xGvx{eZJwAlLj5cgl&u{b z^&_Ou&HD-LKA%da|8iYo+9^N&ng1&@vb%F1-P7;qJW(E{g&@0TM0_)i7d^gzW6H@J zdMn8O#{Z1CsNQV<>gKr`cnG{T_HgD~ANkMNivPHtKW0_e?`)Zcm>2xBzvh>`Y!mEX zR5rS~c}NRE`O}_R@7ZuTvD=$^*~vzw7-S=CFE-`SbWq{rVQD{R#s%dG1&E{mwa288%DnnNd^bL1EqA>P z_IDfq7}>?SzR$VjD<4QZ)y-FWk7dRQ_(X<%FnOVGs6NSy&UV3_Bq9TGVrK`6qx!mA zUB}Rtst*&%k@6R8UEg4E=5wsfKGu<$G1LwO?@93Yp8*J~gaVb_78fe{k0?7 zh-Ri<$AS+S!?V6A{#MuU*SwIINUxnC~e*8i3IO%ACp&9L3_>gez z{5JENuGJa4*+Zl-EK?S$%{Ft%j|=d10p@(#SMxq8e~K)KM+P?v-lEqvd{e{u61UD3 zU#eO=JI(xlNt~ul3SQ9!Ja!>0S2iy=X<&+0vjbK=*re9%r=;mw1XJtc`@f%oGsZ@7 zm$RVkG9OJk&yuJg#>H+~L1^g07$^!q22%rL#>OZd8T_~?4rI0zC=n;^(2hkO*HzSo zE6jM2{he5L8Y}C|B3m4l!odi!Q-j#CV=cHz;GNj+L8nixv&TI(Z-1^J^d(=rLt`!y zcw`l?GDII&A2QgWbmM3T#<(|W+0}c#cb%WyS8cXiHW%4pW-zF&%Z@t`whWFI%F&F= za=AX)JX6DN)ty)&J2y{^SI^FzcBwq?j+Zo(y{{$pk+NVP!S=?b?6&lk*gJrS(?3jG zbcK(j6D->=*z$e})N`*)dh|L%VBv_k^ z-r}j<3fPm*>e!lLN5x1-6EdJ~nsh*rpqE7i_SCs&C@=5lF2za<<``(|I;e ztNhDx=fs>!Rko@1n0jMf|4a&MFQ>hZP5i+|e=97Ic@(acnP+XcLx1mv^4C==4>3J< z-=rJFcZ_2X*?>P$#wP}?@Z869&=-B>#5)3)dbYhB+#TW%E*FOiT7EdfTESWUwgWRN z;c%0JKREbIDY%N6Yum9zu%05mA^msKa=Xk$9k0Khce>|R|Kh=Op479=`F)Xs187&y z+0;Rl32BH569j_-uYp^HW@>la@$ntXWU$XEnw5)|;tzV>1C7$eb$v&VHG7#XQ~l+~ z%3*ZPVbj#_%q17_7WwTIlUtgFezu(53v+Os3Rqg^mQ7R6-l{cOxAz%%cW|UI>VQ4R zC*V50Clw5i05|eT8HDBb#$Ikan-NR>aw9}EO)r+W-v7S@Rn z{W-?Eo2ur+?aBB)NjECall7y%Xw3WL270iYXZ4BJBl4#Byw^tH%#3qz!dH5+cB+?Y z;*sr6-P_XwfA)^j6jhti|D*?diM|j}T{OE*yXvMD2li9^!60+)c(!J}kUtD@6ip20 zY8}32q#P;4vWL}@{+2&NpKDL%7~RMdanl&*En#Z32mOfnsor)P3Em3L;XD=zl*7l2 zMNIBj-`lpn#tVGa?f^UWz?;pxmG=3L9$9nrG5#PpROea#>#GvM<6X<~9W{qs^}3K#qv{+6B|0T4O-%&Vc z`_(HkUZSsSW-(!CZ00wY7=@wy=lFwxVvsotebME%*}32^MV`=?V2)>=$}Si4rSwI` zmrEDz#ARK>3K~ZIZ3(^!b}k)Z^n@v!xX<&46>mMWEpXD_@Z5ezq~(lm__iPK&-Sg+ zahwP&CiepCW&emy=lo;*L34K2-lQB-AFG}7C-g;k^>c!4&^<7{@5kYMCNsW`>)q=d zjrWN7mx06}Q^}WXw=(L-3#W6i5asAKO5EayJh2INrq6Sf&7idJHmc)FaC}eZZy9HC zYd2W;#~XiN^5s`z`v3{hAG@<=s*|-(rPX1bOWAE}{YbGc%C-yOv%V4q{xm}JJhy+I9-~>^#+IdP zlOo*fcku_=w}4lr2BRsaYVQpj__lV;ALN%6@!6b=M`7De^lN>Sf7z>fxFG1OAU09$ zLBR`dUe=WjMQ0sT5cB`<_)quaF->mR8=6I&yu-_R<2a_`m+mQZ#I6zvY@wF>n4218 zYWO+zNpNV&;oTrrW!YB2Y4OWpy4UY0hVG~KxMsJ)2dR5;yZmIH3j+i{n?7Rg{615# zhO0H}`i-^R`)!t! zE6W`5XTRFwSA1=Iy&W^#LVjN!oQ`f|5K8POi3{bX>bJtFv0A<2=!=S1JC46BTlh3* z1>=7%8_jP?kwU-d?eHZf_`ubYGNz&5ge$4QH1$`2pYb`Hae(lEK={cz+t6@OgDiS0}+L@!E6X zgCyZ?`W@v2TkBr;-l+7r_3u$rWhMfGai(~Kk*3l2KvH&eht5q zH|SI5{VnRGFO1VyZ<>5`&d(jbro<2C>}hO$8YlnXB=WioU~88~tyynnZ+)lVH}Agh z_?Q3wQ;xq}b$`nb|7nlErCR^;MgM7!zg%^H%MX83dvI3r=XK_G`6lj!*^5J%&-t4< z<4?+d2wzF`f+;Feuz| zfYvZc@;HhQZzqF3+@&{vp75tM7xDMd+(R4+Kb8jXYyXpEPnQgmheD~|o6N=?*`970 zBpak%W>x#ru5+{K5(={sRwz3+x}(p`gT2-ux=7BKw{?CwtVhrX=giA_%daE+Xg-x# zTfy&jKBElMmKJ}_l!bFgB+#yAPTS`Ga$8+2Fbw?or5|SrBLvsk2a*hI9(~J$RyQe3isy zRe-x%QCuIeBQR|Hlen|+8~H{XpHW>q(7sgCPb7!P0~n^_#>wxUzb5V@dYoBs*(^Af z?>k_>5UZ?sK^Jyy5vcAF*Hjkza4_6M88*h@^kXl$eD zRSuchb;=L;8hlM`jo{2ib5lI2P|L}94Ps1@U-Su$CaU80QSY<~@3p+nBy(F$;)kV$ zzix5hxf9y(jy@P|1U@&sMT_*`lKSt*(vB32)R_%lg^&7XIflW6DTa*!lmCHjV;I>Q*-Wi`kB!Slh&tx0y@nxo@4FPzA@OoK%ADrbv^JVvrR17 zcN+FJm|LX__PsNSH!u0e>G_O5z1nbodlYVNV7X~EDn1?`>(WBS!E{w>t#Urm$) zUknq2CqBFdnLp8%R$Q-ch_Qf%-x~EE>F#bq_9j&rS4aDxyFuS^8=r|Eh3@0+wb^c+ z?r^wkPNuC(VGzS!91YaNj+bu11A}wa!k6Gus-JIJ#m|$b^==uIju(DJAL0)hT+MIe zL#wgJ)=vK6qspg3{w^v@c2joNU7I+Ix&88Ryk(abR(W__=>@ngc53PNNl)Oq8IL4lU|pR7^JTHKc?9?NwLbzsTgHNk*nar{w=AuRb%z15G$QU`mwXGi=_($f zw^b}M+6-OG_T;?3x*2gI_rtmsS(#UQ6Y$!h!M8X}a_)VS{^5dYdM0qS^*r6LQk0`9 zz2{nG-4>?lZgOqnq|*0G^p$v@n0BiFTYnY`RZdy(xY6s{K1RSgr|6H;@223l>Yw7< zPDkQ<+tZ-p$#y@-9}L8aLmgs02Ghrfq{CX_H8cBGF%awLtMon;9IJtw8;V5tbvSpq z5!fs|I$~OG6!TG;yk{3(ZmK@0xiHUjc8y+753O{C1XHwALC$tz6%*~-x(L=8-Vu`% z?(D0Bj|pr2i?S_=P@6J16Z+bU#kqhpNWT(x$hQ$RfD2MNX3}A6FzSmxsCDXN{6WJR z3xqPEOld%*zH0`&v)dfHS>~+npmBB%R0OEjoH_AFMG*6v*Knyt#tkF zUJJ}u?T3{v-?BY|?zXb~^y5J6^TW1PU928e;?=I}typ;zwIk(eBir4#?i-zDKE@x! z)+c)(dqjf~MX%EX5->iLdaiwe z_Br9*Dpfn5?Or_=8PpeOh_uhoPRF7g*-i7l8?yrnvS;^wMs@DZ>&HJ!Tq0=WcWZ2x zUvY=@-p(9g`D@~=m@^f5O-egdcoPvHkv~U-GdJ9h>Vt4?f14b`m3nzU>#v#%<}VRH zrq5?DJO^8h-8%VUD>iELJQTFavL6>D`Z4~X!5U>Z);aJy$p)+QuG+}NQ^j{q%R?9#C zKYzRWefz)iMAzcMxi)AU&ZXR4vFGc(wmIW+@A$AzSW%>0hEQm+spVd zsA~_~y9N17_W9QX{NO@4y-~ebxvcAJ;|Hm|;V$##XD!8;;axild#We=!~gtsTs=0kb0@IS zJ-z|X-73p#%JWr^f29e2`3-H5=6b?{xuDEC!thP|Xl&5l8RFXz7kv{4>tjjYl0o&U zp16dH4f&)%ty7YE-VF;@e^5V67qKdhM`GE_U0|&i;fE(ywx_XL~$vR)clBJi3RUx#`yJZNa1c;;U`k?D#;Y zE5bMZ%o`32XSm;&&Yc=(iLd;>vD#nC0tooH5^la-?ac1l%d6kfpEPe#X7FeF*UJiw zllg)6=|Nju9wpoS|2zJR>@%e&F}BGFW5f4nFwga$%A!1PmrwCe{jse#l<%){pn?Nl ziyzUW)T;-^vh8X9`_%aUAJ@T~6T%O^*O*_qUz&sRibtZDU5YoT@hfhN2*;YA0x8$J zU3ji|SY{8vU*5N+Kk)0CrMLgSM4rF%&s|u5jXhZTG&eP4R`ZQszU@&n@@II#lo8)% ztGyDv84F)HXn1-0Ze0cbedXYeO7Hxe7w`YnRw{>W$EaJ?eE<#~f3&{wT6+W=KL%?y z<0H#(j`V#~X3h71|9q>vnWVhF`;p$z>vvz%``Tx!Kbid5Uq0sbXwWw6gDRfjD7y{u z{lE$+o4+Tdd;xq;%sk9jK9F?(ydGcuA}_o{Z|Jq!T{d_>5zt<2~;dEWjn)wxZ=QaN4rX1woaQFE1W9h4oxu5CS%8&L9noGXR(kdgJ|2Uq(A6zY-Rsb&U2C)~3(D@~(2|H+l0OZDQIPKV5JFUtdyZ zca`I-&H3r)k{X0@VD`Pb2QSsH-{VAif&*kUP1sbhhDCR$FbCd;JzYndm77;T+qY)L zaeCJVo^Xv$Z`vs4kC4*LI3Yf&ccx#mAIT>e+y3=K`I*i&U+X%z_+c`A$qw-6t4?Wi zCM56)*cH30CsHY42lER6ozKB*L<6iIE3A{vz}D1t73eV z=r^79Js98D<(Q~^L%-1Zll$pB^{KSuLT0ZZ%u!{L&#O6e2U7b}ewJ8Q6;n){H0&wZ zQNR(1&0=iVK5r1*N_Z1oJTC+Wr5I-X701mB*Lj6miRKIYwLn9A$jc< z;mS!{l>D3cl_BBEik&E4AoXtY3}45@heLY|4M?N+TEt!-qO2*}FN6+NMZWA@CsuZe zKUW-Pz@LQ)e=eyHX|JQP9kc_1V+$@I+#PEVQ69>+sqYr^)v%TfJL?5wXVLOpS2!v5IIDz2XMU1MHYkU9`yWdoTa%?( zcSEE28N28O4ce+OapBFfl?t00xa&(A=(E<2?!*0SWm=A8Y8ZY(*io?=iX(}SsJMDr zuQi&^>$TH5QYuG|Xy0Q01TDq=VS`K#KpQ`XPG5W?Jht6x6 zc&GL)8&AEqr5W)DhmKY2_2b!lWS0pHYMlb)JNMoh6zy6zvr0AL^*p-KrCdYK~H0$A@H6dP2zbd9#RXXG8gHsGPs7!?~NgOru@L z$veKMEW!xKFSu&%29!SsNw3obV;EMwO$(gnxFqP*>A9}NiA&Smw+`px(Vh~=Gz0c* zLAQ;OPQlWG**ar>cWdq5&VG1s-)|oPez< zhNZV0ASQ*OME(Kbo|+4`IjF-S=jryVyL4&{CyX(FU5xIr=(^dNXg>TDe-KSX_DbkR zYcJ6`&?eP+xm(*T{4|>ZPaJo2#?X?WL**NTALA5a6;Me52}q0t;IRWa*#RZSEo)X3C1}A3uUZ; zO?zu_&gaz0wc6sM=U|G!x$9AP#gFj^(Rs=4PqW%Nv%I^5DDy6HEkhmox-IA9#pssp zyPE|;zw?FDYVacVU=U=G_{djciN;rO9mylST69Jq9p);-6^U>7%lHZRj+y4=wHXJN z$wfYYbo27H9M9&}W9#nD665LT_=5@g`C!Z7sCisXrn7myHyyny<cqL`_peR|G}@|WDH{U}Bv_uO%Jj_h^r)1HI12@RJ=rx1

`MaT#wEhKe$W=Lug)2Px3PuD_)!R-`i<&* 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 Mxh(Gvl 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 z

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 z≈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 F{~zkx!Z!c_ literal 0 HcmV?d00001 diff --git a/lab8/kernel/Makefile b/lab8/kernel/Makefile new file mode 100644 index 000000000..f14f16b85 --- /dev/null +++ b/lab8/kernel/Makefile @@ -0,0 +1,93 @@ +CC := aarch64-linux-gnu-gcc +LD := aarch64-linux-gnu-ld +OBJCOPY := aarch64-linux-gnu-objcopy +GDB := gdb-multiarch +QEMU := qemu-system-aarch64 +KILL_QEMU := killall $(QEMU) + +COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only $(cops) +ASMOPS = -Iinclude +QOPS = -M raspi3b \ + -kernel $(NAME).img \ + -dtb ../bcm2710-rpi-3-b-plus.dtb \ + -initrd ../initramfs.cpio \ + -drive if=sd,file=../create_diskimg/sdcard.img,format=raw +GDBOPS = --init-eval-command="file $(BUILD_DIR)/$(NAME).elf" --init-eval-command="target remote :1234" + +RED=\033[0;31m +GREEN=\033[0;32m +YELLOW=\033[0;33m +BLUE=\033[0;34m +PURPLE=\033[0;35m +CYAN=\033[0;36m +RESET=\033[0m + +# Set the TARGET_PLATFORM and _DEBUG macro to be passed to the GCC definition later. +ifdef DEBUG +COPS+=-D_DEBUG=$(DEBUG) +endif + +ifneq (,$(findstring pi,$(MAKECMDGOALS))) +COPS+=-DRPI +FINISH_STR = "\r\n-------------------------------------------------------------\r\n The $(CYAN)kernel8.img$(RESET) intended for the $(BLUE)Raspberry Pi 3B+$(RESET) is ready.\r\n-------------------------------------------------------------" +else # Default to QEMU +COPS += -DQEMU +FINISH_STR = "\r\n-------------------------------------------------\r\n The $(CYAN)kernel8.img$(RESET) intended for the $(BLUE)QEMU$(RESET) is ready.\r\n-------------------------------------------------" +endif + +NAME = kernel8 +BUILD_DIR = build +SRC_DIR = src +LK_SCRIPT = linker.ld +SESSION_NAME := my-os + +.PHONY: all +all : $(NAME).img + +.PHONY: clean +clean : + rm -rf $(BUILD_DIR) *.img + +$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c + mkdir -p $(@D) + $(CC) $(COPS) -MMD -c $< -o $@ + +$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S + $(CC) $(ASMOPS) -MMD -c $< -o $@ + +C_FILES = $(wildcard $(SRC_DIR)/*.c) +ASM_FILES = $(wildcard $(SRC_DIR)/*.S) +OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o) +OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o) + +DEP_FILES = $(OBJ_FILES:%.o=%.d) +-include $(DEP_FILES) + +$(NAME).img: $(SRC_DIR)/$(LK_SCRIPT) $(OBJ_FILES) + $(LD) -T $(SRC_DIR)/$(LK_SCRIPT) -o $(BUILD_DIR)/$(NAME).elf $(OBJ_FILES) + $(OBJCOPY) $(BUILD_DIR)/$(NAME).elf -O binary $(NAME).img + @echo -e $(FINISH_STR) + +#This target compiles and runs the kernel.img of the QEMU platform by default. +# You can use "make pi run" to run this image in QEMU. +.PHONY: run +run: clean $(NAME).img + $(QEMU) $(QOPS) -serial null -serial stdio + +# This target compiles kernel.img to run on a QEMU. +.PHONY: qemu +qemu: clean $(NAME).img + +# This target compiles kernel.img to run on a Raspberry 3B. +.PHONY: pi +pi: clean $(NAME).img + +# This target will run kernel in QEMU with GDB attached in a tmux session. +.PHONY: debug +debug: clean $(NAME).img + tmux new-session -d -s $(SESSION_NAME) '$(QEMU) $(QOPS) -S -s -serial null -serial stdio' \; split-window -h '$(GDB) $(GDBOPS)' \; attach -t $(SESSION_NAME) + +# This target will kill the QEMU session. +.PHONY: kill +kill: + $(KILL_QEMU) diff --git a/lab8/kernel/include/bcm2837/rpi_base.h b/lab8/kernel/include/bcm2837/rpi_base.h new file mode 100644 index 000000000..f640aaf4d --- /dev/null +++ b/lab8/kernel/include/bcm2837/rpi_base.h @@ -0,0 +1,7 @@ +#ifndef _RPI_BASE_H_ +#define _RPI_BASE_H_ + +#include "bcm2837/rpi_mmu.h" +#define PERIPHERAL_BASE PHYS_TO_KERNEL_VIRT(0x3F000000) + +#endif /*_RPI_BASE_H_ */ diff --git a/lab8/kernel/include/bcm2837/rpi_gpio.h b/lab8/kernel/include/bcm2837/rpi_gpio.h new file mode 100644 index 000000000..e5133708a --- /dev/null +++ b/lab8/kernel/include/bcm2837/rpi_gpio.h @@ -0,0 +1,25 @@ +#ifndef _RPI_GPIO_H_ +#define _RPI_GPIO_H_ + +#include "bcm2837/rpi_base.h" + +#define GPFSEL0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200000)) +#define GPFSEL1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200004)) +#define GPFSEL2 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200008)) +#define GPFSEL3 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0020000C)) +#define GPFSEL4 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200010)) +#define GPFSEL5 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200014)) +#define GPSET0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0020001C)) +#define GPSET1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200020)) +#define GPCLR0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200028)) +#define GPLEV0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200034)) +#define GPLEV1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200038)) +#define GPEDS0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200040)) +#define GPEDS1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200044)) +#define GPHEN0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200064)) +#define GPHEN1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200068)) +#define GPPUD ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200094)) +#define GPPUDCLK0 ((volatile unsigned int*)(PERIPHERAL_BASE+0x00200098)) +#define GPPUDCLK1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0020009C)) + +#endif /*_RPI_GPIO_H_*/ diff --git a/lab8/kernel/include/bcm2837/rpi_irq.h b/lab8/kernel/include/bcm2837/rpi_irq.h new file mode 100644 index 000000000..8423dfea0 --- /dev/null +++ b/lab8/kernel/include/bcm2837/rpi_irq.h @@ -0,0 +1,24 @@ +#ifndef _RPI_IRQ_H_ +#define _RPI_IRQ_H_ + +#include "bcm2837/rpi_base.h" + +/* +The basic pending register shows which interrupt are pending. To speed up interrupts processing, a +number of 'normal' interrupt status bits have been added to this register. This makes the 'IRQ +pending base' register different from the other 'base' interrupt registers +p112-115 https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf +*/ + +#define IRQ_BASIC_PENDING ((volatile unsigned int*)(PERIPHERAL_BASE+0x0000B200)) +#define IRQ_PENDING_1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0000B204)) +#define IRQ_PENDING_2 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0000B208)) +#define FIQ_CONTROL ((volatile unsigned int*)(PERIPHERAL_BASE+0x0000B20C)) +#define ENABLE_IRQS_1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0000B210)) +#define ENABLE_IRQS_2 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0000B214)) +#define ENABLE_BASIC_IRQS ((volatile unsigned int*)(PERIPHERAL_BASE+0x0000B218)) +#define DISABLE_IRQS_1 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0000B21C)) +#define DISABLE_IRQS_2 ((volatile unsigned int*)(PERIPHERAL_BASE+0x0000B220)) +#define DISABLE_BASIC_IRQS ((volatile unsigned int*)(PERIPHERAL_BASE+0x0000B224)) + +#endif /*_RPI_IRQ_H_*/ diff --git a/lab8/kernel/include/bcm2837/rpi_mbox.h b/lab8/kernel/include/bcm2837/rpi_mbox.h new file mode 100644 index 000000000..ba1001472 --- /dev/null +++ b/lab8/kernel/include/bcm2837/rpi_mbox.h @@ -0,0 +1,17 @@ +#ifndef _RPI_MBOX_H_ +#define _RPI_MBOX_H_ + +#include "bcm2837/rpi_base.h" + +#define MBOX_BASE (PERIPHERAL_BASE+0x0000B880) + +// The register access to a mailbox +// https://jsandler18.github.io/extra/mailbox.html +#define MBOX_READ ((volatile unsigned int*)(MBOX_BASE+0x00)) +#define MBOX_POLL ((volatile unsigned int*)(MBOX_BASE+0x10)) +#define MBOX_SENDER ((volatile unsigned int*)(MBOX_BASE+0x14)) +#define MBOX_STATUS ((volatile unsigned int*)(MBOX_BASE+0x18)) +#define MBOX_CONFIG ((volatile unsigned int*)(MBOX_BASE+0x1C)) +#define MBOX_WRITE ((volatile unsigned int*)(MBOX_BASE+0x20)) + +#endif /*_RPI_MBOX_H_ */ diff --git a/lab8/kernel/include/bcm2837/rpi_mmu.h b/lab8/kernel/include/bcm2837/rpi_mmu.h new file mode 100644 index 000000000..e0d82c7dd --- /dev/null +++ b/lab8/kernel/include/bcm2837/rpi_mmu.h @@ -0,0 +1,18 @@ +#ifndef _RPI_MMU_H_ +#define _RPI_MMU_H_ + +#define PHYS_TO_VIRT(x) (x + 0xffff000000000000) +#define VIRT_TO_PHYS(x) (x - 0xffff000000000000) +#define ENTRY_ADDR_MASK 0x0000fffffffff000L + +#define PHYS_TO_KERNEL_VIRT(x) (((unsigned long)(x)) | 0xffff000000000000) +#define KERNEL_VIRT_TO_PHYS(x) (((unsigned long)(x)) & ~0xffff000000000000) + +// e.g. size=0x13200, alignment=0x1000 -> 0x14000 +#define ALIGN_UP(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1)) +// e.g. size=0x13200, alignment=0x1000 -> 0x13000 +#define ALIGN_DOWN(size, alignment) ((size) & ~((alignment) - 1)) + +#define IS_NOT_ALIGN(ptr, alignment) (((unsigned long)ptr & ((alignment) - 1)) != 0) + +#endif /*_RPI_MMU_H_ */ diff --git a/lab8/kernel/include/bcm2837/rpi_uart1.h b/lab8/kernel/include/bcm2837/rpi_uart1.h new file mode 100644 index 000000000..959130656 --- /dev/null +++ b/lab8/kernel/include/bcm2837/rpi_uart1.h @@ -0,0 +1,19 @@ +#ifndef _RPI_UART1_H_ +#define _RPI_UART1_H_ + +#include "bcm2837/rpi_base.h" + +#define AUX_ENABLES ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215004)) +#define AUX_MU_IO_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215040)) +#define AUX_MU_IER_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215044)) +#define AUX_MU_IIR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215048)) +#define AUX_MU_LCR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x0021504C)) +#define AUX_MU_MCR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215050)) +#define AUX_MU_LSR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215054)) +#define AUX_MU_MSR_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215058)) +#define AUX_MU_SCRATCH ((volatile unsigned int*)(PERIPHERAL_BASE+0x0021505C)) +#define AUX_MU_CNTL_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215060)) +#define AUX_MU_STAT_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215064)) +#define AUX_MU_BAUD_REG ((volatile unsigned int*)(PERIPHERAL_BASE+0x00215068)) + +#endif /*_RPI_UART1_H_ */ diff --git a/lab8/kernel/include/cpio.h b/lab8/kernel/include/cpio.h new file mode 100644 index 000000000..bfe2c7044 --- /dev/null +++ b/lab8/kernel/include/cpio.h @@ -0,0 +1,47 @@ +#ifndef _CPIO_H_ +#define _CPIO_H_ + +/* + cpio format : https://manpages.ubuntu.com/manpages/bionic/en/man5/cpio.5.html + We are using "newc" format + header, file path, file data, header ...... + header + file path (padding 4 bytes) + file data (padding 4 bytes) (max size 4gb) +*/ + +#define CPIO_NEWC_HEADER_MAGIC "070701" // big endian constant, to check whether it is big endian or little endian + +// Using newc archive format +struct cpio_newc_header +{ + char c_magic[6]; // fixed, "070701". + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +}; + +/* write pathname, data, next header into corresponding parameter*/ +int cpio_newc_parse_header(struct cpio_newc_header *this_header_pointer, + char **pathname, unsigned int *filesize, char **data, + struct cpio_newc_header **next_header_pointer); + +unsigned int padding_4byte(unsigned int size); + +extern void *CPIO_DEFAULT_START; + +#define CPIO_for_each(c_filepath, c_filesize, c_filedata) \ + struct cpio_newc_header *header_ptr = CPIO_DEFAULT_START; \ + int err = cpio_newc_parse_header(header_ptr, c_filepath, c_filesize, c_filedata, &header_ptr); \ + for (; header_ptr&&!err; cpio_newc_parse_header(header_ptr, c_filepath, c_filesize, c_filedata, &header_ptr)) + +#endif /* _CPIO_H_ */ \ No newline at end of file diff --git a/lab8/kernel/include/debug.h b/lab8/kernel/include/debug.h new file mode 100644 index 000000000..2e7d97904 --- /dev/null +++ b/lab8/kernel/include/debug.h @@ -0,0 +1,19 @@ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "uart1.h" + +#define CYAN "\e[0;36m" // 青色 +#define HRED "\e[0;91m" +#define CRESET "\e[0m" + +#define WARING(fmt, ...) PRINT_MESSAGE(LEVEL_ERROR, "WARING", CYAN, fmt, ##__VA_ARGS__) +#define ERROR(fmt, ...) PRINT_MESSAGE(LEVEL_ERROR, "ERROR", HRED, fmt, ##__VA_ARGS__) +#define PRINT_MESSAGE(level, prefix, color, fmt, ...) \ + do \ + { \ + uart_sendlinek(color "[" prefix "] " CRESET fmt, ##__VA_ARGS__); \ + } while (0) + +#endif /* _DEBUG_H_ */ \ No newline at end of file diff --git a/lab8/kernel/include/dtb.h b/lab8/kernel/include/dtb.h new file mode 100644 index 000000000..7076d8683 --- /dev/null +++ b/lab8/kernel/include/dtb.h @@ -0,0 +1,26 @@ +#ifndef _DTB_H_ +#define _DTB_H_ + +#define uint32_t unsigned int +#define uint64_t unsigned long long + +// manipulate device tree with dtb file format +// linux kernel fdt.h +#define FDT_BEGIN_NODE 0x00000001 +#define FDT_END_NODE 0x00000002 +#define FDT_PROP 0x00000003 +#define FDT_NOP 0x00000004 +#define FDT_END 0x00000009 + +typedef void (*dtb_callback)(uint32_t node_type, char *name, void *value, uint32_t name_size); + +uint32_t uint32_endian_big2little(uint32_t data); +uint64_t uint64_endian_big2little(uint64_t data); + +void traverse_device_tree(void *base, dtb_callback callback); // traverse dtb tree +void dtb_callback_show_tree(uint32_t node_type, char *name, void *value, uint32_t name_size); +void dtb_callback_initramfs(uint32_t node_type, char *name, void *value, uint32_t name_size); + +void dtb_find_and_store_reserved_memory(); + +#endif \ No newline at end of file diff --git a/lab8/kernel/include/exception.h b/lab8/kernel/include/exception.h new file mode 100644 index 000000000..eb975a1aa --- /dev/null +++ b/lab8/kernel/include/exception.h @@ -0,0 +1,92 @@ +#ifndef _EXCEPTION_H_ +#define _EXCEPTION_H_ + +#include "u_list.h" +#include "bcm2837/rpi_mmu.h" + +#define SYSCALL(number, function) \ + case number: \ + function; \ + break; + +// https://github.com/Tekki/raspberrypi-documentation/blob/master/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf p16 +#define CORE0_INTERRUPT_SOURCE ((volatile unsigned int *)(PHYS_TO_KERNEL_VIRT(0x40000060))) +#define INTERRUPT_SOURCE_CNTPNSIRQ (1 << 1) +#define INTERRUPT_SOURCE_GPU (1 << 8) +#define IRQ_PENDING_1_AUX_INT (1 << 29) + +typedef struct trapframe +{ + unsigned long x0; + unsigned long x1; + unsigned long x2; + unsigned long x3; + unsigned long x4; + unsigned long x5; + unsigned long x6; + unsigned long x7; + unsigned long x8; + unsigned long x9; + unsigned long x10; + unsigned long x11; + unsigned long x12; + unsigned long x13; + unsigned long x14; + unsigned long x15; + unsigned long x16; + unsigned long x17; + unsigned long x18; + unsigned long x19; + unsigned long x20; + unsigned long x21; + unsigned long x22; + unsigned long x23; + unsigned long x24; + unsigned long x25; + unsigned long x26; + unsigned long x27; + unsigned long x28; + unsigned long x29; + unsigned long x30; + unsigned long spsr_el1; + unsigned long elr_el1; + unsigned long sp_el0; + +} trapframe_t; + +#define MEMFAIL_DATA_ABORT_LOWER 0b100100 // esr_el1 +#define MEMFAIL_INST_ABORT_LOWER 0b100000 // EC, bits [31:26] + +#define TF_LEVEL0 0b000100 // iss IFSC, bits [5:0] +#define TF_LEVEL1 0b000101 +#define TF_LEVEL2 0b000110 +#define TF_LEVEL3 0b000111 + +#define ESR_EL1_EC_SHIFT 26 +#define ESR_EL1_EC_MASK 0x3F +#define ESR_EL1_EC_SVC64 0x15 + +typedef struct +{ + unsigned int iss : 25, // Instruction specific syndrome + il : 1, // Instruction length bit + ec : 6; // Exception class +} esr_el1_t; + +void el1_interrupt_enable(); +void el1_interrupt_disable(); + +void lock(); +void unlock(); + +void el1h_sync_router(trapframe_t *tpf); +void el1h_irq_router(trapframe_t *tpf); +void el0_sync_router(trapframe_t *tpf); +void el0_irq_router(trapframe_t *tpf); + +void invalid_exception_router(unsigned long long x0); // exception_handler.S + +const char *get_exception_name(unsigned long esr_el1); + + +#endif /*_EXCEPTION_H_*/ diff --git a/lab8/kernel/include/irqtask.h b/lab8/kernel/include/irqtask.h new file mode 100644 index 000000000..52783e26b --- /dev/null +++ b/lab8/kernel/include/irqtask.h @@ -0,0 +1,22 @@ +#ifndef _IRQTASK_H_ +#define _IRQTASK_H_ + +#include "u_list.h" + +// smaller is more preemptive +#define UART_IRQ_PRIORITY 1 +#define TIMER_IRQ_PRIORITY 0 + +typedef struct irqtask +{ + struct list_head listhead; + unsigned long long priority; // store priority (smaller number is more preemptive) + void *task_function; // task function pointer +} irqtask_t; + +void irqtask_add(void *task_function, unsigned long long priority); +void irqtask_run(irqtask_t *the_task); +void irqtask_run_preemptive(); +void irqtask_list_init(); + +#endif diff --git a/lab8/kernel/include/mbox.h b/lab8/kernel/include/mbox.h new file mode 100644 index 000000000..25b712383 --- /dev/null +++ b/lab8/kernel/include/mbox.h @@ -0,0 +1,66 @@ +#ifndef _MBOX_H_ +#define _MBOX_H_ + +extern volatile unsigned int pt[36]; + +// Mailbox Register MMIO +// https://jsandler18.github.io/extra/mailbox.html +// include/bcm2837/rpi_mbox.h + +// Mailbox Channels +// https://github.com/raspberrypi/firmware/wiki/Mailboxes +typedef enum +{ + MBOX_POWER_MANAGEMENT = 0, + MBOX_FRAMEBUFFER, + MBOX_VIRTUAL_UART, + MBOX_VCHIQ, + MBOX_LEDS, + MBOX_BUTTONS, + MBOX_TOUCHSCREEN, + MBOX_UNUSED, + MBOX_TAGS_ARM_TO_VC, + MBOX_TAGS_VC_TO_ARM, +} mbox_channel_type; + +// Status Code from Broadcom Videocode Driver +// brcm_usrlib/dag/vmcsx/vcinclude/bcm2708_chip/arm_control.h +enum mbox_status_reg_bits +{ + BCM_ARM_VC_MS_FULL = 0x80000000, + BCM_ARM_VC_MS_EMPTY = 0x40000000, + BCM_ARM_VC_MS_LEVEL = 0x400000FF, +}; + +enum mbox_buffer_status_code +{ + MBOX_REQUEST_PROCESS = 0x00000000, + MBOX_REQUEST_SUCCEED = 0x80000000, + MBOX_REQUEST_FAILED = 0x80000001, +}; + +// Tag +// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface +// Included partition only +typedef enum +{ + /* Videocore */ + MBOX_TAG_GET_FIRMWARE_VERSION = 0x1, + + /* Hardware */ + MBOX_TAG_GET_BOARD_MODEL = 0x10001, + MBOX_TAG_GET_BOARD_REVISION, + MBOX_TAG_GET_BOARD_MAC_ADDRESS, + MBOX_TAG_GET_BOARD_SERIAL, + MBOX_TAG_GET_ARM_MEMORY, + MBOX_TAG_GET_VC_MEMORY, + MBOX_TAG_GET_CLOCKS, + +} mbox_tag_type; + +#define MBOX_TAG_REQUEST_CODE 0x00000000 +#define MBOX_TAG_LAST_BYTE 0x00000000 + +int mbox_call(mbox_channel_type, unsigned int); + +#endif /*_MBOX_H_*/ diff --git a/lab8/kernel/include/memory.h b/lab8/kernel/include/memory.h new file mode 100644 index 000000000..35f7ddb16 --- /dev/null +++ b/lab8/kernel/include/memory.h @@ -0,0 +1,80 @@ +#ifndef _MEMORY_H_ +#define _MEMORY_H_ + +#include "u_list.h" +#include "bcm2837/rpi_mmu.h" +/* Lab2 */ +void *allocator(unsigned int size); +// void free(void* ptr); + +/* Lab4 */ +#define BUDDY_MEMORY_BASE PHYS_TO_KERNEL_VIRT(0x0) // 0x10000000 - 0x20000000 (SPEC) -> Advanced #3 for all memory region +#define BUDDY_MEMORY_PAGE_COUNT 0x3C000 // let BUDDY_MEMORY use 0x0 ~ 0x3C000000 (SPEC) +#define PAGESIZE 0x1000 // 4KB + +#define CACHE_SEG 0x8 +#define CACHE_offset 3 +#define CACHE_record_num 8 + +// #define MAX_PAGES 0x10000 // 65536 (Entries), PAGESIZE * MAX_PAGES = 0x10000000 (SPEC) + +typedef enum +{ + FRAME_FREE = -2, + FRAME_ALLOCATED = -1, + FRAME_IDX_0 = 0, // 0x1000 + FRAME_IDX_8 = 8, + FRAME_IDX_FINAL = 17, // 0x20 000 000 + FRAME_MAX_IDX = 18 +} frame_value_type; + +typedef enum +{ + CACHE_IDX_0 = 0, // 0x20 + CACHE_IDX_FINAL = 6, // 0x800 + CACHE_MAX_IDX = 7 // 0x1000 +} cache_value_type; + +typedef struct frame +{ + struct list_head listhead; // store freelist + int val; // store order + int used; + unsigned int idx; +} frame_t; + +typedef struct cache +{ + struct list_head listhead; // store freelist + void *data_base; + int cache_order; + int max_available; + int available; + unsigned long long cache_record[CACHE_record_num]; +} cache_t; + +void allocator_init(); +frame_t *release_redundant(frame_t *frame); +frame_t *get_buddy(frame_t *frame); +int coalesce(frame_t *frame_ptr); + +void dump_page_info(); +void dump_cache_info(); + +// buddy system +void *page_malloc(unsigned int size); +void page_free(frame_t *ptr); +void page2caches(int order); +void *cache_malloc(unsigned int size); +void cache_free(void *ptr); + +void *kmalloc(unsigned int size); +void kfree(void *ptr); +void memory_reserve(unsigned long long start, unsigned long long end); + +void freelist_init(); +void page2caches(int c_val); +void *find_CACHE(cache_t *ptr); +frame_t *find_free_page(int val); + +#endif /* _MEMORY_H_ */ \ No newline at end of file diff --git a/lab8/kernel/include/mmu.h b/lab8/kernel/include/mmu.h new file mode 100644 index 000000000..bb58ee390 --- /dev/null +++ b/lab8/kernel/include/mmu.h @@ -0,0 +1,101 @@ +#ifndef _MMU_H_ +#define _MMU_H_ + +#include "stddef.h" +// tcr_el1: The control register for stage 1 of the EL1&0 translation regime. +#define TCR_CONFIG_REGION_48bit (((64 - 48) << 0) | ((64 - 48) << 16)) // T0SZ 和 T1SZ 設為 16 +#define TCR_CONFIG_4KB ((0b00 << 14) | (0b10 << 30)) // TG0 和 TG1 設為 4KB +#define TCR_CONFIG_DEFAULT (TCR_CONFIG_REGION_48bit | TCR_CONFIG_4KB) + +#define MAIR_DEVICE_nGnRnE 0b00000000 // 設備記憶體,無全局無讀取無寫入權限 +#define MAIR_NORMAL_NOCACHE 0b01000100 // 普通記憶體,不緩存 +#define MAIR_IDX_DEVICE_nGnRnE 0 // 設備記憶體索引 +#define MAIR_IDX_NORMAL_NOCACHE 1 // 普通記憶體索引 + +#define PD_TABLE 0b11L // Table Entry Armv8_a_address_translation p.14 +#define PD_BLOCK 0b01L // Block Entry +#define PD_UNX (1L << 54) // non-executable page frame for EL0 if set +#define PD_KNX (1L << 53) // non-executable page frame for EL1 if set +#define PD_ACCESS (1L << 10) // a page fault is generated if not set +#define PD_RDONLY (1L << 7) // 0 for read-write, 1 for read-only. +#define PD_UK_ACCESS (1L << 6) // 0 for only kernel access, 1 for user/kernel access. + +#define PERIPHERAL_START 0x3C000000L +#define PERIPHERAL_END 0x3F000000L +#define USER_DATA_BASE 0x00000000L +#define USER_STACK_BASE 0x0000fffffffff000L +#define USER_SIGNAL_WRAPPER_VA 0x0000FFFFFFFAF000L //<------------------------------------- +#define USER_EXEC_WRAPPER_VA 0x0000FFFFFFFBF000L //<------------------------------------- + +#define MMU_PGD_BASE 0x1000L +#define MMU_PGD_ADDR (MMU_PGD_BASE + 0x0000L) +#define MMU_PUD_ADDR (MMU_PGD_BASE + 0x1000L) +#define MMU_PTE_ADDR (MMU_PGD_BASE + 0x2000L) + +// Used for EL1 +#define BOOT_PGD_ATTR (PD_TABLE) +#define BOOT_PUD_ATTR (PD_TABLE | PD_ACCESS) +#define BOOT_PTE_ATTR_nGnRnE (PD_BLOCK | PD_ACCESS | (MAIR_IDX_DEVICE_nGnRnE << 2) | PD_UNX | PD_KNX | PD_UK_ACCESS) // p.17 +#define BOOT_PTE_ATTR_NOCACHE (PD_BLOCK | PD_ACCESS | (MAIR_IDX_NORMAL_NOCACHE << 2)) + +#ifndef __ASSEMBLER__ + +#include "sched.h" +#include "exception.h" +#include "u_list.h" +#include "stddef.h" + + +#define PERMISSION_INVAILD(userId,VMA_Permission) (userId&~VMA_Permission) +#define DUMP_NAME(number, name) \ + case number: \ + uart_sendlinek(name); \ + uart_sendlinek("\n"); \ + break; + +typedef enum +{ + UNKNOW_AREA = -1, + USER_DATA, + USER_STACK, + PERIPHERAL, + USER_SIGNAL_WRAPPER, + USER_EXEC_WRAPPER +} vma_name_type; + +typedef enum +{ + PGD, + PUD, + PMD, + PTE, +} pagetable_type; + +typedef struct vm_area_struct +{ + list_head_t listhead; + unsigned long virt_addr; + unsigned long phys_addr; + unsigned long area_size; + unsigned long rwx; // 1, 2, 4 + int is_alloced; + vma_name_type name; +} vm_area_struct_t; + +void *set_2M_kernel_mmu(void *x0); +void map_one_page(size_t *pgd_p, size_t va, size_t pa, size_t flag); +void mmu_add_vma(struct thread *t, size_t va, size_t size, size_t pa, size_t rwx, int is_alloced, vma_name_type name); +void mmu_del_vma(struct thread *t); +void mmu_free_page_tables(size_t *page_table, int level); +// void mmu_set_PTE_readonly(size_t *page_table, int level); +// void mmu_pagetable_copy(unsigned long *dst_page_table, unsigned long *src_page_table, int level); +void mmu_memfail_abort_handle(esr_el1_t *esr_el1); + +vm_area_struct_t *check_vma_overlap(thread_t *t,unsigned long user_va, unsigned long size); +int check_permission(int userId, int requiredPermission); +void dump_vma(); +void dump_pagetable(unsigned long user_va, unsigned long pa); + +#endif //__ASSEMBLER__ + +#endif /* _MMU_H_ */ diff --git a/lab8/kernel/include/power.h b/lab8/kernel/include/power.h new file mode 100644 index 000000000..07da61847 --- /dev/null +++ b/lab8/kernel/include/power.h @@ -0,0 +1,9 @@ +#ifndef _POWER_H_ +#define _POWER_H_ + +#include "bcm2837/rpi_mmu.h" +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC PHYS_TO_KERNEL_VIRT(0x3F10001c) +#define PM_WDOG PHYS_TO_KERNEL_VIRT(0x3F100024) + +#endif /*_POWER_H_*/ diff --git a/lab8/kernel/include/sched.h b/lab8/kernel/include/sched.h new file mode 100644 index 000000000..475bc27e7 --- /dev/null +++ b/lab8/kernel/include/sched.h @@ -0,0 +1,79 @@ +#ifndef _SCHED_H_ +#define _SCHED_H_ + +#include "u_list.h" +#include "vfs.h" + +#define PIDMAX 32768 +#define USTACK_SIZE 0x10000 +#define KSTACK_SIZE 0x10000 +#define SIGNAL_MAX 64 +#define STACK_BASE_OFFSET 0x00 + +extern void switch_to(void *curr_context, void *next_context); +extern void *get_current(); +extern void store_context(void *curr_context); +extern void load_context(void *curr_context); + +// arch/arm64/include/asm/processor.h - cpu_context +typedef struct thread_context +{ + unsigned long x19; // callee saved registers: the called function will preserve them and restore them before returning + unsigned long x20; + unsigned long x21; + unsigned long x22; + unsigned long x23; + unsigned long x24; + unsigned long x25; + unsigned long x26; + unsigned long x27; + unsigned long x28; + unsigned long fp; // base pointer for local variable in stack + unsigned long lr; // store return address + unsigned long sp; // stack pointer, varys from function calls + void *pgd; // use for MMU mapping (user space) +} thread_context_t; + +typedef struct thread +{ + list_head_t listhead; // Freelist node + thread_context_t context; // Thread registers + char *data; // Process itself + unsigned int datasize; // Process size + int iszombie; // Process statement + int pid; // Process ID + int isused; // Freelist node statement + char *stack_alloced_ptr; // Process Stack (Process itself) + char *kernel_stack_alloced_ptr; // Process Stack (Kernel syscall) + void (*signal_handler[SIGNAL_MAX + 1])(); // Signal handlers for different signal + int sigcount[SIGNAL_MAX + 1]; // Signal Pending buffer + void (*curr_signal_handler)(); // Allow Signal handler overwritten by others + int signal_is_checking; // Signal Processing Lock + thread_context_t signal_savedContext; // Store registers before signal handler involving + list_head_t vma_list; + char curr_working_dir[MAX_PATH_NAME + 1]; + struct file *file_descriptors_table[MAX_FD + 1]; +} thread_t; + +typedef struct execfile +{ + struct vnode *vnode; + char * pathname; + char *data; + unsigned int filesize; +} execfile; + +void schedule_timer(char *notuse); +void thread_sched_init(); +void idle(); +void schedule(); +void kill_zombies(); +void thread_exit(); +thread_t *thread_create(void *start); +int exec_thread(); +void exec_proc(); +void exec_wrapper(); + +void foo(); + +#endif /* _SCHED_H_ */ diff --git a/lab8/kernel/include/sdhost.h b/lab8/kernel/include/sdhost.h new file mode 100644 index 000000000..ed9639b32 --- /dev/null +++ b/lab8/kernel/include/sdhost.h @@ -0,0 +1,69 @@ +// mmio +#define KVA 0xffff000000000000 +#define MMIO_BASE (KVA + 0x3f000000) + +// SD card command +#define GO_IDLE_STATE 0 +#define SEND_OP_CMD 1 +#define ALL_SEND_CID 2 +#define SEND_RELATIVE_ADDR 3 +#define SELECT_CARD 7 +#define SEND_IF_COND 8 + #define VOLTAGE_CHECK_PATTERN 0x1aa +#define STOP_TRANSMISSION 12 +#define SET_BLOCKLEN 16 +#define READ_SINGLE_BLOCK 17 +#define WRITE_SINGLE_BLOCK 24 +#define SD_APP_OP_COND 41 + #define SDCARD_3_3V (1 << 21) + #define SDCARD_ISHCS (1 << 30) + #define SDCARD_READY (1 << 31) +#define APP_CMD 55 + +// gpio +#define GPIO_BASE (MMIO_BASE + 0x200000) +#define GPIO_GPFSEL4 (GPIO_BASE + 0x10) +#define GPIO_GPFSEL5 (GPIO_BASE + 0x14) +#define GPIO_GPPUD (GPIO_BASE + 0x94) +#define GPIO_GPPUDCLK1 (GPIO_BASE + 0x9c) + +// sdhost +#define SDHOST_BASE (MMIO_BASE + 0x202000) +#define SDHOST_CMD (SDHOST_BASE + 0) + #define SDHOST_READ 0x40 + #define SDHOST_WRITE 0x80 + #define SDHOST_LONG_RESPONSE 0x200 + #define SDHOST_NO_REPONSE 0x400 + #define SDHOST_BUSY 0x800 + #define SDHOST_NEW_CMD 0x8000 +#define SDHOST_ARG (SDHOST_BASE + 0x4) +#define SDHOST_TOUT (SDHOST_BASE + 0x8) + #define SDHOST_TOUT_DEFAULT 0xf00000 +#define SDHOST_CDIV (SDHOST_BASE + 0xc) + #define SDHOST_CDIV_MAXDIV 0x7ff + #define SDHOST_CDIV_DEFAULT 0x148 +#define SDHOST_RESP0 (SDHOST_BASE + 0x10) +#define SDHOST_RESP1 (SDHOST_BASE + 0x14) +#define SDHOST_RESP2 (SDHOST_BASE + 0x18) +#define SDHOST_RESP3 (SDHOST_BASE + 0x1c) +#define SDHOST_HSTS (SDHOST_BASE + 0x20) + #define SDHOST_HSTS_MASK (0x7f8) + #define SDHOST_HSTS_ERR_MASK (0xf8) + #define SDHOST_HSTS_DATA (1 << 0) +#define SDHOST_PWR (SDHOST_BASE + 0x30) +#define SDHOST_DBG (SDHOST_BASE + 0x34) + #define SDHOST_DBG_FSM_DATA 1 + #define SDHOST_DBG_FSM_MASK 0xf + #define SDHOST_DBG_MASK (0x1f << 14 | 0x1f << 9) + #define SDHOST_DBG_FIFO (0x4 << 14 | 0x4 << 9) +#define SDHOST_CFG (SDHOST_BASE + 0x38) + #define SDHOST_CFG_DATA_EN (1 << 4) + #define SDHOST_CFG_SLOW (1 << 3) + #define SDHOST_CFG_INTBUS (1 << 1) +#define SDHOST_SIZE (SDHOST_BASE + 0x3c) +#define SDHOST_DATA (SDHOST_BASE + 0x40) +#define SDHOST_CNT (SDHOST_BASE + 0x50) + +void sd_init(); +void writeblock(int block_idx, void* buf); +void readblock(int block_idx, void* buf); \ No newline at end of file diff --git a/lab8/kernel/include/shell.h b/lab8/kernel/include/shell.h new file mode 100644 index 000000000..276d085d9 --- /dev/null +++ b/lab8/kernel/include/shell.h @@ -0,0 +1,40 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ + +#define CLI_MAX_CMD 15 +#define CMD_MAX_LEN 32 +#define CMD_MAX_PARAM 10 +#define MSG_MAX_LEN 128 + +typedef struct CLI_CMDS +{ + char command[CMD_MAX_LEN]; + char help[MSG_MAX_LEN]; + int (*func)(int, char **); +} CLI_CMDS; + +int _parse_args(char *buffer, int *argc, char **argv); + +void start_shell(); + +void cli_flush_buffer(char *, int); +void cli_cmd_read(char *); +void cli_cmd_exec(char *); +void cli_print_banner(); + +int do_cmd_help(int argc, char **argv); +int do_cmd_hello(int argc, char **argv); +int do_cmd_info(int argc, char **argv); +int do_cmd_reboot(int argc, char **argv); +int do_cmd_ls(int argc, char **argv); +int do_cmd_cd(int argc, char **argv); +int do_cmd_cat(int argc, char **argv); +int do_cmd_malloc(int argc, char **argv); +int do_cmd_dtb(int argc, char **argv); +int do_cmd_exec(int argc, char **argv); +int do_cmd_setTimeout(int argc, char **argv); +int do_cmd_set2sAlert(int argc, char **argv); +int do_cmd_mtest(int argc, char **argv); +int do_cmd_ttest(int argc, char **argv); +int do_cmd_ftest(int argc, char **argv); +#endif /* _SHELL_H_ */ diff --git a/lab8/kernel/include/signal.h b/lab8/kernel/include/signal.h new file mode 100644 index 000000000..afe2c1617 --- /dev/null +++ b/lab8/kernel/include/signal.h @@ -0,0 +1,49 @@ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +#include "exception.h" +#include "memory.h" + +#define SIGHUP 1 /* Hangup (POSIX). */ +#define SIGINT 2 /* Interrupt (ANSI). */ +#define SIGQUIT 3 /* Quit (POSIX). */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ +#define SIGTRAP 5 /* Trace trap (POSIX). */ +#define SIGABRT 6 /* Abort (ANSI). */ +#define SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define SIGBUS 7 /* BUS error (4.2 BSD). */ +#define SIGFPE 8 /* Floating-point exception (ANSI). */ +#define SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ +#define SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ +#define SIGPIPE 13 /* Broken pipe (POSIX). */ +#define SIGALRM 14 /* Alarm clock (POSIX). */ +#define SIGTERM 15 /* Termination (ANSI). */ +#define SIGSTKFLT 16 /* Stack fault. */ +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGCHLD 17 /* Child status has changed (POSIX). */ +#define SIGCONT 18 /* Continue (POSIX). */ +#define SIGSTOP 19 /* Stop, unblockable (POSIX). */ +#define SIGTSTP 20 /* Keyboard stop (POSIX). */ +#define SIGTTIN 21 /* Background read from tty (POSIX). */ +#define SIGTTOU 22 /* Background write to tty (POSIX). */ +#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ +#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ +#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ +#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ +#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ +#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ +#define SIGPOLL SIGIO /* Pollable event occurred (System V). */ +#define SIGIO 29 /* I/O now possible (4.2 BSD). */ +#define SIGPWR 30 /* Power failure restart (System V). */ +#define SIGSYS 31 /* Bad system call. */ +#define SIGUNUSED 31 + +void signal_default_handler(); +void check_signal(trapframe_t *tpf); +void run_signal(trapframe_t *tpf, int signal); +//void __attribute__((aligned(PAGESIZE))) signal_handler_wrapper(); +void signal_handler_wrapper(); + +#endif diff --git a/lab8/kernel/include/stddef.h b/lab8/kernel/include/stddef.h new file mode 100644 index 000000000..61b71d842 --- /dev/null +++ b/lab8/kernel/include/stddef.h @@ -0,0 +1,12 @@ +#ifndef STDDEF_H +#define STDDEF_H + +#define size_t unsigned long +#define NULL ((void *)0) + +// typedef enum { +// false = 0, +// true = 1 +// } boolean; + +#endif \ No newline at end of file diff --git a/lab8/kernel/include/stdio.h b/lab8/kernel/include/stdio.h new file mode 100644 index 000000000..5ee646448 --- /dev/null +++ b/lab8/kernel/include/stdio.h @@ -0,0 +1,29 @@ +#include "sched.h" +#include "vfs.h" +extern thread_t *curr_thread; + +#define stdio_op(fd, c, len) \ + switch (fd) \ + { \ + case (stdin): \ + (vfs_read(curr_thread->file_descriptors_table[fd], c, len)); \ + break; \ + case (stdout): \ + (vfs_write(curr_thread->file_descriptors_table[fd], c, len)); \ + break; \ + case (stderr): \ + (vfs_write(curr_thread->file_descriptors_table[fd], c, len)); \ + break; \ + default: \ + break; \ + } + +char getchar(); +void putchar(char c); +void put_int(int num); +void puts(const char *s); +void put_hex(unsigned int num); +int atoi(char *str); +void Readfile(char *str, int size); +int fake_log2(unsigned long long n); +void delay(int s); \ No newline at end of file diff --git a/lab8/kernel/include/string.h b/lab8/kernel/include/string.h new file mode 100644 index 000000000..f190cdc83 --- /dev/null +++ b/lab8/kernel/include/string.h @@ -0,0 +1,15 @@ +#include "stddef.h" +#define VSPRINT_MAX_BUF_SIZE 0x100 + +size_t strlen(const char *str); + +int strcmp(const char *p1, const char *p2); +int strncmp(const char *s1, const char *s2, unsigned long long n); +int strcasecmp(const char *s1, const char *s2); +char *strcat(char *dest, const char *src); +char *strncat(char *dest, const char *src, int n); +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, unsigned long long n); +unsigned int vsprintf(char *dst, char *fmt, __builtin_va_list args); +void *memset(void *s, int c, size_t n); +char *memcpy(void *dest, const void *src, unsigned long long len); diff --git a/lab8/kernel/include/syscall.h b/lab8/kernel/include/syscall.h new file mode 100644 index 000000000..42464df2a --- /dev/null +++ b/lab8/kernel/include/syscall.h @@ -0,0 +1,39 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ + +#include "exception.h" +#include + +int getpid(trapframe_t *tpf); +size_t uartread(trapframe_t *tpf, char buf[], size_t size); +size_t uartwrite(trapframe_t *tpf, const char buf[], size_t size); +int exec(trapframe_t *tpf, const char *name, char *const argv[]); +int fork(trapframe_t *tpf); +void exit(trapframe_t *tpf, int status); +int syscall_mbox_call(trapframe_t *tpf, unsigned char ch, unsigned int *mbox); +void kill(trapframe_t *tpf, int pid); + +void signal_register(int signal, void (*handler)()); +void signal_kill(int pid, int signal); +void sigreturn(trapframe_t *tpf); + +void *mmap(trapframe_t *tpf, void *addr, size_t len, int prot, int flags, int fd, int file_offset); + +int open(trapframe_t *tpf, const char *pathname, int flags); +int close(trapframe_t *tpf, int fd); +long write(trapframe_t *tpf, int fd, const void *buf, unsigned long count); +long read(trapframe_t *tpf, int fd, void *buf, unsigned long count); +int mkdir(trapframe_t *tpf, const char *pathname, unsigned mode); +int mount(trapframe_t *tpf, const char *src, const char *target, const char *filesystem, unsigned long flags, const void *data); +int chdir(trapframe_t *tpf, const char *path); +long lseek64(trapframe_t *tpf, int fd, long offset, int whence); +int ioctl(trapframe_t *tpf, int fd, unsigned long request, void *info); +int sync(trapframe_t *tpf); + +void syscall_lock(trapframe_t *tpf); +void syscall_unlock(trapframe_t *tpf); + +unsigned int get_file_size(char *thefilepath); +char *get_file_start(char *thefilepath); + +#endif /* _SYSCALL_H_*/ diff --git a/lab8/kernel/include/timer.h b/lab8/kernel/include/timer.h new file mode 100644 index 000000000..8b02b6b8d --- /dev/null +++ b/lab8/kernel/include/timer.h @@ -0,0 +1,36 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ + +#include "u_list.h" +#include "bcm2837/rpi_mmu.h" +#define CORE0_TIMER_IRQ_CTRL PHYS_TO_VIRT(0x40000040) //-------------------------------------------------------------------------- + +void core_timer_enable(); +void core_timer_disable(); +void core_timer_handler(); + +typedef struct timer_event +{ + struct list_head listhead; + unsigned long long interrupt_time; // store as tick time after cpu start + void *callback; // interrupt -> timer_callback -> callback(args) + char *args; // need to free the string by event callback function +} timer_event_t; + +typedef enum +{ + setSecond = 0, + setTick = 1 +} timer_type_t; + +// now the callback only support "funcion(char *)", char* in args +void timer_event_callback(timer_event_t *timer_event); +void add_timer(void *callback, unsigned long long timeout, char *args, int inTickFormat); +unsigned long long get_tick_plus_s(unsigned long long second); +void set_core_timer_interrupt(unsigned long long expired_time); +void set_core_timer_interrupt_by_tick(unsigned long long tick); +void timer_set2sAlert(char *str); +void timer_list_init(); +int timer_list_get_size(); + +#endif /* _TIMER_H_ */ diff --git a/lab8/kernel/include/u_list.h b/lab8/kernel/include/u_list.h new file mode 100644 index 000000000..a4a293954 --- /dev/null +++ b/lab8/kernel/include/u_list.h @@ -0,0 +1,213 @@ +#ifndef _U_LIST_H_ +#define _U_LIST_H_ + +/* + * Circular doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + * + * https://github.com/torvalds/linux/blob/master/include/linux/list. + * https://elixir.bootlin.com/linux/latest/source/scripts/kconfig/list.h#L24 + */ + +typedef struct list_head +{ + struct list_head *next, *prev; +} list_head_t; + +#define LIST_HEAD_INIT(name) \ + { \ + &(name), &(name) \ + } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * INIT_LIST_HEAD - Initialize a list_head structure + * @list: list_head structure to be initialized. + * + * Initializes the list_head to point to itself. If it is a list header, + * the result is an empty list. + */ +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +static inline void list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_is_head - tests whether @list is the list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_head(const struct list_head *list, const struct list_head *head) +{ + return list == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; \ + !list_is_head(pos, (head)); \ + pos = n, n = pos->next) + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_size(const struct list_head *head) +{ + list_head_t *pos; + int i = 0; + list_for_each(pos, head) + { + i++; + } + return i; +} +// ===================================================================================================================== +#define __LIST_HAVE_TYPEOF 1 +/* Offset of member MEMBER in a struct of type TYPE. */ +#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) +/** + * container_of() - Calculate address of object that contains address ptr + * @ptr: pointer to member variable + * @type: type of the structure containing ptr + * @member: name of the member variable in struct @type + * + * Return: @type pointer of object containing ptr + */ +#ifndef container_of +#ifdef __LIST_HAVE_TYPEOF +#define container_of(ptr, type, member) \ + __extension__({ \ + const __typeof__(((type *)0)->member) *__pmember = (ptr); \ + (type *)((char *)__pmember - offsetof(type, member)); \ + }) +#else /* __LIST_HAVE_TYPEOF */ +#define container_of(ptr, type, member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) +#endif /* __LIST_HAVE_TYPEOF */ +#endif /* container_of */ +/** + * list_entry() - Calculate address of entry that contains list node + * @node: pointer to list node + * @type: type of the entry containing the list node + * @member: name of the list_head member variable in struct @type + * + * Return: @type pointer of entry containing node + */ +#define list_entry(node, type, member) container_of(node, type, member) + +/** + * list_first_entry() - get first entry of the list + * @head: pointer to the head of the list + * @type: type of the entry containing the list node + * @member: name of the list_head member variable in struct @type + * + * Return: @type pointer of first entry in list + */ +#define list_first_entry(head, type, member) \ + list_entry((head)->next, type, member) + +/** + * list_for_each_entry - iterate over list entries + * @entry: pointer used as iterator + * @head: pointer to the head of the list + * @member: name of the list_head member variable in struct type of @entry + * + * The nodes and the head of the list must be kept unmodified while + * iterating through it. Any modifications to the the list will cause undefined + * behavior. + * + * FIXME: remove dependency of __typeof__ extension + */ +#ifdef __LIST_HAVE_TYPEOF +#define list_for_each_entry(entry, head, member) \ + for (entry = list_entry((head)->next, __typeof__(*entry), member); \ + &entry->member != (head); \ + entry = list_entry(entry->member.next, __typeof__(*entry), member)) +#endif /* __LIST_HAVE_TYPEOF */ + +#endif /* _U_LIST_H_ */ diff --git a/lab8/kernel/include/uart1.h b/lab8/kernel/include/uart1.h new file mode 100644 index 000000000..7b6bd70ce --- /dev/null +++ b/lab8/kernel/include/uart1.h @@ -0,0 +1,18 @@ +#ifndef _UART1_H_ +#define _UART1_H_ + +void uart_init(); +void uart_flush_FIFO(); +char uart_recv(); +void uart_send(unsigned int c); + +void uart_r_irq_handler(); +void uart_w_irq_handler(); +char uart_async_recv(); +void uart_async_send(char c); + +int uart_sendlinek(char* fmt, ...); +void uart_interrupt_enable(); +void uart_interrupt_disable(); + +#endif /*_UART1_H_*/ diff --git a/lab8/kernel/include/vfs.h b/lab8/kernel/include/vfs.h new file mode 100644 index 000000000..8fd66b49c --- /dev/null +++ b/lab8/kernel/include/vfs.h @@ -0,0 +1,110 @@ +#ifndef _VFS_H_ +#define _VFS_H_ + +#include "stddef.h" + +#define MAX_PATH_NAME 255 +#define MAX_FD 16 +#define O_CREAT 00000100 +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#define MAX_FS_REG 0x50 +#define MAX_DEV_REG 0x10 + +enum stdio_fd +{ + stdin, + stdout, + stderr +}; + +enum fsnode_type +{ + dir_t, + file_t +}; + +struct vnode +{ + struct mount *mount; // Superblock : represents mounted fs + struct vnode_operations *v_ops; // inode & dentry Ops: represents kernel methods for vnode + struct file_operations *f_ops; // file Ops : represents process methods for opened file + void *internal; // vnode itself : directly point to fs's vnode + struct vnode *parent; +}; + +struct mount +{ + struct vnode *root; + struct filesystem *fs; +}; + +struct filesystem +{ + const char *name; + int (*setup_mount)(struct filesystem *fs, struct mount *mount); + int (*sync)(struct filesystem *fs); +}; + +// file handle +struct file +{ + struct vnode *vnode; + size_t f_pos; // RW position of this file handle + struct file_operations *f_ops; + int flags; +}; + +struct file_operations +{ + int (*write)(struct file *file, const void *buf, size_t len); + int (*read)(struct file *file, void *buf, size_t len); + int (*open)(struct vnode *file_node, struct file **target); + int (*close)(struct file *file); + long (*lseek64)(struct file *file, long offset, int whence); + long (*getsize)(struct vnode *vd); +}; + +struct vnode_operations +{ + int (*lookup)(struct vnode *dir_node, struct vnode **target, const char *component_name); + int (*create)(struct vnode *dir_node, struct vnode **target, const char *component_name); + int (*mkdir)(struct vnode *dir_node, struct vnode **target, const char *component_name); + int (*isdir)(struct vnode *dir_node); + int (*getname)(struct vnode *dir_node, const char **name); + int (*getsize)(struct vnode *dir_node); + void (*ls)(struct vnode *dir_node); + void (*dump)(struct vnode *dir_node, int level); +}; + +struct dir_path +{ + char *dir; + int size; +}; + +extern struct filesystem reg_fs[MAX_FS_REG]; + +int register_filesystem(struct filesystem *fs); +int register_dev(struct file_operations *fo); +struct filesystem *find_filesystem(const char *fs_name); +int vfs_open(const char *pathname, int flags, struct file **target); +int vfs_close(struct file *file); +int vfs_write(struct file *file, const void *buf, size_t len); +int vfs_read(struct file *file, void *buf, size_t len); +int vfs_mkdir(const char *pathname); +int vfs_mount(const char *target, const char *filesystem); +int vfs_lookup(const char *pathname, struct vnode **target); +int vfs_mknod(char *pathname, int id); +int vfs_sync(struct filesystem *fs); + +void rootfs_init(); +char *get_absolute_path(char *path, char *curr_working_dir); + +void vfs_cd(char *filepath); +void vfs_dump(struct vnode *_vnode, int level); +void vfs_ls(); +void displaylayer(int level); + +#endif /* _VFS_H_ */ diff --git a/lab8/kernel/include/vfs_dev_framebuffer.h b/lab8/kernel/include/vfs_dev_framebuffer.h new file mode 100644 index 000000000..b996ee8e3 --- /dev/null +++ b/lab8/kernel/include/vfs_dev_framebuffer.h @@ -0,0 +1,24 @@ +#ifndef _DEV_FRAMEBUFFER_H_ +#define _DEV_FRAMEBUFFER_H_ + +#include "stddef.h" +#include "vfs.h" + +struct framebuffer_info +{ + unsigned int width; + unsigned int height; + unsigned int pitch; + unsigned int isrgb; +}; + +int init_dev_framebuffer(); + +int dev_framebuffer_write(struct file *file, const void *buf, size_t len); +int dev_framebuffer_read(struct file *file, void *buf, size_t len); +int dev_framebuffer_open(struct vnode *file_node, struct file **target); +int dev_framebuffer_close(struct file *file); +long dev_framebuffer_lseek64(struct file *file, long offset, int whence); +int dev_framebuffer_op_deny(); + +#endif diff --git a/lab8/kernel/include/vfs_dev_uart.h b/lab8/kernel/include/vfs_dev_uart.h new file mode 100644 index 000000000..b46dceed4 --- /dev/null +++ b/lab8/kernel/include/vfs_dev_uart.h @@ -0,0 +1,15 @@ +#ifndef _DEV_UART_H_ +#define _DEV_UART_H_ + +#include "stddef.h" +#include "vfs.h" + +int init_dev_uart(); + +int dev_uart_write(struct file *file, const void *buf, size_t len); +int dev_uart_read(struct file *file, void *buf, size_t len); +int dev_uart_open(struct vnode *file_node, struct file **target); +int dev_uart_close(struct file *file); +int dev_uart_op_deny(); + +#endif diff --git a/lab8/kernel/include/vfs_fat32.h b/lab8/kernel/include/vfs_fat32.h new file mode 100644 index 000000000..08da954b0 --- /dev/null +++ b/lab8/kernel/include/vfs_fat32.h @@ -0,0 +1,252 @@ +#ifndef FAT32_H +#define FAT32_H + +#include "u_list.h" +#include "vfs.h" + +#define BLOCK_SIZE 512 +#define CLUSTER_ENTRY_PER_BLOCK (BLOCK_SIZE / sizeof(struct cluster_entry_t)) +#define DIR_PER_BLOCK (BLOCK_SIZE / sizeof(struct dir_t)) +#define INVALID_CID 0x0ffffff8 // Last cluster in file (EOC), reserved by FAT32 + +struct partition_t +{ + unsigned char status; + unsigned char chss_head; + unsigned char chss_sector; + unsigned char chss_cylinder; + unsigned char type; + unsigned char chse_head; + unsigned char chse_sector; + unsigned char chse_cylinder; + unsigned int lba; + unsigned int sectors; +} __attribute__((packed)); + +struct boot_sector_t +{ + unsigned char jmpboot[3]; + unsigned char oemname[8]; + unsigned short bytes_per_sector; + unsigned char sector_per_cluster; + unsigned short reserved_sector_cnt; // red + unsigned char fat_cnt; // yellow + unsigned short root_entry_cnt; + unsigned short old_sector_cnt; + unsigned char media; + unsigned short sector_per_fat16; + unsigned short sector_per_track; + unsigned short head_cnt; + unsigned int hidden_sector_cnt; // blue + unsigned int sector_cnt; // FAT32 definition + unsigned int sector_per_fat32; // pink + unsigned short extflags; + unsigned short ver; + unsigned int root_cluster; + unsigned short info; + unsigned short bkbooksec; + unsigned char reserved[12]; + unsigned char drvnum; + unsigned char reserved1; + unsigned char bootsig; + unsigned int volid; + unsigned char vollab[11]; + unsigned char fstype[8]; +} __attribute__((packed)); + +struct fat_info_t +{ + struct boot_sector_t bs; // boot_sector from MBR Partition Table + unsigned int fat_lba; // FAT Region in FAT fs Definition + unsigned int cluster_lba; // Data Region in FAT32 fs Definition +}; + +// attr of dir_t +#define ATTR_READ_ONLY 0x01 +#define ATTR_HIDDEN 0x02 +#define ATTR_SYSTEM 0x04 +#define ATTR_VOLUME_ID 0x08 +#define ATTR_LFN 0x0f +#define ATTR_DIRECTORY 0x10 +#define ATTR_ARCHIVE 0x20 +#define ATTR_FILE_DIR_MASK (ATTR_DIRECTORY | ATTR_ARCHIVE) + +// Directory structure for FAT SFN +// http://elm-chan.org/docs/fat_e.html +struct dir_t +{ + unsigned char name[11]; + unsigned char attr; + unsigned char ntres; + unsigned char crttimetenth; + unsigned short crttime; + unsigned short crtdate; + unsigned short lstaccdate; + unsigned short ch; + unsigned short wrttime; + unsigned short wrtdate; + unsigned short cl; + unsigned int size; +} __attribute__((packed)); + +// Directory structure for FAT LFN +// https://blog.csdn.net/ZCShouCSDN/article/details/97610903 +struct long_dir_t +{ + unsigned char order; + unsigned char name1[10]; + unsigned char attr; + unsigned char type; + unsigned char checksum; + unsigned char name2[12]; + unsigned short fstcluslo; + unsigned char name3[4]; +} __attribute__((packed)); + +struct cluster_entry_t +{ + union + { + unsigned int val; + struct + { + unsigned int idx : 28; + unsigned int reserved : 4; + }; + }; +}; + +struct filename_t +{ + union + { + unsigned char fullname[256]; + struct + { + unsigned char name[13]; + } part[20]; + }; +} __attribute__((packed)); + +struct fat_file_block_t +{ + /* Link fat_file_block_t */ + struct list_head list; + unsigned int oid; // offset if of file, N = offset N* BLOCK_SIZE of file + unsigned int cid; // cluster id + unsigned int bufIsUpdated; + unsigned int isDirty; + unsigned char buf[BLOCK_SIZE]; +}; + +struct fat_file_t +{ + /* Head of fat_file_block_t chain */ + struct list_head list; + unsigned int size; +}; + +struct fat_dir_t +{ + /* Head of fat32_inode chain */ + struct list_head list; +}; + +struct fat_mount_t +{ + /* Link fat_mount_t */ + struct list_head list; + struct mount *mount; +}; + +// type of struct fat32_inode +#define FAT_DIR 1 +#define FAT_FILE 2 + +struct fat32_inode +{ + const char *name; + struct vnode *node; // redirect to vnode + struct fat_info_t *fat; + /* Link fat32_inode */ + struct list_head list; + /* cluster id */ + unsigned int cid; // cluster id + unsigned int type; + union + { + struct fat_dir_t *dir; + struct fat_file_t *file; + }; + + struct boot_sector_t *boot_sector; + struct sfn_file *sfn; + char Name[16]; + struct vnode *entry[16]; + char *data; + size_t datasize; +}; + +struct sfn_file +{ + char name[11]; // 檔案名稱 + char attribute; // 屬性 + char reserved; // 保留位 + char creation_time_tenth_seconds; // 創建時間的1/10秒計數 + unsigned short creation_time; // 創建時間 + unsigned short creation_date; // 創建日期 + unsigned short last_access_date; // 最後訪問日期 + unsigned short first_cluster_high; // 文件起始簇高16位 + unsigned short last_write_time; // 最後修改時間 + unsigned short last_write_date; // 最後修改日期 + unsigned short first_cluster_low; // 文件起始簇低16位 + unsigned int file_size; // 文件大小(字節) +}; + +int +register_fat32(); + +int fat32_mount(struct filesystem *fs, struct mount *mount); +int fat32_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); +int fat32_create(struct vnode *dir_node, struct vnode **target, const char *component_name); +int fat32_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name); +int fat32_isdir(struct vnode *dir_node); +int fat32_getname(struct vnode *dir_node, const char **name); +int fat32_getsize(struct vnode *dir_node); + +int fat32_write(struct file *file, const void *buf, size_t len); +int fat32_read(struct file *file, void *buf, size_t len); +int fat32_open(struct vnode *file_node, struct file **target); +int fat32_close(struct file *file); +long fat32_lseek64(struct file *file, long offset, int whence); +int fat32_sync(struct filesystem *fs); + +unsigned int alloc_cluster(struct fat_info_t *fat, unsigned int prev_cid); +unsigned int get_next_cluster(unsigned int fat_lba, unsigned int cluster_id); + +struct vnode *_create_vnode(struct vnode *parent, const char *name, unsigned int type, unsigned int cid, unsigned int size); + +int _lookup_cache(struct vnode *dir_node, struct vnode **target, const char *component_name); +struct dir_t *__lookup_fat32(struct vnode *dir_node, const char *component_name, unsigned char *buf, int *buflba); +int _lookup_fat32(struct vnode *dir_node, struct vnode **target, const char *component_name); + +int _readfile(void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len); +int _readfile_fat32(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid); +int _readfile_cache(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block); +int _readfile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block); +int _readfile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block); + +int _writefile(const void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len); +int _writefile_fat32(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid); +int _writefile_cache(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block); +int _writefile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block); +int _writefile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block); + +void _sync_dir(struct vnode *dirnode); +void _do_sync_dir(struct vnode *dirnode); +void _do_sync_file(struct vnode *filenode); + +void fat32_dump(struct vnode *vnode, int level); +void fat32_ls(struct vnode *vnode); +int fat32_op_deny(); +#endif diff --git a/lab8/kernel/include/vfs_initramfs.h b/lab8/kernel/include/vfs_initramfs.h new file mode 100644 index 000000000..d7b267e8c --- /dev/null +++ b/lab8/kernel/include/vfs_initramfs.h @@ -0,0 +1,41 @@ +#ifndef _INITRAMFS_H_ +#define _INITRAMFS_H_ + +#include "stddef.h" +#include "vfs.h" + +#define INITRAMFS_MAX_DIR_ENTRY 100 + +// initramfs basically is same as tmpfs, but it is read-only + +struct initramfs_inode +{ + enum fsnode_type type; + char* name; + struct vnode *entry[INITRAMFS_MAX_DIR_ENTRY]; + char *data; + size_t datasize; +}; + +int register_initramfs(); +int initramfs_setup_mount(struct filesystem *fs, struct mount *_mount); + +int initramfs_write(struct file *file, const void *buf, size_t len); +int initramfs_read(struct file *file, void *buf, size_t len); +int initramfs_open(struct vnode *file_node, struct file **target); +int initramfs_close(struct file *file); +long initramfs_lseek64(struct file *file, long offset, int whence); +long initramfs_getsize(struct vnode *vd); + +int initramfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); +int initramfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name); +int initramfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name); + +struct vnode *initramfs_create_vnode(struct mount *_mount, enum fsnode_type type); + +void initramfs_dump(struct vnode *dir_node , int level); +void initramfs_ls(struct vnode *dir_node); +int initramfs_op_deny(); +int initramfs_sync(struct filesystem *fs); + +#endif /* _INITRAMFS_H_ */ diff --git a/lab8/kernel/include/vfs_tmpfs.h b/lab8/kernel/include/vfs_tmpfs.h new file mode 100644 index 000000000..e0415d95d --- /dev/null +++ b/lab8/kernel/include/vfs_tmpfs.h @@ -0,0 +1,42 @@ +#ifndef _TMPFS_H_ +#define _TMPFS_H_ + +#include "stddef.h" +#include "vfs.h" + +// SPEC basic Note #3 +#define MAX_FILE_NAME 15 +#define MAX_DIR_ENTRY 16 +#define MAX_FILE_SIZE 4096 + +struct tmpfs_inode +{ + enum fsnode_type type; + char name[MAX_FILE_NAME]; + struct vnode *entry[MAX_DIR_ENTRY]; + char *data; + size_t datasize; +}; + +int register_tmpfs(); +int tmpfs_setup_mount(struct filesystem *fs, struct mount *_mount); + +int tmpfs_write(struct file *file, const void *buf, size_t len); +int tmpfs_read(struct file *file, void *buf, size_t len); +int tmpfs_open(struct vnode *file_node, struct file **target); +int tmpfs_close(struct file *file); +long tmpfs_lseek64(struct file *file, long offset, int whence); +long tmpfs_getsize(struct vnode *vd); + +int tmpfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); +int tmpfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name); +int tmpfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name); + +void tmpfs_dump(struct vnode *dir_node , int level); +void tmpfs_ls(struct vnode *dir_node); +int tmpfs_op_deny(); +int tmpfs_sync(struct filesystem *fs); + +struct vnode *tmpfs_create_vnode(struct mount *_mount, enum fsnode_type type); + +#endif /* _TMPFS_H_ */ diff --git a/lab8/kernel/initramfs.cpio b/lab8/kernel/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..08fa914524bd41a9ecc4d0eb44983850986ebc91 GIT binary patch literal 1057792 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

-e!a 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 UK7Zw1jl*ekMO}WXtLW$dAG(TTm;e9( literal 0 HcmV?d00001 diff --git a/lab8/kernel/src/boot.S b/lab8/kernel/src/boot.S new file mode 100644 index 000000000..456dfeb7d --- /dev/null +++ b/lab8/kernel/src/boot.S @@ -0,0 +1,82 @@ +#include "mmu.h" + +.section ".text.boot" + +.global _kernel_start + +_kernel_start: + bl from_el2_to_el1 + +set_mmu_configuration: + // set paging configuration (up : 0xffff000000000000 low : 0x0000000000000000) + ldr x4, = TCR_CONFIG_DEFAULT + msr tcr_el1, x4 + + // Set Used Memory Attributes + ldr x4, =((MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8))) + msr mair_el1, x4 + + // set and enable MMU + ldr x4, = MMU_PGD_ADDR // PGD's page frame at 0x1000 + ldr x1, = MMU_PUD_ADDR // PUD's page frame at 0x2000 + + ldr x2, = BOOT_PGD_ATTR + orr x2, x1, x2 // combine the physical address of next level page with attribute. + str x2, [x4] // [MMU_PGD_ADDR] = MMU_PUD_ADDR | BOOT_PGD_ATTR + + ldr x2, = BOOT_PUD_ATTR + mov x3, 0x00000000 + orr x3, x2, x3 // [MMU_PUD_ADDR] = 0x00000000 | BOOT_PUD_ATTR + str x3, [x1] // 1st 1GB mapped by the 1st entry of PUD + mov x3, 0x40000000 + orr x3, x2, x3 // [MMU_PUD_ADDR + 8] = 0x40000000 | BOOT_PUD_ATTR + str x3, [x1, 8] // 2nd 1GB mapped by the 2nd entry of PUD + + msr ttbr0_el1, x4 // load PGD to the bottom translation-based register. + msr ttbr1_el1, x4 // also load PGD to the upper translation based register. + + mov sp, 0x3c000000 // temp stack + bl set_2M_kernel_mmu + + mrs x2, sctlr_el1 // sctlr_el1: Provides top level control of the system, including its memory system, at EL1 and EL0. + orr x2 , x2, 1 // sctlr_el1[0]: EL1&0 stage 1 address translation enabled/disabled. + msr sctlr_el1, x2 + + // indirect branch to the upper virtual address + ldr x2, =set_exception_vector_table + br x2 + +set_exception_vector_table: + adr x1, exception_vector_table // vbar_el1: Vector Base Address Register (EL1) + msr vbar_el1, x1 // Holds the exception base address for any exception that is taken to EL1. + +setup_stack: + ldr x1, =_stack_top + mov sp, x1 + +setup_bss: + ldr x1, =_bss_start + ldr w2, =_bss_size + +init_bss: + cbz w2, run_main + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, init_bss + +run_main: + ldr x1, =dtb_ptr + str x0, [x1], #8 + bl main + +proc_hang: + wfe + b proc_hang + +from_el2_to_el1: + mov x1, (1 << 31) // EL1 uses aarch64 + msr hcr_el2, x1 + mov x1, 0x3c5 // EL1h (SPSel = 1) with interrupt disabled + msr spsr_el2, x1 + msr elr_el2, lr + eret // return to EL1 \ No newline at end of file diff --git a/lab8/kernel/src/cpio.c b/lab8/kernel/src/cpio.c new file mode 100644 index 000000000..56fdfc4e8 --- /dev/null +++ b/lab8/kernel/src/cpio.c @@ -0,0 +1,82 @@ +#include "string.h" +#include "cpio.h" +#include "stdio.h" + +/* Parse an ASCII hex string into an integer. (big endian)*/ +static unsigned int parse_hex_str(char *s, unsigned int max_len) +{ + unsigned int r = 0; + + for (unsigned int i = 0; i < max_len; i++) + { + r *= 16; + if (s[i] >= '0' && s[i] <= '9') + { + r += s[i] - '0'; + } + else if (s[i] >= 'a' && s[i] <= 'f') + { + r += s[i] - 'a' + 10; + } + else if (s[i] >= 'A' && s[i] <= 'F') + { + r += s[i] - 'A' + 10; + } + else + { + return r; + } + } + return r; +} + +/* write pathname, data, next header into corresponding parameter */ +/* if no next header, next_header_pointer = 0 */ +/* return -1 if parse error*/ +int cpio_newc_parse_header(struct cpio_newc_header *this_header_pointer, char **pathname, unsigned int *filesize, char **data, struct cpio_newc_header **next_header_pointer) +{ + /* Ensure magic header exists. */ + if (strncmp(this_header_pointer->c_magic, CPIO_NEWC_HEADER_MAGIC, sizeof(this_header_pointer->c_magic)) != 0) + { + *next_header_pointer = 0; + puts("cpio parse error\r\n"); + return -1; + } + + // transfer big endian 8 byte hex string to unsigned int and store into *filesize + *filesize = parse_hex_str(this_header_pointer->c_filesize, 8); + + // end of header is the pathname + *pathname = ((char *)this_header_pointer) + sizeof(struct cpio_newc_header); + + // get file data, file data is just after pathname + unsigned int pathname_length = parse_hex_str(this_header_pointer->c_namesize, 8); + unsigned int offset = pathname_length + sizeof(struct cpio_newc_header); + // The file data is padded to a multiple of four bytes + offset = padding_4byte(offset); + *data = (char *)this_header_pointer + offset; + + // get next header pointer + if (*filesize == 0) + { + *next_header_pointer = (struct cpio_newc_header *)*data; + } + else + { + offset = *filesize; + *next_header_pointer = (struct cpio_newc_header *)(*data + padding_4byte(offset)); + } + + // if filepath is TRAILER!!! means there is no more files. + if (strncmp(*pathname, "TRAILER!!!", sizeof("TRAILER!!!")) == 0) + { + *next_header_pointer = 0; + } + + return 0; +} + +unsigned int padding_4byte(unsigned int size) +{ + return size + (4 - size % 4) % 4; +} \ No newline at end of file diff --git a/lab8/kernel/src/dtb.c b/lab8/kernel/src/dtb.c new file mode 100644 index 000000000..df97d64fc --- /dev/null +++ b/lab8/kernel/src/dtb.c @@ -0,0 +1,173 @@ +#include "dtb.h" +#include "uart1.h" +#include "cpio.h" +#include "string.h" +#include "stdio.h" +#include "memory.h" +#include "bcm2837/rpi_mmu.h" +#include "debug.h" + +void *CPIO_DEFAULT_START; +void *CPIO_DEFAULT_END; +char *dtb_ptr; + +// stored as big endian +struct fdt_header +{ + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +}; + +struct fdt_reserve_entry +{ + uint64_t address; + uint64_t size; +}; + +uint32_t uint32_endian_big2little(uint32_t data) +{ + char *r = (char *)&data; + return (r[3] << 0) | (r[2] << 8) | (r[1] << 16) | (r[0] << 24); +} + +uint64_t uint64_endian_big2little(uint64_t data) +{ + char *r = (char *)&data; + return ((unsigned long long)r[7] << 0) | ((unsigned long long)r[6] << 8) | ((unsigned long long)r[5] << 16) | ((unsigned long long)r[4] << 24) | ((unsigned long long)r[3] << 32) | ((unsigned long long)r[2] << 40) | ((unsigned long long)r[1] << 48) | ((unsigned long long)r[0] << 56); +} + +void traverse_device_tree(void *dtb_ptr, dtb_callback callback) +{ + struct fdt_header *header = dtb_ptr; + if (uint32_endian_big2little(header->magic) != 0xD00DFEED) + { + ERROR("traverse_device_tree : wrong magic in traverse_device_tree\n"); + return; + } + // https://abcamus.github.io/2016/12/28/uboot%E8%AE%BE%E5%A4%87%E6%A0%91-%E8%A7%A3%E6%9E%90%E8%BF%87%E7%A8%8B/ + // https://blog.csdn.net/wangdapao12138/article/details/82934127 + uint32_t struct_size = uint32_endian_big2little(header->size_dt_struct); + char *dt_struct_ptr = (char *)((char *)header + uint32_endian_big2little(header->off_dt_struct)); + char *dt_strings_ptr = (char *)((char *)header + uint32_endian_big2little(header->off_dt_strings)); + + char *end = (char *)dt_struct_ptr + struct_size; + char *pointer = dt_struct_ptr; + + while (pointer < end) + { + uint32_t token_type = uint32_endian_big2little(*(uint32_t *)pointer); + + pointer += 4; + if (token_type == FDT_BEGIN_NODE) + { + callback(token_type, pointer, 0, 0); + pointer += strlen(pointer); + pointer += 4 - (unsigned long long)pointer % 4; // alignment 4 byte + } + else if (token_type == FDT_END_NODE) + { + callback(token_type, 0, 0, 0); + } + else if (token_type == FDT_PROP) + { + uint32_t len = uint32_endian_big2little(*(uint32_t *)pointer); + pointer += 4; + char *name = (char *)dt_strings_ptr + uint32_endian_big2little(*(uint32_t *)pointer); + pointer += 4; + callback(token_type, name, pointer, len); + pointer += len; + if ((unsigned long long)pointer % 4 != 0) + pointer += 4 - (unsigned long long)pointer % 4; // alignment 4 byte + } + else if (token_type == FDT_NOP) + { + callback(token_type, 0, 0, 0); + } + else if (token_type == FDT_END) + { + callback(token_type, 0, 0, 0); + } + else + { + puts("error type:"); + put_hex(token_type); + puts("\n"); + return; + } + } +} + +void dtb_callback_show_tree(uint32_t node_type, char *name, void *data, uint32_t name_size) +{ + static int level = 0; + if (node_type == FDT_BEGIN_NODE) + { + for (int i = 0; i < level; i++) + puts(" "); + puts(name); + puts("{\n"); + level++; + } + else if (node_type == FDT_END_NODE) + { + level--; + for (int i = 0; i < level; i++) + puts(" "); + puts("}\n"); + } + else if (node_type == FDT_PROP) + { + for (int i = 0; i < level; i++) + puts(" "); + puts(name); + puts("\n"); + } +} + +void dtb_callback_initramfs(uint32_t node_type, char *name, void *value, uint32_t name_size) +{ + // https://github.com/stweil/raspberrypi-documentation/blob/master/configuration/device-tree.md + // linux,initrd-start will be assigned by start.elf based on config.txt + if (node_type == FDT_PROP && strcmp(name, "linux,initrd-start") == 0) + { + CPIO_DEFAULT_START = (void *)(unsigned long long)PHYS_TO_KERNEL_VIRT(uint32_endian_big2little(*(uint32_t *)value)); + } + if (node_type == FDT_PROP && strcmp(name, "linux,initrd-end") == 0) + { + CPIO_DEFAULT_END = (void *)(unsigned long long)PHYS_TO_KERNEL_VIRT(uint32_endian_big2little(*(uint32_t *)value)); + } +} + +void dtb_find_and_store_reserved_memory() +{ + struct fdt_header *header = (struct fdt_header *)dtb_ptr; + if (uint32_endian_big2little(header->magic) != 0xD00DFEED) + { + ERROR("traverse_device_tree : wrong magic in traverse_device_tree\n"); + return; + } + + // off_mem_rsvmap stores all of reserve memory map with address and size + char *dt_mem_rsvmap_ptr = (char *)((char *)header + uint32_endian_big2little(header->off_mem_rsvmap)); + struct fdt_reserve_entry *reverse_entry = (struct fdt_reserve_entry *)dt_mem_rsvmap_ptr; + + // reserve memory which is defined by dtb + while (reverse_entry->address != 0 || reverse_entry->size != 0) + { + unsigned long long start = PHYS_TO_KERNEL_VIRT(uint64_endian_big2little(reverse_entry->address)); + unsigned long long end = uint64_endian_big2little(reverse_entry->size) + start; + memory_reserve(start, end); + reverse_entry++; + } + + // reserve device tree itself + memory_reserve((unsigned long long)dtb_ptr, (unsigned long long)dtb_ptr + uint32_endian_big2little(header->totalsize)); +} \ No newline at end of file diff --git a/lab8/kernel/src/entry.S b/lab8/kernel/src/entry.S new file mode 100644 index 000000000..74e3bcb53 --- /dev/null +++ b/lab8/kernel/src/entry.S @@ -0,0 +1,199 @@ +// save general registers to stack +.macro save_all + sub sp, sp, 32 * 9 + stp x0, x1, [sp ,16 * 0] // store pair of registers + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + str x30, [sp, 16 * 15] + // information for nested interrupt + mrs x0, spsr_el1 + str x0, [sp, 16 * 15 + 8] + mrs x0, elr_el1 + str x0, [sp, 16 * 16] + mrs x0, sp_el0 + str x0, [sp, 16 * 16 + 8] + ldp x0, x1, [sp, 16 * 0] +.endm + +// load general registers from stack +.macro load_all + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + ldr x30, [sp, 16 * 15] + // information for nested interrupt + ldr x0, [sp, 16 * 15 + 8] + msr spsr_el1,x0 + ldr x0, [sp, 16 * 16] + msr elr_el1, x0 + ldr x0, [sp, 16 * 16 + 8] + msr sp_el0, x0 + ldp x0, x1, [sp ,16 * 0] // restore x0 instead of elr_el1 + add sp, sp, 32 * 9 +.endm + +.macro ventry label + .align 7 // entry should be aligned to 0x80 (2^7) + b \label +.endm + +.align 11 // vector table should be aligned to 0x800 (2^11) +.global exception_vector_table + +// exception_vector_table definition +// https://github.com/torvalds/linux/blob/v4.14/arch/arm64/kernel/entry.S#L367 +exception_vector_table: + //Exception from the current EL while using SP_EL0 + ventry el1t_sync_invalid // Synchronous EL1t + ventry el1t_irq_invalid // IRQ EL1t + ventry el1t_fiq_invalid // FIQ EL1t + ventry el1t_error_invalid // Error EL1t + + //Exception from the current EL while using SP_ELx + ventry el1h_sync // Synchronous EL1h + ventry el1h_irq // IRQ EL1h + ventry el1h_fiq_invalid // FIQ EL1h + ventry el1h_error_invalid // Error EL1h + + //Exception from a lower EL and at least one lower EL is AArch64 + ventry el0_sync_64 // Synchronous 64-bit EL0 + ventry el0_irq_64 // IRQ 64-bit EL0 + ventry el0_fiq_invalid_64 // FIQ 64-bit EL0 + ventry el0_error_invalid_64 // Error 64-bit EL0 + + //Exception from a lower EL and at least all lower EL are AArch32 + ventry el0_sync_invalid_32 // Synchronous 32-bit EL0 + ventry el0_irq_invalid_32 // IRQ 32-bit EL0 + ventry el0_fiq_invalid_32 // FIQ 32-bit EL0 + ventry el0_error_invalid_32 // Error 32-bit EL0 + + +el1t_sync_invalid: + save_all + mov x0,0 + bl invalid_exception_router + load_all + eret +el1t_irq_invalid: + save_all + mov x0,1 + bl invalid_exception_router + load_all + eret +el1t_fiq_invalid: + save_all + mov x0,2 + bl invalid_exception_router + load_all + eret +el1t_error_invalid: + save_all + mov x0,3 + bl invalid_exception_router + load_all + eret + + +el1h_sync: + save_all + mov x0, sp + bl el1h_sync_router + bl el1_interrupt_disable + load_all + eret +el1h_irq: + save_all + mov x0, sp + bl el1h_irq_router + bl el1_interrupt_disable + load_all + eret +el1h_fiq_invalid: + save_all + mov x0,6 + bl invalid_exception_router + load_all + eret +el1h_error_invalid: + save_all + mov x0,7 + bl invalid_exception_router + load_all + eret + +el0_sync_64: + save_all + mov x0, sp + bl el0_sync_router + bl el1_interrupt_disable + load_all + eret +el0_irq_64: + save_all + mov x0, sp + bl el0_irq_router // ----------------------------------- + bl el1_interrupt_disable + load_all + eret +el0_fiq_invalid_64: + save_all + mov x0,10 + bl invalid_exception_router + load_all + eret +el0_error_invalid_64: + save_all + mov x0,11 + bl invalid_exception_router + load_all + eret + + +el0_sync_invalid_32: + save_all + mov x0,12 + bl invalid_exception_router + load_all + eret +el0_irq_invalid_32: + save_all + mov x0,13 + bl invalid_exception_router + load_all + eret +el0_fiq_invalid_32: + save_all + mov x0,14 + bl invalid_exception_router + load_all + eret +el0_error_invalid_32: + save_all + mov x0,15 + bl invalid_exception_router + load_all + eret diff --git a/lab8/kernel/src/exception.c b/lab8/kernel/src/exception.c new file mode 100644 index 000000000..1b6a72bce --- /dev/null +++ b/lab8/kernel/src/exception.c @@ -0,0 +1,377 @@ +#include "bcm2837/rpi_irq.h" +#include "bcm2837/rpi_uart1.h" +#include "uart1.h" +#include "exception.h" +#include "timer.h" +#include "syscall.h" +#include "signal.h" +#include "sched.h" +#include "memory.h" +#include "irqtask.h" +#include "mmu.h" +#include "debug.h" + +// 讀取ESR_EL1暫存器的值 +static inline unsigned long read_esr_el1(void) +{ + unsigned long value; + asm volatile("mrs %0, esr_el1" : "=r"(value)); + return value; +} + +// 判斷異常是否由EL0觸發的syscall +static inline int is_el0_syscall() +{ + unsigned long esr_el1 = read_esr_el1(); + unsigned long ec = (esr_el1 >> ESR_EL1_EC_SHIFT) & ESR_EL1_EC_MASK; + if (ec == ESR_EL1_EC_SVC64) + { + return 1; + } + return 0; +} + +// 定義異常類型名稱 +const char *exception_type[] = { + "Unknown reason", + "Trapped WFI or WFE instruction execution", + "Trapped MCR or MRC access with (coproc==0b1111) (AArch32)", + "Trapped MCRR or MRRC access with (coproc==0b1111) (AArch32)", + "Trapped MCR or MRC access with (coproc==0b1110) (AArch32)", + "Trapped LDC or STC access (AArch32)", + "Trapped FP access", + "Trapped VMRS access", + "Trapped PSTATE (AArch32)", + "Instruction Abort from a lower Exception level", + "Instruction Abort taken without a change in Exception level", + "PC alignment fault", + "Data Abort from a lower Exception level", + "Data Abort taken without a change in Exception level", + "SP alignment fault", + "Trapped floating-point exception", + "SError interrupt", + "Breakpoint from a lower Exception level", + "Breakpoint taken without a change in Exception level", + "Software Step from a lower Exception level", + "Software Step taken without a change in Exception level", + "Watchpoint from a lower Exception level", + "Watchpoint taken without a change in Exception level", + "BKPT instruction execution (AArch32)", + "Vector Catch exception (AArch32)", + "BRK instruction execution (AArch64)"}; + +extern list_head_t *run_queue; + +// DAIF, Interrupt Mask Bits +void el1_interrupt_enable() +{ + __asm__ __volatile__("msr daifclr, 0xf"); // umask all DAIF +} + +void el1_interrupt_disable() +{ + __asm__ __volatile__("msr daifset, 0xf"); // mask all DAIF +} + +unsigned long long int lock_counter = 0; + +void lock() +{ + el1_interrupt_disable(); + lock_counter++; +} + +void unlock() +{ + // uart_sendlinek("This is unlock\n"); + lock_counter--; + if (lock_counter < 0) + { + while (1) + ; + } + else if (lock_counter == 0) + { + el1_interrupt_enable(); + } +} + +void el1h_sync_router(trapframe_t *tpf) +{ + uart_sendlinek("\n"); + uart_sendlinek("spsr_el1 : %x\n ", tpf->spsr_el1); + uart_sendlinek("elr_el1 : %x\n ", tpf->elr_el1); + uart_sendlinek("sp_el0 : %x\n ", tpf->sp_el0); + // dump_vma(); + while (1) + ; +} + +void el1h_irq_router(trapframe_t *tpf) +{ + lock(); + // decouple the handler into irqtask queue + // (1) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.113 + // (2) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.16 + if (*IRQ_PENDING_1 & IRQ_PENDING_1_AUX_INT && *CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_GPU) // from aux && from GPU0 -> uart exception + { + if (*AUX_MU_IER_REG & 2) + { + *AUX_MU_IER_REG &= ~(2); // disable write interrupt + irqtask_add(uart_w_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); // run the queued task before returning to the program. + } + else if (*AUX_MU_IER_REG & 1) + { + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + irqtask_add(uart_r_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + } + } + else if (*CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_CNTPNSIRQ) // from CNTPNS (core_timer) // A1 - setTimeout run in el1 + { + core_timer_disable(); + irqtask_add(core_timer_handler, TIMER_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + core_timer_enable(); + + if (list_size(run_queue) > 1) + { + // uart_sendlinek("el1h_irq_router\n"); + schedule(); + } + } + else + { + unlock(); + uart_sendlinek("Hello World el1 64 router other interrupt!\r\n"); + } + + // only do signal handler when return to user mode + if ((tpf->spsr_el1 & 0b1100) == 0) + { + check_signal(tpf); + } +} + +void el0_sync_router(trapframe_t *tpf) +{ + static int count = 0; + unsigned long long esr_el1 = read_esr_el1(); + + // esr_el1: Holds syndrome information for an exception taken to EL1. + esr_el1_t *esr = (esr_el1_t *)&esr_el1; + if (esr->ec == MEMFAIL_DATA_ABORT_LOWER || esr->ec == MEMFAIL_INST_ABORT_LOWER) + { + mmu_memfail_abort_handle(esr); + return; + } + + if (!is_el0_syscall()) + { + const char *exception_name = get_exception_name(esr_el1); + if (count == 0) + ERROR("el0_sync_router: exception occurred - %s\r\n", exception_name); + count++; + return; + } + + el1_interrupt_enable(); // Allow UART input during exception + unsigned long long syscall_no = tpf->x8; + if (syscall_no > 18) + { + uart_sendlinek("SYSCALL No: %d\n", syscall_no); + } + // uart_sendlinek("tpf->x8 : %d\n",tpf->x8); + switch (syscall_no) + { + SYSCALL(0, getpid(tpf)) + SYSCALL(1, uartread(tpf, (char *)tpf->x0, tpf->x1)) + SYSCALL(2, uartwrite(tpf, (char *)tpf->x0, tpf->x1)) + SYSCALL(3, exec(tpf, (char *)tpf->x0, (char **)tpf->x1)) + SYSCALL(4, fork(tpf)) + SYSCALL(5, exit(tpf, tpf->x0)) + SYSCALL(6, syscall_mbox_call(tpf, (unsigned char)tpf->x0, (unsigned int *)tpf->x1)) + SYSCALL(7, kill(tpf, (int)tpf->x0)) + SYSCALL(8, signal_register(tpf->x0, (void (*)())tpf->x1)) + SYSCALL(9, signal_kill(tpf->x0, tpf->x1)) + SYSCALL(10, mmap(tpf, (void *)tpf->x0, tpf->x1, tpf->x2, tpf->x3, tpf->x4, tpf->x5)) + SYSCALL(11, open(tpf, (char *)tpf->x0, tpf->x1);) + SYSCALL(12, close(tpf, tpf->x0)) + SYSCALL(13, write(tpf, tpf->x0, (char *)tpf->x1, tpf->x2)) + SYSCALL(14, read(tpf, tpf->x0, (char *)tpf->x1, tpf->x2)) + SYSCALL(15, mkdir(tpf, (char *)tpf->x0, tpf->x1)) + SYSCALL(16, mount(tpf, (char *)tpf->x0, (char *)tpf->x1, (char *)tpf->x2, tpf->x3, (void *)tpf->x4)) + SYSCALL(17, chdir(tpf, (char *)tpf->x0)) + SYSCALL(18, lseek64(tpf, tpf->x0, tpf->x1, tpf->x2)) + SYSCALL(19, ioctl(tpf, tpf->x0, tpf->x1, (void *)tpf->x2)) + SYSCALL(20, sync(tpf)) + SYSCALL(50, sigreturn(tpf)) + SYSCALL(114, syscall_lock(tpf)) + SYSCALL(514, syscall_unlock(tpf)) + default: + uart_sendlinek("el0_sync_router other syscall, syscall_no: %d\r\n", syscall_no); + break; + } +} + +void el0_irq_router(trapframe_t *tpf) +{ + lock(); + // decouple the handler into irqtask queue + // (1) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.113 + // (2) https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf - Pg.16 + if (*IRQ_PENDING_1 & IRQ_PENDING_1_AUX_INT && *CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_GPU) // from aux && from GPU0 -> uart exception + { + if (*AUX_MU_IER_REG & 2) + { + *AUX_MU_IER_REG &= ~(2); // disable write interrupt + irqtask_add(uart_w_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); // run the queued task before returning to the program. + } + else if (*AUX_MU_IER_REG & 1) + { + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + irqtask_add(uart_r_irq_handler, UART_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + } + } + else if (*CORE0_INTERRUPT_SOURCE & INTERRUPT_SOURCE_CNTPNSIRQ) // from CNTPNS (core_timer) // A1 - setTimeout run in el1 + { + core_timer_disable(); + irqtask_add(core_timer_handler, TIMER_IRQ_PRIORITY); + unlock(); + irqtask_run_preemptive(); + core_timer_enable(); + + if (list_size(run_queue) > 1) + { + // uart_sendlinek("el0_irq_router\n"); + schedule(); + } + } + else + { + unlock(); + uart_sendlinek("Hello World el0 64 router other interrupt!\r\n"); + } + + // only do signal handler when return to user mode + if ((tpf->spsr_el1 & 0b1100) == 0) + { + check_signal(tpf); + } +} + +void invalid_exception_router(unsigned long long x0) +{ + uart_sendlinek("\n invalid exception %x \n", x0); + while (1) + ; +} + +// 獲取異常類型名稱 +const char *get_exception_name(unsigned long esr_el1) +{ + unsigned long ec = (esr_el1 >> ESR_EL1_EC_SHIFT) & ESR_EL1_EC_MASK; + if (ec < sizeof(exception_type) / sizeof(exception_type[0])) + { + return exception_type[ec]; + } + return "Unknown exception"; +} + +// ------------------------------------------------------------------------------------------ + +/* +Preemption +Now, any interrupt handler can preempt the task’s execution, but the newly enqueued task still needs to wait for the currently running task’s completion. +It’d be better if the newly enqueued task with a higher priority can preempt the currently running task. +To achieve the preemption, the kernel can check the last executing task’s priority before returning to the previous interrupt handler. +If there are higher priority tasks, execute the highest priority task. +*/ + +int curr_task_priority = 9999; // Small number has higher priority + +struct list_head *task_list; +void irqtask_list_init() +{ + task_list = allocator(sizeof(list_head_t)); + INIT_LIST_HEAD(task_list); +} + +void irqtask_add(void *task_function, unsigned long long priority) +{ + irqtask_t *the_task = kmalloc(sizeof(irqtask_t)); // free by irq_tasl_run_preemptive() + + // store all the related information into irqtask node + // manually copy the device's buffer + the_task->priority = priority; + the_task->task_function = task_function; + INIT_LIST_HEAD(&(the_task->listhead)); + + // add the timer_event into timer_event_list (sorted) + // if the priorities are the same -> FIFO + struct list_head *curr; + + // mask the device's interrupt line + // el1_interrupt_disable(); + // enqueue the processing task to the event queue with sorting. + list_for_each(curr, task_list) + { + if (((irqtask_t *)curr)->priority > the_task->priority) + { + list_add(&(the_task->listhead), curr->prev); + break; + } + } + // if the priority is lowest + if (list_is_head(curr, task_list)) + { + list_add_tail(&(the_task->listhead), task_list); + } + // unmask the interrupt line + // el1_interrupt_enable(); +} + +void irqtask_run_preemptive() +{ + // el1_interrupt_enable(); + while (!list_empty(task_list)) + { + // critical section protects new coming node + + lock(); + irqtask_t *the_task = (irqtask_t *)task_list->next; + // Run new task (early return) if its priority is lower than the scheduled task. + if (curr_task_priority <= the_task->priority) + { + unlock(); + break; + } + // get the scheduled task and run it. + list_del_entry((struct list_head *)the_task); + int prev_task_priority = curr_task_priority; + curr_task_priority = the_task->priority; + // uart_sendlinek("preemptive curr_task_priority: %d\r\n", curr_task_priority); + unlock(); + + irqtask_run(the_task); + + lock(); + curr_task_priority = prev_task_priority; + unlock(); + // free(the_task); + } +} + +void irqtask_run(irqtask_t *the_task) +{ + ((void (*)())the_task->task_function)(); + kfree(the_task); +} diff --git a/lab8/kernel/src/linker.ld b/lab8/kernel/src/linker.ld new file mode 100644 index 000000000..45b64f607 --- /dev/null +++ b/lab8/kernel/src/linker.ld @@ -0,0 +1,44 @@ +_heap_stack_size = 50M; + +SECTIONS +{ + . = 0xffff000000000000; + . += 0x80000; + _kernel_start = .; + + .text : { + *(.text.boot) + *(.text) + } + + .rodata : { + *(.rodata) + } + + .data : { + *(.data) + } + + .bss : { + . = ALIGN(8); + _bss_start = .; + *(.bss) + *(COMMON) + } + _bss_end = .; + _bss_size = (_bss_end - _bss_start)>>3; + + .heap : { + . = ALIGN(8); + _heap_top = .; + . += _heap_stack_size; + _heap_end = .; + } + + _kernel_end = .; + + . = 0xffff00002c000000; + _stack_end = .; + . = 0xffff00003c000000; + _stack_top = .; +} \ No newline at end of file diff --git a/lab8/kernel/src/main.c b/lab8/kernel/src/main.c new file mode 100644 index 000000000..582faa2ff --- /dev/null +++ b/lab8/kernel/src/main.c @@ -0,0 +1,45 @@ +#include "uart1.h" +#include "shell.h" +#include "memory.h" +#include "dtb.h" +#include "exception.h" +#include "timer.h" +#include "sched.h" +#include "uart1.h" +#include "irqtask.h" +#include "vfs.h" +//#include "bcm2837/rpi_mmu.h" + +extern list_head_t *run_queue; +extern char *dtb_ptr; +int Set_dtb = 0; + +void main(char *arg) +{ + // uart_sendlinek("in main\n"); + dtb_ptr = (char *)PHYS_TO_KERNEL_VIRT(arg); + if (!Set_dtb) + { + traverse_device_tree(dtb_ptr, dtb_callback_initramfs); + Set_dtb = 1; + } + uart_init(); + allocator_init(); + rootfs_init(); + irqtask_list_init(); + timer_list_init(); + thread_sched_init(); + //uart_sendlinek("in main\n"); + + core_timer_enable(); + uart_interrupt_enable(); + uart_flush_FIFO(); + + el1_interrupt_enable(); // enable interrupt in EL1 -> EL1 + + //start_shell(); + // uart_sendlinek("RQ size : %d \n",list_size(run_queue)); + + //schedule(); + load_context(&((((thread_t*)run_queue->next))->context)); +} diff --git a/lab8/kernel/src/mbox.c b/lab8/kernel/src/mbox.c new file mode 100644 index 000000000..530412d28 --- /dev/null +++ b/lab8/kernel/src/mbox.c @@ -0,0 +1,23 @@ +#include "bcm2837/rpi_mbox.h" +#include "mbox.h" + +/* Aligned to 16-byte boundary while we have 28-bits for VC */ +volatile unsigned int __attribute__((aligned(16))) pt[36]; + +int mbox_call( mbox_channel_type channel, unsigned int value ) +{ + // Add channel to lower 4 bit + value &= ~(0xF); + value |= channel; + while ( (*MBOX_STATUS & BCM_ARM_VC_MS_FULL) != 0 ) {} + // Write to Register + *MBOX_WRITE = value; + while(1) { + while ( *MBOX_STATUS & BCM_ARM_VC_MS_EMPTY ) {} + // Read from Register + if (value == *MBOX_READ) + return pt[1] == MBOX_REQUEST_SUCCEED; + } + return 0; +} + diff --git a/lab8/kernel/src/memory.c b/lab8/kernel/src/memory.c new file mode 100644 index 000000000..a80a1219a --- /dev/null +++ b/lab8/kernel/src/memory.c @@ -0,0 +1,491 @@ +#include "memory.h" +#include "u_list.h" +#include "uart1.h" +#include "exception.h" +#include "dtb.h" +#include "stdio.h" +#include "mmu.h" +#include "bcm2837/rpi_mmu.h" + +extern char _heap_top; +static char *htop_ptr = &_heap_top; + +extern char _kernel_start; +extern char _kernel_end; +extern char *CPIO_DEFAULT_START; +extern char *CPIO_DEFAULT_END; +extern char _stack_end; +extern char _stack_top; + +void *allocator(unsigned int size) +{ + lock(); + // -> htop_ptr + // htop_ptr + 0x02: heap_block size + // htop_ptr + 0x10 ~ htop_ptr + 0x10 * k: + // { heap_block } + // -> htop_ptr + // header 0x10 bytes block + // |--------------------------------------------------------------| + // | fill zero 0x8 bytes | size 0x8 bytes | size padding to 0x16 | + // |--------------------------------------------------------------| + + // 0x10 for heap_block header + char *r = htop_ptr + 0x10; + // size paddling to multiple of 0x10 + size = 0x10 + size - size % 0x10; + *(unsigned int *)(r - 0x8) = size; + htop_ptr += size; + unlock(); + return r; +} + +// void free(void* ptr) { +// // TBD +// } + +// ------------------------------------------------------------ + +static frame_t *frame_array; // store memory's statement and page's corresponding index +static list_head_t frame_freelist[FRAME_MAX_IDX]; // store available block for page +static list_head_t cache_list[CACHE_MAX_IDX]; // store available block for cache + +void allocator_init() +{ + frame_array = allocator(BUDDY_MEMORY_PAGE_COUNT * sizeof(frame_t)); + + // init frame freelist + for (int i = FRAME_IDX_0; i <= FRAME_IDX_FINAL; i++) + { + INIT_LIST_HEAD(&frame_freelist[i]); + } + + // init cache list + for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + { + INIT_LIST_HEAD(&cache_list[i]); + } + + for (int i = 0; i < BUDDY_MEMORY_PAGE_COUNT; i++) + { + // init listhead for each frame + INIT_LIST_HEAD(&(frame_array[i].listhead)); + frame_array[i].idx = i; + } + freelist_init(); + dump_page_info(); + + /* Startup reserving the following region: + Spin tables for multicore boot (0x0000 - 0x1000) + Devicetree (Optional, if you have implement it) + Kernel image in the physical memory + Your simple allocator (startup allocator) (Stack + Heap in my case) + Initramfs + */ + uart_sendlinek("\r\n* Startup Allocation *\r\n"); + uart_sendlinek("buddy system: usable memory region: 0x%x ~ 0x%x\n", BUDDY_MEMORY_BASE, BUDDY_MEMORY_BASE + BUDDY_MEMORY_PAGE_COUNT * PAGESIZE); + dtb_find_and_store_reserved_memory(); // find spin tables in dtb + memory_reserve(PHYS_TO_KERNEL_VIRT(MMU_PGD_ADDR), PHYS_TO_KERNEL_VIRT(MMU_PTE_ADDR + 0x2000)); // // PGD's page frame at 0x1000 // PUD's page frame at 0x2000 PMD 0x3000-0x5000 + memory_reserve((unsigned long long)&_kernel_start, (unsigned long long)&_kernel_end); // kernel + memory_reserve((unsigned long long)&_stack_end, (unsigned long long)&_stack_top); + memory_reserve((unsigned long long)CPIO_DEFAULT_START, (unsigned long long)CPIO_DEFAULT_END); +} + +void freelist_init() +{ + int PAGE_COUNT = BUDDY_MEMORY_PAGE_COUNT; + for (int i = 0; i <= FRAME_IDX_FINAL; i++) + { + // uart_sendlinek("\n %ld,%ld \n",PAGE_COUNT,(1 << i)); + if ((PAGE_COUNT & (1 << i))) + { + PAGE_COUNT -= (1 << i); + frame_array[PAGE_COUNT].val = i; + frame_array[PAGE_COUNT].used = FRAME_FREE; + list_add(&(frame_array[PAGE_COUNT].listhead), &frame_freelist[i]); + } + if (i == FRAME_IDX_FINAL && PAGE_COUNT) + { + while (PAGE_COUNT) + { + PAGE_COUNT -= (1 << i); + frame_array[PAGE_COUNT].val = FRAME_IDX_FINAL; + frame_array[PAGE_COUNT].used = FRAME_FREE; + list_add(&(frame_array[PAGE_COUNT].listhead), &frame_freelist[FRAME_IDX_FINAL]); + } + } + } +} + +frame_t *release_redundant(frame_t *frame) +{ + // order -1 -> add its buddy to free list (frame itself will be used in master function) + frame->val -= 1; + frame_t *buddyptr = get_buddy(frame); + buddyptr->val = frame->val; + buddyptr->used = FRAME_FREE; + list_add(&(buddyptr->listhead), &frame_freelist[buddyptr->val]); + return frame; +} + +frame_t *get_buddy(frame_t *frame) +{ + // XOR(idx, order) + if ((frame->idx ^ (1 << frame->val)) > BUDDY_MEMORY_PAGE_COUNT) + { + uart_sendlinek("[!] BUDDY of Page: 0x%x at level: %d Does not exit", frame->idx, frame->val); + // return -1; + } + return &frame_array[frame->idx ^ (1 << frame->val)]; +} + +void dump_page_info() +{ + // unsigned int exp2 = 1; + // uart_sendlinek(" ┌───────────────────── [ Number of Available Page Blocks ] ─────────────────────┐\r\n │ "); + // for (int i = FRAME_IDX_0; i < FRAME_IDX_8; i++) + // { + // uart_sendlinek("%4dKB(%1d) ", 4 * exp2, i); + // exp2 *= 2; + // } + // uart_sendlinek("│\r\n │ "); + // for (int i = FRAME_IDX_0; i < FRAME_IDX_8; i++) + // uart_sendlinek(" %4d ", list_size(&frame_freelist[i])); + // uart_sendlinek("│\r\n "); + // uart_sendlinek("└────────────────────────────────────────"); + // uart_sendlinek("─────────────────────────────────────────┘\r\n"); + + // exp2 = 1; + // uart_sendlinek(" ┌──────────────────────────────────── "); + // uart_sendlinek("[ Number of Available Page Blocks ]"); + // uart_sendlinek(" ───────────────────────────────────┐\r\n │"); + // for (int i = FRAME_IDX_8; i < FRAME_MAX_IDX; i++) + // { + // uart_sendlinek("%4dMB(%2d) ", exp2, i); + // exp2 *= 2; + // } + // uart_sendlinek("│\r\n │"); + // for (int i = FRAME_IDX_8; i < FRAME_MAX_IDX; i++) + // uart_sendlinek(" %4d ", list_size(&frame_freelist[i])); + // uart_sendlinek("│\r\n "); + // uart_sendlinek("└──────────────────────────────────────────────────────"); + // uart_sendlinek("────────────────────────────────────────────────────────┘\r\n"); +} + +void dump_cache_info() +{ + // unsigned int exp2 = 1; + // uart_sendlinek(" ┌──────────────── [ Number of Available Cache Blocks ] ────────────────┐\r\n │ "); + // for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + // { + // uart_sendlinek("%4dB(%1d) ", CACHE_SEG * exp2, i); + // exp2 *= 2; + // } + // uart_sendlinek("│\r\n │ "); + // ; + // for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + // { + // if (!list_empty(&cache_list[i])) + // { + // // uart_sendlinek("I free !!!!!!!!!!!!"); + // int num = 0; + // list_head_t *pos; + // list_for_each(pos, &cache_list[i]) + // { + // num += ((cache_t *)pos)->available; + // } + // uart_sendlinek("%5d ", num); + // } + // else + // { + // uart_sendlinek("%5d ", 0); + // } + // } + + // uart_sendlinek("│\r\n "); + // uart_sendlinek("└───────────────────────────────────"); + // uart_sendlinek("────────────────────────────────────┘\r\n"); +} + +void memory_reserve(unsigned long long start, unsigned long long end) +{ + start -= start % PAGESIZE; // floor (align 0x1000) + end = end % PAGESIZE ? end + PAGESIZE - (end % PAGESIZE) : end; // ceiling (align 0x1000) + + // uart_sendlinek("Reserved Memory: "); + // uart_sendlinek("start 0x%x ~ ", start); + // uart_sendlinek("end 0x%x\r\n", end); + + // delete page from free list + for (int order = FRAME_IDX_FINAL; order >= 0; order--) + { + list_head_t *pos; + // uart_sendlinek("\n use %d level page to match \n",order); + list_for_each(pos, &frame_freelist[order]) + { + unsigned long long pagestart = ((frame_t *)pos)->idx * PAGESIZE + BUDDY_MEMORY_BASE; + unsigned long long pageend = pagestart + (PAGESIZE << order); + // uart_sendlinek("\n from 0x%x to 0x%x\n",pagestart,pageend); + + if (start <= pagestart && end >= pageend) // if page all in reserved memory -> delete it from freelist + { + ((frame_t *)pos)->used = FRAME_ALLOCATED; + // uart_sendlinek(" [!] Reserved page in 0x%x - 0x%x\n", pagestart, pageend); + // uart_sendlinek(" Before\n"); + // dump_page_info(); + list_del_entry(pos); + // uart_sendlinek(" Remove usable block for reserved memory: order %d\r\n", order); + // uart_sendlinek(" After\n"); + // dump_page_info(); + } + else if (start >= pageend || end <= pagestart) // no intersection + { + continue; + } + else // partial intersection, separate the page into smaller size. + { + // dump_page_info(); + list_del_entry(pos); + list_head_t *temppos = pos->prev; + list_add(&release_redundant((frame_t *)pos)->listhead, &frame_freelist[order - 1]); + pos = temppos; + // dump_page_info(); + } + } + } +} + +void *kmalloc(unsigned int size) +{ + lock(); + + // uart_sendlinek("\n\n"); + // uart_sendlinek("================================\r\n"); + // uart_sendlinek("[+] Request kmalloc size: %d\r\n", size); + // uart_sendlinek("================================\r\n"); + // if size is larger than cache size, go for page + if (size > (CACHE_SEG << CACHE_IDX_FINAL)) + { + void *r = page_malloc(size); + unlock(); + return r; + } + // go for cache + void *r = cache_malloc(size); + unlock(); + return r; +}; + +void *page_malloc(unsigned int size) +{ + // uart_sendlinek("this is page_malloc \r\n"); + int val; + int find_PageSize = 0; + frame_t *target_frame_ptr; + // turn size into minimum 4KB * 2**val + for (int i = FRAME_IDX_0; i <= FRAME_IDX_FINAL; i++) + { + + if (size <= (PAGESIZE << i) && !find_PageSize) + { + val = i; + // uart_sendlinek(" block size = 0x%x\n", PAGESIZE << i); + find_PageSize = 1; + } + + if (find_PageSize && !list_empty(&frame_freelist[i])) + { + // uart_sendlinek(" free page at level : %d\n", i); + target_frame_ptr = (frame_t *)(frame_freelist[i].next); + for (int min_FreePageLevel = i; min_FreePageLevel > val; min_FreePageLevel--) // ex: 10000 -> 01111 + { + target_frame_ptr = release_redundant(target_frame_ptr); + } + break; + } + + if (i == FRAME_IDX_FINAL) + { + // uart_sendlinek("[!] request size exceeded for page_malloc!!!!\r\n"); + return (void *)0; + } + } + // get the available frame from freelist + target_frame_ptr->used = FRAME_ALLOCATED; + + // uart_sendlinek(" [+] Allocate page - size : %d(0x%x)\r\n", size, size); + // uart_sendlinek(" Before\r\n"); + // dump_page_info(); + list_del_entry((struct list_head *)target_frame_ptr); + // uart_sendlinek(" physical address : 0x%x\n", BUDDY_MEMORY_BASE + (PAGESIZE * (target_frame_ptr->idx))); + // uart_sendlinek(" After\r\n"); + // dump_page_info(); + + return (void *)BUDDY_MEMORY_BASE + (PAGESIZE * (target_frame_ptr->idx)); +}; + +void *cache_malloc(unsigned int size) +{ + int c_val; + // uart_sendlinek("this is cache_malloc \r\n"); + for (int i = CACHE_IDX_0; i <= CACHE_IDX_FINAL; i++) + { + if (size <= (CACHE_SEG << i)) + { + c_val = i; + break; + } + } + + if (list_empty(&cache_list[c_val])) + { + // uart_sendlinek("[!] No free size for cache \r\n"); //--------------------------------------------------- + page2caches(c_val); + } + + // cache_t *ptr = (cache_t *)(cache_list[c_val].prev); + + // uart_sendlinek("this is cache_malloc \r\n"); + // uart_sendlinek("[+] Allocate cache - size : %d(0x%x)\r\n", size, size); + // uart_sendlinek(" Before\r\n"); + // dump_cache_info(); + + void *ptr = find_CACHE((cache_t *)cache_list[c_val].next); + // uart_sendlinek("ptr : %x\n",ptr); + // uart_sendlinek(" After\r\n"); + // dump_cache_info(); + + return ptr; +}; + +void *find_CACHE(cache_t *ptr) +{ + // uart_sendlinek("ptr : %x\n",ptr); + unsigned long long num; + int record_num; + for (record_num = 0; ptr->cache_record[record_num] + 1 == 0 && record_num < CACHE_record_num; record_num++) + ; + + num = ptr->cache_record[record_num] + 1; + num = ((~num) & (ptr->cache_record[record_num])) + 1; + + // uart_sendlinek("before cache_record[%d] : %x\n", record_num, ptr->cache_record[record_num]); + ptr->cache_record[record_num] += num; + ptr->available--; + // uart_sendlinek("after cache_record[%d] : %x\n", record_num, ptr->cache_record[record_num]); + + int val = fake_log2(num) + record_num * 64; + void *target = ptr->data_base + val * (CACHE_SEG << (ptr->cache_order)); + // uart_sendlinek("data_base addr : 0x%x\n", ptr->data_base); + // uart_sendlinek("target addr : 0x%x\n", target); + + if (!(ptr->available)) + { + list_del_entry((list_head_t *)ptr); + } + + return target; +} + +void page2caches(int c_val) +{ + // uart_sendlinek("[!] Split Page for cache\r\n"); + void *ptr = page_malloc(PAGESIZE); + // uart_sendlinek("ptr : %x\n",ptr); + cache_t *Pageinfo = (cache_t *)ptr; + Pageinfo->data_base = ptr; + Pageinfo->cache_order = c_val; + Pageinfo->max_available = (PAGESIZE >> (CACHE_offset + c_val)); + + while (sizeof(*Pageinfo) >= Pageinfo->data_base - ptr) + { + Pageinfo->data_base += (CACHE_SEG << c_val); + (Pageinfo->max_available)--; + } + Pageinfo->available = Pageinfo->max_available; + + for (int i = 0; i < CACHE_record_num; i++) + Pageinfo->cache_record[i] = 0; + + // uart_sendlinek(" max_available : %d\n", Pageinfo->max_available); + // uart_sendlinek(" Pageinfo size : 0x%x\n", sizeof(*Pageinfo)); + // uart_sendlinek(" offset size : 0x%x\n", (CACHE_SEG << c_val)); + + list_add(&(Pageinfo->listhead), &cache_list[c_val]); + // return Pageinfo; +} + +//------------------------------------------------------------------------------------------------------------------------------- kfree + +void kfree(void *ptr) +{ + // uart_sendlinek("\r\n"); + // uart_sendlinek("==========================\r\n"); + //uart_sendlinek("[+] Request kfree 0x%x\r\n", ptr); + // uart_sendlinek("==========================\r\n"); + + // If no cache assigned, go for page + lock(); + frame_t *target_frame_ptr = &frame_array[((unsigned long long)ptr - BUDDY_MEMORY_BASE) >> 12]; + if ((unsigned long long)ptr % PAGESIZE == 0) + { + page_free(target_frame_ptr); + unlock(); + return; + } + // go for cache + cache_free(ptr); + unlock(); +}; + +void page_free(frame_t *target_frame_ptr) +{ + frame_t *buddyptr = get_buddy(target_frame_ptr); + target_frame_ptr->used = FRAME_FREE; + while (buddyptr->used == FRAME_FREE && buddyptr->val == target_frame_ptr->val) + { + list_del_entry((list_head_t *)buddyptr); + target_frame_ptr = &frame_array[(target_frame_ptr->idx) & (buddyptr->idx)]; + target_frame_ptr->val++; + buddyptr = get_buddy(target_frame_ptr); + if (buddyptr < 0) + break; + } + + // uart_sendlinek(" Before\r\n"); + // dump_page_info(); + list_add(&(target_frame_ptr->listhead), &frame_freelist[target_frame_ptr->val]); + // uart_sendlinek(" After\r\n"); + // dump_page_info(); +} + +void cache_free(void *ptr) +{ + // uart_sendlinek("ptr : %x\n",ptr); + int idx = ((unsigned long long)ptr - BUDDY_MEMORY_BASE) >> 12; + frame_t *target_frame_ptr = &frame_array[idx]; + cache_t *cache_ptr = (cache_t *)((unsigned long long)(idx * PAGESIZE) + BUDDY_MEMORY_BASE); //<------- + // uart_sendlinek("target_frame_ptr : %x\n",target_frame_ptr); + //uart_sendlinek("cache_ptr : %x\n",cache_ptr); + int num = (ptr - cache_ptr->data_base) / (CACHE_SEG << cache_ptr->cache_order); + //uart_sendlinek("num : %d\n",num); + int record_num = (num >> 6); + num = num - (record_num << 6); + cache_ptr->cache_record[record_num] -= (1 << num); + + // uart_sendlinek("[+] Free cache: 0x%x, val = %d\r\n", ptr, cache_ptr->cache_order); + // uart_sendlinek(" Before\r\n"); + // dump_cache_info(); + if (cache_ptr->available == 0) + { + list_add(&(cache_ptr->listhead), &cache_list[cache_ptr->cache_order]); + } + cache_ptr->available++; + if (cache_ptr->available == cache_ptr->max_available) + { + list_del_entry((list_head_t *)cache_ptr); + page_free(target_frame_ptr); + } + // uart_sendlinek(" After\r\n"); + // dump_cache_info(); +} \ No newline at end of file diff --git a/lab8/kernel/src/mmu.c b/lab8/kernel/src/mmu.c new file mode 100644 index 000000000..95e3bde7f --- /dev/null +++ b/lab8/kernel/src/mmu.c @@ -0,0 +1,380 @@ +#include "bcm2837/rpi_mmu.h" +#include "mmu.h" +#include "memory.h" +#include "string.h" +#include "uart1.h" +#include "debug.h" + +extern thread_t *curr_thread; + +void *set_2M_kernel_mmu(void *x0) +{ + // Turn + // Two-level Translation (1GB) - in boot.S + // to + // Three-level Translation (2MB) - set PUD point to new table + unsigned long *pud_table = (unsigned long *)MMU_PUD_ADDR; + + unsigned long *pte_table1 = (unsigned long *)MMU_PTE_ADDR; + unsigned long *pte_table2 = (unsigned long *)(MMU_PTE_ADDR + 0x1000L); + for (int i = 0; i < 512; i++) + { + unsigned long addr = 0x200000L * i; + if (addr >= PERIPHERAL_END) + { + pte_table1[i] = (0x00000000 + addr) + BOOT_PTE_ATTR_nGnRnE; + continue; + } + pte_table1[i] = (0x00000000 + addr) | BOOT_PTE_ATTR_NOCACHE; // 0 * 2MB // No definition for 3-level attribute, use nocache. + pte_table2[i] = (0x40000000 + addr) | BOOT_PTE_ATTR_NOCACHE; // 512 * 2MB + } + + // set PUD + pud_table[0] = (unsigned long)pte_table1 | BOOT_PUD_ATTR; + pud_table[1] = (unsigned long)pte_table2 | BOOT_PUD_ATTR; + + return x0; +} + +void map_one_page(size_t *virt_pgd_p, size_t user_va, size_t pa, size_t flag) +{ + size_t *table_p = virt_pgd_p; + for (int level = 0; level < 4; level++) + { + unsigned int idx = (user_va >> (39 - level * 9)) & 0x1ff; // p.14, 9-bit only + + if (level == 3) + { + table_p[idx] = pa; + table_p[idx] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2) | PD_KNX | flag; // el0 only + return; + } + + if (!table_p[idx]) + { + size_t *newtable_p = kmalloc(0x1000); // create a table + memset(newtable_p, 0, 0x1000); + table_p[idx] = KERNEL_VIRT_TO_PHYS((size_t)newtable_p); // point to that table + table_p[idx] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2); + } + + table_p = (size_t *)PHYS_TO_KERNEL_VIRT((size_t)(table_p[idx] & ENTRY_ADDR_MASK)); // PAGE_SIZE + } +} + +void mmu_add_vma(struct thread *t, size_t va, size_t size, size_t pa, size_t rwx, int is_alloced, vma_name_type name) +{ + if (IS_NOT_ALIGN(pa, PAGESIZE) || IS_NOT_ALIGN(va, PAGESIZE)) + { + // ERROR("CHECK_ALIGN : 0x%x\n",CHECK_ALIGN(pa,PAGESIZE)); + uart_sendlinek("\n\n"); + ERROR("Input User Vitural Address or Physical Address Should be Aliged to PAGESIZE\n"); + ERROR("Input User Vitural Address : 0x%x\n", va); + ERROR("Input Physical Address : 0x%x\n", pa); + return; + } + vm_area_struct_t *the_area_ptr = check_vma_overlap(t, va, (unsigned long)size); + if (the_area_ptr != 0) + { + uart_sendlinek("\n\n"); + ERROR("check_vma_overlap : 0x%x\n", the_area_ptr); + ERROR("Vitural Memory Area is Overlap !!\n"); + // dump_vma(); + return; + } + + size = ALIGN_UP(size, PAGESIZE); + vm_area_struct_t *new_area = kmalloc(sizeof(vm_area_struct_t)); + new_area->rwx = rwx; + new_area->area_size = size; + new_area->virt_addr = va; + new_area->phys_addr = pa; + new_area->is_alloced = is_alloced; + new_area->name = name; + list_add_tail((list_head_t *)new_area, &t->vma_list); +} + +void mmu_del_vma(struct thread *t) +{ + list_head_t *curr = &t->vma_list; + list_head_t *n; + list_for_each_safe(curr, n, &t->vma_list) + { + vm_area_struct_t *vma = (vm_area_struct_t *)curr; + if (vma->is_alloced) + { + kfree((void *)PHYS_TO_KERNEL_VIRT(vma->phys_addr)); + } + list_del_entry(curr); + kfree(curr); + } +} + +void mmu_free_page_tables(size_t *page_table, int level) +{ + size_t *table_virt = (size_t *)PHYS_TO_KERNEL_VIRT(page_table); + for (int i = 0; i < 512; i++) + { + if (table_virt[i] != 0) + { + size_t *next_table = (size_t *)(table_virt[i] & ENTRY_ADDR_MASK); + if ((table_virt[i] & PD_TABLE) == PD_TABLE) + { + if (level < PMD) + mmu_free_page_tables(next_table, level + 1); + table_virt[i] = 0L; + kfree((void *)PHYS_TO_KERNEL_VIRT(next_table)); + } + } + } +} + +// void mmu_set_PTE_readonly(size_t *page_table, int level) +// { +// size_t *table_virt = (size_t *)PHYS_TO_KERNEL_VIRT(page_table); +// for (int i = 0; i < 512; i++) +// { +// if (table_virt[i] != 0) +// { +// size_t *next_table = (size_t)(table_virt[i] & ENTRY_ADDR_MASK); +// if (table_virt[i] & PD_TABLE == PD_TABLE) +// { +// if (level < PMD) +// { +// mmu_set_PTE_readonly(next_table, level + 1); +// } +// else +// { +// table_virt[i] &= PD_RDONLY; +// } +// } +// } +// } +// } + +// void mmu_pagetable_copy(size_t *dst_page_table, size_t *src_page_table, int level) +// { +// size_t *dst_page_table_va = (size_t *)PHYS_TO_KERNEL_VIRT(dst_page_table); +// size_t *src_page_table_va = (size_t *)PHYS_TO_KERNEL_VIRT(src_page_table); +// for (int i = 0; i < 512; i++) +// { +// if (src_page_table_va[i] != 0) +// { +// size_t *next_src_table = (size_t)(src_page_table_va[i] & ENTRY_ADDR_MASK); +// size_t *next_dst_table = kmalloc(PAGESIZE); +// memset(next_dst_table, 0, 0x1000); +// dst_page_table_va[i] = KERNEL_VIRT_TO_PHYS((size_t)next_dst_table); // point to that table +// dst_page_table_va[i] |= PD_ACCESS | PD_TABLE | (MAIR_IDX_NORMAL_NOCACHE << 2); +// // size_t *next_dst_table = (size_t)(dst_page_table_va[i] & ENTRY_ADDR_MASK); +// if (src_page_table_va[i] & PD_TABLE == PD_TABLE) +// { +// if (level < PTE) +// { +// mmu_pagetable_copy(next_dst_table,next_src_table,level); +// } +// else +// { +// //-------- +// } +// } +// } +// } +// } + +void mmu_memfail_abort_handle(esr_el1_t *esr_el1) +{ + lock(); + unsigned long long far_el1; + __asm__ __volatile__("mrs %0, FAR_EL1\n\t" : "=r"(far_el1)); + + list_head_t *pos; + vm_area_struct_t *vma; + vm_area_struct_t *the_area_ptr = 0; + list_for_each(pos, &curr_thread->vma_list) + { + vma = (vm_area_struct_t *)pos; + if (vma->virt_addr <= far_el1 && vma->virt_addr + vma->area_size >= far_el1) + { + the_area_ptr = vma; + break; + } + } + // area is not part of process's address space + if (!the_area_ptr) + { + uart_sendlinek("\n\n"); + ERROR("[Segmentation fault]: Kill Process\r\n"); + ERROR("Invilad Vitural Address Access: %x\n", far_el1); + thread_exit(); + // dump_vma(); + unlock(); + while (1) + schedule(); + + return; + } + + // For translation fault, only map one page frame for the fault address + if ((esr_el1->iss & 0x3f) == TF_LEVEL0 || + (esr_el1->iss & 0x3f) == TF_LEVEL1 || + (esr_el1->iss & 0x3f) == TF_LEVEL2 || + (esr_el1->iss & 0x3f) == TF_LEVEL3) + { + // uart_sendlinek("\n"); + // WARING("[Translation fault]: 0x%x\r\n", far_el1); // far_el1: Fault address register. + // Holds the faulting Virtual Address for all synchronous Instruction or Data Abort, PC alignment fault and Watchpoint exceptions that are taken to EL1. + + size_t addr_offset = (far_el1 - the_area_ptr->virt_addr); + // addr_offset = (addr_offset % 0x1000) == 0 ? addr_offset : addr_offset - (addr_offset % 0x1000); + addr_offset = ALIGN_DOWN(addr_offset, 0x1000); + + size_t flag = 0; + if (!(the_area_ptr->rwx & (0b1 << 2))) + flag |= PD_UNX; // 4: executable + if (!(the_area_ptr->rwx & (0b1 << 1))) + flag |= PD_RDONLY; // 2: writable + if (the_area_ptr->rwx & (0b1 << 0)) + flag |= PD_UK_ACCESS; // 1: readable / accessible + map_one_page((size_t *)PHYS_TO_KERNEL_VIRT(curr_thread->context.pgd), the_area_ptr->virt_addr + addr_offset, the_area_ptr->phys_addr + addr_offset, flag); + // dump_pagetable(the_area_ptr->virt_addr + addr_offset,the_area_ptr->phys_addr + addr_offset); + } + else + { + // For other Fault (permisson ...etc) + // uart_sendlinek("[Other Fault]: Kill Process\r\n"); + // uart_sendlinek("esr_el1: 0x%x\r\n", esr_el1); + uart_sendlinek("\n\n"); + if ((unsigned long)esr_el1 & (1 << 10)) + { + ERROR("[Permission Fault] due to a write of an Allocation Tag to Canonically Tagged memory.\r\n"); + } + if ((unsigned long)esr_el1 & (1 << 9)) + { + ERROR("[Permission Fault] due to the NoTagAccess memory attribute..\r\n"); + } + // check_permission(,the_area_ptr->rwx); + thread_exit(); + // dump_vma(); + unlock(); + while (1) + schedule(); + } + unlock(); +} + +vm_area_struct_t *check_vma_overlap(thread_t *t, unsigned long user_va, unsigned long size) +{ + list_head_t *pos; + vm_area_struct_t *vma; + list_for_each(pos, &t->vma_list) + { + vma = (vm_area_struct_t *)pos; + // Detect existing vma overlapped + if (!(vma->virt_addr >= (unsigned long)(user_va + size) || vma->virt_addr + vma->area_size <= (unsigned long)user_va)) + { + return vma; + } + } + return 0; +} + +int check_permission(int userId, int VMA_Permission) +{ + switch (PERMISSION_INVAILD(userId, VMA_Permission)) + { + DUMP_NAME(1, "Read is Invaild in This Vitural Memory Area") + DUMP_NAME(2, "Write is Invaild in This Vitural Memory Area") + DUMP_NAME(3, "Write & Read is Invaild in This Vitural Memory Area") + DUMP_NAME(4, "Exec is Invaild in This Vitural Memory Area") + DUMP_NAME(5, "Exec & Read is Invaild in This Vitural Memory Area") + DUMP_NAME(6, "Exec & Write is Invaild in This Vitural Memory Area") + DUMP_NAME(7, "Exec & Write & Read is Invaild in This Vitural Memory Area") + default: + uart_sendlinek("[other Fault]: UNKNOW FAULT"); + break; + } + return PERMISSION_INVAILD(userId, VMA_Permission); +} + +void dump_vma() +{ + uart_sendlinek(" +--------------------------+\n"); + uart_sendlinek(" | DUMP Vitural Memory Area |\n"); + uart_sendlinek(" +--------------------------+\n"); + list_head_t *pos; + list_for_each(pos, &curr_thread->vma_list) + { + uart_sendlinek("===============================================\n"); + vm_area_struct_t *vma_ptr = (vm_area_struct_t *)pos; + + uart_sendlinek("Vitural Memory Area Name : "); + switch (vma_ptr->name) + { + DUMP_NAME(UNKNOW_AREA, "UNKNOW_AREA") + DUMP_NAME(USER_DATA, "USER_DATA") + DUMP_NAME(USER_STACK, "USER_STACK") + DUMP_NAME(PERIPHERAL, "PERIPHERAL") + DUMP_NAME(USER_SIGNAL_WRAPPER, "USER_SIGNAL_WRAPPER") + DUMP_NAME(USER_EXEC_WRAPPER, "USER_EXEC_WRAPPER") + default: + uart_sendlinek("unnamed: %d\n", vma_ptr->name); + break; + } + uart_sendlinek("Base Vitural Address : 0x%x\n", ((vm_area_struct_t *)pos)->virt_addr); + uart_sendlinek("Base Physical Address : 0x%x\n", ((vm_area_struct_t *)pos)->phys_addr); + uart_sendlinek("Area Size : 0x%x\n", ((vm_area_struct_t *)pos)->area_size); + uart_sendlinek("Exec, Write, Read : 0x%x\n", ((vm_area_struct_t *)pos)->rwx); + uart_sendlinek("===============================================\n\n"); + } +} + +void dump_pagetable(unsigned long user_va, unsigned long pa) +{ + uart_sendlinek(" +---------------------------+\n"); + uart_sendlinek(" | DUMP PAGE TABLE & ADDRESS |\n"); + uart_sendlinek(" +---------------------------+\n"); + unsigned long *pagetable_pa = curr_thread->context.pgd; + unsigned long *pagetable_kernel_va = (unsigned long *)PHYS_TO_KERNEL_VIRT(pagetable_pa); + + uart_sendlinek("===============================================\n"); + uart_sendlinek("User Physical Address : 0x%x\n", pa); + uart_sendlinek("User Vitural Address : 0x%x\n", user_va); + unsigned long offset = user_va & 0xFFF; + uart_sendlinek("Vitural Address offset: 0x%x\n", offset); + for (int level = 0; level < 4; level++) + { + uart_sendlinek("-----------------------------------------------\n"); + uart_sendlinek("PAGE TABLE : "); + switch (level) + { + DUMP_NAME(PGD, "PGD") + DUMP_NAME(PUD, "PUD") + DUMP_NAME(PMD, "PMD") + DUMP_NAME(PTE, "PTE") + + default: + uart_sendlinek("unnamed: %d\n", level); + break; + } + uart_sendlinek("Pagetable Physical Address: 0x%x\n", pagetable_pa); + uart_sendlinek("Pagetable Vitural Address: 0x%x\n", pagetable_kernel_va); + + unsigned int idx = (user_va >> (39 - level * 9)) & 0x1FF; + uart_sendlinek("Index of Pagetable: 0x%x\n", idx); + uart_sendlinek("Entry %x of Pagetable: 0x%x\n", idx, pagetable_kernel_va[idx]); + if (level == PTE) + { + pagetable_pa = (unsigned long *)(pagetable_kernel_va[idx] & ENTRY_ADDR_MASK); + uart_sendlinek("The Page Base Physical Address: 0x%x\n", pagetable_pa); + uart_sendlinek("The Physical Address: 0x%x\n", (unsigned long)pagetable_pa | offset); + } + else + { + pagetable_pa = (unsigned long *)(pagetable_kernel_va[idx] & ENTRY_ADDR_MASK); + uart_sendlinek("next Pagetable Physical Address: 0x%x\n", pagetable_pa); + pagetable_kernel_va = (unsigned long *)PHYS_TO_KERNEL_VIRT(pagetable_pa); + uart_sendlinek("next Pagetable Vitural Address: 0x%x\n", pagetable_kernel_va); + } + uart_sendlinek("-----------------------------------------------\n"); + } +} \ No newline at end of file diff --git a/lab8/kernel/src/sched.S b/lab8/kernel/src/sched.S new file mode 100644 index 000000000..7d0f93cd2 --- /dev/null +++ b/lab8/kernel/src/sched.S @@ -0,0 +1,57 @@ +.global switch_to +switch_to: // (prev, next) = (x0, x1) + stp x19, x20, [x0, 16 * 0] // store callee saved register + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] // store sp, fp, lr + mov x9, sp + str x9, [x0, 16 * 6] + + ldp x19, x20, [x1, 16 * 0] // load callee saved register + ldp x21, x22, [x1, 16 * 1] + ldp x23, x24, [x1, 16 * 2] + ldp x25, x26, [x1, 16 * 3] + ldp x27, x28, [x1, 16 * 4] + ldp fp, lr, [x1, 16 * 5] // load sp, fp, lr + ldp x9, x0, [x1, 16 * 6] + mov sp, x9 + msr tpidr_el1, x1 // update current thread id + + dsb ish // ensure write has completed, lock for context switch + msr ttbr0_el1, x0 // switch translation based address. + tlbi vmalle1is // invalidate all TLB entries in stage 1, el1 and inner shareable + dsb ish // ensure completion of TLB invalidatation + isb // clear pipeline + + ret + +.global get_current +get_current: + mrs x0, tpidr_el1 // get the current thread id + ret + +.global store_context +store_context: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + ret + +.global load_context +load_context: + ldp x19, x20, [x0, 16 * 0] + ldp x21, x22, [x0, 16 * 1] + ldp x23, x24, [x0, 16 * 2] + ldp x25, x26, [x0, 16 * 3] + ldp x27, x28, [x0, 16 * 4] + ldp fp, lr, [x0, 16 * 5] + ldr x9, [x0, 16 * 6] + mov sp, x9 + ret diff --git a/lab8/kernel/src/sched.c b/lab8/kernel/src/sched.c new file mode 100644 index 000000000..09bbbcd17 --- /dev/null +++ b/lab8/kernel/src/sched.c @@ -0,0 +1,270 @@ +#include "sched.h" +#include "uart1.h" +#include "exception.h" +#include "memory.h" +#include "timer.h" +#include "shell.h" +#include "signal.h" +#include "stdio.h" +#include "mmu.h" +#include "string.h" + +list_head_t *run_queue; +execfile c_execfile; + +thread_t threads[PIDMAX + 1]; +thread_t *curr_thread; + +int pid_history = 0; +int timer_sched_flag = 0; +int shell_flag = 0; + +void thread_sched_init() +{ + lock(); + // init thread freelist and run_queue + run_queue = kmalloc(sizeof(list_head_t)); + INIT_LIST_HEAD(run_queue); + + // init pids + for (int i = 0; i <= PIDMAX; i++) + { + threads[i].isused = 0; + threads[i].pid = i; + threads[i].iszombie = 0; + } + + thread_t *idlethread = thread_create(start_shell); + curr_thread = idlethread; + asm volatile("msr tpidr_el1, %0" ::"r"(&curr_thread->context)); // Don't let thread structure NULL as we enable the functionality + + // thread_create(idle); + unlock(); +} + +thread_t *thread_create(void *start) +{ + lock(); + thread_t *r; + // find usable PID, don't use the previous one + if (pid_history > PIDMAX) + { + unlock(); + return 0; + } + + if (!threads[pid_history].isused) + { + r = &threads[pid_history]; + pid_history += 1; + } + else + { + unlock(); + return 0; + } + + INIT_LIST_HEAD(&r->vma_list); + r->iszombie = 0; + r->isused = 1; + r->stack_alloced_ptr = kmalloc(USTACK_SIZE); + r->kernel_stack_alloced_ptr = kmalloc(KSTACK_SIZE); + r->context.lr = (unsigned long long)start; + r->context.sp = (unsigned long long)r->kernel_stack_alloced_ptr + KSTACK_SIZE - STACK_BASE_OFFSET; + r->context.fp = r->context.sp; // frame pointer for local variable, which is also in stack. + + strcpy(r->curr_working_dir, "/"); // new <----------------------------------------------------------------------- + vfs_open("/dev/uart", 0, &r->file_descriptors_table[stdin]); + vfs_open("/dev/uart", 0, &r->file_descriptors_table[stdout]); + vfs_open("/dev/uart", 0, &r->file_descriptors_table[stderr]); + + r->context.pgd = kmalloc(0x1000); + memset(r->context.pgd, 0, 0x1000); + r->context.pgd = (void *)KERNEL_VIRT_TO_PHYS(r->context.pgd); + + r->signal_is_checking = 0; + // initial all signal handler with signal_default_handler (kill thread) + + // uart_sendlinek("signal_default_handler : 0x%x\n", signal_default_handler); + for (int i = 0; i < SIGNAL_MAX; i++) + { + r->signal_handler[i] = signal_default_handler; + r->sigcount[i] = 0; + } + + list_add_tail(&r->listhead, run_queue); + unlock(); + return r; +} + +void schedule() +{ + lock(); + // uart_sendlinek("Run queue size :%d \n", list_size(run_queue)); + do + { + // uart_sendlinek("Run queue size :%d \n", list_size(run_queue)); + curr_thread = (thread_t *)curr_thread->listhead.next; + } while (list_is_head(&curr_thread->listhead, run_queue)); // find a runnable thread + unlock(); + // uart_sendlinek("curr_thread :%d \n",curr_thread->pid); + // uart_sendlinek("curr_thread->context.lr :0x%x \n",curr_thread->context.lr); + switch_to(get_current(), &curr_thread->context); +} + +void idle() +{ + // uart_sendlinek("This is idle\n"); + while (shell_flag > 0) + // while (list_size(run_queue) > 1) + { + // uart_sendlinek("This is idle\n"); + kill_zombies(); // reclaim threads marked as DEAD + schedule(); // switch to next thread in run queue + // delay(10000); + } + kill_zombies(); +} + +void thread_exit() +{ + // thread cannot deallocate the stack while still using it, wait for someone to recycle it. + // In this lab, idle thread handles this task, instead of parent thread. + lock(); + curr_thread->iszombie = 1; + shell_flag--; + unlock(); + // delay(10000); + // schedule(); +} + +void kill_zombies() +{ + lock(); + list_head_t *curr; + thread_t *t; + list_for_each(curr, run_queue) + { + t = (thread_t *)curr; + if (t->iszombie) + { + list_del_entry(curr); + mmu_free_page_tables(t->context.pgd, 0); + mmu_del_vma(t); + for (int i = 0; i < MAX_FD; i++) + { + if (t->file_descriptors_table[i]) + vfs_close(t->file_descriptors_table[i]); + } + kfree(t->kernel_stack_alloced_ptr); + kfree((void *)PHYS_TO_KERNEL_VIRT(t->context.pgd)); + t->iszombie = 0; + t->isused = 0; + } + } + unlock(); +} + +void foo() +{ + // Lab5 Basic 1 Test function + for (int i = 0; i < 10; ++i) + { + uart_sendlinek("Thread id: %d %d\n", curr_thread->pid, i); + int r = 1000000; + while (r--) + { + asm volatile("nop"); + } + schedule(); + } + // uart_sendlinek("exit\n"); + thread_exit(); +} + +int exec_thread() +{ + lock(); + shell_flag++; + thread_t *t = thread_create(exec_proc); + curr_thread = t; + // uart_sendlinek("timer_sched_flag : %d\n", timer_sched_flag); + if (!timer_sched_flag) + { + timer_sched_flag = 1; + add_timer(schedule_timer, 1, "", setSecond); // start scheduler --------------------------------------------------------- + } + + unlock(); + schedule(); + + return 0; +} + +void exec_proc() +{ + el1_interrupt_disable(); // daif 會在 eret 時更改。 + // char *data = c_execfile.data; + // unsigned int filesize = c_execfile.filesize; + thread_t *t = curr_thread; + + // char *data = target_file->f_ops; + unsigned int filesize = (c_execfile.vnode)->f_ops->getsize(c_execfile.vnode); + + t->data = kmalloc(filesize); + t->datasize = filesize; + + // copy file into data + struct file *f; + vfs_open(c_execfile.pathname, 0, &f); + vfs_read(f, t->data, t->datasize); + vfs_close(f); + + //memcpy(t->data, data, t->datasize); + + mmu_add_vma(t, USER_DATA_BASE, t->datasize, (size_t)KERNEL_VIRT_TO_PHYS(t->data), 0b111, 1, USER_DATA); + mmu_add_vma(t, USER_STACK_BASE - USTACK_SIZE, USTACK_SIZE, (size_t)KERNEL_VIRT_TO_PHYS(t->stack_alloced_ptr), 0b111, 1, USER_STACK); + mmu_add_vma(t, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0, PERIPHERAL); + mmu_add_vma(t, USER_SIGNAL_WRAPPER_VA, 0x1000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(signal_handler_wrapper), PAGESIZE), 0b101, 0, USER_SIGNAL_WRAPPER); + mmu_add_vma(t, USER_EXEC_WRAPPER_VA, 0x2000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(exec_wrapper), PAGESIZE), 0b101, 0, USER_EXEC_WRAPPER); + + t->context.sp = USER_STACK_BASE - STACK_BASE_OFFSET; + t->context.fp = USER_STACK_BASE - STACK_BASE_OFFSET; + t->context.lr = USER_DATA_BASE; + + // for (int i = 0; i < filesize; i++) + // { + // t->data[i] = data[i]; + // } + // dump_vma(); + + // vfs_open("/dev/uart", 0, &curr_thread->file_descriptors_table[0]); // stdin + // vfs_open("/dev/uart", 0, &curr_thread->file_descriptors_table[1]); // stdout + // vfs_open("/dev/uart", 0, &curr_thread->file_descriptors_table[2]); // stderr + + asm("msr tpidr_el1, %0\n\t" // Hold the "kernel(el1)" thread structure information + "msr elr_el1, %1\n\t" // When el0 -> el1, store return address for el1 -> el0 + "msr spsr_el1, xzr\n\t" // EL1h (SPSel = 1) with interrupt disabled + "msr sp_el0, %2\n\t" // el0 stack pointer for el1 process + "mov sp, %3\n\t" // sp is reference for the same el process. For example, el2 cannot use sp_el2, it has to use sp to find its own stack. + "mov x0, %4\n\t" ::"r"(&t->context), + "r"(exec_wrapper), "r"(t->context.sp), "r"(t->kernel_stack_alloced_ptr + KSTACK_SIZE - STACK_BASE_OFFSET), "r"(t->context.lr)); + + asm("eret\n\t"); +} + +void exec_wrapper() +{ + asm("blr x0\n\t" + "mov x8,50\n\t" + "svc 0\n\t"); +} + +void schedule_timer(char *notuse) +{ + unsigned long long cntfrq_el0; + __asm__ __volatile__("mrs %0, cntfrq_el0\n\t" : "=r"(cntfrq_el0)); + add_timer(schedule_timer, cntfrq_el0 >> 5, "", setTick); + // schedule(); + // 32 * default timer -> trigger next schedule timer +} diff --git a/lab8/kernel/src/sdhost.c b/lab8/kernel/src/sdhost.c new file mode 100644 index 000000000..81e139178 --- /dev/null +++ b/lab8/kernel/src/sdhost.c @@ -0,0 +1,179 @@ +#include "sdhost.h" + +// helper +#define set(io_addr, val) \ + asm volatile("str %w1, [%0]" ::"r"(io_addr), "r"(val) : "memory"); + +#define get(io_addr, val) \ + asm volatile("ldr %w0, [%1]" : "=r"(val) : "r"(io_addr) : "memory"); + +static inline void delay(unsigned long tick) { + while (tick--) { + asm volatile("nop"); + } +} + +static int is_hcs; // high capcacity(SDHC) + +static void pin_setup() { + set(GPIO_GPFSEL4, 0x24000000); + set(GPIO_GPFSEL5, 0x924); + set(GPIO_GPPUD, 0); + delay(15000); + set(GPIO_GPPUDCLK1, 0xffffffff); + delay(15000); + set(GPIO_GPPUDCLK1, 0); +} + +static void sdhost_setup() { + unsigned int tmp; + set(SDHOST_PWR, 0); + set(SDHOST_CMD, 0); + set(SDHOST_ARG, 0); + set(SDHOST_TOUT, SDHOST_TOUT_DEFAULT); + set(SDHOST_CDIV, 0); + set(SDHOST_HSTS, SDHOST_HSTS_MASK); + set(SDHOST_CFG, 0); + set(SDHOST_CNT, 0); + set(SDHOST_SIZE, 0); + get(SDHOST_DBG, tmp); + tmp &= ~SDHOST_DBG_MASK; + tmp |= SDHOST_DBG_FIFO; + set(SDHOST_DBG, tmp); + delay(250000); + set(SDHOST_PWR, 1); + delay(250000); + set(SDHOST_CFG, SDHOST_CFG_SLOW | SDHOST_CFG_INTBUS | SDHOST_CFG_DATA_EN); + set(SDHOST_CDIV, SDHOST_CDIV_DEFAULT); +} + +static int wait_sd() { + int cnt = 1000000; + unsigned int cmd; + do { + if (cnt == 0) { + return -1; + } + get(SDHOST_CMD, cmd); + --cnt; + } while (cmd & SDHOST_NEW_CMD); + return 0; +} + +static int sd_cmd(unsigned cmd, unsigned int arg) { + set(SDHOST_ARG, arg); + set(SDHOST_CMD, cmd | SDHOST_NEW_CMD); + return wait_sd(); +} + +static int sdcard_setup() { + unsigned int tmp; + sd_cmd(GO_IDLE_STATE | SDHOST_NO_REPONSE, 0); + sd_cmd(SEND_IF_COND, VOLTAGE_CHECK_PATTERN); + get(SDHOST_RESP0, tmp); + if (tmp != VOLTAGE_CHECK_PATTERN) { + return -1; + } + while (1) { + if (sd_cmd(APP_CMD, 0) == -1) { + // MMC card or invalid card status + // currently not support + continue; + } + sd_cmd(SD_APP_OP_COND, SDCARD_3_3V | SDCARD_ISHCS); + get(SDHOST_RESP0, tmp); + if (tmp & SDCARD_READY) { + break; + } + delay(1000000); + } + + is_hcs = tmp & SDCARD_ISHCS; + sd_cmd(ALL_SEND_CID | SDHOST_LONG_RESPONSE, 0); + sd_cmd(SEND_RELATIVE_ADDR, 0); + get(SDHOST_RESP0, tmp); + sd_cmd(SELECT_CARD, tmp); + sd_cmd(SET_BLOCKLEN, 512); + return 0; +} + +static int wait_fifo() { + int cnt = 1000000; + unsigned int hsts; + do { + if (cnt == 0) { + return -1; + } + get(SDHOST_HSTS, hsts); + --cnt; + } while ((hsts & SDHOST_HSTS_DATA) == 0); + return 0; +} + +static void set_block(int size, int cnt) { + set(SDHOST_SIZE, size); + set(SDHOST_CNT, cnt); +} + +static void wait_finish() { + unsigned int dbg; + do { + get(SDHOST_DBG, dbg); + } while ((dbg & SDHOST_DBG_FSM_MASK) != SDHOST_HSTS_DATA); +} + +void readblock(int block_idx, void* buf) { + unsigned int* buf_u = (unsigned int*)buf; + int succ = 0; + if (!is_hcs) { + block_idx <<= 9; + } + do{ + set_block(512, 1); + sd_cmd(READ_SINGLE_BLOCK | SDHOST_READ, block_idx); + for (int i = 0; i < 128; ++i) { + wait_fifo(); + get(SDHOST_DATA, buf_u[i]); + } + unsigned int hsts; + get(SDHOST_HSTS, hsts); + if (hsts & SDHOST_HSTS_ERR_MASK) { + set(SDHOST_HSTS, SDHOST_HSTS_ERR_MASK); + sd_cmd(STOP_TRANSMISSION | SDHOST_BUSY, 0); + } else { + succ = 1; + } + } while(!succ); + wait_finish(); +} + +void writeblock(int block_idx, void* buf) { + unsigned int* buf_u = (unsigned int*)buf; + int succ = 0; + if (!is_hcs) { + block_idx <<= 9; + } + do{ + set_block(512, 1); + sd_cmd(WRITE_SINGLE_BLOCK | SDHOST_WRITE, block_idx); + for (int i = 0; i < 128; ++i) { + wait_fifo(); + set(SDHOST_DATA, buf_u[i]); + } + unsigned int hsts; + get(SDHOST_HSTS, hsts); + if (hsts & SDHOST_HSTS_ERR_MASK) { + set(SDHOST_HSTS, SDHOST_HSTS_ERR_MASK); + sd_cmd(STOP_TRANSMISSION | SDHOST_BUSY, 0); + } else { + succ = 1; + } + } while(!succ); + wait_finish(); +} + +void sd_init() { + pin_setup(); + sdhost_setup(); + sdcard_setup(); +} diff --git a/lab8/kernel/src/shell.c b/lab8/kernel/src/shell.c new file mode 100644 index 000000000..3d823c341 --- /dev/null +++ b/lab8/kernel/src/shell.c @@ -0,0 +1,572 @@ +#include "shell.h" +#include "mbox.h" +#include "power.h" +#include "stdio.h" +#include "string.h" +#include "cpio.h" +#include "memory.h" +#include "dtb.h" +#include "timer.h" +#include "sched.h" +#include "signal.h" +#include "syscall.h" +#include "vfs.h" +#include "vfs_tmpfs.h" +#include "debug.h" + +#include "uart1.h" + +#define USTACK_SIZE 0x10000 + +extern unsigned long long int lock_counter; +extern list_head_t *run_queue; +extern execfile c_execfile; +extern struct mount *rootfs; + +struct CLI_CMDS cmd_list[CLI_MAX_CMD] = { + {.command = "cat", .help = "concatenate files and print on the standard output", .func = do_cmd_cat}, + {.command = "dtb", .help = "show device tree", .func = do_cmd_dtb}, + {.command = "hello", .help = "print Hello World!", .func = do_cmd_hello}, + {.command = "help", .help = "print all available commands", .func = do_cmd_help}, + {.command = "info", .help = "get device information via mailbox", .func = do_cmd_info}, + {.command = "malloc", .help = "test malloc", .func = do_cmd_malloc}, + {.command = "reboot", .help = "reboot the device", .func = do_cmd_reboot}, + {.command = "exec", .help = "execute user programs ", .func = do_cmd_exec}, + {.command = "setTime", .help = "setTime [MESSAGE] [SECONDS] ", .func = do_cmd_setTimeout}, + {.command = "2sAlert", .help = "set core timer interrupt every 2 second ", .func = do_cmd_set2sAlert}, + {.command = "mtest", .help = "memory testcase generator, allocate and free", .func = do_cmd_mtest}, + {.command = "ttest", .help = "thread tester with dummy function - foo()", .func = do_cmd_ttest}, + {.command = "ls", .help = "list directory contents", .func = do_cmd_ls}, + {.command = "cd", .help = "change directory", .func = do_cmd_cd}, + {.command = "ftest", .help = "get run_queue size", .func = do_cmd_ftest}}; + +extern char *dtb_ptr; +extern thread_t *curr_thread; +extern void *CPIO_DEFAULT_START; + +void start_shell() +{ + // uart_sendlinek("In start_shell\n"); + char input_buffer[CMD_MAX_LEN]; + + cli_print_banner(); + while (1) + { + cli_flush_buffer(input_buffer, CMD_MAX_LEN); + // uart_sendlinek("lock_counter : %d\n",lock_counter); + puts("【 Ciallo~(∠・ω< )⌒★ 】 # "); + cli_cmd_read(input_buffer); + cli_cmd_exec(input_buffer); + idle(); + // uart_sendlinek("idle finish\n"); + } + // return 0; +} + +void cli_flush_buffer(char *buffer, int length) +{ + for (int i = 0; i < length; i++) + { + buffer[i] = '\0'; + } +}; + +void cli_cmd_read(char *buffer) +{ + char c = '\0'; + int idx = 0; + + while (idx < CMD_MAX_LEN - 1) + { + c = getchar(); + // vfs_read(uart, c, 0); + + if (c == 127) // backspace + { + if (idx != 0) + { + puts("\b \b"); + // vfs_write("/dev/uart","\b \b",0); + idx--; + } + } + else if (c == '\n') + { + break; + } + else if (c <= 16 || c >= 32 || c < 127) + { + putchar(c); + // vfs_write("/dev/uart","\b \b",0); + buffer[idx++] = c; + } + } + buffer[idx] = '\0'; + puts("\r\n"); + // vfs_write("/dev/uart","\r\n",0); +} + +int _parse_args(char *buffer, int *argc, char **argv) +{ + char get_cmd = 0; + for (int i = 0; buffer[i] != '\0'; i++) + { + if (!get_cmd) + { + if (buffer[i] == ' ') + { + buffer[i] = '\0'; + get_cmd = 1; + } + } + else + { + if (buffer[i - 1] == '\0' && buffer[i] != ' ' && buffer[i] != '\0') + { + if (*argc >= CMD_MAX_PARAM) + { + return -1; + } + argv[*argc] = buffer + i; + (*argc)++; + } + else if (buffer[i] == ' ') + { + buffer[i] = '\0'; + } + } + } + return 0; +} + +void print_args(int argc, char **argv) +{ + puts("argc: "); + put_int(argc); + puts("\r\n"); + for (int i = 0; i < argc; i++) + { + puts("argv["); + put_int(i); + puts("]: "); + puts(argv[i]); + puts("\r\n"); + } +} + +void cli_cmd_exec(char *buffer) +{ + char *cmd = buffer; + int argc = 0; + char *argv[CMD_MAX_PARAM]; + if (_parse_args(buffer, &argc, argv) == -1) + { + puts("Too many arguments\r\n"); + return; + } + // print_args(argc, argv); + + for (int i = 0; i < CLI_MAX_CMD; i++) + { + if (strcmp(cmd, cmd_list[i].command) == 0) + { + cmd_list[i].func(argc, argv); + return; + } + } + if (*buffer) + { + puts(buffer); + puts(": command not found\r\n"); + } +} + +void cli_print_banner() +{ + // uart_sendlinek("In cli_print_banner\n"); + puts("\r\n"); + puts("============================================================================================\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@-@@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ *@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@# =@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= :@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@- %@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% *@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#%@@@@@@@@@@@@@@@@@@@* -@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@% *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:=@@@@@@@@@@@@@@@@@@@: %@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@- :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@* #@@@@@@@@@@@@@@@@@* -@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@#- :#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+ +%@@@@@@@@@@@@@@+ -%@@@@@@@@@@@@\r\n"); + puts("@@@@*=: :=#@@@@@@@@#=: =*@@@@@@@@@@\r\n"); + puts("@@@@@#= =*%@@@@@@@@@@*+- :=*%@@@@@@@@@@\r\n"); + puts("@@@@@@@- @@@@@@@@@@@# -@@@@@@@@@@@@@@@@@@%: -%@%@@@@@@@@@@@@@@%= :#@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@= @%++*%@@@@@%: +@@@@#==#@@@@@@@@@@@% %* -%@@#-=+%@@@@@@@- %@@@@@+::=*%@@@@\r\n"); + puts("@@@@@@@= @% =%@+ #@+ =%@@\r\n"); + puts("@@@@@@@= @% ************- =@ #+ :%@@\r\n"); + puts("@@@@@@@= @% @@@@@@@@@@@@+ @@% #= += %@@@* =@@@@- :@@@@\r\n"); + puts("@@@@@@@= @% ##########%@+ :@@% #= +@@@@@@= %@#= -#@@= -@@@@\r\n"); + puts("@@@@@@@= @% :::::::::::@+ :@@% #= +#+=++@= -: -: -@@@@\r\n"); + puts("@@@@@@@= @% @@@@@@@@@@@@+ :@@% #= ++ @= - : -@@@@\r\n"); + puts("@@@@@@@= :@% @@@@@@@@@@@@+ :@@% #= ++ @= %@#- :*%@- -@@@@\r\n"); + puts("@@@@@@@= =@% :@@% #= ++ @= %@@@+ -@@@@- -@@@@\r\n"); + puts("@@@@@@@- #@% ****: +**= +@@% #= ++ @= *####: #####: -@@@@\r\n"); + puts("@@@@@@@ :@@%-=*%@@@@@- #@@#+*#%@@@@% #= ++ =@+ -@@@@\r\n"); + puts("@@@@@@* %@@@@#*=--@@@- #@@#-=+*%@@@% %= *+ =@@+ +@@@@@= :@@@@@# -@@@@\r\n"); + puts("@@@@@@: *@%+- =@@- #@#: :=*+ :@= +*=%@@@+ =%@@@@@* -@@@@@@+: -@@@@\r\n"); + puts("@@@@@= *#- *- #- *@= +@@@@@@#+*@@@@@@*- :+%@@@@@#+*@@@@\r\n"); + puts("@@@@+ -%@: -=**%@@@- #@@%#*+=: *@@= *@@@@@@@@@@@@=: :-%@@@@@@@@@\r\n"); + puts("@@@+ -#@@@%- =@@@@@@@@@- #@@@@@@@@% =%@@@= *@@@@@@@@@@@@@#- :*%@@@@@@@@@@\r\n"); + puts("@@=:+%@@@@@@@%+--=*%@@@@@- :@@@@@@#*=-=*@@@@@@= #@@@@@@@@@@@@@@@* =@@@@@@@@@@@@@\r\n"); + puts("@%%@@@@@@@@@@@@@@@%##@@@@- #@@@@%#%@@@@@@@@@@@= +@@@@@@@@@@@@@@@@@* -@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@- =%@@@@@@@@@@@@@@@@@@@= *@@@@@@@@@@@@@@@@@@@: %@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@++%@@@@@@@@@@@@@@@@@@@@@*+%@@@@@@@@@@@@@@@@@@@@+ -@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% +@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= %@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= :@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@* =@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% =@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ *@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@-%@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@=@@@@@@@@@@@@@@@@@\r\n"); + puts("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@@@@@@@@@@@@@@@\r\n"); + puts("============================================================================================\r\n"); +} + +int do_cmd_help(int argc, char **argv) +{ + for (int i = 0; i < CLI_MAX_CMD; i++) + { + puts(cmd_list[i].command); + puts("\t\t\t: "); + puts(cmd_list[i].help); + puts("\r\n"); + } + return 0; +} + +int do_cmd_hello(int argc, char **argv) +{ + puts("Hello World!\r\n"); + return 0; +} + +int do_cmd_info(int argc, char **argv) +{ + // print hw revision + pt[0] = 8 * 4; + pt[1] = MBOX_REQUEST_PROCESS; + pt[2] = MBOX_TAG_GET_BOARD_REVISION; + pt[3] = 4; + pt[4] = MBOX_TAG_REQUEST_CODE; + pt[5] = 0; + pt[6] = 0; + pt[7] = MBOX_TAG_LAST_BYTE; + + if (mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt))) + { + puts("Hardware Revision\t: 0x"); + // put_hex(pt[6]); + put_hex(pt[5]); + puts("\r\n"); + } + // print arm memory + pt[0] = 8 * 4; + pt[1] = MBOX_REQUEST_PROCESS; + pt[2] = MBOX_TAG_GET_ARM_MEMORY; + pt[3] = 8; + pt[4] = MBOX_TAG_REQUEST_CODE; + pt[5] = 0; + pt[6] = 0; + pt[7] = MBOX_TAG_LAST_BYTE; + + if (mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt))) + { + puts("ARM Memory Base Address\t: 0x"); + put_hex(pt[5]); + puts("\r\n"); + puts("ARM Memory Size\t\t: 0x"); + put_hex(pt[6]); + puts("\r\n"); + } + return 0; +} + +int do_cmd_reboot(int argc, char **argv) +{ + if (argc == 0) + { + + puts("Reboot in 10 seconds ...\r\n\r\n"); + volatile unsigned int *rst_addr = (unsigned int *)PM_RSTC; + *rst_addr = PM_PASSWORD | 0x20; + volatile unsigned int *wdg_addr = (unsigned int *)PM_WDOG; + *wdg_addr = PM_PASSWORD | 0x70000; + } + else if (argc == 1 && strcmp(argv[0], "-c") == 0) + { + puts("Cancel reboot...\r\n"); + volatile unsigned int *rst_addr = (unsigned int *)PM_RSTC; + *rst_addr = PM_PASSWORD | 0x0; + volatile unsigned int *wdg_addr = (unsigned int *)PM_WDOG; + *wdg_addr = PM_PASSWORD | 0x0; + } + return 0; +} + +int do_cmd_ls(int argc, char **argv) +{ + // char *c_filepath; + // char *c_filedata; + // unsigned int c_filesize; + + // CPIO_for_each(&c_filepath, &c_filesize, &c_filedata) + // { + // if (header_ptr != 0) + // { + // puts(c_filepath); + // puts("\r\n"); + // } + // } + vfs_ls(); + return 0; +} + +int do_cmd_cat(int argc, char **argv) +{ + int FLAG_getfile = 0; + char *filepath; + char *c_filepath; + char *c_filedata; + unsigned int c_filesize; + + if (argc == 1) + { + filepath = argv[0]; + } + else + { + puts("Too many arguments\r\n"); + return -1; + } + + CPIO_for_each(&c_filepath, &c_filesize, &c_filedata) + { + if (strcmp(c_filepath, filepath) == 0) + { + FLAG_getfile = 1; + Readfile(c_filedata, c_filesize); + break; + } + } + + if (!FLAG_getfile) + { + puts("cat: "); + puts(filepath); + puts(": No such file or directory\r\n"); + } + return 0; +} + +int do_cmd_malloc(int argc, char **argv) +{ + // test malloc + char *test1 = allocator(0x18); + strcpy(test1, "test malloc1"); + puts(test1); + puts("\r\n"); + + char *test2 = allocator(0x20); + strcpy(test2, "test malloc2"); + puts(test2); + puts("\r\n"); + + char *test3 = allocator(0x28); + strcpy(test3, "test malloc3"); + puts(test3); + puts("\r\n"); + return 0; +} + +int do_cmd_dtb(int argc, char **argv) +{ + traverse_device_tree(dtb_ptr, dtb_callback_show_tree); + return 0; +} + +int do_cmd_exec(int argc, char **argv) +{ + char *filepath; + + if (argc == 1) + { + filepath = argv[0]; + } + else + { + puts("Too many arguments\r\n"); + return -1; + } + + char abs_path[MAX_PATH_NAME]; + struct vnode *target_file; + strcpy(abs_path, filepath); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + + strcpy(abs_path,"/initramfs/vfs2.img");// + if (vfs_lookup(abs_path, &target_file) != 0) + { + WARING("File : %s Does not Exit!!\n", abs_path); + return 0; + }; + + c_execfile.vnode = target_file; + c_execfile.pathname = abs_path; + exec_thread(); + return 0; +} + +int do_cmd_setTimeout(int argc, char **argv) +{ + char *msg; + int sec; + if (argc == 2) + { + msg = argv[0]; + sec = atoi(argv[1]); + } + else + { + puts("setTimeout [MESSAGE] [SECONDS]\r\n"); + return -1; + } + add_timer(puts, sec, msg, setSecond); + return 0; +} + +int do_cmd_set2sAlert(int argc, char **argv) +{ + add_timer(timer_set2sAlert, 2, "2sAlert", setSecond); + return 0; +} + +int do_cmd_mtest(int argc, char **argv) +{ + // char *a = kmalloc(513); + // uart_sendlinek("a : %x\n", a); + // //kfree(a); + + // char *b = kmalloc(512); + // uart_sendlinek("b : %x\n", b); + // //kfree(b); + + // char *c = kmalloc(8); + // //kfree(c); + + return 0; +} + +int do_cmd_ttest(int argc, char **argv) +{ + uart_sendlinek("run_queue size : %d\n", list_size(run_queue)); + list_head_t *pos; + list_for_each(pos, run_queue) + { + uart_sendlinek("pid : %d\n", ((thread_t *)pos)->pid); + for (int i = 0; i < SIGNAL_MAX; i++) + { + uart_sendlinek("signal_handler : 0x%x\n", ((thread_t *)pos)->signal_handler[i]); + } + } + return 0; +} + +int do_cmd_ftest(int argc, char **argv) +{ + struct file *testfiler; + char testbufr[0x30] = {}; + vfs_open("/boot/WORLD", 0, &testbufr); + vfs_read(testfiler, testbufr, 25); + uart_sendlinek("%s", testbufr); + + // ============================== test for file operation start================================== + // uart_sendlinek("\n\n"); + // uart_sendlinek("+-----------------------------+\n"); + // uart_sendlinek("| mkdir,mount test |\n"); + // uart_sendlinek("+-----------------------------+\n"); + + // vfs_mkdir("/lll"); + // vfs_mkdir("/aaa"); + // vfs_mkdir("/bbb"); + // vfs_mkdir("/lll/ddd"); + // vfs_mount("/lll/ddd", "tmpfs"); + // vfs_mkdir("/lll/ddd/fff"); + // vfs_dump(rootfs->root, 0); + + // uart_sendlinek("\n\n"); + // uart_sendlinek("+-----------------------------+\n"); + // uart_sendlinek("| open,write,read test |\n"); + // uart_sendlinek("+-----------------------------+\n"); + + // struct file *testfilew; + // struct file *testfiler; + // char testbufw[0x30] = "ABCDEABBBBBBDDDDDDDDDDD\n"; + // char testbufr[0x30] = {}; + + // vfs_open("/lll/ddd/ggg.file", O_CREAT, &testfilew); + // vfs_open("/lll/ddd/ggg.file", O_CREAT, &testfiler); + // vfs_write(testfilew, testbufw, 25); + // vfs_read(testfiler, testbufr, 25); + + // uart_sendlinek("%s", testbufr); + // vfs_dump(rootfs->root, 0); + // ============================== test for file operation end ================================== + + // ============================== test for get_absolute_path start================================== + // char *currt_path = "/root"; + // uart_sendlinek("currt_path : %s\n", currt_path); + // char *path1 = "/"; + // uart_sendlinek("path1 rel_path : %s\n", path1); + // get_absolute_path(path1, currt_path); + // // uart_sendlinek("path1 abs_path : %s\n", path1); + // uart_sendlinek("---------------------------------------\n"); + // char *path2 = "desktop"; + // uart_sendlinek("path2 rel_path : %s\n", path2); + // get_absolute_path(path2, currt_path); + // // uart_sendlinek("path2 abs_path : %s\n", path2); + // uart_sendlinek("---------------------------------------\n"); + // char *path3 = ".///////"; + // uart_sendlinek("path3 rel_path : %s\n", path3); + // get_absolute_path(path3, currt_path); + // // uart_sendlinek("path3 abs_path : %s\n", path3); + // ============================== test for get_absolute_path end================================== + + // char test[11] = "abcdefghijk"; + // char *t2 = &test[3]; + // uart_sendlinek("abs_path : %s\n", test); + // uart_sendlinek("abs_path : %s\n", t2); + // t2 = &test[5]; + // uart_sendlinek("abs_path : %s\n", t2); + + return 0; +} + +int do_cmd_cd(int argc, char **argv) +{ + char *filepath; + if (argc == 1) + { + filepath = argv[0]; + } + else + { + puts("Too many arguments\r\n"); + return -1; + } + vfs_cd(filepath); + return 0; +} \ No newline at end of file diff --git a/lab8/kernel/src/signal.c b/lab8/kernel/src/signal.c new file mode 100644 index 000000000..454315f6e --- /dev/null +++ b/lab8/kernel/src/signal.c @@ -0,0 +1,90 @@ +#include "signal.h" +#include "syscall.h" +#include "sched.h" +#include "memory.h" +#include "mmu.h" + +extern thread_t *curr_thread; + +/** + ( ) + [Signal] [UserProcess] ( [ Registered Signal Handler ] ) [UserProcess] + | \ ( / \ ) / + | \ ( / \ ) / +-------|--------------------[SystemCall]-------------------------------------(-----------------/---------------------------------\----------------------)--/--------------- + | \ [Signal Check] (-> \ ) / + V \ / ^ ( \ \ )/ + [Job Pending] [Exception Handler] | ( \ [ Default Signal Handler ]-------- [Exception Handler]) + | | ( ) + --------------------- ( CONTENT SWITCHING FOR SIGNAL HANDLER ) + +**/ + +void check_signal(trapframe_t *tpf) +{ + if (curr_thread->signal_is_checking) + return; + lock(); + // Prevent nested running signal handler. No need to handle + curr_thread->signal_is_checking = 1; + unlock(); + for (int i = 0; i <= SIGNAL_MAX; i++) + { + store_context(&curr_thread->signal_savedContext); + if (curr_thread->sigcount[i] > 0) + { + lock(); + curr_thread->sigcount[i]--; + unlock(); + run_signal(tpf, i); + } + } + lock(); + curr_thread->signal_is_checking = 0; + unlock(); +} + +void run_signal(trapframe_t *tpf, int signal) +{ + curr_thread->curr_signal_handler = curr_thread->signal_handler[signal]; + + // run default handler in kernel + if (curr_thread->curr_signal_handler == signal_default_handler) + { + signal_default_handler(); + return; + } + + // run registered handler in userspace + // char *temp_signal_userstack = kmalloc(USTACK_SIZE); + // asm("msr elr_el1, %0\n\t" + // "msr sp_el0, %1\n\t" + // "msr spsr_el1, %2\n\t" + // "eret\n\t" ::"r"(signal_handler_wrapper), + // "r"(temp_signal_userstack + USTACK_SIZE), + // "r"(tpf->spsr_el1)); + + asm("msr elr_el1, %0\n\t" + "msr sp_el0, %1\n\t" + "msr spsr_el1, %2\n\t" + "mov x0, %3\n\t" + "eret\n\t" ::"r"(USER_SIGNAL_WRAPPER_VA + ((size_t)signal_handler_wrapper % 0x1000)), + "r"(tpf->sp_el0), + "r"(tpf->spsr_el1), + "r"(curr_thread->curr_signal_handler)); +} + +void signal_handler_wrapper() +{ + //(curr_thread->curr_signal_handler)(); + // system call sigreturn + // uart_sendlinek("signal_handler_wrapper\n"); + asm("blr x0\n\t" + "mov x8,50\n\t" + "svc 0\n\t"); +} + +void signal_default_handler() +{ + kill(0, curr_thread->pid); +} diff --git a/lab8/kernel/src/stdio.c b/lab8/kernel/src/stdio.c new file mode 100644 index 000000000..a1909d4b7 --- /dev/null +++ b/lab8/kernel/src/stdio.c @@ -0,0 +1,121 @@ +#include "stdio.h" +#include "uart1.h" +#include "vfs.h" +#include "sched.h" + +extern thread_t *curr_thread; + +char getchar() +{ + char c[1]; + stdio_op(stdin, c, 1); + return c[0] == '\r' ? '\n' : c[0]; +} + +void putchar(char c) +{ + char cp[2] = {c,'\0'}; + stdio_op(stdout, cp, 1); +} + +void puts(const char *s) +{ + while (*s) + putchar(*s++); +} + +void Readfile(char *str, int size) +{ + while (size--) + { + putchar(*str++); + } +} + +// Function to print an integer to the UART +void put_int(int num) +{ + // Handle the case when the number is 0 + if (num == 0) + { + putchar('0'); + return; + } + + // Temporary array to store the reversed digits as characters + char temp[12]; // Assuming int can have at most 10 digits + int idx = 0; + + // Handle negative numbers + if (num < 0) + { + putchar('-'); + num = -num; + } + + // Convert the number to characters and store in the temporary array in reverse order + while (num > 0) + { + temp[idx++] = (char)(num % 10 + '0'); + num /= 10; + } + + // Reverse output the character digits + while (idx > 0) + { + putchar(temp[--idx]); + } +} + +void put_hex(unsigned int num) +{ + unsigned int hex; + int index = 28; + puts("0x"); + while (index >= 0) + { + hex = (num >> index) & 0xF; + hex += hex > 9 ? 0x37 : 0x30; + putchar(hex); + index -= 4; + } +} + +// A simple atoi() function +int atoi(char *str) +{ + // Initialize result + int res = 0; + + // Iterate through all characters + // of input string and update result + // take ASCII character of corresponding digit and + // subtract the code from '0' to get numerical + // value and multiply res by 10 to shuffle + // digits left to update running total + for (int i = 0; str[i] != '\0'; ++i) + { + if (str[i] > '9' || str[i] < '0') + return res; + res = res * 10 + str[i] - '0'; + } + + // return result. + return res; +} + +int fake_log2(unsigned long long n) +{ + int val = 0; + while (n >>= 1) + val++; + return val; +} + +void delay(int r) +{ + while (r--) + { + asm volatile("nop"); + } +} diff --git a/lab8/kernel/src/string.c b/lab8/kernel/src/string.c new file mode 100644 index 000000000..27e2c76a2 --- /dev/null +++ b/lab8/kernel/src/string.c @@ -0,0 +1,292 @@ +#include "string.h" + +size_t strlen(const char *str) +{ + size_t count = 0; + while ((unsigned char)*str++) + count++; + return count; +} + +int strcmp(const char *p1, const char *p2) +{ + const unsigned char *s1 = (const unsigned char *)p1; + const unsigned char *s2 = (const unsigned char *)p2; + unsigned char c1, c2; + + do + { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0') + return c1 - c2; + } while (c1 == c2); + return c1 - c2; +} + +int strcasecmp(const char *s1, const char *s2) +{ + char c1, c2; + + while (1) { + c1 = *s1++; + c2 = *s2++; + + if (!c1 || !c2) { + break; + } + + if ('A' <= c1 && c1 <= 'Z') { + c1 |= 0x20; + } + + if ('A' <= c2 && c2 <= 'Z') { + c2 |= 0x20; + } + + if (c1 != c2) { + break; + } + } + + return c1 - c2; +} + +int strncmp(const char *s1, const char *s2, unsigned long long n) +{ + unsigned char c1 = '\0'; + unsigned char c2 = '\0'; + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + } while (--n4 > 0); + n &= 3; + } + while (n > 0) + { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + n--; + } + return c1 - c2; +} + +char *strcpy(char *dest, const char *src) +{ + while ((*dest++ = *src++)) + ; + return dest; +} + +char *strncpy(char *dest, const char *src, unsigned long long n) +{ + // for (int i = 0; i < n ; i++) { + // dest[i] = src[i]; + // } + + while (n-- && (*dest++ = *src++) ) + ; + return dest; +} + +char *strcat(char *dest, const char *src) +{ + strcpy(dest + strlen(dest), src); + return dest; +} + +char *strncat(char *dest, const char *src, int n) +{ + char *t; + + t = dest; + + while (*t) { + t++; + } + + while (n > 0 && *src) { + *t = *src; + t++; + src++; + n--; + } + + *t = '\0'; + + return dest; +} + +unsigned int vsprintf(char *dst, char *fmt, __builtin_va_list args) +{ + long int arg; + int len, sign, i; + char *p, *orig = dst, tmpstr[19]; + + // failsafes + if (dst == (void *)0 || fmt == (void *)0) + { + return 0; + } + + // main loop + arg = 0; + while (*fmt) + { + if (dst - orig > VSPRINT_MAX_BUF_SIZE - 0x10) + { + return -1; + } + // argument access + if (*fmt == '%') + { + fmt++; + // literal % + if (*fmt == '%') + { + goto put; + } + len = 0; + // size modifier + while (*fmt >= '0' && *fmt <= '9') + { + len *= 10; + len += *fmt - '0'; + fmt++; + } + // skip long modifier + if (*fmt == 'l') + { + fmt++; + } + // character + if (*fmt == 'c') + { + arg = __builtin_va_arg(args, int); + *dst++ = (char)arg; + fmt++; + continue; + } + else + // decimal number + if (*fmt == 'd') + { + arg = __builtin_va_arg(args, int); + // check input + sign = 0; + if ((int)arg < 0) + { + arg *= -1; + sign++; + } + if (arg > 99999999999999999L) + { + arg = 99999999999999999L; + } + // convert to string + i = 18; + tmpstr[i] = 0; + do + { + tmpstr[--i] = '0' + (arg % 10); + arg /= 10; + } while (arg != 0 && i > 0); + if (sign) + { + tmpstr[--i] = '-'; + } + if (len > 0 && len < 18) + { + while (i > 18 - len) + { + tmpstr[--i] = ' '; + } + } + p = &tmpstr[i]; + goto copystring; + } + else if (*fmt == 'x') + { + arg = __builtin_va_arg(args, long int); + i = 16; + tmpstr[i] = 0; + do + { + char n = arg & 0xf; + tmpstr[--i] = n + (n > 9 ? 0x37 : 0x30); + arg >>= 4; + } while (arg != 0 && i > 0); + if (len > 0 && len <= 16) + { + while (i > 16 - len) + { + tmpstr[--i] = '0'; + } + } + p = &tmpstr[i]; + goto copystring; + } + else if (*fmt == 's') + { + p = __builtin_va_arg(args, char *); + copystring: + if (p == (void *)0) + { + p = "(null)"; + } + while (*p) + { + *dst++ = *p++; + } + } + } + else + { + put: + *dst++ = *fmt; + } + fmt++; + } + *dst = 0; + return dst - orig; +} + +void *memset(void *s, int c, size_t n) +{ + char *start = s; + for (size_t i = 0; i < n; i++) + { + start[i] = c; + } + + return s; +} + +char *memcpy(void *dest, const void *src, unsigned long long len) +{ + char *d = dest; + const char *s = src; + while (len--) + *d++ = *s++; + return dest; +} \ No newline at end of file diff --git a/lab8/kernel/src/syscall.c b/lab8/kernel/src/syscall.c new file mode 100644 index 000000000..71f4d67a6 --- /dev/null +++ b/lab8/kernel/src/syscall.c @@ -0,0 +1,352 @@ +#include "bcm2837/rpi_mbox.h" +#include "syscall.h" +#include "sched.h" +#include "uart1.h" +#include "stdio.h" +#include "exception.h" +#include "memory.h" +#include "mbox.h" +#include "signal.h" +#include "string.h" + +#include "debug.h" +#include "cpio.h" +#include "dtb.h" +#include "mmu.h" + +extern void *CPIO_DEFAULT_START; +extern thread_t *curr_thread; +extern thread_t threads[PIDMAX + 1]; + +// trap is like a shared buffer for user space and kernel space +// Because general-purpose registers are used for both arguments and return value, +// We may receive the arguments we need, and overwrite them with return value. + +int getpid(trapframe_t *tpf) +{ + // uart_sendlinek("this is getpid"); + tpf->x0 = curr_thread->pid; + return curr_thread->pid; +} + +size_t uartread(trapframe_t *tpf, char buf[], size_t size) +{ + int i = 0; + stdio_op(stdin, buf, size); + tpf->x0 = i; + return i; +} + +size_t uartwrite(trapframe_t *tpf, const char buf[], size_t size) +{ + int i = 0; + char *cptr = buf; + stdio_op(stdout, buf, size); + tpf->x0 = i; + return i; +} + +// In this lab, you won’t have to deal with argument passing +int exec(trapframe_t *tpf, const char *name, char *const argv[]) +{ + lock(); + mmu_del_vma(curr_thread); + INIT_LIST_HEAD(&curr_thread->vma_list); + + // use virtual file system + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, name); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + + // uart_sendlinek("file name : %s\n", name); + // uart_sendlinek("curr_working_dir : %s\n", curr_thread->curr_working_dir); + // uart_sendlinek("abs_path : %s\n", abs_path); + + struct vnode *target_file; + if (vfs_lookup(abs_path, &target_file) != 0) + { + WARING("File : %s Does not Exit!!", abs_path); + return 0; + }; + curr_thread->datasize = target_file->f_ops->getsize(target_file); + uart_sendlinek("datasize : %d\n", curr_thread->datasize); + + // curr_thread->data = kmalloc(curr_thread->datasize > PAGESIZE ? curr_thread->datasize : PAGESIZE); + curr_thread->data = kmalloc(curr_thread->datasize); + curr_thread->stack_alloced_ptr = kmalloc(USTACK_SIZE); + + // data copy + memcpy(curr_thread->signal_handler, curr_thread->signal_handler, SIGNAL_MAX * 8); + struct file *f; + vfs_open(abs_path, 0, &f); + vfs_read(f, curr_thread->data, curr_thread->datasize); + vfs_close(f); + + // clean vma & page_tables + asm("dsb ish\n\t"); // ensure write has completed + mmu_free_page_tables(curr_thread->context.pgd, 0); + memset((void *)PHYS_TO_KERNEL_VIRT(curr_thread->context.pgd), 0, 0x1000); + asm("tlbi vmalle1is\n\t" // invalidate all TLB entries + "dsb ish\n\t" // ensure completion of TLB invalidatation + "isb\n\t"); // clear pipeline + mmu_del_vma(curr_thread); + + // new vma + mmu_add_vma(curr_thread, USER_DATA_BASE, curr_thread->datasize, (size_t)KERNEL_VIRT_TO_PHYS(curr_thread->data), 0b111, 1, USER_DATA); + mmu_add_vma(curr_thread, USER_STACK_BASE - USTACK_SIZE, USTACK_SIZE, (size_t)KERNEL_VIRT_TO_PHYS(curr_thread->stack_alloced_ptr), 0b011, 1, USER_STACK); + mmu_add_vma(curr_thread, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0, PERIPHERAL); + mmu_add_vma(curr_thread, USER_SIGNAL_WRAPPER_VA, 0x1000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(signal_handler_wrapper), 0x1000), 0b101, 0, USER_SIGNAL_WRAPPER); + mmu_add_vma(curr_thread, USER_EXEC_WRAPPER_VA, 0x2000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(exec_wrapper), PAGESIZE), 0b101, 0, USER_EXEC_WRAPPER); + + tpf->elr_el1 = USER_DATA_BASE; + tpf->sp_el0 = USER_STACK_BASE - STACK_BASE_OFFSET; + tpf->x0 = 0; + unlock(); + return 0; +} + +// extern unsigned long long int lock_counter; +int fork(trapframe_t *tpf) +{ + lock(); + thread_t *newt = thread_create(curr_thread->data); + // mmu_set_PTE_readonly(curr_thread->context.pgd,0); + // mmu_pagetable_copy(newt->context.pgd,curr_thread->context.pgd,0); + // uart_sendlinek("fork\n"); + memcpy(newt->signal_handler, curr_thread->signal_handler, SIGNAL_MAX * 8); + memcpy(newt->stack_alloced_ptr, curr_thread->kernel_stack_alloced_ptr, USTACK_SIZE); + memcpy(newt->kernel_stack_alloced_ptr, curr_thread->kernel_stack_alloced_ptr, KSTACK_SIZE); + memcpy(newt->curr_working_dir, curr_thread->curr_working_dir,MAX_PATH_NAME+1); + + newt->datasize = curr_thread->datasize; + newt->data = kmalloc(newt->datasize); + memcpy(newt->data,curr_thread->data,newt->datasize); + //newt->curr_working_dir = curr_thread->curr_working_dir; + // memcpy(newt->file_descriptors_table, curr_thread->file_descriptors_table, MAX_FD * 8); // <------------------------------------------------ + mmu_add_vma(newt, USER_DATA_BASE, newt->datasize, (size_t)KERNEL_VIRT_TO_PHYS(newt->data), 0b111, 1, USER_DATA); + mmu_add_vma(newt, USER_STACK_BASE - USTACK_SIZE, USTACK_SIZE, (size_t)KERNEL_VIRT_TO_PHYS(newt->stack_alloced_ptr), 0b011, 1, USER_STACK); + mmu_add_vma(newt, PERIPHERAL_START, PERIPHERAL_END - PERIPHERAL_START, PERIPHERAL_START, 0b011, 0, PERIPHERAL); + mmu_add_vma(newt, USER_SIGNAL_WRAPPER_VA, 0x1000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(signal_handler_wrapper), 0x1000), 0b101, 0, USER_SIGNAL_WRAPPER); + mmu_add_vma(newt, USER_EXEC_WRAPPER_VA, 0x2000, ALIGN_DOWN((size_t)KERNEL_VIRT_TO_PHYS(exec_wrapper), PAGESIZE), 0b101, 0, USER_EXEC_WRAPPER); + + int parent_pid = curr_thread->pid; + + store_context(get_current()); + // for child + if (parent_pid != curr_thread->pid) + { + goto child; + } + + // 除了PGD以外的context都複製。 + void *temp_pgd = newt->context.pgd; + newt->context = curr_thread->context; + newt->context.pgd = temp_pgd; + //memcpy(newt->context.pgd,curr_thread->context.pgd,PAGESIZE); + + newt->context.fp += newt->kernel_stack_alloced_ptr - curr_thread->kernel_stack_alloced_ptr; // move fp + newt->context.sp += newt->kernel_stack_alloced_ptr - curr_thread->kernel_stack_alloced_ptr; // move kernel sp + + unlock(); + + tpf->x0 = newt->pid; + return newt->pid; + +child: + tpf->x0 = 0; + return 0; +} + +void exit(trapframe_t *tpf, int status) +{ + thread_exit(); + while (1) + schedule(); +} + +int syscall_mbox_call(trapframe_t *tpf, unsigned char ch, unsigned int *mbox) +{ + lock(); + + unsigned int size_of_mbox = mbox[0]; + memcpy((char *)pt, mbox, size_of_mbox); + mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt)); + memcpy(mbox, (char *)pt, size_of_mbox); + + // tpf->x0 = 8; + unlock(); + return 0; +} + +// only need to implement the anonymous page mapping in this Lab. +void *mmap(trapframe_t *tpf, void *addr, size_t len, int prot, int flags, int fd, int file_offset) +{ + len = ALIGN_UP(len, PAGESIZE); + unsigned long base_user_va = ALIGN_DOWN((unsigned long)addr, PAGESIZE); + uart_sendlinek("+\n"); + uart_sendlinek("| User request new vma base vitural address: 0x%x\n", (unsigned long)addr); + uart_sendlinek("| Aligned to PAGESIZE: 0x%x\n", base_user_va); + uart_sendlinek("| User request new vma size: 0x%x\n", len); + uart_sendlinek("| Exec, Write, Read : 0x%d\n", prot); + uart_sendlinek("+\n"); + + // Req #2 check if overlap + vm_area_struct_t *the_area_ptr = check_vma_overlap(curr_thread, base_user_va, (unsigned long)len); + // take as a hint to decide new region's start address + if (the_area_ptr) + { + WARING("Vitural Memory Area Overlap\n"); + WARING("Find another vma base vitural address\n"); + tpf->x0 = (unsigned long)mmap(tpf, (void *)(the_area_ptr->virt_addr + the_area_ptr->area_size), len, prot, flags, fd, file_offset); + return (void *)tpf->x0; + } + // create new valid region, map and set the page attributes (prot) + mmu_add_vma(curr_thread, base_user_va, len, KERNEL_VIRT_TO_PHYS((unsigned long)kmalloc(len)), prot, 1, UNKNOW_AREA); + tpf->x0 = base_user_va; + return (void *)tpf->x0; +} + +void kill(trapframe_t *tpf, int pid) +{ + if (pid < 0 || pid >= PIDMAX || !threads[pid].isused) + return; + + lock(); + + if (pid == curr_thread->pid) + { + uart_sendlinek("[!] you kill youself !! \n"); + thread_exit(); + unlock(); + while (1) + schedule(); + } + else + { + threads[pid].iszombie = 1; + unlock(); + } + schedule(); +} + +void signal_register(int signal, void (*handler)()) +{ + if (signal > SIGNAL_MAX || signal < 0) + return; + // uart_sendlinek("handler : 0x%x\n", handler); + curr_thread->signal_handler[signal] = handler; +} + +void signal_kill(int pid, int signal) +{ + if (pid > PIDMAX || pid < 0 || !threads[pid].isused) + return; + lock(); + threads[pid].sigcount[signal]++; + unlock(); +} + +void sigreturn(trapframe_t *tpf) +{ + // unsigned long signal_ustack = tpf->sp_el0 % USTACK_SIZE == 0 ? tpf->sp_el0 - USTACK_SIZE : tpf->sp_el0 & (~(USTACK_SIZE - 1)); + // kfree((char *)signal_ustack); + load_context(&curr_thread->signal_savedContext); +} + +void syscall_unlock(trapframe_t *tpf) +{ + unlock(); +} + +void syscall_lock(trapframe_t *tpf) +{ + lock(); +} + +char *get_file_start(char *thefilepath) +{ + int FLAG_getfile = 0; + char *filepath; + char *filedata; + unsigned int filesize; + // struct cpio_newc_header *header_pointer = CPIO_DEFAULT_START; + + CPIO_for_each(&filepath, &filesize, &filedata) + { + if (strcmp(thefilepath, filepath) == 0) + { + FLAG_getfile = 1; + return filedata; + } + } + + if (!FLAG_getfile) + { + uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + } + + // while (header_pointer != 0) + // { + // int error = cpio_newc_parse_header(header_pointer, &filepath, &filesize, &filedata, &header_pointer); + // //if parse header error + // if (error) + // { + // uart_sendlinek("error"); + // break; + // } + + // if (strcmp(thefilepath, filepath) == 0) + // { + // return filedata; + // } + + // //if this is TRAILER!!! (last of file) + // if (header_pointer == 0) + // uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + // } + + return 0; +} + +unsigned int get_file_size(char *thefilepath) +{ + int FLAG_getfile = 0; + char *filepath; + char *filedata; + unsigned int filesize; + + CPIO_for_each(&filepath, &filesize, &filedata) + { + if (strcmp(thefilepath, filepath) == 0) + { + FLAG_getfile = 1; + return filesize; + } + } + + if (!FLAG_getfile) + { + uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + } + + // while (header_pointer != 0) + // { + // int error = cpio_newc_parse_header(header_pointer, &filepath, &filesize, &filedata, &header_pointer); + // // if parse header error + // if (error) + // { + // uart_sendlinek("error"); + // break; + // } + + // if (strcmp(thefilepath, filepath) == 0) + // { + // return filesize; + // } + + // // if this is TRAILER!!! (last of file) + // if (header_pointer == 0) + // uart_sendlinek("execfile: %s: No such file or directory\r\n", thefilepath); + // } + return 0; +} diff --git a/lab8/kernel/src/syscall_fs.c b/lab8/kernel/src/syscall_fs.c new file mode 100644 index 000000000..3f6e95391 --- /dev/null +++ b/lab8/kernel/src/syscall_fs.c @@ -0,0 +1,157 @@ +#include "bcm2837/rpi_mbox.h" +#include "vfs.h" +#include "string.h" +#include "sched.h" +#include "exception.h" +#include "uart1.h" +#include "vfs_dev_framebuffer.h" +#include "stdio.h" + +extern void *CPIO_DEFAULT_START; +extern thread_t *curr_thread; +extern thread_t threads[PIDMAX + 1]; + +int open(trapframe_t *tpf, const char *pathname, int flags) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, pathname); + + uart_sendlinek("file name : %s\n", pathname); + uart_sendlinek("curr_working_dir : %s\n", curr_thread->curr_working_dir); + uart_sendlinek("abs_path : %s\n", abs_path); + + // update abs_path + get_absolute_path(abs_path, curr_thread->curr_working_dir); + for (int i = 0; i < MAX_FD; i++) + { + // find a usable fd + if (!curr_thread->file_descriptors_table[i]) + { + // uart_sendlinek("i : %d\n", i); + // while (1) + // ; + + if (vfs_open(abs_path, flags, &curr_thread->file_descriptors_table[i]) != 0) + { + break; + } + + tpf->x0 = i; + return i; + } + } + + tpf->x0 = -1; + return -1; +} + +int close(trapframe_t *tpf, int fd) +{ + // find an opened fd + if (curr_thread->file_descriptors_table[fd]) + { + vfs_close(curr_thread->file_descriptors_table[fd]); + curr_thread->file_descriptors_table[fd] = 0; + tpf->x0 = 0; + return 0; + } + + tpf->x0 = -1; + return -1; +} + +long write(trapframe_t *tpf, int fd, const void *buf, unsigned long count) +{ + // uart_sendlinek("fd : %d\n", fd); + if (curr_thread->file_descriptors_table[fd]) + { + tpf->x0 = vfs_write(curr_thread->file_descriptors_table[fd], buf, count); + return tpf->x0; + } + tpf->x0 = -1; + return tpf->x0; +} + +long read(trapframe_t *tpf, int fd, void *buf, unsigned long count) +{ + if (curr_thread->file_descriptors_table[fd]) + { + tpf->x0 = vfs_read(curr_thread->file_descriptors_table[fd], buf, count); + return tpf->x0; + } + tpf->x0 = -1; + return tpf->x0; +} + +int mkdir(trapframe_t *tpf, const char *pathname, unsigned mode) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, pathname); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + tpf->x0 = vfs_mkdir(abs_path); + return tpf->x0; +} + +int mount(trapframe_t *tpf, const char *src, const char *target, const char *filesystem, unsigned long flags, const void *data) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, target); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + + tpf->x0 = vfs_mount(abs_path, filesystem); + return tpf->x0; +} + +int chdir(trapframe_t *tpf, const char *path) +{ + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, path); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + strcpy(curr_thread->curr_working_dir, abs_path); + + return 0; +} + +long lseek64(trapframe_t *tpf, int fd, long offset, int whence) +{ + if (whence == SEEK_SET) // used for dev_framebuffer + { + curr_thread->file_descriptors_table[fd]->f_pos = offset; + tpf->x0 = offset; + } + else // other is not supported + { + tpf->x0 = -1; + } + + return tpf->x0; +} +extern unsigned int height; +extern unsigned int isrgb; +extern unsigned int pitch; +extern unsigned int width; +int ioctl(trapframe_t *tpf, int fb, unsigned long request, void *info) +{ + if (request == 0) // used for get info (SPEC) + { + struct framebuffer_info *fb_info = info; + fb_info->height = height; + fb_info->isrgb = isrgb; + fb_info->pitch = pitch; + fb_info->width = width; + } + + tpf->x0 = 0; + return tpf->x0; +} + +int sync(trapframe_t *tpf) +{ + for (int i = 0; i < MAX_FS_REG;i++) + { + if(!reg_fs[i].name) continue; + vfs_sync(®_fs[i]); + } + tpf->x0 = 0; + return tpf->x0; +} \ No newline at end of file diff --git a/lab8/kernel/src/timer.c b/lab8/kernel/src/timer.c new file mode 100644 index 000000000..061bbb05d --- /dev/null +++ b/lab8/kernel/src/timer.c @@ -0,0 +1,177 @@ +#include "timer.h" +#include "uart1.h" +#include "memory.h" +#include "string.h" +#include "exception.h" +#include + +#define STR(x) #x +#define XSTR(s) STR(s) + +struct list_head *timer_event_list; // first head has nothing, store timer_event_t after it + +void timer_list_init() +{ + uint64_t tmp; + asm volatile("mrs %0, cntkctl_el1" : "=r"(tmp)); + tmp |= 1; + asm volatile("msr cntkctl_el1, %0" ::"r"(tmp)); + + timer_event_list = allocator(sizeof(list_head_t)); + INIT_LIST_HEAD(timer_event_list); +} + +void core_timer_enable() +{ + __asm__ __volatile__( + "mov x1, 1\n\t" + "msr cntp_ctl_el0, x1\n\t" // cntp_ctl_el0[0]: enable, Control register for the EL1 physical timer. + // cntp_tval_el0: Holds the timer value for the EL1 physical timer + "mov x2, 2\n\t" + "ldr x1, =" XSTR(CORE0_TIMER_IRQ_CTRL) "\n\t" + "str w2, [x1]\n\t" // QA7_rev3.4.pdf: Core0 Timer IRQ allows Non-secure physical timer(nCNTPNSIRQ) + ); +} + +void core_timer_disable() +{ + __asm__ __volatile__( + "mov x2, 0\n\t" + "ldr x1, =" XSTR(CORE0_TIMER_IRQ_CTRL) "\n\t" + "str w2, [x1]\n\t" // QA7_rev3.4.pdf: Mask all timer interrupt + ); +} + +void core_timer_handler() +{ + lock(); + //uart_sendlinek("\nThis is core_timer_handler\n"); + if (list_empty(timer_event_list)) + { + uart_sendlinek("\ntimer_event_list is empty\n"); + set_core_timer_interrupt(10000); // disable timer interrupt (set a very big value) + unlock(); + return; + } + timer_event_callback((timer_event_t *)timer_event_list->next); // do callback and set new interrupt + unlock(); +} + +void timer_event_callback(timer_event_t *timer_event) +{ + list_del_entry((struct list_head *)timer_event); // delete the event in queue + // free(timer_event->args); // free the event's space + // free(timer_event); + ((void (*)(char *))timer_event->callback)(timer_event->args); // call the event + + kfree(timer_event->args); + kfree(timer_event); + + // set queue linked list to next time event if it exists + if (!list_empty(timer_event_list)) + { + set_core_timer_interrupt_by_tick(((timer_event_t *)timer_event_list->next)->interrupt_time); + } + else + { + set_core_timer_interrupt(10000); // disable timer interrupt (set a very big value) + } +} + +void timer_set2sAlert(char *str) +{ + unsigned long long cntpct_el0; + __asm__ __volatile__("mrs %0, cntpct_el0\n\t" : "=r"(cntpct_el0)); // tick auchor + unsigned long long cntfrq_el0; + __asm__ __volatile__("mrs %0, cntfrq_el0\n\t" : "=r"(cntfrq_el0)); // tick frequency + + uart_sendlinek("\n"); + uart_sendlinek("[Interrupt start]\n"); + for (int i = 0; i < 1000000000; i++) + ; + uart_sendlinek("[Interrupt finish]\n"); + + // uart_sendlinek("[Interrupt][el1_irq][%s] %d seconds after booting\n", str, cntpct_el0 / cntfrq_el0); + + add_timer(timer_set2sAlert, 2, "2sAlert",setSecond); +} + +void add_timer(void *callback, unsigned long long timeout, char *args, int inTickFormat) +{ + timer_event_t *the_timer_event = kmalloc(sizeof(timer_event_t)); // free by timer_event_callback + // store all the related information in timer_event + the_timer_event->args = kmalloc(strlen(args) + 1); + strcpy(the_timer_event->args, args); + + if (inTickFormat == 0) + { + the_timer_event->interrupt_time = get_tick_plus_s(timeout); // store interrupt time into timer_event + } + else + { + the_timer_event->interrupt_time = get_tick_plus_s(0) + timeout; + } + + the_timer_event->callback = callback; + INIT_LIST_HEAD(&the_timer_event->listhead); + + // add the timer_event into timer_event_list (sorted) + struct list_head *curr; + lock(); + list_for_each(curr, timer_event_list) + { + if (((timer_event_t *)curr)->interrupt_time > the_timer_event->interrupt_time) + { + list_add(&the_timer_event->listhead, curr->prev); // add this timer at the place just before the bigger one (sorted) + break; + } + } + // if the timer_event is the biggest, run this code block + if (list_is_head(curr, timer_event_list)) + { + list_add_tail(&the_timer_event->listhead, timer_event_list); + } + // set interrupt to first event + set_core_timer_interrupt_by_tick(((timer_event_t *)timer_event_list->next)->interrupt_time); + unlock(); +} + +// get cpu tick add some second +unsigned long long get_tick_plus_s(unsigned long long second) +{ + unsigned long long cntpct_el0 = 0; + __asm__ __volatile__("mrs %0, cntpct_el0\n\t" : "=r"(cntpct_el0)); // tick auchor + unsigned long long cntfrq_el0 = 0; + __asm__ __volatile__("mrs %0, cntfrq_el0\n\t" : "=r"(cntfrq_el0)); // tick frequency + return (cntpct_el0 + cntfrq_el0 * second); +} + +// set timer interrupt time to [expired_time] seconds after now (relatively) +void set_core_timer_interrupt(unsigned long long expired_time) +{ + __asm__ __volatile__( + "mrs x1, cntfrq_el0\n\t" // cntfrq_el0 -> frequency of the timer + "mul x1, x1, %0\n\t" // cntpct_el0 = cntfrq_el0 * seconds: relative timer to cntfrq_el0 + "msr cntp_tval_el0, x1\n\t" // Set expired time to cntp_tval_el0, which stores time value of EL1 physical timer. + : "=r"(expired_time)); +} + +// directly set timer interrupt time to a cpu tick (directly) +void set_core_timer_interrupt_by_tick(unsigned long long tick) +{ + __asm__ __volatile__( + "msr cntp_cval_el0, %0\n\t" // cntp_cval_el0 -> absolute timer + : "=r"(tick)); +} + +// get timer pending queue size +int timer_list_get_size() +{ + int r = 0; + struct list_head *curr; + list_for_each(curr, timer_event_list) + { + r++; + } + return r; +} diff --git a/lab8/kernel/src/uart1.c b/lab8/kernel/src/uart1.c new file mode 100644 index 000000000..30e7bae36 --- /dev/null +++ b/lab8/kernel/src/uart1.c @@ -0,0 +1,177 @@ +#include "bcm2837/rpi_gpio.h" +#include "bcm2837/rpi_uart1.h" +#include "bcm2837/rpi_irq.h" +#include "uart1.h" +#include "string.h" +#include "exception.h" +#include "vfs.h" + +// implement first in first out buffer with a read index and a write index +static char uart_tx_buffer[VSPRINT_MAX_BUF_SIZE]; +unsigned int uart_tx_buffer_widx = 0; // write index +unsigned int uart_tx_buffer_ridx = 0; // read index +static char uart_rx_buffer[VSPRINT_MAX_BUF_SIZE]; +unsigned int uart_rx_buffer_widx = 0; +unsigned int uart_rx_buffer_ridx = 0; + +void uart_init() +{ + register unsigned int selector; + + /* initialize UART */ + *AUX_ENABLES = 1; // enable UART1 + *AUX_MU_CNTL_REG = 0; // disable TX/RX + + /* configure UART */ + *AUX_MU_IER_REG = 0; // disable interrupt + *AUX_MU_LCR_REG = 3; // 8 bit data size + *AUX_MU_MCR_REG = 0; // disable flow control + *AUX_MU_BAUD_REG = 270; // 115200 baud rate + + /* map UART1 to GPIO pins */ + selector = *GPFSEL1; + selector &= ~(7 << 12); // clean gpio14, and (11 111 111 111 111 111 000 111 111 111 111)2 + selector |= 2 << 12; // set gpio14 to alt5 + selector &= ~(7 << 15); // clean gpio15, and (11 111 111 111 111 000 111 111 111 111 111)2 + selector |= 2 << 15; // set gpio15 to alt5 + *GPFSEL1 = selector; + + /* enable pin 14, 15 - ref: Page 101 */ + *GPPUD = 0; + selector = 150; + while (selector--) + { + asm volatile("nop"); + } + *GPPUDCLK0 = (1 << 14) | (1 << 15); + selector = 150; + while (selector--) + { + asm volatile("nop"); + } + *GPPUDCLK0 = 0; + + *AUX_MU_CNTL_REG = 3; +} + +void uart_flush_FIFO() +{ + // On write: + // Writing with bit 1 set will clear the receive FIFO + // Writing with bit 2 set will clear the transmit FIFOF + *AUX_MU_IIR_REG |= 6; +} + +char uart_recv() +{ + char r; + while (!(*AUX_MU_LSR_REG & 0x01)) + ; + r = (char)(*AUX_MU_IO_REG); + return r; +} + +void uart_send(unsigned int c) +{ + while (!(*AUX_MU_LSR_REG & 0x20)) + ; + *AUX_MU_IO_REG = c; +} + +// AUX_MU_IER_REG -> BCM2837-ARM-Peripherals.pdf - Pg.12 +void uart_interrupt_enable() +{ + *AUX_MU_IER_REG |= 1; // enable read interrupt + *AUX_MU_IER_REG |= 2; // enable write interrupt + *ENABLE_IRQS_1 |= 1 << 29; // Pg.112 +} + +void uart_interrupt_disable() +{ + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + *AUX_MU_IER_REG &= ~(2); // disable write interrupt +} + +// scanf +void uart_r_irq_handler() +{ + if ((uart_rx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_rx_buffer_ridx) + { + *AUX_MU_IER_REG &= ~(1); // disable read interrupt + return; + } + uart_rx_buffer[uart_rx_buffer_widx++] = uart_recv(); + if (uart_rx_buffer_widx >= VSPRINT_MAX_BUF_SIZE) + uart_rx_buffer_widx = 0; + *AUX_MU_IER_REG |= 1; +} + +// printf +void uart_w_irq_handler() +{ + if (uart_tx_buffer_ridx == uart_tx_buffer_widx) + { + *AUX_MU_IER_REG &= ~(2); // disable write interrupt + return; // buffer empty + } + uart_send(uart_tx_buffer[uart_tx_buffer_ridx++]); + if (uart_tx_buffer_ridx >= VSPRINT_MAX_BUF_SIZE) + uart_tx_buffer_ridx = 0; + *AUX_MU_IER_REG |= 2; // enable write interrupt +} + +// uart_async_getc read from buffer +// uart_r_irq_handler write to buffer then output +char uart_async_recv() +{ + *AUX_MU_IER_REG |= 1; // enable read interrupt + // do while if buffer empty + while (uart_rx_buffer_ridx == uart_rx_buffer_widx) + { + *AUX_MU_IER_REG |= 1; // enable read interrupt + } + lock(); + char r = uart_rx_buffer[uart_rx_buffer_ridx++]; + + if (uart_rx_buffer_ridx >= VSPRINT_MAX_BUF_SIZE) + uart_rx_buffer_ridx = 0; + unlock(); + return r; +} + +// uart_async_putc writes to buffer +// uart_w_irq_handler read from buffer then output +void uart_async_send(char c) +{ + // if buffer full, wait for uart_w_irq_handler + while ((uart_tx_buffer_widx + 1) % VSPRINT_MAX_BUF_SIZE == uart_tx_buffer_ridx) + { + // uart_puts("buffer full\r\n"); + *AUX_MU_IER_REG |= 2; // enable write interrupt + } + lock(); + uart_tx_buffer[uart_tx_buffer_widx++] = c; + if (uart_tx_buffer_widx >= VSPRINT_MAX_BUF_SIZE) + uart_tx_buffer_widx = 0; // cycle pointer + unlock(); + *AUX_MU_IER_REG |= 2; // enable write interrupt +} + +int uart_sendlinek(char *fmt, ...) +{ + __builtin_va_list args; + __builtin_va_start(args, fmt); + char buf[VSPRINT_MAX_BUF_SIZE]; + + char *str = (char *)buf; + int count = vsprintf(str, fmt, args); + + while (*str) + { + if (*str == '\n') + uart_send('\r'); + uart_send(*str++); + } + __builtin_va_end(args); + return count; +} \ No newline at end of file diff --git a/lab8/kernel/src/vfs.c b/lab8/kernel/src/vfs.c new file mode 100644 index 000000000..cca9b42c9 --- /dev/null +++ b/lab8/kernel/src/vfs.c @@ -0,0 +1,464 @@ +#include "sdhost.h" + +#include "vfs.h" +#include "vfs_dev_framebuffer.h" +#include "vfs_dev_uart.h" +#include "vfs_initramfs.h" +#include "vfs_tmpfs.h" + +#include "memory.h" +#include "string.h" +#include "uart1.h" +#include "sched.h" +#include "debug.h" + +struct mount *rootfs; +struct filesystem reg_fs[MAX_FS_REG]; +struct file_operations reg_dev[MAX_DEV_REG]; +extern thread_t *curr_thread; + +void rootfs_init() +{ + // sd_init + sd_init(); + + // tmpfs + int idx = register_tmpfs(); + rootfs = kmalloc(sizeof(struct mount)); + reg_fs[idx].setup_mount(®_fs[idx], rootfs); + + // initramfs + vfs_mkdir("/initramfs"); + register_initramfs(); + vfs_mount("/initramfs", "initramfs"); + + // fat32 + vfs_mkdir("/boot"); + register_fat32(); + vfs_mount("/boot", "fat32"); + + // // dev_fs + vfs_mkdir("/dev"); + int uart_id = init_dev_uart(); + vfs_mknod("/dev/uart", uart_id); + int framebuffer_id = init_dev_framebuffer(); + vfs_mknod("/dev/framebuffer", framebuffer_id); +} + +int register_filesystem(struct filesystem *fs) +{ + for (int i = 0; i < MAX_FS_REG; i++) + { + if (!reg_fs[i].name) + { + reg_fs[i].name = fs->name; + reg_fs[i].setup_mount = fs->setup_mount; + reg_fs[i].sync = fs->sync; // =================================================== + return i; + } + } + return -1; +} + +int vfs_lookup(const char *pathname, struct vnode **target) +{ + // int is_fat = 0; + // if (!strcmp(pathname, "/boot")) + // { + // is_fat = 1; + // uart_sendlinek("is boot...\n"); + // } + + // if no path input, return root + if (strlen(pathname) == 0 || (!strcmp(&pathname[0], "/") && strlen(pathname) == 1)) + { + *target = rootfs->root; + // uart_sendlinek("path : %s is root \n", pathname); + return 0; + } + struct vnode *dirnode = rootfs->root; + char component_name[MAX_FILE_NAME + 1] = {}; + int c_idx = 0; + // deal with directory + for (int i = 1; i < strlen(pathname); i++) + { + if (pathname[i] == '/') + { + component_name[c_idx++] = 0; + // if fs's v_ops error, return -1 + if (dirnode->v_ops->lookup(dirnode, &dirnode, component_name) != 0) + return -1; + // redirect to mounted filesystem + while (dirnode->mount) + { + dirnode = dirnode->mount->root; + // if (is_fat) + // break; + } + c_idx = 0; + } + else + { + component_name[c_idx++] = pathname[i]; + } + } + + // deal with file + component_name[c_idx++] = 0; + // if fs's v_ops error, return -1 + if (dirnode->v_ops->lookup(dirnode, &dirnode, component_name) != 0) + return -1; + // redirect to mounted filesystem + while (dirnode->mount) + { + // if (is_fat) + // break; + dirnode = dirnode->mount->root; + } + // return file's vnode + *target = dirnode; + + return 0; +} + +int register_dev(struct file_operations *fo) +{ + for (int i = 0; i < MAX_FS_REG; i++) + { + if (!reg_dev[i].open) + { + // return unique id for the assigned device + reg_dev[i] = *fo; + return i; + } + } + return -1; +} + +struct filesystem *find_filesystem(const char *fs_name) +{ + for (int i = 0; i < MAX_FS_REG; i++) + { + if (strcmp(reg_fs[i].name, fs_name) == 0) + { + return ®_fs[i]; + } + } + return 0; +} + +int vfs_mount(const char *target, const char *filesystem) +{ + struct vnode *dirnode; + // search for the target filesystem + struct filesystem *fs = find_filesystem(filesystem); + if (!fs) + { + uart_sendlinek("vfs_mount cannot find filesystem\r\n"); + return -1; + } + + if (vfs_lookup(target, &dirnode) == -1) + { + uart_sendlinek("vfs_mount cannot find dir\r\n"); + return -1; + } + else + { + // mount fs on dirnode + dirnode->mount = kmalloc(sizeof(struct mount)); + // uart_sendlinek("fs name : %s\n",fs->name); + fs->setup_mount(fs, dirnode->mount); + } + return 0; +} + +// file ops +int vfs_mkdir(const char *pathname) +{ + struct vnode *node; + if (vfs_lookup(pathname, &node) == 0) + { + WARING("Directory Exit!! : %s\n", pathname); + return 0; + } + + char dirname[MAX_PATH_NAME] = {}; // before add folder + char newdirname[MAX_PATH_NAME] = {}; // after add folder + + // search for last directory + int last_slash_idx = 0; + for (int i = 0; i < strlen(pathname); i++) + { + if (pathname[i] == '/') + { + last_slash_idx = i; + } + } + + memcpy(dirname, pathname, last_slash_idx); + strcpy(newdirname, pathname + last_slash_idx + 1); + + // create new directory if upper directory is found + // struct vnode *node; + if (vfs_lookup(dirname, &node) == 0) + { + // node is the old dir, &node is new dir + node->v_ops->mkdir(node, &node, newdirname); + return 0; + } + + uart_sendlinek("vfs_mkdir cannot find pathname"); + return -1; +} +// file ops +int vfs_open(const char *pathname, int flags, struct file **target) +{ + // 1. Lookup pathname + // 3. Create a new file if O_CREAT is specified in flags and vnode not found + // uart_sendlinek("\nhere!!!!!\n"); + struct vnode *node; + if (vfs_lookup(pathname, &node) != 0 && (flags & O_CREAT)) + { + // grep all of the directory path + int last_slash_idx = 0; + for (int i = 0; i < strlen(pathname); i++) + { + if (pathname[i] == '/') + { + last_slash_idx = i; + } + } + + char dirname[MAX_PATH_NAME + 1]; + strcpy(dirname, pathname); + dirname[last_slash_idx] = 0; + // update dirname to node + if (vfs_lookup(dirname, &node) != 0) + { + uart_sendlinek("cannot ocreate no dir name\r\n"); + return -1; + } + // create a new file node on node, &node is new file, 3rd arg is filename + node->v_ops->create(node, &node, pathname + last_slash_idx + 1); + *target = kmalloc(sizeof(struct file)); + // attach opened file on the new node + node->f_ops->open(node, target); + (*target)->flags = flags; + return 0; + } + else // 2. Create a new file handle for this vnode if found. + { + // attach opened file on the node + + *target = kmalloc(sizeof(struct file)); + node->f_ops->open(node, target); + (*target)->flags = flags; + return 0; + } + + // lookup error code shows if file exist or not or other error occurs + // 4. Return error code if fails + return -1; +} + +// file ops +int vfs_close(struct file *file) +{ + // 1. release the file handle + // 2. Return error code if fails + file->f_ops->close(file); + return 0; +} + +// file ops +int vfs_write(struct file *file, const void *buf, size_t len) +{ + // 1. write len byte from buf to the opened file. + // 2. return written size or error code if an error occurs. + return file->f_ops->write(file, buf, len); +} + +// file ops +int vfs_read(struct file *file, void *buf, size_t len) +{ + // 1. read min(len, readable size) byte to buf from the opened file. + // 2. block if nothing to read for FIFO type + // 2. return read size or error code if an error occurs. + return file->f_ops->read(file, buf, len); +} + +// for device operations only +int vfs_mknod(char *pathname, int id) +{ + struct file *f; + // create leaf and its file operations + vfs_open(pathname, O_CREAT, &f); + f->vnode->f_ops = ®_dev[id]; + vfs_close(f); + return 0; +} + + +int vfs_sync(struct filesystem *fs) +{ + return fs->sync(fs); +} + +// void vfs_test() +// { +// // test read/write +// vfs_mkdir("/lll"); +// vfs_mkdir("/lll/ddd"); +// // test mount +// vfs_mount("/lll/ddd", "tmpfs"); + +// struct file* testfilew; +// struct file *testfiler; +// char testbufw[0x30] = "ABCDEABBBBBBDDDDDDDDDDD"; +// char testbufr[0x30] = {}; +// vfs_open("/lll/ddd/ggg", O_CREAT, &testfilew); +// vfs_open("/lll/ddd/ggg", O_CREAT, &testfiler); +// vfs_write(testfilew, testbufw, 10); +// vfs_read(testfiler, testbufr, 10); +// uart_sendline("%s",testbufr); + +// struct file *testfile_initramfs; +// vfs_open("/initramfs/get_simpleexec.sh", O_CREAT, &testfile_initramfs); +// vfs_read(testfile_initramfs, testbufr, 30); +// uart_sendline("%s", testbufr); +// } + +char *get_absolute_path(char *path, char *curr_working_dir) +{ + char absolute_path[MAX_PATH_NAME + 1] = {}; + int max_pathdeep = 10; + struct dir_path *ctmp = kmalloc(sizeof(struct dir_path) * max_pathdeep); + int deep = 0; + + if (path[0] == '/') + { + // uart_sendlinek("Input path is absolute_path: %s\n", path); + strcpy(absolute_path, path); + } + else + { + // uart_sendlinek("Input path is relative_path: %s\n", path); + strcpy(absolute_path, curr_working_dir); + if (strcmp(curr_working_dir, "/") != 0) + { + strcat(absolute_path, "/"); + } + strcat(absolute_path, path); + } + // uart_sendlinek("absolute_path: %s\n", absolute_path); + // uart_sendlinek("strlen of bsolute_path: %d\n", strlen(absolute_path)); + + int dir_namesize = 0; + for (int i = 0; i < strlen(absolute_path); i++) + { + dir_namesize++; + if (absolute_path[i + 1] == '/' || i + 1 == strlen(absolute_path)) + { + ctmp[deep].size = dir_namesize; + ctmp[deep].dir = &absolute_path[i + 1 - dir_namesize]; + dir_namesize = 0; + // deep ++; + // uart_sendlinek("ctmp[%d].dir : %s\n", deep, ctmp[deep].dir); + // uart_sendlinek("size : %d\n", ctmp[deep].size); + + if (!strncmp(ctmp[deep].dir, "/..", 3)) + { + // uart_sendlinek("Go back!!\n"); + deep > 0 ? deep-- : deep; + } + else if (!strncmp(ctmp[deep].dir, "/.", 2) || ctmp[deep].size <= 1) + { + // uart_sendlinek("Do Nothing!!\n"); + } + else + { + deep++; + } + } + } + + // uart_sendlinek("deep : %d\n", deep); + int n = 0; + char *cpath = &path[n]; + if (deep == 0) + { + // memset(path,0,MAX_PATH_NAME + 1); + strncpy(cpath, "/\0", 2); + kfree(ctmp); + // uart_sendlinek("absolute_path: %s\n", path); + return path; + } + + for (int i = 0; i < deep; i++) + { + strncpy(cpath, ctmp[i].dir, ctmp[i].size); + n += ctmp[i].size; + cpath = &path[n]; + strncpy(cpath, "\0", 1); + } + + // uart_sendlinek("absolute_path: %s\n", path); + kfree(ctmp); + return path; +} + +void vfs_dump(struct vnode *_vnode, int level) +{ + // uart_sendlinek("In vfs_dump\n"); + displaylayer(level); + if (_vnode->mount != 0) + { + // tmpfs_dump(_vnode->internal, level); + _vnode->v_ops->dump(_vnode, level); + while (_vnode->mount) + { + displaylayer(level); + uart_sendlinek(" !!mount!!\n"); + _vnode = _vnode->mount->root; + } + vfs_dump(_vnode, level); + } + else + { + // tmpfs_dump(_vnode->internal, level); + _vnode->v_ops->dump(_vnode, level); + } +} + +void vfs_ls() +{ + struct vnode *node; + uart_sendlinek("In directory : %s\n", curr_thread->curr_working_dir); + if (vfs_lookup(curr_thread->curr_working_dir, &node) == 0) + { + //uart_sendlinek("find!!\n"); + node->v_ops->ls(node); + } +} + +void vfs_cd(char *filepath) +{ + uart_sendlinek("Before change directory : %s\n", curr_thread->curr_working_dir); + + char abs_path[MAX_PATH_NAME]; + strcpy(abs_path, filepath); + get_absolute_path(abs_path, curr_thread->curr_working_dir); + // uart_sendlinek("abs_path : %s\n",abs_path); + strcpy(curr_thread->curr_working_dir, abs_path); + + uart_sendlinek("In directory : %s\n", curr_thread->curr_working_dir); +} + +void displaylayer(int level) +{ + for (int i = 0; i < level; i++) + { + uart_sendlinek(" "); + } +} \ No newline at end of file diff --git a/lab8/kernel/src/vfs_dev_framebuffer.c b/lab8/kernel/src/vfs_dev_framebuffer.c new file mode 100644 index 000000000..44cd9833a --- /dev/null +++ b/lab8/kernel/src/vfs_dev_framebuffer.c @@ -0,0 +1,133 @@ +#include "vfs.h" +#include "vfs_dev_framebuffer.h" +#include "uart1.h" +#include "memory.h" +#include "stdio.h" +#include "mbox.h" +#include "string.h" +#include "exception.h" +#include "debug.h" + +// #define MBOX_CH_PROP 8 + +// //The following code is for mailbox initialize used in lab7. +unsigned int width, height, pitch, isrgb; /* dimensions and channel order */ +unsigned char *lfb; /* raw frame buffer address */ + +struct file_operations dev_framebuffer_operations = { + dev_framebuffer_write, (void *)dev_framebuffer_op_deny, dev_framebuffer_open, + dev_framebuffer_close, dev_framebuffer_lseek64, (void *)dev_framebuffer_op_deny}; + +// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface +int init_dev_framebuffer() +{ + // The following code is for mailbox initialize used in lab7. + pt[0] = 35 * 4; + pt[1] = MBOX_TAG_REQUEST_CODE; + + pt[2] = 0x48003; // set phy wh + pt[3] = 8; + pt[4] = 8; + pt[5] = 1024; // FrameBufferInfo.width + pt[6] = 768; // FrameBufferInfo.height + + pt[7] = 0x48004; // set virt wh + pt[8] = 8; + pt[9] = 8; + pt[10] = 1024; // FrameBufferInfo.virtual_width + pt[11] = 768; // FrameBufferInfo.virtual_height + + pt[12] = 0x48009; // set virt offset + pt[13] = 8; + pt[14] = 8; + pt[15] = 0; // FrameBufferInfo.x_offset + pt[16] = 0; // FrameBufferInfo.y.offset + + pt[17] = 0x48005; // set depth + pt[18] = 4; + pt[19] = 4; + pt[20] = 32; // FrameBufferInfo.depth + + pt[21] = 0x48006; // set pixel order + pt[22] = 4; + pt[23] = 4; + pt[24] = 1; // RGB, not BGR preferably + + pt[25] = 0x40001; // get framebuffer, gets alignment on request + pt[26] = 8; + pt[27] = 8; + pt[28] = 4096; // FrameBufferInfo.pointer + pt[29] = 0; // FrameBufferInfo.size + + pt[30] = 0x40008; // get pitch + pt[31] = 4; + pt[32] = 4; + pt[33] = 0; // FrameBufferInfo.pitch + + pt[34] = MBOX_TAG_LAST_BYTE; + + // this might not return exactly what we asked for, could be + // the closest supported resolution instead + if (mbox_call(MBOX_TAGS_ARM_TO_VC, (unsigned int)((unsigned long)&pt)) && pt[20] == 32 && pt[28] != 0) + { + pt[28] &= 0x3FFFFFFF; // convert GPU address to ARM address + width = pt[5]; // get actual physical width + height = pt[6]; // get actual physical height + pitch = pt[33]; // get number of bytes per line + isrgb = pt[24]; // get the actual channel order + lfb = (void *)PHYS_TO_KERNEL_VIRT(((unsigned long)pt[28])); // raw frame buffer address + } + else + { + ERROR("Unable to set screen resolution to 1024x768x32\n"); + } + + return register_dev(&dev_framebuffer_operations); +} + +int dev_framebuffer_write(struct file *file, const void *buf, size_t len) +{ + lock(); + // uart_sendlinek + if (len + file->f_pos > pitch * height) + { + ERROR("How come? dev_framebuffer_write to no where!\r\n"); + len = pitch * height - file->f_pos; + } + memcpy(lfb + file->f_pos, buf, len); + file->f_pos += len; + unlock(); + return len; +} + +int dev_framebuffer_open(struct vnode *file_node, struct file **target) +{ + (*target)->f_pos = 0; + (*target)->vnode = file_node; + (*target)->f_ops = &dev_framebuffer_operations; + return 0; +} + +int dev_framebuffer_close(struct file *file) +{ + kfree(file); + return 0; +} + +long dev_framebuffer_lseek64(struct file *file, long offset, int whence) +{ + lock(); + if (whence == SEEK_SET) + { + file->f_pos = offset; + unlock(); + return file->f_pos; + } + unlock(); + return -1; +} + +int dev_framebuffer_op_deny() +{ + return -1; +} diff --git a/lab8/kernel/src/vfs_dev_uart.c b/lab8/kernel/src/vfs_dev_uart.c new file mode 100644 index 000000000..d1f1bb590 --- /dev/null +++ b/lab8/kernel/src/vfs_dev_uart.c @@ -0,0 +1,55 @@ +#include "vfs.h" +#include "vfs_dev_uart.h" +#include "uart1.h" +#include "memory.h" +#include "string.h" + +struct file_operations dev_file_operations = { + dev_uart_write, dev_uart_read, dev_uart_open, dev_uart_close, + (void *)dev_uart_op_deny, (void *)dev_uart_op_deny}; + +int init_dev_uart() +{ + return register_dev(&dev_file_operations); +} + +int dev_uart_write(struct file *file, const void *buf, size_t len) +{ + char *cbuf = buf; + int i = len; + while (i--) + { + uart_async_send(*(cbuf++)); + } + return len; +} + +int dev_uart_read(struct file *file, void *buf, size_t len) +{ + char *cbuf = buf; + int i = len; + while (i--) + { + *cbuf = uart_async_recv(); + cbuf++; + } + return len; +} + +int dev_uart_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_ops = &dev_file_operations; + return 0; +} + +int dev_uart_close(struct file *file) +{ + kfree(file); + return 0; +} + +int dev_uart_op_deny() +{ + return -1; +} diff --git a/lab8/kernel/src/vfs_fat32.c b/lab8/kernel/src/vfs_fat32.c new file mode 100644 index 000000000..9adeb7b4f --- /dev/null +++ b/lab8/kernel/src/vfs_fat32.c @@ -0,0 +1,242 @@ +#include "vfs_fat32.h" +#include "sdhost.h" +#include "memory.h" +#include "string.h" +#include "u_list.h" +#include +#include "uart1.h" +#include "exception.h" + +struct list_head mounts; // Store all new mountpoints that probably need to be sync'd + +static inline unsigned int get_first_cluster(struct sfn_file *entry) +{ + return (entry->first_cluster_high << 16) | entry->first_cluster_low; +} + +struct vnode_operations fat32_v_ops = { + fat32_lookup, fat32_create, fat32_mkdir, + fat32_isdir, fat32_getname, fat32_getsize, + fat32_ls, fat32_dump}; + +struct file_operations fat32_f_ops = { + fat32_write, + fat32_read, + fat32_open, + fat32_close, + fat32_lseek64, +}; + +int register_fat32() +{ + struct filesystem fs; + fs.name = "fat32"; + fs.setup_mount = fat32_mount; + fs.sync = fat32_sync; + return register_filesystem(&fs); +} + +int fat32_mount(struct filesystem *fs, struct mount *mount) +{ + struct partition_t *partition; + struct fat32_inode *data; + struct vnode *node; + unsigned int lba; + unsigned char buf[BLOCK_SIZE]; + + // Read partition table from MBR, which is at first block + readblock(0, buf); + // MBR format + // 000 ~ 1BD: Code area + // 1BE ~ 1FD: Master Partition Table + // 1FE ~ 1FF: Boot Record Signature + + // https://lexra.pixnet.net/blog/post/303910876 + partition = (struct partition_t *)&buf[0x1be]; + // check Boot Record Signature, constants + if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) + { + return -1; + } + // https://en.wikipedia.org/wiki/Partition_type + if (partition[0].type != 0xb && partition[0].type != 0xc) // check Partition type, only FAT32 + { + return -1; + } + lba = partition[0].lba; + readblock(partition[0].lba, buf); + + data = kmalloc(sizeof(struct fat32_inode)); + data->boot_sector = kmalloc(sizeof(struct boot_sector_t)); + memcpy((void *)data->boot_sector, (void *)buf, sizeof(struct boot_sector_t)); + + // oldnode should attach mount the fs + mount->root = kmalloc(sizeof(struct vnode)); + node = mount->root; + node->mount = 0; + node->v_ops = &fat32_v_ops; + node->f_ops = &fat32_f_ops; + node->internal = data; + + struct boot_sector_t *bs = data->boot_sector; + // int file_block = lba + bs->hidden_sector_cnt + bs->reserved_sector_cnt + bs->fat_cnt * bs->sector_per_fat32; + int file_block = bs->hidden_sector_cnt + bs->reserved_sector_cnt + bs->fat_cnt * bs->sector_per_fat32; + + uart_sendlinek("bs->hidden_sector_cnt: 0x%x\n", bs->hidden_sector_cnt); + uart_sendlinek("bs->reserved_sector_cnt: 0x%x\n", bs->reserved_sector_cnt); + uart_sendlinek("bs->fat_cnt: 0x%x\n", bs->fat_cnt); + uart_sendlinek("bs->sector_per_fat32: 0x%x\n", bs->sector_per_fat32); + uart_sendlinek("file_block: 0x%x\n", file_block); + + readblock(file_block, buf); + + // char *n = buf; + struct sfn_file *file_ptr = buf; + + int high_block; + int low_block; + int block; + unsigned long file_size; + struct fat32_inode *tmp; + for (int i = 0; i < 16; i++) + { + high_block = file_ptr->first_cluster_high; + low_block = file_ptr->first_cluster_low; + // block = file_block + high_block * 256 + low_block - 2; + block = get_first_cluster(file_ptr) + file_block + 2; + file_size = file_ptr->file_size; + if (!file_size) + break; + uart_sendlinek("name : %s\n", file_ptr->name); + uart_sendlinek("high_block: %d\n", high_block); + uart_sendlinek("low_block: %d\n", low_block); + uart_sendlinek("file_size: 0x%x\n", file_size); + + data->entry[i] = kmalloc(sizeof(struct vnode)); + data->entry[i]->f_ops = &fat32_f_ops; + data->entry[i]->v_ops = &fat32_v_ops; + data->entry[i]->internal = kmalloc(sizeof(struct fat32_inode)); + tmp = (struct fat32_inode *)(data->entry[i]->internal); + memcpy(tmp->Name, file_ptr->name, 16); + tmp->sfn = file_ptr; + tmp->datasize = ALIGN_UP(file_size, BLOCK_SIZE); + tmp->data = kmalloc(tmp->datasize); + for (int j = 0; j < tmp->datasize / BLOCK_SIZE; j++) + { + readblock(block + j, tmp->data + j * BLOCK_SIZE); + } + uart_sendlinek("%s\n", *((char *)tmp->data)); + file_ptr++; + } + + for (int i = 0; i < 16; i++) + { + if (data->entry[i] != 0) + { + uart_sendlinek("%d\n", i); + uart_sendlinek("%s\n", ((struct fat32_inode *)data->entry[i]->internal)->Name); + } + } + + return 0; +} + +int fat32_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct fat32_inode *dir_inode = dir_node->internal; + int child_idx = 0; + for (; child_idx < 16; child_idx++) + { + struct vnode *vnode = dir_inode->entry[child_idx]; + if (!vnode) + break; + struct fat32_inode *inode = vnode->internal; + if (strcasecmp(component_name, inode->name) == 0) + { + *target = vnode; + return 0; + } + } + return -1; +} + +int fat32_create(struct vnode *dir_node, struct vnode **target, const char *component_name) { + +}; +int fat32_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) { + +}; +int fat32_isdir(struct vnode *dir_node) { + +}; +int fat32_getname(struct vnode *dir_node, const char **name) { + +}; +int fat32_getsize(struct vnode *dir_node) { + +}; +int fat32_write(struct file *file, const void *buf, size_t len) { + +}; +int fat32_read(struct file *file, void *buf, size_t len) +{ + struct fat32_inode *inode = file->vnode->internal; + // overflow, shrink size + if (len + file->f_pos > inode->datasize) + { + memcpy(buf, inode->data + file->f_pos, inode->datasize - file->f_pos); + file->f_pos += inode->datasize - file->f_pos; + return inode->datasize - file->f_pos; + } + else + { + memcpy(buf, inode->data + file->f_pos, len); + file->f_pos += len; + return len; + } + return -1; +}; +int fat32_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_ops = file_node->f_ops; + (*target)->f_pos = 0; + return 0; +}; +int fat32_close(struct file *file) +{ + kfree(file); + return 0; +}; +long fat32_lseek64(struct file *file, long offset, int whence) { + +}; +int fat32_sync(struct filesystem *fs) { + +}; + +int fat32_op_deny() +{ + return -1; +} + +void fat32_dump(struct vnode *vnode, int level) +{ +} + +void fat32_ls(struct vnode *vnode) +{ + // uart_sendlinek("in fat32_ls\n"); + struct fat32_inode *inode = (struct fat32_inode *)vnode->internal; + int child_idx = 0; + for (; child_idx <= 16; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + vnode = inode->entry[child_idx]; + uart_sendlinek("%s\n", ((struct fat32_inode *)vnode->internal)->Name); + // uart_sendlinek("0x%x\n", ((struct fat32_inode *)vnode->internal)->datasize); + } +} \ No newline at end of file diff --git a/lab8/kernel/src/vfs_initramfs.c b/lab8/kernel/src/vfs_initramfs.c new file mode 100644 index 000000000..11ea52eb2 --- /dev/null +++ b/lab8/kernel/src/vfs_initramfs.c @@ -0,0 +1,206 @@ +#include "vfs_initramfs.h" +#include "vfs.h" +#include "string.h" +#include "memory.h" +#include "cpio.h" +#include "uart1.h" +#include "debug.h" + +struct file_operations initramfs_file_operations = { + initramfs_write, initramfs_read, initramfs_open, + initramfs_close, initramfs_lseek64, initramfs_getsize}; + +struct vnode_operations initramfs_vnode_operations = { + initramfs_lookup, initramfs_create, initramfs_mkdir, + (void *)initramfs_op_deny,(void *)initramfs_op_deny,(void *)initramfs_op_deny, + initramfs_ls, initramfs_dump}; + +int register_initramfs() +{ + struct filesystem fs; + fs.name = "initramfs"; + fs.setup_mount = initramfs_setup_mount; + fs.sync = initramfs_sync; + return register_filesystem(&fs); +} + +int initramfs_setup_mount(struct filesystem *fs, struct mount *_mount) +{ + _mount->fs = fs; + _mount->root = initramfs_create_vnode(0, dir_t); + // create entry under _mount, cpio files should be attached on it + struct initramfs_inode *ramdir_inode = _mount->root->internal; + + // add all file in initramfs to filesystem + char *filepath; + char *filedata; + unsigned int filesize; + // struct cpio_newc_header *header_pointer = CPIO_DEFAULT_START; + int idx = 0; + + CPIO_for_each(&filepath, &filesize, &filedata) + { + struct vnode *filevnode = initramfs_create_vnode(0, file_t); + struct initramfs_inode *fileinode = filevnode->internal; + fileinode->data = filedata; + fileinode->datasize = filesize; + fileinode->name = filepath; + // uart_sendlinek("file name: %s\n",filepath); + ramdir_inode->entry[idx++] = filevnode; + } + + return 0; +} + +struct vnode *initramfs_create_vnode(struct mount *_mount, enum fsnode_type type) +{ + struct vnode *v = kmalloc(sizeof(struct vnode)); + v->f_ops = &initramfs_file_operations; + v->v_ops = &initramfs_vnode_operations; + v->mount = _mount; + struct initramfs_inode *inode = kmalloc(sizeof(struct initramfs_inode)); + memset(inode, 0, sizeof(struct initramfs_inode)); + inode->type = type; + inode->data = kmalloc(0x1000); + v->internal = inode; + return v; +} + +// file operations +int initramfs_write(struct file *file, const void *buf, size_t len) +{ + // read-only + return -1; +} + +int initramfs_read(struct file *file, void *buf, size_t len) +{ + struct initramfs_inode *inode = file->vnode->internal; + // overflow, shrink size + if (len + file->f_pos > inode->datasize) + { + memcpy(buf, inode->data + file->f_pos, inode->datasize - file->f_pos); + file->f_pos += inode->datasize - file->f_pos; + return inode->datasize - file->f_pos; + } + else + { + memcpy(buf, inode->data + file->f_pos, len); + file->f_pos += len; + return len; + } + return -1; +} + +int initramfs_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_ops = file_node->f_ops; + (*target)->f_pos = 0; + return 0; +} + +int initramfs_close(struct file *file) +{ + kfree(file); + return 0; +} + +long initramfs_lseek64(struct file *file, long offset, int whence) +{ + if (whence == SEEK_SET) + { + file->f_pos = offset; + return file->f_pos; + } + return -1; +} + +// vnode operations +int initramfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct initramfs_inode *dir_inode = dir_node->internal; + int child_idx = 0; + for (; child_idx < INITRAMFS_MAX_DIR_ENTRY; child_idx++) + { + struct vnode *vnode = dir_inode->entry[child_idx]; + if (!vnode) + break; + struct initramfs_inode *inode = vnode->internal; + if (strcmp(component_name, inode->name) == 0) + { + *target = vnode; + return 0; + } + } + return -1; +} + +int initramfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + // read-only + return -1; +} + +int initramfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + // read-only + return -1; +} + +long initramfs_getsize(struct vnode *vd) +{ + struct initramfs_inode *inode = vd->internal; + return inode->datasize; +} + +void initramfs_dump(struct vnode *vnode, int level) +{ + struct initramfs_inode *inode = (struct initramfs_inode *)vnode->internal; + int child_idx = 0; + + uart_sendlinek("+----------------+\n"); + + for (; child_idx <= INITRAMFS_MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + // uart_sendlinek("0x%x\n",inode->entry[child_idx]); + displaylayer(level+1); + vnode = inode->entry[child_idx]; + uart_sendlinek("%s\n", ((struct initramfs_inode *)vnode->internal)->name); + + // displaylayer(level+2); + // uart_sendlinek("datasize size : %d\n", ((struct initramfs_inode *)vnode->internal)->datasize); + displaylayer(level+2); + uart_sendlinek("datasize size : %d\n", initramfs_getsize(vnode)); + } + displaylayer(level); + uart_sendlinek("+----------------+\n"); +} + +void initramfs_ls(struct vnode *vnode) +{ + struct initramfs_inode *inode = (struct initramfs_inode *)vnode->internal; + int child_idx = 0; + for (; child_idx <= INITRAMFS_MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + vnode = inode->entry[child_idx]; + uart_sendlinek("%s\n", ((struct initramfs_inode *)vnode->internal)->name); + } +} + +int initramfs_op_deny(){ + return -1; +} + +int initramfs_sync(struct filesystem *fs) +{ + return 0; +} \ No newline at end of file diff --git a/lab8/kernel/src/vfs_tmpfs.c b/lab8/kernel/src/vfs_tmpfs.c new file mode 100644 index 000000000..0c3c601ae --- /dev/null +++ b/lab8/kernel/src/vfs_tmpfs.c @@ -0,0 +1,270 @@ +#include "vfs_tmpfs.h" +#include "vfs.h" +#include "string.h" +#include "memory.h" +#include "uart1.h" + +struct file_operations tmpfs_file_operations = { + tmpfs_write, tmpfs_read, tmpfs_open, + tmpfs_close, tmpfs_lseek64, tmpfs_getsize}; + +struct vnode_operations tmpfs_vnode_operations = { + tmpfs_lookup, tmpfs_create, tmpfs_mkdir, + (void *)tmpfs_op_deny,(void *)tmpfs_op_deny,(void *)tmpfs_op_deny, + tmpfs_ls, tmpfs_dump}; + +int register_tmpfs() +{ + struct filesystem fs; + fs.name = "tmpfs"; + fs.setup_mount = tmpfs_setup_mount; + fs.sync = tmpfs_sync; + return register_filesystem(&fs); +} + +int tmpfs_setup_mount(struct filesystem *fs, struct mount *_mount) +{ + _mount->fs = fs; + _mount->root = tmpfs_create_vnode(0, dir_t); + return 0; +} + +struct vnode *tmpfs_create_vnode(struct mount *_mount, enum fsnode_type type) +{ + struct vnode *v = kmalloc(sizeof(struct vnode)); + v->f_ops = &tmpfs_file_operations; + v->v_ops = &tmpfs_vnode_operations; + v->mount = 0; + struct tmpfs_inode *inode = kmalloc(sizeof(struct tmpfs_inode)); + memset(inode, 0, sizeof(struct tmpfs_inode)); + inode->type = type; + inode->data = kmalloc(0x1000); + v->internal = inode; + return v; +} + +// vnode operations +int tmpfs_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct tmpfs_inode *dir_inode = dir_node->internal; + int child_idx = 0; + // BFS search tree + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + struct vnode *vnode = dir_inode->entry[child_idx]; + if (!vnode) + break; + struct tmpfs_inode *inode = vnode->internal; + if (strcmp(component_name, inode->name) == 0) + { + *target = vnode; + return 0; + } + } + return -1; +} + +// dir ops +int tmpfs_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct tmpfs_inode *inode = dir_node->internal; + + if (inode->type != dir_t) + { + uart_sendlinek("tmpfs mkdir not dir_t\r\n"); + return -1; + } + + int child_idx = 0; + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + } + + if (child_idx > MAX_DIR_ENTRY) + { + uart_sendlinek("DIR ENTRY FULL\r\n"); + return -1; + } + + if (strlen(component_name) > MAX_FILE_NAME) + { + uart_sendlinek("FILE NAME TOO LONG\r\n"); + return -1; + } + + struct vnode *_vnode = tmpfs_create_vnode(0, dir_t); + inode->entry[child_idx] = _vnode; + + struct tmpfs_inode *newinode = _vnode->internal; + strcpy(newinode->name, component_name); + + *target = _vnode; + return 0; +} + +// file operations +int tmpfs_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_ops = file_node->f_ops; + (*target)->f_pos = 0; + return 0; +} + +// file operations +int tmpfs_write(struct file *file, const void *buf, size_t len) +{ + struct tmpfs_inode *inode = file->vnode->internal; + // write from f_pos + memcpy(inode->data + file->f_pos, buf, len); + // update f_pos and size + file->f_pos += len; + if (inode->datasize < file->f_pos) + inode->datasize = file->f_pos; + return len; +} + +int tmpfs_read(struct file *file, void *buf, size_t len) +{ + struct tmpfs_inode *inode = file->vnode->internal; + // if buffer overflow, shrink the request read length + // read from f_pos + if (len + file->f_pos > inode->datasize) + { + len = inode->datasize - file->f_pos; + memcpy(buf, inode->data + file->f_pos, len); + file->f_pos += inode->datasize - file->f_pos; + return len; + } + else + { + memcpy(buf, inode->data + file->f_pos, len); + file->f_pos += len; + return len; + } + return -1; +} + +int tmpfs_close(struct file *file) +{ + kfree(file); + return 0; +} + +long tmpfs_lseek64(struct file *file, long offset, int whence) +{ + if (whence == SEEK_SET) + { + file->f_pos = offset; + return file->f_pos; + } + return -1; +} + +// file ops +int tmpfs_create(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct tmpfs_inode *inode = dir_node->internal; + if (inode->type != dir_t) + { + uart_sendlinek("tmpfs create not dir_t\r\n"); + return -1; + } + + int child_idx = 0; + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + break; + struct tmpfs_inode *child_inode = inode->entry[child_idx]->internal; + if (strcmp(child_inode->name, component_name) == 0) + { + uart_sendlinek("tmpfs create file exists\r\n"); + return -1; + } + } + + if (child_idx > MAX_DIR_ENTRY) + { + uart_sendlinek("DIR ENTRY FULL\r\n"); + return -1; + } + + if (strlen(component_name) > MAX_FILE_NAME) + { + uart_sendlinek("FILE NAME TOO LONG\r\n"); + return -1; + } + + struct vnode *_vnode = tmpfs_create_vnode(0, file_t); + inode->entry[child_idx] = _vnode; + + struct tmpfs_inode *newinode = _vnode->internal; + strcpy(newinode->name, component_name); + + *target = _vnode; + return 0; +} + +long tmpfs_getsize(struct vnode *vd) +{ + struct tmpfs_inode *inode = vd->internal; + return inode->datasize; +} + +void tmpfs_dump(struct vnode *vnode, int level) +{ + struct tmpfs_inode *inode = (struct tmpfs_inode *)vnode->internal; + + uart_sendlinek("+-%s", inode->name); + switch (inode->type) + { + case dir_t: + uart_sendlinek("(dir)\n"); + break; + case file_t: + uart_sendlinek("(file)\n"); + break; + + default: + break; + } + int child_idx = 0; + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + vfs_dump(inode->entry[child_idx], level + 1); + } +} + +void tmpfs_ls(struct vnode *vnode) +{ + struct tmpfs_inode *inode = (struct tmpfs_inode *)vnode->internal; + int child_idx = 0; + for (; child_idx <= MAX_DIR_ENTRY; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + vnode = inode->entry[child_idx]; + uart_sendlinek("%s\n", ((struct tmpfs_inode *)vnode->internal)->name); + } +} + +int tmpfs_op_deny() +{ + return -1; +} + +int tmpfs_sync(struct filesystem *fs) +{ + return 0; +} diff --git a/lab8/send_img_to_bootloader.py b/lab8/send_img_to_bootloader.py new file mode 100644 index 000000000..29d43b781 --- /dev/null +++ b/lab8/send_img_to_bootloader.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 + +from serial import Serial +from pwn import * +import argparse +from sys import platform + +if platform == "linux" or platform == "linux2": + parser = argparse.ArgumentParser(description='NYCU OSDI kernel sender') + parser.add_argument('--filename', metavar='PATH', default='kernel8.img', type=str, help='path to kernel8.img') + parser.add_argument('--device', metavar='TTY',default='/dev/ttyUSB0', type=str, help='path to UART device') + parser.add_argument('--baud', metavar='Hz',default=115200, type=int, help='baud rate') + args = parser.parse_args() + + with open(args.filename,'rb') as fd: + with Serial(args.device, args.baud) as ser: + + kernel_raw = fd.read() + length = len(kernel_raw) + + print("Kernel image size : ", hex(length)) + for i in range(8): + ser.write(p64(length)[i:i+1]) + ser.flush() + + print("Start sending kernel image by uart1...") + for i in range(length): + # Use kernel_raw[i: i+1] is byte type. Instead of using kernel_raw[i] it will retrieve int type then cause error + ser.write(kernel_raw[i: i+1]) + ser.flush() + if i % 100 == 0: + print("{:>6}/{:>6} bytes".format(i, length)) + print("{:>6}/{:>6} bytes".format(length, length)) + print("Transfer finished!") + +else: + parser = argparse.ArgumentParser(description='NYCU OSDI kernel sender') + parser.add_argument('--filename', metavar='PATH', default='kernel8.img', type=str, help='path to kernel8.img') + parser.add_argument('--device', metavar='COM',default='COM3', type=str, help='COM# to UART device') + parser.add_argument('--baud', metavar='Hz',default=115200, type=int, help='baud rate') + args = parser.parse_args() + + with open(args.filename,'rb') as fd: + with Serial(args.device, args.baud) as ser: + + kernel_raw = fd.read() + length = len(kernel_raw) + + print("Kernel image size : ", hex(length)) + for i in range(8): + ser.write(p64(length)[i:i+1]) + ser.flush() + + print("Start sending kernel image by uart1...") + for i in range(length): + # Use kernel_raw[i: i+1] is byte type. Instead of using kernel_raw[i] it will retrieve int type then cause error + ser.write(kernel_raw[i: i+1]) + ser.flush() + if i % 100 == 0: + print("{:>6}/{:>6} bytes".format(i, length)) + print("{:>6}/{:>6} bytes".format(length, length)) + print("Transfer finished!") \ No newline at end of file diff --git a/vfs_fat32.c b/vfs_fat32.c new file mode 100644 index 000000000..2d30979a4 --- /dev/null +++ b/vfs_fat32.c @@ -0,0 +1,1689 @@ +#include "vfs_fat32.h" +#include "sdhost.h" +#include "memory.h" +#include "string.h" +#include "u_list.h" +#include +#include "uart1.h" +#include "exception.h" + +struct list_head mounts; // Store all new mountpoints that probably need to be sync'd + +struct vnode_operations fat32_v_ops = { + fat32_lookup, fat32_create, fat32_mkdir, + fat32_isdir, fat32_getname, fat32_getsize, + fat32_ls, fat32_dump}; + +struct file_operations fat32_f_ops = { + fat32_write, + fat32_read, + fat32_open, + fat32_close, + fat32_lseek64, +}; + +int register_fat32() +{ + struct filesystem fs; + fs.name = "fat32"; + fs.setup_mount = fat32_mount; + fs.sync = fat32_sync; + return register_filesystem(&fs); +} + +int fat32_mount(struct filesystem *fs, struct mount *mount) +{ + struct partition_t *partition; + struct fat_info_t *fat; + struct fat_dir_t *dir; + struct fat32_inode *data; + struct vnode *oldnode, *node; + struct fat_mount_t *newmount; + unsigned int lba; + unsigned char buf[BLOCK_SIZE]; + + // Read partition table from MBR, which is at first block + readblock(0, buf); + // MBR format + // 000 ~ 1BD: Code area + // 1BE ~ 1FD: Master Partition Table + // 1FE ~ 1FF: Boot Record Signature + + // https://lexra.pixnet.net/blog/post/303910876 + partition = (struct partition_t *)&buf[0x1be]; + // check Boot Record Signature, constants + if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) + { + return -1; + } + // https://en.wikipedia.org/wiki/Partition_type + if (partition[0].type != 0xb && partition[0].type != 0xc) // check Partition type, only FAT32 + { + return -1; + } + lba = partition[0].lba; + // uart_sendlinek("lba: 0x%x\n", lba); + + readblock(partition[0].lba, buf); + + node = kmalloc(sizeof(struct vnode)); + data = kmalloc(sizeof(struct fat32_inode)); + fat = kmalloc(sizeof(struct fat_info_t)); + dir = kmalloc(sizeof(struct fat_dir_t)); + newmount = kmalloc(sizeof(struct fat_mount_t)); + + memcpy((void *)&fat->bs, (void *)buf, sizeof(fat->bs)); + + // According to FAT fs design, FAT Region is after reserved sectors + // https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system + + fat->fat_lba = lba + fat->bs.reserved_sector_cnt; + fat->cluster_lba = fat->fat_lba + fat->bs.fat_cnt * fat->bs.sector_per_fat32; + // uart_sendlinek("fat->cluster_lba: 0x%x\n", fat->cluster_lba); + + INIT_LIST_HEAD(&dir->list); + + // oldnode should attach mount the fs + mount->root = kmalloc(sizeof(struct vnode)); + oldnode = mount->root; + oldnode->mount = 0; + oldnode->v_ops = &fat32_v_ops; + oldnode->f_ops = &fat32_f_ops; + oldnode->internal = data; + + data->boot_sector = kmalloc(sizeof(struct boot_sector_t)); + memcpy((void *)data->boot_sector, (void *)buf, sizeof(struct boot_sector_t)); + + struct boot_sector_t *bs = data->boot_sector; + int file_block = bs->hidden_sector_cnt + bs->reserved_sector_cnt + bs->fat_cnt * bs->sector_per_fat32; + + uart_sendlinek("bs->hidden_sector_cnt: 0x%x\n", bs->hidden_sector_cnt); + uart_sendlinek("bs->reserved_sector_cnt: 0x%x\n", bs->reserved_sector_cnt); + uart_sendlinek("bs->fat_cnt: 0x%x\n", bs->fat_cnt); + uart_sendlinek("bs->sector_per_fat32: 0x%x\n", bs->sector_per_fat32); + uart_sendlinek("file_block: 0x%x\n", file_block); + + readblock(fat->cluster_lba, buf); + + // char *n = buf; + struct sfn_file *file_ptr = buf; + + int high_block; + int low_block; + int block; + unsigned long file_size; + struct fat32_inode *tmp; + for (int i = 0; i < 16; i++) + { + high_block = file_ptr->first_cluster_high; + low_block = file_ptr->first_cluster_low; + block = fat->cluster_lba + high_block * 256 + low_block - 2; + file_size = file_ptr->file_size; + if (!file_size) + break; + uart_sendlinek("name : %s\n", file_ptr->name); + uart_sendlinek("high_block: %d\n", high_block); + uart_sendlinek("low_block: %d\n", low_block); + uart_sendlinek("file_size: 0x%x\n", file_size); + + data->entry[i] = kmalloc(sizeof(struct vnode)); + data->entry[i]->f_ops = &fat32_f_ops; + data->entry[i]->v_ops = &fat32_v_ops; + oldnode->internal = kmalloc(sizeof(struct fat32_inode)); + tmp = (struct fat32_inode *)oldnode->internal; + memcpy(tmp->Name, file_ptr->name, 11); + tmp->sfn = file_ptr; + tmp->datasize = ALIGN_UP(file_size, BLOCK_SIZE); + tmp->data = kmalloc(tmp->datasize); + for (int j = 0; j < tmp->datasize / BLOCK_SIZE; j++) + { + readblock(block + j, tmp->data + j * BLOCK_SIZE); + } + + file_ptr++; + } + + // oldnode = mount->root; + // uart_sendlinek("mount->root: 0x%x",oldnode); + + // node->mount = oldnode->mount; + // node->v_ops = oldnode->v_ops; + // node->f_ops = oldnode->f_ops; + // node->parent = oldnode->parent; + // node->internal = oldnode->internal; + + // data->node = node; + // data->fat = fat; + // data->cid = 2; // In FAT32, Root Directory Table starts from cluster #2 + // data->type = FAT_DIR; + // data->dir = dir; + + // oldnode->mount = mount; + // oldnode->v_ops = &fat32_v_ops; + // oldnode->f_ops = &fat32_f_ops; + // oldnode->internal = data; + + lock(); + list_add(&newmount->list, &mounts); + unlock(); + newmount->mount = mount; + + return 0; +} + +int fat32_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + // if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) + // return -1; + // if (!_lookup_cache(dir_node, target, component_name)) + // return 0; + // return _lookup_fat32(dir_node, target, component_name); + struct fat32_inode *dir_inode = dir_node->internal; + int child_idx = 0; + for (; child_idx < 16; child_idx++) + { + struct vnode *vnode = dir_inode->entry[child_idx]; + if (!vnode) + break; + struct fat32_inode *inode = vnode->internal; + if (strcasecmp(component_name, inode->name) == 0) + { + *target = vnode; + return 0; + } + } + return -1; +} + +// ======================================================================================== + +// struct vnode_operations fat32_v_ops = { +// fat32_lookup, fat32_create, fat32_mkdir, +// fat32_isdir, fat32_getname, fat32_getsize, +// fat32_ls,fat32_dump}; + +// struct file_operations fat32_f_ops = { +// fat32_write, +// fat32_read, +// fat32_open, +// fat32_close, +// fat32_lseek64, +// }; + +// int register_fat32() +// { +// struct filesystem fs; +// fs.name = "fat32"; +// fs.setup_mount = fat32_mount; +// fs.sync = fat32_sync; +// INIT_LIST_HEAD(&mounts); +// return register_filesystem(&fs); +// } + +// /* filesystem methods */ +// int fat32_mount(struct filesystem *fs, struct mount *mount) +// { +// struct partition_t *partition; +// struct fat_info_t *fat; +// struct fat_dir_t *dir; +// struct fat32_inode *data; +// struct vnode *oldnode, *node; +// struct fat_mount_t *newmount; +// unsigned int lba; +// unsigned char buf[BLOCK_SIZE]; + +// // Read partition table from MBR, which is at first block +// readblock(0, buf); +// // MBR format +// // 000 ~ 1BD: Code area +// // 1BE ~ 1FD: Master Partition Table +// // 1FE ~ 1FF: Boot Record Signature + +// // https://lexra.pixnet.net/blog/post/303910876 +// partition = (struct partition_t *)&buf[0x1be]; +// // check Boot Record Signature, constants +// if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) +// { +// return -1; +// } +// // https://en.wikipedia.org/wiki/Partition_type +// if (partition[0].type != 0xb && partition[0].type != 0xc) // check Partition type, only FAT32 +// { +// return -1; +// } +// lba = partition[0].lba; +// readblock(partition[0].lba, buf); + +// node = kmalloc(sizeof(struct vnode)); +// data = kmalloc(sizeof(struct fat32_inode)); +// fat = kmalloc(sizeof(struct fat_info_t)); +// dir = kmalloc(sizeof(struct fat_dir_t)); +// newmount = kmalloc(sizeof(struct fat_mount_t)); + +// memcpy((void *)&fat->bs, (void *)buf, sizeof(fat->bs)); + +// // According to FAT fs design, FAT Region is after reserved sectors +// // https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system +// fat->fat_lba = lba + fat->bs.reserved_sector_cnt; +// fat->cluster_lba = fat->fat_lba + fat->bs.fat_cnt * fat->bs.sector_per_fat32; + +// INIT_LIST_HEAD(&dir->list); + +// // oldnode should attach mount the fs +// mount->root = kmalloc(sizeof(struct vnode)); +// oldnode = mount->root; +// oldnode->mount = 0; +// oldnode->v_ops = &fat32_v_ops; +// oldnode->f_ops = &fat32_f_ops; +// oldnode->internal = data; + +// data->node = oldnode; +// data->fat = fat; +// data->cid = 2; // In FAT32, Root Directory Table starts from cluster #2 +// data->type = FAT_DIR; +// data->dir = dir; + +// // oldnode = mount->root; +// // uart_sendlinek("mount->root: 0x%x",oldnode); + +// // node->mount = oldnode->mount; +// // node->v_ops = oldnode->v_ops; +// // node->f_ops = oldnode->f_ops; +// // node->parent = oldnode->parent; +// // node->internal = oldnode->internal; + +// // data->node = node; +// // data->fat = fat; +// // data->cid = 2; // In FAT32, Root Directory Table starts from cluster #2 +// // data->type = FAT_DIR; +// // data->dir = dir; + +// // oldnode->mount = mount; +// // oldnode->v_ops = &fat32_v_ops; +// // oldnode->f_ops = &fat32_f_ops; +// // oldnode->internal = data; + +// lock(); +// list_add(&newmount->list, &mounts); +// unlock(); +// newmount->mount = mount; + +// return 0; +// } + +// int fat32_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) +// { +// if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) +// return -1; +// if (!_lookup_cache(dir_node, target, component_name)) +// return 0; +// return _lookup_fat32(dir_node, target, component_name); +// } + +int fat32_create(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) + return -1; + if (!fat32_lookup(dir_node, target, component_name)) + return -1; + *target = _create_vnode(dir_node, component_name, FAT_FILE, -1, 0); + return 0; +} + +int fat32_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) + return -1; + if (!fat32_lookup(dir_node, target, component_name)) + return -1; + *target = _create_vnode(dir_node, component_name, FAT_DIR, -1, 0); + return 0; +} + +int fat32_isdir(struct vnode *dir_node) +{ + return (((struct fat32_inode *)dir_node->internal)->type == FAT_DIR) ? 1 : 0; +} + +int fat32_getname(struct vnode *dir_node, const char **name) +{ + *name = ((struct fat32_inode *)dir_node->internal)->name; + return 0; +} + +int fat32_getsize(struct vnode *dir_node) +{ + if (((struct fat32_inode *)dir_node->internal)->type == FAT_DIR) + return 0; + return ((struct fat32_inode *)dir_node->internal)->file->size; +} + +/* file_operations methods */ +int fat32_write(struct file *file, const void *buf, size_t len) +{ + struct fat32_inode *data; + int filesize; + int ret; + + if (fat32_isdir(file->vnode)) + return -1; + if (!len) + return len; + + filesize = fat32_getsize(file->vnode); + data = file->vnode->internal; + + ret = _writefile(buf, data, file->f_pos, len); + if (ret <= 0) + { + return ret; + } + + file->f_pos += ret; + if (file->f_pos > filesize) + { + data->file->size = file->f_pos; + } + + return ret; +} + +int fat32_read(struct file *file, void *buf, size_t len) +{ + struct fat32_inode *data; + int filesize; + int ret; + + if (fat32_isdir(file->vnode)) + return -1; + + filesize = fat32_getsize(file->vnode); + data = file->vnode->internal; + + if (file->f_pos + len > filesize) + { + len = filesize - file->f_pos; + } + if (!len) + return len; + + ret = _readfile(buf, data, file->f_pos, len); + if (ret <= 0) + return ret; + + file->f_pos += ret; + return ret; +} + +int fat32_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_pos = 0; + (*target)->f_ops = file_node->f_ops; + return 0; +} + +int fat32_close(struct file *file) +{ + file->vnode = NULL; + file->f_pos = 0; + file->f_ops = NULL; + return 0; +} + +long fat32_lseek64(struct file *file, long offset, int whence) +{ + int filesize; + int base; + + if (!fat32_isdir(file->vnode)) + return -1; + + filesize = fat32_getsize(file->vnode); + + if (filesize < 0) + return -1; + + switch (whence) + { + case SEEK_SET: + base = 0; + break; + case SEEK_CUR: + base = file->f_pos; + break; + case SEEK_END: + base = filesize; + break; + default: + return -1; + } + + if (base + offset > filesize) + { + return -1; + } + file->f_pos = base + offset; + + return 0; +} + +int fat32_sync(struct filesystem *fs) +{ + struct fat_mount_t *entry; + + list_for_each_entry(entry, &mounts, list) + { + _sync_dir(entry->mount->root); + } + + return 0; +} + +// ------------------------------------------------------------------------ +// Utils +// + +unsigned int get_next_cluster(unsigned int fat_lba, unsigned int cluster_id) +{ + struct cluster_entry_t *ce; + unsigned int idx; + unsigned char buf[BLOCK_SIZE]; + + if (cluster_id >= INVALID_CID) + { + return cluster_id; + } + + // Get fat allocation table and its cluster entry in Data region + fat_lba += cluster_id / CLUSTER_ENTRY_PER_BLOCK; + idx = cluster_id % CLUSTER_ENTRY_PER_BLOCK; + + readblock(fat_lba, buf); + ce = &(((struct cluster_entry_t *)buf)[idx]); + + return ce->val; +} + +unsigned int alloc_cluster(struct fat_info_t *fat, unsigned int prev_cid) +{ + struct cluster_entry_t *ce; + unsigned int fat_lba; + unsigned int cid; + int found; + unsigned char buf[BLOCK_SIZE]; + + fat_lba = fat->fat_lba; + cid = 0; + // find unused cluster by clusters -> fats + while (fat_lba < fat->cluster_lba) + { + found = 0; + readblock(fat_lba, buf); + + for (int i = 0; i < CLUSTER_ENTRY_PER_BLOCK; ++i) + { + ce = &(((struct cluster_entry_t *)buf)[i]); + + if (!ce->val) + { + found = 1; + break; + } + + ++cid; + } + + if (found) + { + break; + } + fat_lba += 1; + } + // Only called if prev_cid is larger than 0xfffffff8, realloc ce; + if (found && prev_cid) + { + unsigned int target_lba; + unsigned int target_idx; + + target_lba = fat_lba + prev_cid / CLUSTER_ENTRY_PER_BLOCK; + target_idx = prev_cid % CLUSTER_ENTRY_PER_BLOCK; + readblock(target_lba, buf); + ce = &(((struct cluster_entry_t *)buf)[target_idx]); + ce->val = cid; + writeblock(target_lba, buf); + } + + if (!found) + { + uart_sendlinek("fat32 alloc_cluster: No space!"); + return -1; + } + + return cid; +} + +/* vnode_operations methods */ +struct vnode *_create_vnode(struct vnode *parent, const char *name, unsigned int type, unsigned int cid, unsigned int size) +{ + struct vnode *node; + struct fat32_inode *info, *data; + char *buf; + int len; + + info = parent->internal; + len = strlen(name); + + buf = kmalloc(len + 1); + node = kmalloc(sizeof(struct vnode)); + data = kmalloc(sizeof(struct fat32_inode)); + + strcpy(buf, name); + + data->name = buf; + data->node = node; + data->fat = info->fat; + data->cid = cid; + data->type = type; + + if (type == FAT_DIR) + { + struct fat_dir_t *dir; + dir = kmalloc(sizeof(struct fat_dir_t)); + INIT_LIST_HEAD(&dir->list); + data->dir = dir; + } + else + { + struct fat_file_t *file; + file = kmalloc(sizeof(struct fat_file_t)); + INIT_LIST_HEAD(&file->list); + file->size = size; + data->file = file; + } + + node->mount = parent->mount; + node->v_ops = &fat32_v_ops; + node->f_ops = &fat32_f_ops; + node->parent = parent; + node->internal = data; + + // attach to parent's dir_t or file_t list + list_add(&data->list, &info->dir->list); + + return node; +} + +int _lookup_cache(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct fat32_inode *data, *entry; + struct fat_dir_t *dir; + int found; + + data = dir_node->internal; + dir = data->dir; + found = 0; + + list_for_each_entry(entry, &dir->list, list) + { + if (!strcasecmp(component_name, entry->name)) + { // same as strcmp, but tr [:lower:] + found = 1; + break; + } + } + if (!found) + { + return -1; + } + *target = entry->node; + return 0; +} + +struct dir_t *__lookup_fat32(struct vnode *dir_node, const char *component_name, unsigned char *buf, int *buflba) +{ + struct dir_t *dir; + struct fat32_inode *data; + struct fat_info_t *fat; + struct filename_t name; + unsigned int cid; + int found, dirend, lfn; + + data = dir_node->internal; + fat = data->fat; + cid = data->cid; + + found = 0; + dirend = 0; + + memset(&name, 0, sizeof(struct filename_t)); + + while (1) + { + int lba; + + lba = fat->cluster_lba + (cid - 2) * fat->bs.sector_per_cluster; // cluster start from #2 + readblock(lba, buf); + + // only called by sync, to update buffer + if (buflba) + { + *buflba = lba; + } + + for (int i = 0; i < DIR_PER_BLOCK; ++i) + { + unsigned char len; + dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * i]); + + if (dir->name[0] == 0) + { + dirend = 1; + break; + } + + if ((dir->attr & ATTR_LFN) == ATTR_LFN) + { + struct long_dir_t *ldir; + int n; + + lfn = 1; + + ldir = (struct long_dir_t *)dir; + n = (dir->name[0] & 0x3f) - 1; // every lfn entry has 16 bytes + // update filename_t if it is LFN + for (int i = 0; ldir->name1[i] != 0xff && i < 10; i += 2) + { + name.part[n].name[i / 2] = ldir->name1[i]; // LDIR_Name1 1th ~ 5th + } + for (int i = 0; ldir->name2[i] != 0xff && i < 12; i += 2) + { + name.part[n].name[5 + i / 2] = ldir->name2[i]; // LDIR_Name2 6th ~ 11th + } + for (int i = 0; ldir->name3[i] != 0xff && i < 4; i += 2) + { + name.part[n].name[11 + i / 2] = ldir->name3[i]; // LDIR_Name3 12th ~ 13th + } + + continue; + } + + if (lfn == 1) + { + if (!strcasecmp(component_name, (void *)name.fullname)) + { + found = 1; + break; + } + + lfn = 0; + memset(&name, 0, sizeof(struct filename_t)); + continue; + } + + lfn = 0; + len = 8; + + // SFN lookup + while (len) + { + if (dir->name[len - 1] != 0x20) + { + break; + } + len -= 1; + } + + memcpy((void *)name.fullname, (void *)dir->name, len); + name.fullname[len] = 0; + + len = 3; + + while (len) + { + if (dir->name[8 + len - 1] != 0x20) + { + break; + } + len -= 1; + } + + if (len >= 0) + { + strcat((void *)name.fullname, "."); + strncat((void *)name.fullname, (void *)&dir->name[8], len); + } + + if (!strcasecmp(component_name, (void *)name.fullname)) + { + found = 1; + break; + } + + memset(&name, 0, sizeof(struct filename_t)); + } + + if (found) + { + break; + } + + if (dirend) + { + break; + } + + // try next cluster and lookup again + cid = get_next_cluster(fat->fat_lba, cid); + + if (cid >= INVALID_CID) + { + break; + } + } + + if (!found) + { + return NULL; + } + + return dir; +} + +int _lookup_fat32(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct vnode *node; + struct dir_t *dir; + unsigned int type, cid; + unsigned char buf[BLOCK_SIZE]; + + dir = __lookup_fat32(dir_node, component_name, buf, NULL); + + if (!dir) + { + return -1; + } + + if (!(dir->attr & ATTR_FILE_DIR_MASK)) + { + return -1; + } + + cid = (dir->ch << 16) | dir->cl; // upper part of cluster id + lower part of cluster id + + if (dir->attr & ATTR_ARCHIVE) + { + type = FAT_FILE; + } + else + { + type = FAT_DIR; + } + + node = _create_vnode(dir_node, component_name, type, cid, dir->size); + + *target = node; + + return 0; +} + +int _writefile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block) +{ + struct fat_file_block_t *entry; + struct list_head *head; + + head = &data->file->list; + + if (list_empty(head)) + { + return -1; + } + + list_for_each_entry(entry, head, list) + { + *block = entry; + if (foid == entry->oid) + { // offset match + return 0; + } + } + + return -1; +} + +int _writefile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block) +{ + struct fat_info_t *info; + unsigned int curoid, curcid; + + info = data->fat; + + // block is from cache + if (*block) + { + curoid = (*block)->oid; + curcid = (*block)->cid; + + if (curoid == foid) + { // offset match + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + } + else + { + curoid = 0; + curcid = fcid; + } + + // create new block in cache + while (1) + { + struct fat_file_block_t *newblock; + + newblock = kmalloc(sizeof(struct fat_file_block_t)); + + newblock->oid = curoid; + newblock->cid = curcid; + newblock->bufIsUpdated = 0; + newblock->isDirty = 1; + + list_add_tail(&newblock->list, &data->file->list); + + *block = newblock; + + if (curoid == foid) + { + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + } +} + +int _writefile_cache(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block) +{ + int wsize; + + // if cache block is not updated yet, read from sdcard + if (!block->bufIsUpdated) + { + // read the data from sdcard + struct fat_info_t *info; + int lba; + + info = data->fat; + lba = info->cluster_lba + (block->cid - 2) * info->bs.sector_per_cluster; + + readblock(lba, block->buf); + + block->bufIsUpdated = 1; + } + + wsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + memcpy((void *)&block->buf[bckoff], (void *)&buf[bufoff], wsize); + + return wsize; +} + +int _writefile_fat32(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid) +{ + struct list_head *head; + struct fat_info_t *info; + struct fat_file_block_t *block; + int lba; + int wsize; + + head = &data->file->list; + info = data->fat; + + block = kmalloc(sizeof(struct fat_file_block_t)); + + wsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + // read the address from sdcard and write it + if (cid >= INVALID_CID) + { + memset(block->buf, 0, BLOCK_SIZE); + } + else + { + lba = info->cluster_lba + (cid - 2) * info->bs.sector_per_cluster; + + readblock(lba, block->buf); + } + + memcpy((void *)&block->buf[bckoff], (void *)&buf[bufoff], wsize); + + block->oid = oid; + block->cid = cid; + block->bufIsUpdated = 1; + block->isDirty = 1; // wait for sync + + list_add_tail(&block->list, head); + + return wsize; +} + +int _writefile(const void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len) +{ + struct fat_file_block_t *block; + struct list_head *head; + unsigned int foid; // first block id + unsigned int coid; // current block id + unsigned int cid; // target cluster id + unsigned long long bufoff, result; + int ret; + + block = NULL; + head = &data->file->list; + foid = fileoff / BLOCK_SIZE; + coid = 0; + cid = data->cid; + bufoff = 0; + result = 0; + + // Seek, find the particular offset + ret = _writefile_seek_cache(data, foid, &block); + + if (ret < 0) + { + ret = _writefile_seek_fat32(data, foid, cid, &block); + } + + if (ret < 0) + { + return 0; + } + + // Write + while (len) + { + unsigned long long bckoff; + + bckoff = (fileoff + result) % BLOCK_SIZE; + + if (&block->list != head) + { + // cache has the blocks to be written + ret = _writefile_cache(data, bckoff, buf, bufoff, len, block); + cid = block->cid; + block = list_first_entry(&block->list, struct fat_file_block_t, list); + } + else + { + // Read block from sdcard, create cache, then write it + cid = get_next_cluster(data->fat->fat_lba, cid); + ret = _writefile_fat32(data, bckoff, buf, bufoff, len, coid, cid); + } + + if (ret < 0) + { + break; + } + + bufoff += ret; + result += ret; + coid += 1; + len -= ret; + } + + return result; +} + +int _readfile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block) +{ + struct fat_file_block_t *entry; + struct list_head *head; + + // check the cache list + head = &data->file->list; + + // if cache is none, return not found + if (list_empty(head)) + { + return -1; + } + + // find that offset in cache + list_for_each_entry(entry, head, list) + { + *block = entry; + if (foid == entry->oid) + { + return 0; + } + } + + return -1; +} + +int _readfile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block) +{ + struct fat_info_t *info; + unsigned int curoid, curcid; + + info = data->fat; + + // if block found in cache, change to that offset in fat32 + if (*block) + { + curoid = (*block)->oid; + curcid = (*block)->cid; + + if (curoid == foid) + { + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + + if (curcid >= INVALID_CID) + { + return -1; + } + } + else + { + curoid = 0; + curcid = fcid; + } + + while (1) + { + // add new offset block to cache + struct fat_file_block_t *newblock; + + newblock = kmalloc(sizeof(struct fat_file_block_t)); + + newblock->oid = curoid; + newblock->cid = curcid; + newblock->bufIsUpdated = 0; + newblock->isDirty = 0; + + list_add_tail(&newblock->list, &data->file->list); + + *block = newblock; + + if (curoid == foid) + { + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + + if (curcid >= INVALID_CID) + { + return -1; + } + } +} + +int _readfile_cache(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block) +{ + int rsize; + + if (!block->bufIsUpdated) + { + // read the data from sdcard + struct fat_info_t *info; + int lba; + + info = data->fat; + lba = info->cluster_lba + (block->cid - 2) * info->bs.sector_per_cluster; + readblock(lba, block->buf); + + block->bufIsUpdated = 1; + } + + // if the size is overflow, resize it + rsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + + memcpy((void *)&buf[bufoff], (void *)&block->buf[bckoff], rsize); + + return rsize; +} + +int _readfile_fat32(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid) +{ + struct list_head *head; + struct fat_info_t *info; + struct fat_file_block_t *block; + int lba; + int rsize; + + head = &data->file->list; + info = data->fat; + + block = kmalloc(sizeof(struct fat_file_block_t)); + + rsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + lba = info->cluster_lba + (cid - 2) * info->bs.sector_per_cluster; + + // read from fat32 + readblock(lba, block->buf); + + memcpy((void *)&buf[bufoff], (void *)&block->buf[bckoff], rsize); + + block->oid = oid; + block->cid = cid; + block->bufIsUpdated = 1; + + list_add_tail(&block->list, head); + + return rsize; +} + +int _readfile(void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len) +{ + struct fat_file_block_t *block; + struct list_head *head; + unsigned int foid; // first block id + unsigned int coid; // current block id + unsigned int cid; // target cluster id + unsigned long long bufoff, result; + int ret; + + block = NULL; + head = &data->file->list; + foid = fileoff / BLOCK_SIZE; + coid = 0; + cid = data->cid; + bufoff = 0; + result = 0; + + // Seek, find the particular offset + ret = _readfile_seek_cache(data, foid, &block); + if (ret < 0) + { + ret = _readfile_seek_fat32(data, foid, cid, &block); + } + + if (ret < 0) + { + return 0; + } + + // Read + while (len) + { + unsigned long long bckoff; + + bckoff = (fileoff + result) % BLOCK_SIZE; + + if (&block->list != head) + { + // cache found + ret = _readfile_cache(data, bckoff, buf, bufoff, len, block); + + cid = block->cid; + block = list_first_entry(&block->list, struct fat_file_block_t, list); + } + else + { + // Read block from sdcard, create cache + cid = get_next_cluster(data->fat->fat_lba, cid); + + if (cid >= INVALID_CID) + { + break; + } + + ret = _readfile_fat32(data, bckoff, buf, bufoff, len, coid, cid); + } + + if (ret < 0) + { + break; + } + + bufoff += ret; + result += ret; + coid += 1; + len -= ret; + } + + return result; +} + +void _do_sync_dir(struct vnode *dirnode) +{ + struct fat32_inode *data, *entry; + struct list_head *head; + struct dir_t *dir; + struct long_dir_t *ldir; + unsigned int cid; + int lba, idx, lfnidx; + unsigned char buf[BLOCK_SIZE]; + + data = dirnode->internal; + head = &data->dir->list; + cid = data->cid; + idx = 0; + lfnidx = 1; + + if (cid >= INVALID_CID) + { + uart_sendlinek("fat32 _do_sync_dir: invalid dirnode->data->cid"); + } + + // get the buf from dirnode's offset + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + readblock(lba, buf); + + list_for_each_entry(entry, head, list) + { + struct dir_t *origindir; + const char *name; + const char *ext; + int lfn, namelen, extpos, i, buflba; + unsigned char lookupbuf[BLOCK_SIZE]; + + name = entry->name; + + // If entry is a old file, update its size + origindir = __lookup_fat32(dirnode, name, lookupbuf, &buflba); + + if (origindir) + { + if (entry->type == FAT_FILE) + { + origindir->size = entry->file->size; + writeblock(buflba, lookupbuf); + } + continue; + } + + // Else if entry is a new file + ext = NULL; + extpos = -1; + + do + { + + namelen = strlen(name); + if (namelen >= 13) + { + lfn = 1; + break; + } + for (i = 0; i < namelen; ++i) + { + // get idx of extension name + if (name[namelen - 1 - i] == '.') + { + break; + } + } + if (i < namelen) + { + ext = &name[namelen - i]; + extpos = namelen - 1 - i; + } + if (i >= 4) + { + lfn = 1; + break; + } + if (namelen - 1 - i > 8) + { + // SFN: 8.3 + lfn = 1; + break; + } + + lfn = 0; + } while (0); + + // Seek idx to the end of dir + while (1) + { + dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * idx]); + + if (dir->name[0] == 0) + { + break; + } + + idx += 1; + + if (idx >= 16) + { // if idx is over Directory Entry, create a new one + unsigned int newcid; + + writeblock(lba, buf); + + newcid = get_next_cluster(data->fat->fat_lba, cid); + if (newcid >= INVALID_CID) + { + newcid = alloc_cluster(data->fat, cid); + } + + cid = newcid; + + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + + readblock(lba, buf); + idx = 0; + } + } + + // Write LFN + if (lfn) + { + int ord; + int first; + + ord = ((namelen - 1) / 13) + 1; + first = 0x40; // LAST_LONG_ENTRY flag in LFN LDIR_Ord + + for (; ord > 0; --ord) + { + int end; + ldir = (struct long_dir_t *)(&buf[sizeof(struct long_dir_t) * idx]); + + ldir->order = first | ord; + ldir->attr = ATTR_LFN; + ldir->type = 0; + // TODO: Calculate checksum, SFN + LFN + ldir->checksum = 0; + ldir->fstcluslo = 0; + + first = 0; + end = 0; + + for (i = 0; i < 10; i += 2) + { + if (end) + { // padding 0xff if filename end + ldir->name1[i] = 0xff; + ldir->name1[i + 1] = 0xff; + } + else + { + ldir->name1[i] = name[(ord - 1) * 13 + i / 2]; + ldir->name1[i + 1] = 0; + if (ldir->name1[i] == 0) + { + end = 1; + } + } + } + for (i = 0; i < 12; i += 2) + { + if (end) + { + ldir->name2[i] = 0xff; + ldir->name2[i + 1] = 0xff; + } + else + { + ldir->name2[i] = name[(ord - 1) * 13 + 5 + i / 2]; + ldir->name2[i + 1] = 0; + if (ldir->name2[i] == 0) + { + end = 1; + } + } + } + for (i = 0; i < 4; i += 2) + { + if (end) + { + ldir->name3[i] = 0xff; + ldir->name3[i + 1] = 0xff; + } + else + { + ldir->name3[i] = name[(ord - 1) * 13 + 11 + i / 2]; + ldir->name3[i + 1] = 0; + if (ldir->name3[i] == 0) + { + end = 1; + } + } + } + + idx += 1; + + if (idx >= 16) + { + unsigned int newcid; + + writeblock(lba, buf); + + newcid = get_next_cluster(data->fat->fat_lba, cid); + if (newcid >= INVALID_CID) + { + newcid = alloc_cluster(data->fat, cid); + } + + cid = newcid; + + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + readblock(lba, buf); + + idx = 0; + } + } + } + + // Write SFN + dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * idx]); + + // TODO: Set these properties properly + dir->ntres = 0; + dir->crttimetenth = 0; + dir->crttime = 0; + dir->crtdate = 0; + dir->lstaccdate = 0; + dir->wrttime = 0; + dir->wrtdate = 0; + + if (entry->type == FAT_DIR) + { + dir->attr = ATTR_DIRECTORY; + dir->size = 0; + } + else + { + dir->attr = ATTR_ARCHIVE; + dir->size = entry->file->size; + } + + if (entry->cid >= INVALID_CID) + { + entry->cid = alloc_cluster(data->fat, 0); + } + + dir->ch = (entry->cid >> 16) & 0xffff; + dir->cl = entry->cid & 0xffff; + + if (lfn) + { + int lfni; + + // Creating SFN body + // TODO: handle lfnidx + for (i = 7, lfni = lfnidx; i >= 0 && lfni;) + { + dir->name[i--] = '0' + lfni % 10; + lfni /= 10; + } + + lfnidx++; + // numeric-tail: ~n (1 <= n <= 6) + dir->name[i--] = '~'; + + // TODO: handle letter case + memcpy((void *)dir->name, name, i + 1); + } + else + { + // TODO: handle letter case + for (i = 0; i != extpos && name[i]; ++i) + { + dir->name[i] = name[i]; + } + + for (; i < 8; ++i) + { + dir->name[i] = ' '; // in SFN, each part is padded with space + } + } + + // SFN format: 8.3 + // TODO: handle letter case + for (i = 0; i < 3 && ext[i]; ++i) + { + dir->name[8 + i] = ext[i]; + } + + for (; i < 3; ++i) + { + dir->name[8 + i] = ' '; + } + + idx += 1; + + if (idx >= 16) + { + int newcid; + + writeblock(lba, buf); + + newcid = get_next_cluster(data->fat->fat_lba, cid); + if (newcid >= INVALID_CID) + { + newcid = alloc_cluster(data->fat, cid); + } + + cid = newcid; + + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + + // TODO: Cache data block of directory + readblock(lba, buf); + + idx = 0; + } + } + + if (idx) + { + writeblock(lba, buf); + } +} + +void _do_sync_file(struct vnode *filenode) +{ + struct fat_file_block_t *entry; + struct fat32_inode *data; + struct list_head *head; + unsigned int cid; + + data = filenode->internal; + head = &data->file->list; + cid = data->cid; + + if (cid >= INVALID_CID) + { + // uart_sendlinek("fat32 _do_sync_file: invalid cid"); + return; + } + + list_for_each_entry(entry, head, list) + { + int lba; + + if (entry->oid == 0) + { + // cache is valid but not sync'd, just an informational warning + if (!(entry->cid >= INVALID_CID) && data->cid != entry->cid) + { + uart_sendlinek("_do_sync_file: cid isn't sync"); + } + + entry->cid = data->cid; + } + + if (entry->cid >= INVALID_CID) + { + entry->cid = alloc_cluster(data->fat, cid); + } + + // if the file is sync'd, pass + if (!entry->isDirty) + { + continue; + } + + // cache buf is not updated, initialize it to avoid error + if (!entry->bufIsUpdated) + { + memset(entry->buf, 0, BLOCK_SIZE); + entry->bufIsUpdated = 1; + } + + // sync to fat32 fs + lba = data->fat->cluster_lba + (entry->cid - 2) * data->fat->bs.sector_per_cluster; + writeblock(lba, entry->buf); + + entry->isDirty = 0; + + cid = entry->cid; + } +} + +void _sync_dir(struct vnode *dirnode) +{ + struct fat32_inode *data, *entry; + struct list_head *head; + + // Init: dirnode is mounted fs + data = dirnode->internal; + head = &data->dir->list; + + _do_sync_dir(dirnode); + + list_for_each_entry(entry, head, list) + { + if (entry->type == FAT_DIR) + { + _sync_dir(entry->node); // recursive to next dirnode + } + else + { + _do_sync_file(entry->node); + } + } +} + +int fat32_op_deny() +{ + return -1; +} + +void fat32_dump(struct vnode *vnode, int level) +{ +} + +void fat32_ls(struct vnode *vnode) +{ + uart_sendlinek("in fat32_ls\n"); + struct fat32_inode *inode = (struct fat32_inode *)vnode->internal; + int child_idx = 0; + for (; child_idx <= 16; child_idx++) + { + if (!inode->entry[child_idx]) + { + // break; + } + vnode = inode->entry[child_idx]; + uart_sendlinek("%s\n", ((struct fat32_inode *)vnode->internal)->name); + } +} \ No newline at end of file From 78da35b36f55336d25105aea39317c778226d958 Mon Sep 17 00:00:00 2001 From: SianGx0102 Date: Mon, 24 Jun 2024 16:36:57 +0800 Subject: [PATCH 4/5] EX --- lab8/kernel/src/vfs_fat32.c | 1519 ++++++++++++++++++++++++++++++++--- lab8/tmp_file/vfs_fat32.c | 242 ++++++ 2 files changed, 1632 insertions(+), 129 deletions(-) create mode 100644 lab8/tmp_file/vfs_fat32.c diff --git a/lab8/kernel/src/vfs_fat32.c b/lab8/kernel/src/vfs_fat32.c index 9adeb7b4f..62488b8bc 100644 --- a/lab8/kernel/src/vfs_fat32.c +++ b/lab8/kernel/src/vfs_fat32.c @@ -9,15 +9,12 @@ struct list_head mounts; // Store all new mountpoints that probably need to be sync'd -static inline unsigned int get_first_cluster(struct sfn_file *entry) -{ - return (entry->first_cluster_high << 16) | entry->first_cluster_low; -} +// ======================================================================================== struct vnode_operations fat32_v_ops = { fat32_lookup, fat32_create, fat32_mkdir, fat32_isdir, fat32_getname, fat32_getsize, - fat32_ls, fat32_dump}; + fat32_ls,fat32_dump}; struct file_operations fat32_f_ops = { fat32_write, @@ -33,14 +30,19 @@ int register_fat32() fs.name = "fat32"; fs.setup_mount = fat32_mount; fs.sync = fat32_sync; + INIT_LIST_HEAD(&mounts); return register_filesystem(&fs); } +/* filesystem methods */ int fat32_mount(struct filesystem *fs, struct mount *mount) { struct partition_t *partition; + struct fat_info_t *fat; + struct fat_dir_t *dir; struct fat32_inode *data; - struct vnode *node; + struct vnode *oldnode, *node; + struct fat_mount_t *newmount; unsigned int lba; unsigned char buf[BLOCK_SIZE]; @@ -66,177 +68,1436 @@ int fat32_mount(struct filesystem *fs, struct mount *mount) lba = partition[0].lba; readblock(partition[0].lba, buf); + node = kmalloc(sizeof(struct vnode)); data = kmalloc(sizeof(struct fat32_inode)); - data->boot_sector = kmalloc(sizeof(struct boot_sector_t)); - memcpy((void *)data->boot_sector, (void *)buf, sizeof(struct boot_sector_t)); + fat = kmalloc(sizeof(struct fat_info_t)); + dir = kmalloc(sizeof(struct fat_dir_t)); + newmount = kmalloc(sizeof(struct fat_mount_t)); + + memcpy((void *)&fat->bs, (void *)buf, sizeof(fat->bs)); + + // According to FAT fs design, FAT Region is after reserved sectors + // https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system + fat->fat_lba = lba + fat->bs.reserved_sector_cnt; + fat->cluster_lba = fat->fat_lba + fat->bs.fat_cnt * fat->bs.sector_per_fat32; + + INIT_LIST_HEAD(&dir->list); // oldnode should attach mount the fs mount->root = kmalloc(sizeof(struct vnode)); - node = mount->root; - node->mount = 0; - node->v_ops = &fat32_v_ops; - node->f_ops = &fat32_f_ops; - node->internal = data; + oldnode = mount->root; + oldnode->mount = 0; + oldnode->v_ops = &fat32_v_ops; + oldnode->f_ops = &fat32_f_ops; + oldnode->internal = data; - struct boot_sector_t *bs = data->boot_sector; - // int file_block = lba + bs->hidden_sector_cnt + bs->reserved_sector_cnt + bs->fat_cnt * bs->sector_per_fat32; - int file_block = bs->hidden_sector_cnt + bs->reserved_sector_cnt + bs->fat_cnt * bs->sector_per_fat32; - - uart_sendlinek("bs->hidden_sector_cnt: 0x%x\n", bs->hidden_sector_cnt); - uart_sendlinek("bs->reserved_sector_cnt: 0x%x\n", bs->reserved_sector_cnt); - uart_sendlinek("bs->fat_cnt: 0x%x\n", bs->fat_cnt); - uart_sendlinek("bs->sector_per_fat32: 0x%x\n", bs->sector_per_fat32); - uart_sendlinek("file_block: 0x%x\n", file_block); - - readblock(file_block, buf); - - // char *n = buf; - struct sfn_file *file_ptr = buf; - - int high_block; - int low_block; - int block; - unsigned long file_size; - struct fat32_inode *tmp; - for (int i = 0; i < 16; i++) - { - high_block = file_ptr->first_cluster_high; - low_block = file_ptr->first_cluster_low; - // block = file_block + high_block * 256 + low_block - 2; - block = get_first_cluster(file_ptr) + file_block + 2; - file_size = file_ptr->file_size; - if (!file_size) - break; - uart_sendlinek("name : %s\n", file_ptr->name); - uart_sendlinek("high_block: %d\n", high_block); - uart_sendlinek("low_block: %d\n", low_block); - uart_sendlinek("file_size: 0x%x\n", file_size); + data->node = oldnode; + data->fat = fat; + data->cid = 2; // In FAT32, Root Directory Table starts from cluster #2 + data->type = FAT_DIR; + data->dir = dir; - data->entry[i] = kmalloc(sizeof(struct vnode)); - data->entry[i]->f_ops = &fat32_f_ops; - data->entry[i]->v_ops = &fat32_v_ops; - data->entry[i]->internal = kmalloc(sizeof(struct fat32_inode)); - tmp = (struct fat32_inode *)(data->entry[i]->internal); - memcpy(tmp->Name, file_ptr->name, 16); - tmp->sfn = file_ptr; - tmp->datasize = ALIGN_UP(file_size, BLOCK_SIZE); - tmp->data = kmalloc(tmp->datasize); - for (int j = 0; j < tmp->datasize / BLOCK_SIZE; j++) - { - readblock(block + j, tmp->data + j * BLOCK_SIZE); - } - uart_sendlinek("%s\n", *((char *)tmp->data)); - file_ptr++; - } + // oldnode = mount->root; + // uart_sendlinek("mount->root: 0x%x",oldnode); - for (int i = 0; i < 16; i++) - { - if (data->entry[i] != 0) - { - uart_sendlinek("%d\n", i); - uart_sendlinek("%s\n", ((struct fat32_inode *)data->entry[i]->internal)->Name); - } - } + // node->mount = oldnode->mount; + // node->v_ops = oldnode->v_ops; + // node->f_ops = oldnode->f_ops; + // node->parent = oldnode->parent; + // node->internal = oldnode->internal; + + // data->node = node; + // data->fat = fat; + // data->cid = 2; // In FAT32, Root Directory Table starts from cluster #2 + // data->type = FAT_DIR; + // data->dir = dir; + + // oldnode->mount = mount; + // oldnode->v_ops = &fat32_v_ops; + // oldnode->f_ops = &fat32_f_ops; + // oldnode->internal = data; + + lock(); + list_add(&newmount->list, &mounts); + unlock(); + newmount->mount = mount; return 0; } int fat32_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) { - struct fat32_inode *dir_inode = dir_node->internal; - int child_idx = 0; - for (; child_idx < 16; child_idx++) - { - struct vnode *vnode = dir_inode->entry[child_idx]; - if (!vnode) - break; - struct fat32_inode *inode = vnode->internal; - if (strcasecmp(component_name, inode->name) == 0) - { - *target = vnode; - return 0; - } - } - return -1; + if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) + return -1; + if (!_lookup_cache(dir_node, target, component_name)) + return 0; + return _lookup_fat32(dir_node, target, component_name); +} + +int fat32_create(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) + return -1; + if (!fat32_lookup(dir_node, target, component_name)) + return -1; + *target = _create_vnode(dir_node, component_name, FAT_FILE, -1, 0); + return 0; } -int fat32_create(struct vnode *dir_node, struct vnode **target, const char *component_name) { +int fat32_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) + return -1; + if (!fat32_lookup(dir_node, target, component_name)) + return -1; + *target = _create_vnode(dir_node, component_name, FAT_DIR, -1, 0); + return 0; +} -}; -int fat32_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) { +int fat32_isdir(struct vnode *dir_node) +{ + return (((struct fat32_inode *)dir_node->internal)->type == FAT_DIR) ? 1 : 0; +} -}; -int fat32_isdir(struct vnode *dir_node) { +int fat32_getname(struct vnode *dir_node, const char **name) +{ + *name = ((struct fat32_inode *)dir_node->internal)->name; + return 0; +} -}; -int fat32_getname(struct vnode *dir_node, const char **name) { +int fat32_getsize(struct vnode *dir_node) +{ + if (((struct fat32_inode *)dir_node->internal)->type == FAT_DIR) + return 0; + return ((struct fat32_inode *)dir_node->internal)->file->size; +} -}; -int fat32_getsize(struct vnode *dir_node) { +/* file_operations methods */ +int fat32_write(struct file *file, const void *buf, size_t len) +{ + struct fat32_inode *data; + int filesize; + int ret; -}; -int fat32_write(struct file *file, const void *buf, size_t len) { + if (fat32_isdir(file->vnode)) + return -1; + if (!len) + return len; + + filesize = fat32_getsize(file->vnode); + data = file->vnode->internal; + + ret = _writefile(buf, data, file->f_pos, len); + if (ret <= 0) + { + return ret; + } + + file->f_pos += ret; + if (file->f_pos > filesize) + { + data->file->size = file->f_pos; + } + + return ret; +} -}; int fat32_read(struct file *file, void *buf, size_t len) { - struct fat32_inode *inode = file->vnode->internal; - // overflow, shrink size - if (len + file->f_pos > inode->datasize) + struct fat32_inode *data; + int filesize; + int ret; + + if (fat32_isdir(file->vnode)) + return -1; + + filesize = fat32_getsize(file->vnode); + data = file->vnode->internal; + + if (file->f_pos + len > filesize) { - memcpy(buf, inode->data + file->f_pos, inode->datasize - file->f_pos); - file->f_pos += inode->datasize - file->f_pos; - return inode->datasize - file->f_pos; + len = filesize - file->f_pos; } - else - { - memcpy(buf, inode->data + file->f_pos, len); - file->f_pos += len; + if (!len) return len; - } - return -1; -}; + + ret = _readfile(buf, data, file->f_pos, len); + if (ret <= 0) + return ret; + + file->f_pos += ret; + return ret; +} + int fat32_open(struct vnode *file_node, struct file **target) { (*target)->vnode = file_node; - (*target)->f_ops = file_node->f_ops; (*target)->f_pos = 0; + (*target)->f_ops = file_node->f_ops; return 0; -}; +} + int fat32_close(struct file *file) { - kfree(file); + file->vnode = NULL; + file->f_pos = 0; + file->f_ops = NULL; return 0; -}; -long fat32_lseek64(struct file *file, long offset, int whence) { +} -}; -int fat32_sync(struct filesystem *fs) { +long fat32_lseek64(struct file *file, long offset, int whence) +{ + int filesize; + int base; -}; + if (!fat32_isdir(file->vnode)) + return -1; -int fat32_op_deny() + filesize = fat32_getsize(file->vnode); + + if (filesize < 0) + return -1; + + switch (whence) + { + case SEEK_SET: + base = 0; + break; + case SEEK_CUR: + base = file->f_pos; + break; + case SEEK_END: + base = filesize; + break; + default: + return -1; + } + + if (base + offset > filesize) + { + return -1; + } + file->f_pos = base + offset; + + return 0; +} + +int fat32_sync(struct filesystem *fs) { - return -1; + struct fat_mount_t *entry; + + list_for_each_entry(entry, &mounts, list) + { + _sync_dir(entry->mount->root); + } + + return 0; } -void fat32_dump(struct vnode *vnode, int level) +// ------------------------------------------------------------------------ +// Utils +// + +unsigned int get_next_cluster(unsigned int fat_lba, unsigned int cluster_id) { + struct cluster_entry_t *ce; + unsigned int idx; + unsigned char buf[BLOCK_SIZE]; + + if (cluster_id >= INVALID_CID) + { + return cluster_id; + } + + // Get fat allocation table and its cluster entry in Data region + fat_lba += cluster_id / CLUSTER_ENTRY_PER_BLOCK; + idx = cluster_id % CLUSTER_ENTRY_PER_BLOCK; + + readblock(fat_lba, buf); + ce = &(((struct cluster_entry_t *)buf)[idx]); + + return ce->val; } -void fat32_ls(struct vnode *vnode) +unsigned int alloc_cluster(struct fat_info_t *fat, unsigned int prev_cid) { - // uart_sendlinek("in fat32_ls\n"); - struct fat32_inode *inode = (struct fat32_inode *)vnode->internal; - int child_idx = 0; - for (; child_idx <= 16; child_idx++) + struct cluster_entry_t *ce; + unsigned int fat_lba; + unsigned int cid; + int found; + unsigned char buf[BLOCK_SIZE]; + + fat_lba = fat->fat_lba; + cid = 0; + // find unused cluster by clusters -> fats + while (fat_lba < fat->cluster_lba) { - if (!inode->entry[child_idx]) + found = 0; + readblock(fat_lba, buf); + + for (int i = 0; i < CLUSTER_ENTRY_PER_BLOCK; ++i) + { + ce = &(((struct cluster_entry_t *)buf)[i]); + + if (!ce->val) + { + found = 1; + break; + } + + ++cid; + } + + if (found) + { + break; + } + fat_lba += 1; + } + // Only called if prev_cid is larger than 0xfffffff8, realloc ce; + if (found && prev_cid) + { + unsigned int target_lba; + unsigned int target_idx; + + target_lba = fat_lba + prev_cid / CLUSTER_ENTRY_PER_BLOCK; + target_idx = prev_cid % CLUSTER_ENTRY_PER_BLOCK; + readblock(target_lba, buf); + ce = &(((struct cluster_entry_t *)buf)[target_idx]); + ce->val = cid; + writeblock(target_lba, buf); + } + + if (!found) + { + uart_sendlinek("fat32 alloc_cluster: No space!"); + return -1; + } + + return cid; +} + +/* vnode_operations methods */ +struct vnode *_create_vnode(struct vnode *parent, const char *name, unsigned int type, unsigned int cid, unsigned int size) +{ + struct vnode *node; + struct fat32_inode *info, *data; + char *buf; + int len; + + info = parent->internal; + len = strlen(name); + + buf = kmalloc(len + 1); + node = kmalloc(sizeof(struct vnode)); + data = kmalloc(sizeof(struct fat32_inode)); + + strcpy(buf, name); + + data->name = buf; + data->node = node; + data->fat = info->fat; + data->cid = cid; + data->type = type; + + if (type == FAT_DIR) + { + struct fat_dir_t *dir; + dir = kmalloc(sizeof(struct fat_dir_t)); + INIT_LIST_HEAD(&dir->list); + data->dir = dir; + } + else + { + struct fat_file_t *file; + file = kmalloc(sizeof(struct fat_file_t)); + INIT_LIST_HEAD(&file->list); + file->size = size; + data->file = file; + } + + node->mount = parent->mount; + node->v_ops = &fat32_v_ops; + node->f_ops = &fat32_f_ops; + node->parent = parent; + node->internal = data; + + // attach to parent's dir_t or file_t list + list_add(&data->list, &info->dir->list); + + return node; +} + +int _lookup_cache(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct fat32_inode *data, *entry; + struct fat_dir_t *dir; + int found; + + data = dir_node->internal; + dir = data->dir; + found = 0; + + list_for_each_entry(entry, &dir->list, list) + { + if (!strcasecmp(component_name, entry->name)) + { // same as strcmp, but tr [:lower:] + found = 1; + break; + } + } + if (!found) + { + return -1; + } + *target = entry->node; + return 0; +} + +struct dir_t *__lookup_fat32(struct vnode *dir_node, const char *component_name, unsigned char *buf, int *buflba) +{ + struct dir_t *dir; + struct fat32_inode *data; + struct fat_info_t *fat; + struct filename_t name; + unsigned int cid; + int found, dirend, lfn; + + data = dir_node->internal; + fat = data->fat; + cid = data->cid; + + found = 0; + dirend = 0; + + memset(&name, 0, sizeof(struct filename_t)); + + while (1) + { + int lba; + + lba = fat->cluster_lba + (cid - 2) * fat->bs.sector_per_cluster; // cluster start from #2 + readblock(lba, buf); + + // only called by sync, to update buffer + if (buflba) + { + *buflba = lba; + } + + for (int i = 0; i < DIR_PER_BLOCK; ++i) + { + unsigned char len; + dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * i]); + + if (dir->name[0] == 0) + { + dirend = 1; + break; + } + + if ((dir->attr & ATTR_LFN) == ATTR_LFN) + { + struct long_dir_t *ldir; + int n; + + lfn = 1; + + ldir = (struct long_dir_t *)dir; + n = (dir->name[0] & 0x3f) - 1; // every lfn entry has 16 bytes + // update filename_t if it is LFN + for (int i = 0; ldir->name1[i] != 0xff && i < 10; i += 2) + { + name.part[n].name[i / 2] = ldir->name1[i]; // LDIR_Name1 1th ~ 5th + } + for (int i = 0; ldir->name2[i] != 0xff && i < 12; i += 2) + { + name.part[n].name[5 + i / 2] = ldir->name2[i]; // LDIR_Name2 6th ~ 11th + } + for (int i = 0; ldir->name3[i] != 0xff && i < 4; i += 2) + { + name.part[n].name[11 + i / 2] = ldir->name3[i]; // LDIR_Name3 12th ~ 13th + } + + continue; + } + + if (lfn == 1) + { + if (!strcasecmp(component_name, (void *)name.fullname)) + { + found = 1; + break; + } + + lfn = 0; + memset(&name, 0, sizeof(struct filename_t)); + continue; + } + + lfn = 0; + len = 8; + + // SFN lookup + while (len) + { + if (dir->name[len - 1] != 0x20) + { + break; + } + len -= 1; + } + + memcpy((void *)name.fullname, (void *)dir->name, len); + name.fullname[len] = 0; + + len = 3; + + while (len) + { + if (dir->name[8 + len - 1] != 0x20) + { + break; + } + len -= 1; + } + + if (len >= 0) + { + strcat((void *)name.fullname, "."); + strncat((void *)name.fullname, (void *)&dir->name[8], len); + } + + if (!strcasecmp(component_name, (void *)name.fullname)) + { + found = 1; + break; + } + + memset(&name, 0, sizeof(struct filename_t)); + } + + if (found) + { + break; + } + + if (dirend) { break; } + + // try next cluster and lookup again + cid = get_next_cluster(fat->fat_lba, cid); + + if (cid >= INVALID_CID) + { + break; + } + } + + if (!found) + { + return NULL; + } + + return dir; +} + +int _lookup_fat32(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct vnode *node; + struct dir_t *dir; + unsigned int type, cid; + unsigned char buf[BLOCK_SIZE]; + + dir = __lookup_fat32(dir_node, component_name, buf, NULL); + + if (!dir) + { + return -1; + } + + if (!(dir->attr & ATTR_FILE_DIR_MASK)) + { + return -1; + } + + cid = (dir->ch << 16) | dir->cl; // upper part of cluster id + lower part of cluster id + + if (dir->attr & ATTR_ARCHIVE) + { + type = FAT_FILE; + } + else + { + type = FAT_DIR; + } + + node = _create_vnode(dir_node, component_name, type, cid, dir->size); + + *target = node; + + return 0; +} + +int _writefile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block) +{ + struct fat_file_block_t *entry; + struct list_head *head; + + head = &data->file->list; + + if (list_empty(head)) + { + return -1; + } + + list_for_each_entry(entry, head, list) + { + *block = entry; + if (foid == entry->oid) + { // offset match + return 0; + } + } + + return -1; +} + +int _writefile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block) +{ + struct fat_info_t *info; + unsigned int curoid, curcid; + + info = data->fat; + + // block is from cache + if (*block) + { + curoid = (*block)->oid; + curcid = (*block)->cid; + + if (curoid == foid) + { // offset match + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + } + else + { + curoid = 0; + curcid = fcid; + } + + // create new block in cache + while (1) + { + struct fat_file_block_t *newblock; + + newblock = kmalloc(sizeof(struct fat_file_block_t)); + + newblock->oid = curoid; + newblock->cid = curcid; + newblock->bufIsUpdated = 0; + newblock->isDirty = 1; + + list_add_tail(&newblock->list, &data->file->list); + + *block = newblock; + + if (curoid == foid) + { + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + } +} + +int _writefile_cache(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block) +{ + int wsize; + + // if cache block is not updated yet, read from sdcard + if (!block->bufIsUpdated) + { + // read the data from sdcard + struct fat_info_t *info; + int lba; + + info = data->fat; + lba = info->cluster_lba + (block->cid - 2) * info->bs.sector_per_cluster; + + readblock(lba, block->buf); + + block->bufIsUpdated = 1; + } + + wsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + memcpy((void *)&block->buf[bckoff], (void *)&buf[bufoff], wsize); + + return wsize; +} + +int _writefile_fat32(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid) +{ + struct list_head *head; + struct fat_info_t *info; + struct fat_file_block_t *block; + int lba; + int wsize; + + head = &data->file->list; + info = data->fat; + + block = kmalloc(sizeof(struct fat_file_block_t)); + + wsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + // read the address from sdcard and write it + if (cid >= INVALID_CID) + { + memset(block->buf, 0, BLOCK_SIZE); + } + else + { + lba = info->cluster_lba + (cid - 2) * info->bs.sector_per_cluster; + + readblock(lba, block->buf); + } + + memcpy((void *)&block->buf[bckoff], (void *)&buf[bufoff], wsize); + + block->oid = oid; + block->cid = cid; + block->bufIsUpdated = 1; + block->isDirty = 1; // wait for sync + + list_add_tail(&block->list, head); + + return wsize; +} + +int _writefile(const void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len) +{ + struct fat_file_block_t *block; + struct list_head *head; + unsigned int foid; // first block id + unsigned int coid; // current block id + unsigned int cid; // target cluster id + unsigned long long bufoff, result; + int ret; + + block = NULL; + head = &data->file->list; + foid = fileoff / BLOCK_SIZE; + coid = 0; + cid = data->cid; + bufoff = 0; + result = 0; + + // Seek, find the particular offset + ret = _writefile_seek_cache(data, foid, &block); + + if (ret < 0) + { + ret = _writefile_seek_fat32(data, foid, cid, &block); + } + + if (ret < 0) + { + return 0; + } + + // Write + while (len) + { + unsigned long long bckoff; + + bckoff = (fileoff + result) % BLOCK_SIZE; + + if (&block->list != head) + { + // cache has the blocks to be written + ret = _writefile_cache(data, bckoff, buf, bufoff, len, block); + cid = block->cid; + block = list_first_entry(&block->list, struct fat_file_block_t, list); + } + else + { + // Read block from sdcard, create cache, then write it + cid = get_next_cluster(data->fat->fat_lba, cid); + ret = _writefile_fat32(data, bckoff, buf, bufoff, len, coid, cid); + } + + if (ret < 0) + { + break; + } + + bufoff += ret; + result += ret; + coid += 1; + len -= ret; + } + + return result; +} + +int _readfile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block) +{ + struct fat_file_block_t *entry; + struct list_head *head; + + // check the cache list + head = &data->file->list; + + // if cache is none, return not found + if (list_empty(head)) + { + return -1; + } + + // find that offset in cache + list_for_each_entry(entry, head, list) + { + *block = entry; + if (foid == entry->oid) + { + return 0; + } + } + + return -1; +} + +int _readfile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block) +{ + struct fat_info_t *info; + unsigned int curoid, curcid; + + info = data->fat; + + // if block found in cache, change to that offset in fat32 + if (*block) + { + curoid = (*block)->oid; + curcid = (*block)->cid; + + if (curoid == foid) + { + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + + if (curcid >= INVALID_CID) + { + return -1; + } + } + else + { + curoid = 0; + curcid = fcid; + } + + while (1) + { + // add new offset block to cache + struct fat_file_block_t *newblock; + + newblock = kmalloc(sizeof(struct fat_file_block_t)); + + newblock->oid = curoid; + newblock->cid = curcid; + newblock->bufIsUpdated = 0; + newblock->isDirty = 0; + + list_add_tail(&newblock->list, &data->file->list); + + *block = newblock; + + if (curoid == foid) + { + return 0; + } + + curoid++; + curcid = get_next_cluster(info->fat_lba, curcid); + + if (curcid >= INVALID_CID) + { + return -1; + } + } +} + +int _readfile_cache(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block) +{ + int rsize; + + if (!block->bufIsUpdated) + { + // read the data from sdcard + struct fat_info_t *info; + int lba; + + info = data->fat; + lba = info->cluster_lba + (block->cid - 2) * info->bs.sector_per_cluster; + readblock(lba, block->buf); + + block->bufIsUpdated = 1; + } + + // if the size is overflow, resize it + rsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + + memcpy((void *)&buf[bufoff], (void *)&block->buf[bckoff], rsize); + + return rsize; +} + +int _readfile_fat32(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid) +{ + struct list_head *head; + struct fat_info_t *info; + struct fat_file_block_t *block; + int lba; + int rsize; + + head = &data->file->list; + info = data->fat; + + block = kmalloc(sizeof(struct fat_file_block_t)); + + rsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; + lba = info->cluster_lba + (cid - 2) * info->bs.sector_per_cluster; + + // read from fat32 + readblock(lba, block->buf); + + memcpy((void *)&buf[bufoff], (void *)&block->buf[bckoff], rsize); + + block->oid = oid; + block->cid = cid; + block->bufIsUpdated = 1; + + list_add_tail(&block->list, head); + + return rsize; +} + +int _readfile(void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len) +{ + struct fat_file_block_t *block; + struct list_head *head; + unsigned int foid; // first block id + unsigned int coid; // current block id + unsigned int cid; // target cluster id + unsigned long long bufoff, result; + int ret; + + block = NULL; + head = &data->file->list; + foid = fileoff / BLOCK_SIZE; + coid = 0; + cid = data->cid; + bufoff = 0; + result = 0; + + // Seek, find the particular offset + ret = _readfile_seek_cache(data, foid, &block); + if (ret < 0) + { + ret = _readfile_seek_fat32(data, foid, cid, &block); + } + + if (ret < 0) + { + return 0; + } + + // Read + while (len) + { + unsigned long long bckoff; + + bckoff = (fileoff + result) % BLOCK_SIZE; + + if (&block->list != head) + { + // cache found + ret = _readfile_cache(data, bckoff, buf, bufoff, len, block); + + cid = block->cid; + block = list_first_entry(&block->list, struct fat_file_block_t, list); + } + else + { + // Read block from sdcard, create cache + cid = get_next_cluster(data->fat->fat_lba, cid); + + if (cid >= INVALID_CID) + { + break; + } + + ret = _readfile_fat32(data, bckoff, buf, bufoff, len, coid, cid); + } + + if (ret < 0) + { + break; + } + + bufoff += ret; + result += ret; + coid += 1; + len -= ret; + } + + return result; +} + +void _do_sync_dir(struct vnode *dirnode) +{ + struct fat32_inode *data, *entry; + struct list_head *head; + struct dir_t *dir; + struct long_dir_t *ldir; + unsigned int cid; + int lba, idx, lfnidx; + unsigned char buf[BLOCK_SIZE]; + + data = dirnode->internal; + head = &data->dir->list; + cid = data->cid; + idx = 0; + lfnidx = 1; + + if (cid >= INVALID_CID) + { + uart_sendlinek("fat32 _do_sync_dir: invalid dirnode->data->cid"); + } + + // get the buf from dirnode's offset + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + readblock(lba, buf); + + list_for_each_entry(entry, head, list) + { + struct dir_t *origindir; + const char *name; + const char *ext; + int lfn, namelen, extpos, i, buflba; + unsigned char lookupbuf[BLOCK_SIZE]; + + name = entry->name; + + // If entry is a old file, update its size + origindir = __lookup_fat32(dirnode, name, lookupbuf, &buflba); + + if (origindir) + { + if (entry->type == FAT_FILE) + { + origindir->size = entry->file->size; + writeblock(buflba, lookupbuf); + } + continue; + } + + // Else if entry is a new file + ext = NULL; + extpos = -1; + + do + { + + namelen = strlen(name); + if (namelen >= 13) + { + lfn = 1; + break; + } + for (i = 0; i < namelen; ++i) + { + // get idx of extension name + if (name[namelen - 1 - i] == '.') + { + break; + } + } + if (i < namelen) + { + ext = &name[namelen - i]; + extpos = namelen - 1 - i; + } + if (i >= 4) + { + lfn = 1; + break; + } + if (namelen - 1 - i > 8) + { + // SFN: 8.3 + lfn = 1; + break; + } + + lfn = 0; + } while (0); + + // Seek idx to the end of dir + while (1) + { + dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * idx]); + + if (dir->name[0] == 0) + { + break; + } + + idx += 1; + + if (idx >= 16) + { // if idx is over Directory Entry, create a new one + unsigned int newcid; + + writeblock(lba, buf); + + newcid = get_next_cluster(data->fat->fat_lba, cid); + if (newcid >= INVALID_CID) + { + newcid = alloc_cluster(data->fat, cid); + } + + cid = newcid; + + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + + readblock(lba, buf); + idx = 0; + } + } + + // Write LFN + if (lfn) + { + int ord; + int first; + + ord = ((namelen - 1) / 13) + 1; + first = 0x40; // LAST_LONG_ENTRY flag in LFN LDIR_Ord + + for (; ord > 0; --ord) + { + int end; + ldir = (struct long_dir_t *)(&buf[sizeof(struct long_dir_t) * idx]); + + ldir->order = first | ord; + ldir->attr = ATTR_LFN; + ldir->type = 0; + // TODO: Calculate checksum, SFN + LFN + ldir->checksum = 0; + ldir->fstcluslo = 0; + + first = 0; + end = 0; + + for (i = 0; i < 10; i += 2) + { + if (end) + { // padding 0xff if filename end + ldir->name1[i] = 0xff; + ldir->name1[i + 1] = 0xff; + } + else + { + ldir->name1[i] = name[(ord - 1) * 13 + i / 2]; + ldir->name1[i + 1] = 0; + if (ldir->name1[i] == 0) + { + end = 1; + } + } + } + for (i = 0; i < 12; i += 2) + { + if (end) + { + ldir->name2[i] = 0xff; + ldir->name2[i + 1] = 0xff; + } + else + { + ldir->name2[i] = name[(ord - 1) * 13 + 5 + i / 2]; + ldir->name2[i + 1] = 0; + if (ldir->name2[i] == 0) + { + end = 1; + } + } + } + for (i = 0; i < 4; i += 2) + { + if (end) + { + ldir->name3[i] = 0xff; + ldir->name3[i + 1] = 0xff; + } + else + { + ldir->name3[i] = name[(ord - 1) * 13 + 11 + i / 2]; + ldir->name3[i + 1] = 0; + if (ldir->name3[i] == 0) + { + end = 1; + } + } + } + + idx += 1; + + if (idx >= 16) + { + unsigned int newcid; + + writeblock(lba, buf); + + newcid = get_next_cluster(data->fat->fat_lba, cid); + if (newcid >= INVALID_CID) + { + newcid = alloc_cluster(data->fat, cid); + } + + cid = newcid; + + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + readblock(lba, buf); + + idx = 0; + } + } + } + + // Write SFN + dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * idx]); + + // TODO: Set these properties properly + dir->ntres = 0; + dir->crttimetenth = 0; + dir->crttime = 0; + dir->crtdate = 0; + dir->lstaccdate = 0; + dir->wrttime = 0; + dir->wrtdate = 0; + + if (entry->type == FAT_DIR) + { + dir->attr = ATTR_DIRECTORY; + dir->size = 0; + } + else + { + dir->attr = ATTR_ARCHIVE; + dir->size = entry->file->size; + } + + if (entry->cid >= INVALID_CID) + { + entry->cid = alloc_cluster(data->fat, 0); + } + + dir->ch = (entry->cid >> 16) & 0xffff; + dir->cl = entry->cid & 0xffff; + + if (lfn) + { + int lfni; + + // Creating SFN body + // TODO: handle lfnidx + for (i = 7, lfni = lfnidx; i >= 0 && lfni;) + { + dir->name[i--] = '0' + lfni % 10; + lfni /= 10; + } + + lfnidx++; + // numeric-tail: ~n (1 <= n <= 6) + dir->name[i--] = '~'; + + // TODO: handle letter case + memcpy((void *)dir->name, name, i + 1); + } + else + { + // TODO: handle letter case + for (i = 0; i != extpos && name[i]; ++i) + { + dir->name[i] = name[i]; + } + + for (; i < 8; ++i) + { + dir->name[i] = ' '; // in SFN, each part is padded with space + } + } + + // SFN format: 8.3 + // TODO: handle letter case + for (i = 0; i < 3 && ext[i]; ++i) + { + dir->name[8 + i] = ext[i]; + } + + for (; i < 3; ++i) + { + dir->name[8 + i] = ' '; + } + + idx += 1; + + if (idx >= 16) + { + int newcid; + + writeblock(lba, buf); + + newcid = get_next_cluster(data->fat->fat_lba, cid); + if (newcid >= INVALID_CID) + { + newcid = alloc_cluster(data->fat, cid); + } + + cid = newcid; + + lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; + + // TODO: Cache data block of directory + readblock(lba, buf); + + idx = 0; + } + } + + if (idx) + { + writeblock(lba, buf); + } +} + +void _do_sync_file(struct vnode *filenode) +{ + struct fat_file_block_t *entry; + struct fat32_inode *data; + struct list_head *head; + unsigned int cid; + + data = filenode->internal; + head = &data->file->list; + cid = data->cid; + + if (cid >= INVALID_CID) + { + // uart_sendlinek("fat32 _do_sync_file: invalid cid"); + return; + } + + list_for_each_entry(entry, head, list) + { + int lba; + + if (entry->oid == 0) + { + // cache is valid but not sync'd, just an informational warning + if (!(entry->cid >= INVALID_CID) && data->cid != entry->cid) + { + uart_sendlinek("_do_sync_file: cid isn't sync"); + } + + entry->cid = data->cid; + } + + if (entry->cid >= INVALID_CID) + { + entry->cid = alloc_cluster(data->fat, cid); + } + + // if the file is sync'd, pass + if (!entry->isDirty) + { + continue; + } + + // cache buf is not updated, initialize it to avoid error + if (!entry->bufIsUpdated) + { + memset(entry->buf, 0, BLOCK_SIZE); + entry->bufIsUpdated = 1; + } + + // sync to fat32 fs + lba = data->fat->cluster_lba + (entry->cid - 2) * data->fat->bs.sector_per_cluster; + writeblock(lba, entry->buf); + + entry->isDirty = 0; + + cid = entry->cid; + } +} + +void _sync_dir(struct vnode *dirnode) +{ + struct fat32_inode *data, *entry; + struct list_head *head; + + // Init: dirnode is mounted fs + data = dirnode->internal; + head = &data->dir->list; + + _do_sync_dir(dirnode); + + list_for_each_entry(entry, head, list) + { + if (entry->type == FAT_DIR) + { + _sync_dir(entry->node); // recursive to next dirnode + } + else + { + _do_sync_file(entry->node); + } + } +} + +int fat32_op_deny() +{ + return -1; +} + +void fat32_dump(struct vnode *vnode, int level) +{ +} + +void fat32_ls(struct vnode *vnode) +{ + uart_sendlinek("in fat32_ls\n"); + struct fat32_inode *inode = (struct fat32_inode *)vnode->internal; + int child_idx = 0; + for (; child_idx <= 16; child_idx++) + { + if (!inode->entry[child_idx]) + { + // break; + } vnode = inode->entry[child_idx]; - uart_sendlinek("%s\n", ((struct fat32_inode *)vnode->internal)->Name); - // uart_sendlinek("0x%x\n", ((struct fat32_inode *)vnode->internal)->datasize); + uart_sendlinek("%s\n", ((struct fat32_inode *)vnode->internal)->name); } } \ No newline at end of file diff --git a/lab8/tmp_file/vfs_fat32.c b/lab8/tmp_file/vfs_fat32.c new file mode 100644 index 000000000..9adeb7b4f --- /dev/null +++ b/lab8/tmp_file/vfs_fat32.c @@ -0,0 +1,242 @@ +#include "vfs_fat32.h" +#include "sdhost.h" +#include "memory.h" +#include "string.h" +#include "u_list.h" +#include +#include "uart1.h" +#include "exception.h" + +struct list_head mounts; // Store all new mountpoints that probably need to be sync'd + +static inline unsigned int get_first_cluster(struct sfn_file *entry) +{ + return (entry->first_cluster_high << 16) | entry->first_cluster_low; +} + +struct vnode_operations fat32_v_ops = { + fat32_lookup, fat32_create, fat32_mkdir, + fat32_isdir, fat32_getname, fat32_getsize, + fat32_ls, fat32_dump}; + +struct file_operations fat32_f_ops = { + fat32_write, + fat32_read, + fat32_open, + fat32_close, + fat32_lseek64, +}; + +int register_fat32() +{ + struct filesystem fs; + fs.name = "fat32"; + fs.setup_mount = fat32_mount; + fs.sync = fat32_sync; + return register_filesystem(&fs); +} + +int fat32_mount(struct filesystem *fs, struct mount *mount) +{ + struct partition_t *partition; + struct fat32_inode *data; + struct vnode *node; + unsigned int lba; + unsigned char buf[BLOCK_SIZE]; + + // Read partition table from MBR, which is at first block + readblock(0, buf); + // MBR format + // 000 ~ 1BD: Code area + // 1BE ~ 1FD: Master Partition Table + // 1FE ~ 1FF: Boot Record Signature + + // https://lexra.pixnet.net/blog/post/303910876 + partition = (struct partition_t *)&buf[0x1be]; + // check Boot Record Signature, constants + if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) + { + return -1; + } + // https://en.wikipedia.org/wiki/Partition_type + if (partition[0].type != 0xb && partition[0].type != 0xc) // check Partition type, only FAT32 + { + return -1; + } + lba = partition[0].lba; + readblock(partition[0].lba, buf); + + data = kmalloc(sizeof(struct fat32_inode)); + data->boot_sector = kmalloc(sizeof(struct boot_sector_t)); + memcpy((void *)data->boot_sector, (void *)buf, sizeof(struct boot_sector_t)); + + // oldnode should attach mount the fs + mount->root = kmalloc(sizeof(struct vnode)); + node = mount->root; + node->mount = 0; + node->v_ops = &fat32_v_ops; + node->f_ops = &fat32_f_ops; + node->internal = data; + + struct boot_sector_t *bs = data->boot_sector; + // int file_block = lba + bs->hidden_sector_cnt + bs->reserved_sector_cnt + bs->fat_cnt * bs->sector_per_fat32; + int file_block = bs->hidden_sector_cnt + bs->reserved_sector_cnt + bs->fat_cnt * bs->sector_per_fat32; + + uart_sendlinek("bs->hidden_sector_cnt: 0x%x\n", bs->hidden_sector_cnt); + uart_sendlinek("bs->reserved_sector_cnt: 0x%x\n", bs->reserved_sector_cnt); + uart_sendlinek("bs->fat_cnt: 0x%x\n", bs->fat_cnt); + uart_sendlinek("bs->sector_per_fat32: 0x%x\n", bs->sector_per_fat32); + uart_sendlinek("file_block: 0x%x\n", file_block); + + readblock(file_block, buf); + + // char *n = buf; + struct sfn_file *file_ptr = buf; + + int high_block; + int low_block; + int block; + unsigned long file_size; + struct fat32_inode *tmp; + for (int i = 0; i < 16; i++) + { + high_block = file_ptr->first_cluster_high; + low_block = file_ptr->first_cluster_low; + // block = file_block + high_block * 256 + low_block - 2; + block = get_first_cluster(file_ptr) + file_block + 2; + file_size = file_ptr->file_size; + if (!file_size) + break; + uart_sendlinek("name : %s\n", file_ptr->name); + uart_sendlinek("high_block: %d\n", high_block); + uart_sendlinek("low_block: %d\n", low_block); + uart_sendlinek("file_size: 0x%x\n", file_size); + + data->entry[i] = kmalloc(sizeof(struct vnode)); + data->entry[i]->f_ops = &fat32_f_ops; + data->entry[i]->v_ops = &fat32_v_ops; + data->entry[i]->internal = kmalloc(sizeof(struct fat32_inode)); + tmp = (struct fat32_inode *)(data->entry[i]->internal); + memcpy(tmp->Name, file_ptr->name, 16); + tmp->sfn = file_ptr; + tmp->datasize = ALIGN_UP(file_size, BLOCK_SIZE); + tmp->data = kmalloc(tmp->datasize); + for (int j = 0; j < tmp->datasize / BLOCK_SIZE; j++) + { + readblock(block + j, tmp->data + j * BLOCK_SIZE); + } + uart_sendlinek("%s\n", *((char *)tmp->data)); + file_ptr++; + } + + for (int i = 0; i < 16; i++) + { + if (data->entry[i] != 0) + { + uart_sendlinek("%d\n", i); + uart_sendlinek("%s\n", ((struct fat32_inode *)data->entry[i]->internal)->Name); + } + } + + return 0; +} + +int fat32_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) +{ + struct fat32_inode *dir_inode = dir_node->internal; + int child_idx = 0; + for (; child_idx < 16; child_idx++) + { + struct vnode *vnode = dir_inode->entry[child_idx]; + if (!vnode) + break; + struct fat32_inode *inode = vnode->internal; + if (strcasecmp(component_name, inode->name) == 0) + { + *target = vnode; + return 0; + } + } + return -1; +} + +int fat32_create(struct vnode *dir_node, struct vnode **target, const char *component_name) { + +}; +int fat32_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) { + +}; +int fat32_isdir(struct vnode *dir_node) { + +}; +int fat32_getname(struct vnode *dir_node, const char **name) { + +}; +int fat32_getsize(struct vnode *dir_node) { + +}; +int fat32_write(struct file *file, const void *buf, size_t len) { + +}; +int fat32_read(struct file *file, void *buf, size_t len) +{ + struct fat32_inode *inode = file->vnode->internal; + // overflow, shrink size + if (len + file->f_pos > inode->datasize) + { + memcpy(buf, inode->data + file->f_pos, inode->datasize - file->f_pos); + file->f_pos += inode->datasize - file->f_pos; + return inode->datasize - file->f_pos; + } + else + { + memcpy(buf, inode->data + file->f_pos, len); + file->f_pos += len; + return len; + } + return -1; +}; +int fat32_open(struct vnode *file_node, struct file **target) +{ + (*target)->vnode = file_node; + (*target)->f_ops = file_node->f_ops; + (*target)->f_pos = 0; + return 0; +}; +int fat32_close(struct file *file) +{ + kfree(file); + return 0; +}; +long fat32_lseek64(struct file *file, long offset, int whence) { + +}; +int fat32_sync(struct filesystem *fs) { + +}; + +int fat32_op_deny() +{ + return -1; +} + +void fat32_dump(struct vnode *vnode, int level) +{ +} + +void fat32_ls(struct vnode *vnode) +{ + // uart_sendlinek("in fat32_ls\n"); + struct fat32_inode *inode = (struct fat32_inode *)vnode->internal; + int child_idx = 0; + for (; child_idx <= 16; child_idx++) + { + if (!inode->entry[child_idx]) + { + break; + } + vnode = inode->entry[child_idx]; + uart_sendlinek("%s\n", ((struct fat32_inode *)vnode->internal)->Name); + // uart_sendlinek("0x%x\n", ((struct fat32_inode *)vnode->internal)->datasize); + } +} \ No newline at end of file From 8ac45053ca9b2d645dcdfdfb9843d8beb737df2b Mon Sep 17 00:00:00 2001 From: SianGx0102 Date: Wed, 26 Jun 2024 13:50:27 +0800 Subject: [PATCH 5/5] lab8 --- lab8/create_diskimg/{sdcard => }/FAT_R.TXT | 0 lab8/create_diskimg/create_img.sh | 30 +- lab8/create_diskimg/create_sfn_img.sh | 45 - lab8/kernel/include/vfs_fat32.h | 239 +-- lab8/kernel/src/shell.c | 31 +- lab8/kernel/src/vfs.c | 14 +- lab8/kernel/src/vfs_fat32.c | 1648 ++++---------------- 7 files changed, 407 insertions(+), 1600 deletions(-) rename lab8/create_diskimg/{sdcard => }/FAT_R.TXT (100%) delete mode 100755 lab8/create_diskimg/create_sfn_img.sh diff --git a/lab8/create_diskimg/sdcard/FAT_R.TXT b/lab8/create_diskimg/FAT_R.TXT similarity index 100% rename from lab8/create_diskimg/sdcard/FAT_R.TXT rename to lab8/create_diskimg/FAT_R.TXT diff --git a/lab8/create_diskimg/create_img.sh b/lab8/create_diskimg/create_img.sh index 73514bd63..cb8363e64 100755 --- a/lab8/create_diskimg/create_img.sh +++ b/lab8/create_diskimg/create_img.sh @@ -1,5 +1,6 @@ #!/bin/sh + IMG_NAME=sdcard.img truncate -s 64M $IMG_NAME @@ -11,32 +12,39 @@ echo p # Primary partition echo 1 # Partition number echo # First sector (Accept default: 1) echo # Last sector (Accept default: varies) +echo a # Toggle bootable flag echo t # Change partition type -echo c # Master Boot Record primary partitions type:LBA +echo b # W95 FAT32 echo w # Write changes ) | sudo fdisk $IMG_NAME -LOOPBACK=`sudo losetup --partscan --show --find $IMG_NAME` +LOOPBACK=$(sudo losetup --partscan --show --find $IMG_NAME) echo ${LOOPBACK} | grep --quiet "/dev/loop" -if [ $? = 1 ] -then +if [ $? = 1 ]; then echo "[!] losetup failed!" exit 1 fi -sudo mkfs.vfat -F 32 ${LOOPBACK}p1 +sudo mkfs.msdos -F 32 ${LOOPBACK}p1 mkdir -p mnt -sudo mount -t vfat ${LOOPBACK}p1 mnt - -sudo cp -r sdcard/* mnt -sudo cp ./bootloader.img mnt/bootloader.img -sudo cp ./initramfs.cpio mnt/initramfs.cpio +sudo mount -t msdos ${LOOPBACK}p1 mnt -sudo umount mnt +sudo cp ../kernel/kernel8.img mnt/KERNEL8.IMG +sudo cp ./initramfs.cpio mnt/INITRD +sudo cp ../config.txt mnt/CONFIT.TXT +sudo cp ../bcm2710-rpi-3-b-plus.dtb mnt/BCM2710.DTB +sudo cp ./FAT_R.TXT mnt/FAT_R.TXT +sudo bash -c "echo "Hello" > mnt/HELLO" +sudo bash -c 'echo -e "W\no\nr\nl\nd" > mnt/WORLD' +sudo umount -l mnt sudo losetup -d ${LOOPBACK} +sudo rm -rf mnt + +#mv sdcard.img ../ # 1fc400 + # dd if=./sdcard.img of=/dev/ diff --git a/lab8/create_diskimg/create_sfn_img.sh b/lab8/create_diskimg/create_sfn_img.sh deleted file mode 100755 index c4c7a9991..000000000 --- a/lab8/create_diskimg/create_sfn_img.sh +++ /dev/null @@ -1,45 +0,0 @@ -IMG_NAME=sdcard.img - -truncate -s 64M $IMG_NAME - -( -echo o # Create a new empty DOS partition table -echo n # Add a new partition -echo p # Primary partition -echo 1 # Partition number -echo # First sector (Accept default: 1) -echo # Last sector (Accept default: varies) -echo a # Toggle bootable flag -echo t # Change partition type -echo b # W95 FAT32 -echo w # Write changes -) | sudo fdisk $IMG_NAME - -LOOPBACK=$(sudo losetup --partscan --show --find $IMG_NAME) - -echo ${LOOPBACK} | grep --quiet "/dev/loop" - -if [ $? = 1 ]; then - echo "[!] losetup failed!" - exit 1 -fi - -sudo mkfs.msdos -F 32 ${LOOPBACK}p1 - -mkdir -p mnt - -sudo mount -t msdos ${LOOPBACK}p1 mnt - -sudo cp ../kernel/kernel8.img mnt/KERNEL8.IMG -sudo cp ../initramfs.cpio mnt/INITRAMFS.CPIO -sudo cp ../bcm2710-rpi-3-b-plus.dtb mnt/BCM2710-RPI-3-B-PLUS.DTB -sudo bash -c "echo "Hello" > mnt/HELLO" -sudo bash -c "echo "W\no\nr\nl\nd" > mnt/WORLD" - -sudo umount -l mnt -sudo losetup -d ${LOOPBACK} -sudo rm -rf mnt - -mv sdcard.img ../ # 1fc400 - -#dd if=./sdcard.img of=/dev/ diff --git a/lab8/kernel/include/vfs_fat32.h b/lab8/kernel/include/vfs_fat32.h index 08da954b0..60824c2e3 100644 --- a/lab8/kernel/include/vfs_fat32.h +++ b/lab8/kernel/include/vfs_fat32.h @@ -5,10 +5,18 @@ #include "vfs.h" #define BLOCK_SIZE 512 -#define CLUSTER_ENTRY_PER_BLOCK (BLOCK_SIZE / sizeof(struct cluster_entry_t)) -#define DIR_PER_BLOCK (BLOCK_SIZE / sizeof(struct dir_t)) -#define INVALID_CID 0x0ffffff8 // Last cluster in file (EOC), reserved by FAT32 +#define FAT32_MAX_FILENAME 8 +#define FAT32_MAX_EXTENSION 3 +#define FAT32_FREE_CLUSTER 0x00000000 +#define FAT32_END_OF_CHAIN 0x0FFFFFF8 + +// #define CLUSTER_ENTRY_PER_BLOCK (BLOCK_SIZE / sizeof(struct cluster_entry_t)) +// #define DIR_PER_BLOCK (BLOCK_SIZE / sizeof(struct dir_t)) +// #define INVALID_CID 0x0ffffff8 // Last cluster in file (EOC), reserved by FAT32 + +static unsigned int *file_allocation_table; +static struct fs_info *fs_info; struct partition_t { unsigned char status; @@ -23,27 +31,34 @@ struct partition_t unsigned int sectors; } __attribute__((packed)); +struct MBR +{ + char bootstrap_code[0x1BE]; // 引導代碼區塊 + struct partition_t partition_table[4]; // 分區表,共4個分區 + unsigned short signature; // MBR簽名,0x55AA +} __attribute__((packed)); + struct boot_sector_t { unsigned char jmpboot[3]; unsigned char oemname[8]; unsigned short bytes_per_sector; - unsigned char sector_per_cluster; - unsigned short reserved_sector_cnt; // red - unsigned char fat_cnt; // yellow + unsigned char sector_per_cluster; // 每簇扇區數 + unsigned short reserved_sector_cnt; // 保留扇區數 + unsigned char fat_cnt; // FAT 表數量,通常為 2 unsigned short root_entry_cnt; unsigned short old_sector_cnt; unsigned char media; unsigned short sector_per_fat16; unsigned short sector_per_track; unsigned short head_cnt; - unsigned int hidden_sector_cnt; // blue + unsigned int hidden_sector_cnt; // 隱藏扇區數,文件系統開始前的扇區數 unsigned int sector_cnt; // FAT32 definition - unsigned int sector_per_fat32; // pink + unsigned int sector_per_fat32; // 每個 FAT 表的扇區數 unsigned short extflags; unsigned short ver; unsigned int root_cluster; - unsigned short info; + unsigned short info; // 文件系統信息扇區號 unsigned short bkbooksec; unsigned char reserved[12]; unsigned char drvnum; @@ -54,12 +69,17 @@ struct boot_sector_t unsigned char fstype[8]; } __attribute__((packed)); -struct fat_info_t +// FAT32 FSINFO structure +struct fs_info { - struct boot_sector_t bs; // boot_sector from MBR Partition Table - unsigned int fat_lba; // FAT Region in FAT fs Definition - unsigned int cluster_lba; // Data Region in FAT32 fs Definition -}; + unsigned int lead_signature; // Should be 0x41615252 + unsigned char reserved1[480]; // Must be zero + unsigned int structure_signature; // Should be 0x61417272 + unsigned int free_count; // Number of free clusters; -1 if unknown + unsigned int next_free; // Next free cluster; 0xFFFFFFFF if unknown + unsigned char reserved2[12]; // Must be zero + unsigned int trail_signature; // Should be 0xAA550000 +} __attribute__((packed)); // attr of dir_t #define ATTR_READ_ONLY 0x01 @@ -71,140 +91,39 @@ struct fat_info_t #define ATTR_ARCHIVE 0x20 #define ATTR_FILE_DIR_MASK (ATTR_DIRECTORY | ATTR_ARCHIVE) -// Directory structure for FAT SFN -// http://elm-chan.org/docs/fat_e.html -struct dir_t -{ - unsigned char name[11]; - unsigned char attr; - unsigned char ntres; - unsigned char crttimetenth; - unsigned short crttime; - unsigned short crtdate; - unsigned short lstaccdate; - unsigned short ch; - unsigned short wrttime; - unsigned short wrtdate; - unsigned short cl; - unsigned int size; -} __attribute__((packed)); - -// Directory structure for FAT LFN -// https://blog.csdn.net/ZCShouCSDN/article/details/97610903 -struct long_dir_t -{ - unsigned char order; - unsigned char name1[10]; - unsigned char attr; - unsigned char type; - unsigned char checksum; - unsigned char name2[12]; - unsigned short fstcluslo; - unsigned char name3[4]; -} __attribute__((packed)); - -struct cluster_entry_t -{ - union - { - unsigned int val; - struct - { - unsigned int idx : 28; - unsigned int reserved : 4; - }; - }; -}; - -struct filename_t -{ - union - { - unsigned char fullname[256]; - struct - { - unsigned char name[13]; - } part[20]; - }; -} __attribute__((packed)); - -struct fat_file_block_t -{ - /* Link fat_file_block_t */ - struct list_head list; - unsigned int oid; // offset if of file, N = offset N* BLOCK_SIZE of file - unsigned int cid; // cluster id - unsigned int bufIsUpdated; - unsigned int isDirty; - unsigned char buf[BLOCK_SIZE]; -}; - -struct fat_file_t -{ - /* Head of fat_file_block_t chain */ - struct list_head list; - unsigned int size; -}; - -struct fat_dir_t -{ - /* Head of fat32_inode chain */ - struct list_head list; -}; - -struct fat_mount_t -{ - /* Link fat_mount_t */ - struct list_head list; - struct mount *mount; -}; - // type of struct fat32_inode #define FAT_DIR 1 #define FAT_FILE 2 struct fat32_inode { - const char *name; - struct vnode *node; // redirect to vnode - struct fat_info_t *fat; - /* Link fat32_inode */ - struct list_head list; - /* cluster id */ - unsigned int cid; // cluster id - unsigned int type; - union - { - struct fat_dir_t *dir; - struct fat_file_t *file; - }; - struct boot_sector_t *boot_sector; struct sfn_file *sfn; - char Name[16]; + char name[16]; struct vnode *entry[16]; - char *data; + // char *data; + int data_block_cnt; size_t datasize; }; struct sfn_file { - char name[11]; // 檔案名稱 - char attribute; // 屬性 - char reserved; // 保留位 - char creation_time_tenth_seconds; // 創建時間的1/10秒計數 - unsigned short creation_time; // 創建時間 - unsigned short creation_date; // 創建日期 - unsigned short last_access_date; // 最後訪問日期 - unsigned short first_cluster_high; // 文件起始簇高16位 - unsigned short last_write_time; // 最後修改時間 - unsigned short last_write_date; // 最後修改日期 - unsigned short first_cluster_low; // 文件起始簇低16位 - unsigned int file_size; // 文件大小(字節) + char name[FAT32_MAX_FILENAME]; // 文件名,最多8個字節,不足部分使用空格填充 + char extension[FAT32_MAX_EXTENSION]; // 文件擴展名,最多3個字節,不足部分使用空格填充 + char attribute; // 屬性 + char reserved; // 保留位 + char creation_time_tenth_seconds; // 創建時間的1/10秒計數 + unsigned short creation_time; // 創建時間 + unsigned short creation_date; // 創建日期 + unsigned short last_access_date; // 最後訪問日期 + unsigned short first_cluster_high; // 文件起始簇高16位 + unsigned short last_write_time; // 最後修改時間 + unsigned short last_write_date; // 最後修改日期 + unsigned short first_cluster_low; // 文件起始簇低16位 + unsigned int file_size; // 文件大小(字節) }; -int -register_fat32(); +int register_fat32(); int fat32_mount(struct filesystem *fs, struct mount *mount); int fat32_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name); @@ -221,32 +140,38 @@ int fat32_close(struct file *file); long fat32_lseek64(struct file *file, long offset, int whence); int fat32_sync(struct filesystem *fs); -unsigned int alloc_cluster(struct fat_info_t *fat, unsigned int prev_cid); -unsigned int get_next_cluster(unsigned int fat_lba, unsigned int cluster_id); - -struct vnode *_create_vnode(struct vnode *parent, const char *name, unsigned int type, unsigned int cid, unsigned int size); - -int _lookup_cache(struct vnode *dir_node, struct vnode **target, const char *component_name); -struct dir_t *__lookup_fat32(struct vnode *dir_node, const char *component_name, unsigned char *buf, int *buflba); -int _lookup_fat32(struct vnode *dir_node, struct vnode **target, const char *component_name); - -int _readfile(void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len); -int _readfile_fat32(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid); -int _readfile_cache(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block); -int _readfile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block); -int _readfile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block); - -int _writefile(const void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len); -int _writefile_fat32(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid); -int _writefile_cache(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block); -int _writefile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block); -int _writefile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block); - -void _sync_dir(struct vnode *dirnode); -void _do_sync_dir(struct vnode *dirnode); -void _do_sync_file(struct vnode *filenode); - void fat32_dump(struct vnode *vnode, int level); void fat32_ls(struct vnode *vnode); int fat32_op_deny(); + +static inline unsigned int get_first_cluster(struct sfn_file *entry) +{ + return (entry->first_cluster_high << 16) | entry->first_cluster_low; +} + +static inline void fat32_get_file_name(char *name_array, struct sfn_file *entry) +{ + int idx = 0; + for (int i = 0; i < FAT32_MAX_FILENAME; i++, idx++) + { + if (entry->name[i] == ' ') + { + break; + } + name_array[idx] = entry->name[i]; + } + for (int i = 0; i < FAT32_MAX_EXTENSION; i++, idx++) + { + if (entry->extension[i] == ' ') + { + break; + } + else if (i == 0) + { + name_array[idx++] = '.'; + } + name_array[idx] = entry->extension[i]; + } + name_array[idx] = '\0'; +} #endif diff --git a/lab8/kernel/src/shell.c b/lab8/kernel/src/shell.c index 3d823c341..6f23eb049 100644 --- a/lab8/kernel/src/shell.c +++ b/lab8/kernel/src/shell.c @@ -417,7 +417,7 @@ int do_cmd_exec(int argc, char **argv) strcpy(abs_path, filepath); get_absolute_path(abs_path, curr_thread->curr_working_dir); - strcpy(abs_path,"/initramfs/vfs2.img");// + strcpy(abs_path, "/initramfs/vfs2.img"); // if (vfs_lookup(abs_path, &target_file) != 0) { WARING("File : %s Does not Exit!!\n", abs_path); @@ -487,11 +487,36 @@ int do_cmd_ttest(int argc, char **argv) int do_cmd_ftest(int argc, char **argv) { + // ============================== test for fat file read&write start================================== + struct file *testfile; + char testbuf[512] = {}; + vfs_open("/boot/FAT_R.TXT", 0, &testfile); + vfs_read(testfile, testbuf, 25); + uart_sendlinek("%s", testbuf); + vfs_close(testfile); + + struct file *testfilew; + char testbufw[512] = "abcdefg"; + vfs_open("/boot/FAT_R.TXT", 0, &testfilew); + vfs_write(testfilew, testbufw, 8); + // uart_sendlinek("%s", testbufw); + vfs_close(testfilew); + struct file *testfiler; - char testbufr[0x30] = {}; - vfs_open("/boot/WORLD", 0, &testbufr); + char testbufr[512] = {}; + vfs_open("/boot/FAT_R.TXT", 0, &testfiler); vfs_read(testfiler, testbufr, 25); uart_sendlinek("%s", testbufr); + vfs_close(testfiler); + + // char test[512] = "" + // char testbufw[512] = "abcdefghijk\n"; + // uart_sendlinek("%s", testbufw); + + // char *t = &testbufw[10]; + // memcpy(t,"abcdefg",7); + // uart_sendlinek("%s", testbufw); + // ============================== test for fat file read&write end ================================== // ============================== test for file operation start================================== // uart_sendlinek("\n\n"); diff --git a/lab8/kernel/src/vfs.c b/lab8/kernel/src/vfs.c index cca9b42c9..e352acee2 100644 --- a/lab8/kernel/src/vfs.c +++ b/lab8/kernel/src/vfs.c @@ -447,12 +447,20 @@ void vfs_cd(char *filepath) uart_sendlinek("Before change directory : %s\n", curr_thread->curr_working_dir); char abs_path[MAX_PATH_NAME]; + struct vnode *tmp; + strcpy(abs_path, filepath); get_absolute_path(abs_path, curr_thread->curr_working_dir); // uart_sendlinek("abs_path : %s\n",abs_path); - strcpy(curr_thread->curr_working_dir, abs_path); - - uart_sendlinek("In directory : %s\n", curr_thread->curr_working_dir); + if (vfs_lookup(abs_path, tmp) == 0) + { + strcpy(curr_thread->curr_working_dir, abs_path); + uart_sendlinek("In directory : %s\n", curr_thread->curr_working_dir); + } + else + { + uart_sendlinek("No such directory : %s\n", abs_path); + } } void displaylayer(int level) diff --git a/lab8/kernel/src/vfs_fat32.c b/lab8/kernel/src/vfs_fat32.c index 62488b8bc..d5c9a6d84 100644 --- a/lab8/kernel/src/vfs_fat32.c +++ b/lab8/kernel/src/vfs_fat32.c @@ -3,18 +3,16 @@ #include "memory.h" #include "string.h" #include "u_list.h" -#include +#include "debug.h" #include "uart1.h" #include "exception.h" struct list_head mounts; // Store all new mountpoints that probably need to be sync'd -// ======================================================================================== - struct vnode_operations fat32_v_ops = { fat32_lookup, fat32_create, fat32_mkdir, fat32_isdir, fat32_getname, fat32_getsize, - fat32_ls,fat32_dump}; + fat32_ls, fat32_dump}; struct file_operations fat32_f_ops = { fat32_write, @@ -22,7 +20,7 @@ struct file_operations fat32_f_ops = { fat32_open, fat32_close, fat32_lseek64, -}; + fat32_getsize}; int register_fat32() { @@ -30,31 +28,29 @@ int register_fat32() fs.name = "fat32"; fs.setup_mount = fat32_mount; fs.sync = fat32_sync; - INIT_LIST_HEAD(&mounts); return register_filesystem(&fs); } -/* filesystem methods */ int fat32_mount(struct filesystem *fs, struct mount *mount) { struct partition_t *partition; - struct fat_info_t *fat; - struct fat_dir_t *dir; struct fat32_inode *data; - struct vnode *oldnode, *node; - struct fat_mount_t *newmount; + struct vnode *node; unsigned int lba; unsigned char buf[BLOCK_SIZE]; + unsigned char filedata_buf[BLOCK_SIZE]; // Read partition table from MBR, which is at first block readblock(0, buf); + struct MBR *mbr = kmalloc(sizeof(struct MBR)); + memcpy(mbr, buf, sizeof(struct MBR)); // MBR format // 000 ~ 1BD: Code area // 1BE ~ 1FD: Master Partition Table // 1FE ~ 1FF: Boot Record Signature // https://lexra.pixnet.net/blog/post/303910876 - partition = (struct partition_t *)&buf[0x1be]; + partition = &(mbr->partition_table[0]); // check Boot Record Signature, constants if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) { @@ -68,1436 +64,326 @@ int fat32_mount(struct filesystem *fs, struct mount *mount) lba = partition[0].lba; readblock(partition[0].lba, buf); - node = kmalloc(sizeof(struct vnode)); data = kmalloc(sizeof(struct fat32_inode)); - fat = kmalloc(sizeof(struct fat_info_t)); - dir = kmalloc(sizeof(struct fat_dir_t)); - newmount = kmalloc(sizeof(struct fat_mount_t)); - - memcpy((void *)&fat->bs, (void *)buf, sizeof(fat->bs)); - - // According to FAT fs design, FAT Region is after reserved sectors - // https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system - fat->fat_lba = lba + fat->bs.reserved_sector_cnt; - fat->cluster_lba = fat->fat_lba + fat->bs.fat_cnt * fat->bs.sector_per_fat32; - - INIT_LIST_HEAD(&dir->list); + data->boot_sector = kmalloc(sizeof(struct boot_sector_t)); + memcpy((void *)data->boot_sector, (void *)buf, sizeof(struct boot_sector_t)); // oldnode should attach mount the fs mount->root = kmalloc(sizeof(struct vnode)); - oldnode = mount->root; - oldnode->mount = 0; - oldnode->v_ops = &fat32_v_ops; - oldnode->f_ops = &fat32_f_ops; - oldnode->internal = data; + node = mount->root; + node->mount = 0; + node->v_ops = &fat32_v_ops; + node->f_ops = &fat32_f_ops; + node->internal = data; + + struct boot_sector_t *bs = data->boot_sector; + // int file_block = lba + bs->hidden_sector_cnt + bs->reserved_sector_cnt + bs->fat_cnt * bs->sector_per_fat32; + int file_block = bs->hidden_sector_cnt + bs->reserved_sector_cnt + bs->fat_cnt * bs->sector_per_fat32; + + uart_sendlinek("bs->hidden_sector_cnt: 0x%x\n", bs->hidden_sector_cnt); + uart_sendlinek("bs->reserved_sector_cnt: 0x%x\n", bs->reserved_sector_cnt); + uart_sendlinek("bs->fat_cnt: 0x%x\n", bs->fat_cnt); + uart_sendlinek("bs->sector_per_fat32: 0x%x\n", bs->sector_per_fat32); + uart_sendlinek("file_block: 0x%x\n", file_block); + + readblock(file_block, buf); + + // char *n = buf; + struct sfn_file *file_ptr = buf; + + // int high_block; + // int low_block; + int block; + unsigned long file_size; + struct fat32_inode *tmp; + char name_array[16]; + for (int i = 0; i < 16; i++) + { + // high_block = file_ptr->first_cluster_high; + // low_block = file_ptr->first_cluster_low; + // block = file_block + high_block * 256 + low_block - 2; + block = file_block + get_first_cluster(file_ptr) - 2; + file_size = file_ptr->file_size; + if (file_ptr->name[0] == (char *)0) + break; + uart_sendlinek("name : %s\n", file_ptr->name); + // uart_sendlinek("high_block: %d\n", high_block); + // uart_sendlinek("low_block: %d\n", low_block); + uart_sendlinek("file_size: 0x%x\n", file_size); + uart_sendlinek("fat32_f_ops addr: 0x%x\n", &fat32_f_ops); - data->node = oldnode; - data->fat = fat; - data->cid = 2; // In FAT32, Root Directory Table starts from cluster #2 - data->type = FAT_DIR; - data->dir = dir; + data->entry[i] = kmalloc(sizeof(struct vnode)); + data->entry[i]->f_ops = &fat32_f_ops; + data->entry[i]->v_ops = &fat32_v_ops; + data->entry[i]->internal = kmalloc(sizeof(struct fat32_inode)); + tmp = (struct fat32_inode *)(data->entry[i]->internal); + fat32_get_file_name(tmp->name, file_ptr); + uart_sendlinek("name_array : %s\n", tmp->name); + tmp->sfn = file_ptr; + tmp->datasize = file_size; - // oldnode = mount->root; - // uart_sendlinek("mount->root: 0x%x",oldnode); + // tmp->data = kmalloc(tmp->datasize); + // for (int j = 0; j < tmp->datasize / BLOCK_SIZE; j++) + // { + // readblock(block + j, tmp->data + j * BLOCK_SIZE); + // } + tmp->data_block_cnt = block; + // tmp->data = kmalloc(BLOCK_SIZE); + // readblock(block, filedata_buf); + // uart_sendlinek("%s\n", filedata_buf); + // memcpy(tmp->data, filedata_buf, BLOCK_SIZE); - // node->mount = oldnode->mount; - // node->v_ops = oldnode->v_ops; - // node->f_ops = oldnode->f_ops; - // node->parent = oldnode->parent; - // node->internal = oldnode->internal; + file_ptr++; + } - // data->node = node; - // data->fat = fat; - // data->cid = 2; // In FAT32, Root Directory Table starts from cluster #2 - // data->type = FAT_DIR; - // data->dir = dir; + for (int i = 0; i < 16; i++) + { + if (data->entry[i] != 0) + { + uart_sendlinek("%d\n", i); + uart_sendlinek("%s\n", ((struct fat32_inode *)data->entry[i]->internal)->name); + } + } - // oldnode->mount = mount; - // oldnode->v_ops = &fat32_v_ops; - // oldnode->f_ops = &fat32_f_ops; - // oldnode->internal = data; + int max_cluster_num = (bs->sector_per_fat32 * bs->bytes_per_sector / sizeof(unsigned int)); + uart_sendlinek("sector_per_fat32 : %d\n", bs->sector_per_fat32); + uart_sendlinek("bytes_per_sector : %d\n", bs->bytes_per_sector); + uart_sendlinek("max_cluster_num : %d\n", max_cluster_num); + file_allocation_table = kmalloc(max_cluster_num); - lock(); - list_add(&newmount->list, &mounts); - unlock(); - newmount->mount = mount; + for (int i = 0; i < bs->sector_per_fat32; i++) + readblock(bs->hidden_sector_cnt + bs->reserved_sector_cnt + i, file_allocation_table + i * bs->bytes_per_sector / sizeof(unsigned int)); + readblock(bs->hidden_sector_cnt + bs->info, buf); + fs_info = kmalloc(sizeof(struct fs_info)); + memcpy(fs_info, buf, sizeof(struct fs_info)); return 0; } int fat32_lookup(struct vnode *dir_node, struct vnode **target, const char *component_name) { - if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) - return -1; - if (!_lookup_cache(dir_node, target, component_name)) - return 0; - return _lookup_fat32(dir_node, target, component_name); + struct fat32_inode *dir_inode = dir_node->internal; + int child_idx = 0; + for (; child_idx < 16; child_idx++) + { + struct vnode *vnode = dir_inode->entry[child_idx]; + if (!vnode) + break; + struct fat32_inode *inode = vnode->internal; + // uart_sendlinek("vnode name : %s\n", inode->Name); + // uart_sendlinek("vnode name size: %d\n", strlen(inode->Name)); + // uart_sendlinek("component_name %s\n", component_name); + // uart_sendlinek("component_name size: %d\n", strlen(component_name)); + if (strcmp(component_name, inode->name) == 0) + { + // uart_sendlinek("GET %s\n", component_name); + *target = vnode; + return 0; + } + } + return -1; } int fat32_create(struct vnode *dir_node, struct vnode **target, const char *component_name) { - if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) - return -1; - if (!fat32_lookup(dir_node, target, component_name)) - return -1; - *target = _create_vnode(dir_node, component_name, FAT_FILE, -1, 0); + uart_sendlinek("component_name : %s\n", component_name); + + unsigned char buf[BLOCK_SIZE]; + unsigned char name[FAT32_MAX_FILENAME] = {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; + unsigned char extension[FAT32_MAX_EXTENSION] = {0x20, 0x20, 0x20}; + struct fat32_inode *inode = dir_node->internal; + struct boot_sector_t *bs = inode->boot_sector; + + int file_block = bs->hidden_sector_cnt + bs->reserved_sector_cnt + bs->fat_cnt * bs->sector_per_fat32; + readblock(file_block, buf); + struct sfn_file *file_ptr = buf; + for (int i = 0; i < 16; i++, file_ptr++) + { + uart_sendlinek("%s\n", file_ptr->name); + if (file_ptr->name[0] == (char *)0) + { + uart_sendlinek("%d\n", i); + break; + } + } + int name_cnt = 0; + for (; name_cnt < strlen(component_name); name_cnt++) + { + if (component_name[name_cnt] == '.' || component_name[name_cnt] == '\0') + { + break; + } + if (name_cnt < FAT32_MAX_FILENAME) + { + name[name_cnt] = component_name[name_cnt]; + } + } + if (component_name[name_cnt] == '.') + { + name_cnt++; + for (int i = 0; name_cnt < strlen(component_name); i++, name_cnt++) + { + if (component_name[name_cnt] == '\0') + { + break; + } + if (i < FAT32_MAX_EXTENSION) + { + extension[i] = component_name[name_cnt]; + } + } + } + // uart_sendlinek("new file name : %s\n", name); + // uart_sendlinek("new file extension : %s\n", extension); + memcpy(file_ptr->name, name, FAT32_MAX_FILENAME); + memcpy(file_ptr->extension, extension, FAT32_MAX_EXTENSION); + // =============================================================================================== + + int max_cluster_num = (bs->sector_per_fat32 * bs->bytes_per_sector / sizeof(unsigned int)); + // find_free_cluster + int free_cluster = fs_info->next_free; + for (; free_cluster < max_cluster_num; free_cluster++) + { + if (file_allocation_table[free_cluster] == FAT32_FREE_CLUSTER) + { + break; + } + } + uart_sendlinek("free_cluster : %d\n", free_cluster); + file_ptr->attribute = 0x20; + file_ptr->creation_time_tenth_seconds = 0; + file_ptr->creation_time = 0; + file_ptr->creation_date = 0; + file_ptr->last_access_date = 0; + file_ptr->first_cluster_high = (free_cluster & 0xFFFF0000) >> 16; + file_ptr->last_write_time = 0; + file_ptr->last_write_date = 0; + file_ptr->first_cluster_low = free_cluster & 0x0000FFFF; + file_ptr->file_size = 512; + file_allocation_table[free_cluster] = FAT32_END_OF_CHAIN; + + writeblock(file_block, buf); + + struct vnode *_vnode = kmalloc(sizeof(struct vnode)); + + _vnode->f_ops = &fat32_f_ops; + _vnode->v_ops = &fat32_v_ops; + _vnode->internal = kmalloc(sizeof(struct fat32_inode)); + struct fat32_inode *_inode = (struct fat32_inode *)(_vnode->internal); + fat32_get_file_name(_inode->name, file_ptr); + _inode->sfn = file_ptr; + _inode->datasize = 512; + *target = _vnode; + + int find_entry = 0; + for (; find_entry < 16; find_entry++) + { + if (!inode->entry[find_entry]) + { + uart_sendlinek("%d\n", find_entry); + break; + } + } + inode->entry[find_entry] = _vnode; + return 0; -} +}; int fat32_mkdir(struct vnode *dir_node, struct vnode **target, const char *component_name) { - if (((struct fat32_inode *)dir_node->internal)->type != FAT_DIR) - return -1; - if (!fat32_lookup(dir_node, target, component_name)) - return -1; - *target = _create_vnode(dir_node, component_name, FAT_DIR, -1, 0); return 0; -} - +}; int fat32_isdir(struct vnode *dir_node) { - return (((struct fat32_inode *)dir_node->internal)->type == FAT_DIR) ? 1 : 0; -} - + return 0; +}; int fat32_getname(struct vnode *dir_node, const char **name) { - *name = ((struct fat32_inode *)dir_node->internal)->name; return 0; -} - +}; int fat32_getsize(struct vnode *dir_node) { - if (((struct fat32_inode *)dir_node->internal)->type == FAT_DIR) - return 0; - return ((struct fat32_inode *)dir_node->internal)->file->size; -} - -/* file_operations methods */ + return 0; +}; int fat32_write(struct file *file, const void *buf, size_t len) { - struct fat32_inode *data; - int filesize; - int ret; - - if (fat32_isdir(file->vnode)) - return -1; - if (!len) - return len; - - filesize = fat32_getsize(file->vnode); - data = file->vnode->internal; - - ret = _writefile(buf, data, file->f_pos, len); - if (ret <= 0) - { - return ret; - } - - file->f_pos += ret; - if (file->f_pos > filesize) - { - data->file->size = file->f_pos; - } - - return ret; -} - + unsigned char filedata_buf[BLOCK_SIZE]; + // char *pt = buf; + struct fat32_inode *inode = file->vnode->internal; + // memcpy(filedata_buf,buf,BLOCK_SIZE); + // uart_sendlinek("IN fat32_write\n"); + // uart_sendlinek("old file->f_pos : %d\n",file->f_pos); + uart_sendlinek("fat32_write : %s\n", buf); + readblock(inode->data_block_cnt, filedata_buf); + // uart_sendlinek("old filedata_buf : %s\n",filedata_buf); + // char *tmp = &filedata_buf[file->f_pos]; + memcpy(filedata_buf + file->f_pos, buf, len); + uart_sendlinek("filedata_buf : %s\n", filedata_buf); + writeblock(inode->data_block_cnt, filedata_buf); + + inode->datasize = len + file->f_pos > inode->datasize ? len + file->f_pos : inode->datasize; + // uart_sendlinek("new file->f_pos : %d\n",file->f_pos); + // uart_sendlinek("new filedata_buf : %s\n",filedata_buf); + // uart_sendlinek("new filedata_buf size: %d\n",sizeof(filedata_buf)); + return len; +}; int fat32_read(struct file *file, void *buf, size_t len) { - struct fat32_inode *data; - int filesize; - int ret; - - if (fat32_isdir(file->vnode)) - return -1; - - filesize = fat32_getsize(file->vnode); - data = file->vnode->internal; - - if (file->f_pos + len > filesize) - { - len = filesize - file->f_pos; - } - if (!len) - return len; - - ret = _readfile(buf, data, file->f_pos, len); - if (ret <= 0) - return ret; - - file->f_pos += ret; - return ret; -} + // uart_sendlinek("in fat32_read\n"); + unsigned char filedata_buf[BLOCK_SIZE]; + struct fat32_inode *inode = file->vnode->internal; + readblock(inode->data_block_cnt, filedata_buf); + len = len > inode->datasize ? inode->datasize : len; + memcpy(buf, filedata_buf, len); + return len; +}; int fat32_open(struct vnode *file_node, struct file **target) { + // uart_sendlinek("fat32_f_ops addr: 0x%x\n", file_node->f_ops); (*target)->vnode = file_node; - (*target)->f_pos = 0; (*target)->f_ops = file_node->f_ops; + (*target)->f_pos = 0; return 0; -} - +}; int fat32_close(struct file *file) { - file->vnode = NULL; - file->f_pos = 0; - file->f_ops = NULL; + kfree(file); return 0; -} - +}; long fat32_lseek64(struct file *file, long offset, int whence) { - int filesize; - int base; - - if (!fat32_isdir(file->vnode)) - return -1; - - filesize = fat32_getsize(file->vnode); - - if (filesize < 0) - return -1; - - switch (whence) - { - case SEEK_SET: - base = 0; - break; - case SEEK_CUR: - base = file->f_pos; - break; - case SEEK_END: - base = filesize; - break; - default: - return -1; - } - - if (base + offset > filesize) - { - return -1; - } - file->f_pos = base + offset; - return 0; -} - +}; int fat32_sync(struct filesystem *fs) { - struct fat_mount_t *entry; - - list_for_each_entry(entry, &mounts, list) - { - _sync_dir(entry->mount->root); - } - return 0; -} - -// ------------------------------------------------------------------------ -// Utils -// - -unsigned int get_next_cluster(unsigned int fat_lba, unsigned int cluster_id) -{ - struct cluster_entry_t *ce; - unsigned int idx; - unsigned char buf[BLOCK_SIZE]; - - if (cluster_id >= INVALID_CID) - { - return cluster_id; - } - - // Get fat allocation table and its cluster entry in Data region - fat_lba += cluster_id / CLUSTER_ENTRY_PER_BLOCK; - idx = cluster_id % CLUSTER_ENTRY_PER_BLOCK; - - readblock(fat_lba, buf); - ce = &(((struct cluster_entry_t *)buf)[idx]); - - return ce->val; -} +}; -unsigned int alloc_cluster(struct fat_info_t *fat, unsigned int prev_cid) +int fat32_op_deny() { - struct cluster_entry_t *ce; - unsigned int fat_lba; - unsigned int cid; - int found; - unsigned char buf[BLOCK_SIZE]; - - fat_lba = fat->fat_lba; - cid = 0; - // find unused cluster by clusters -> fats - while (fat_lba < fat->cluster_lba) - { - found = 0; - readblock(fat_lba, buf); - - for (int i = 0; i < CLUSTER_ENTRY_PER_BLOCK; ++i) - { - ce = &(((struct cluster_entry_t *)buf)[i]); - - if (!ce->val) - { - found = 1; - break; - } - - ++cid; - } - - if (found) - { - break; - } - fat_lba += 1; - } - // Only called if prev_cid is larger than 0xfffffff8, realloc ce; - if (found && prev_cid) - { - unsigned int target_lba; - unsigned int target_idx; - - target_lba = fat_lba + prev_cid / CLUSTER_ENTRY_PER_BLOCK; - target_idx = prev_cid % CLUSTER_ENTRY_PER_BLOCK; - readblock(target_lba, buf); - ce = &(((struct cluster_entry_t *)buf)[target_idx]); - ce->val = cid; - writeblock(target_lba, buf); - } - - if (!found) - { - uart_sendlinek("fat32 alloc_cluster: No space!"); - return -1; - } - - return cid; + return -1; } -/* vnode_operations methods */ -struct vnode *_create_vnode(struct vnode *parent, const char *name, unsigned int type, unsigned int cid, unsigned int size) +void fat32_dump(struct vnode *vnode, int level) { - struct vnode *node; - struct fat32_inode *info, *data; - char *buf; - int len; - - info = parent->internal; - len = strlen(name); - - buf = kmalloc(len + 1); - node = kmalloc(sizeof(struct vnode)); - data = kmalloc(sizeof(struct fat32_inode)); - - strcpy(buf, name); - - data->name = buf; - data->node = node; - data->fat = info->fat; - data->cid = cid; - data->type = type; - - if (type == FAT_DIR) - { - struct fat_dir_t *dir; - dir = kmalloc(sizeof(struct fat_dir_t)); - INIT_LIST_HEAD(&dir->list); - data->dir = dir; - } - else - { - struct fat_file_t *file; - file = kmalloc(sizeof(struct fat_file_t)); - INIT_LIST_HEAD(&file->list); - file->size = size; - data->file = file; - } - - node->mount = parent->mount; - node->v_ops = &fat32_v_ops; - node->f_ops = &fat32_f_ops; - node->parent = parent; - node->internal = data; - - // attach to parent's dir_t or file_t list - list_add(&data->list, &info->dir->list); - - return node; } -int _lookup_cache(struct vnode *dir_node, struct vnode **target, const char *component_name) +void fat32_ls(struct vnode *vnode) { - struct fat32_inode *data, *entry; - struct fat_dir_t *dir; - int found; - - data = dir_node->internal; - dir = data->dir; - found = 0; - - list_for_each_entry(entry, &dir->list, list) + // uart_sendlinek("in fat32_ls\n"); + char name_array[16]; + struct fat32_inode *inode = (struct fat32_inode *)vnode->internal; + int child_idx = 0; + for (; child_idx <= 16; child_idx++) { - if (!strcasecmp(component_name, entry->name)) - { // same as strcmp, but tr [:lower:] - found = 1; + if (!inode->entry[child_idx]) + { break; } + vnode = inode->entry[child_idx]; + // fat32_get_file_name(name_array,((struct fat32_inode *)vnode->internal)->sfn); + // uart_sendlinek("%s\n", name_array); + uart_sendlinek("%s\n", ((struct fat32_inode *)vnode->internal)->name); } - if (!found) - { - return -1; - } - *target = entry->node; - return 0; } - -struct dir_t *__lookup_fat32(struct vnode *dir_node, const char *component_name, unsigned char *buf, int *buflba) -{ - struct dir_t *dir; - struct fat32_inode *data; - struct fat_info_t *fat; - struct filename_t name; - unsigned int cid; - int found, dirend, lfn; - - data = dir_node->internal; - fat = data->fat; - cid = data->cid; - - found = 0; - dirend = 0; - - memset(&name, 0, sizeof(struct filename_t)); - - while (1) - { - int lba; - - lba = fat->cluster_lba + (cid - 2) * fat->bs.sector_per_cluster; // cluster start from #2 - readblock(lba, buf); - - // only called by sync, to update buffer - if (buflba) - { - *buflba = lba; - } - - for (int i = 0; i < DIR_PER_BLOCK; ++i) - { - unsigned char len; - dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * i]); - - if (dir->name[0] == 0) - { - dirend = 1; - break; - } - - if ((dir->attr & ATTR_LFN) == ATTR_LFN) - { - struct long_dir_t *ldir; - int n; - - lfn = 1; - - ldir = (struct long_dir_t *)dir; - n = (dir->name[0] & 0x3f) - 1; // every lfn entry has 16 bytes - // update filename_t if it is LFN - for (int i = 0; ldir->name1[i] != 0xff && i < 10; i += 2) - { - name.part[n].name[i / 2] = ldir->name1[i]; // LDIR_Name1 1th ~ 5th - } - for (int i = 0; ldir->name2[i] != 0xff && i < 12; i += 2) - { - name.part[n].name[5 + i / 2] = ldir->name2[i]; // LDIR_Name2 6th ~ 11th - } - for (int i = 0; ldir->name3[i] != 0xff && i < 4; i += 2) - { - name.part[n].name[11 + i / 2] = ldir->name3[i]; // LDIR_Name3 12th ~ 13th - } - - continue; - } - - if (lfn == 1) - { - if (!strcasecmp(component_name, (void *)name.fullname)) - { - found = 1; - break; - } - - lfn = 0; - memset(&name, 0, sizeof(struct filename_t)); - continue; - } - - lfn = 0; - len = 8; - - // SFN lookup - while (len) - { - if (dir->name[len - 1] != 0x20) - { - break; - } - len -= 1; - } - - memcpy((void *)name.fullname, (void *)dir->name, len); - name.fullname[len] = 0; - - len = 3; - - while (len) - { - if (dir->name[8 + len - 1] != 0x20) - { - break; - } - len -= 1; - } - - if (len >= 0) - { - strcat((void *)name.fullname, "."); - strncat((void *)name.fullname, (void *)&dir->name[8], len); - } - - if (!strcasecmp(component_name, (void *)name.fullname)) - { - found = 1; - break; - } - - memset(&name, 0, sizeof(struct filename_t)); - } - - if (found) - { - break; - } - - if (dirend) - { - break; - } - - // try next cluster and lookup again - cid = get_next_cluster(fat->fat_lba, cid); - - if (cid >= INVALID_CID) - { - break; - } - } - - if (!found) - { - return NULL; - } - - return dir; -} - -int _lookup_fat32(struct vnode *dir_node, struct vnode **target, const char *component_name) -{ - struct vnode *node; - struct dir_t *dir; - unsigned int type, cid; - unsigned char buf[BLOCK_SIZE]; - - dir = __lookup_fat32(dir_node, component_name, buf, NULL); - - if (!dir) - { - return -1; - } - - if (!(dir->attr & ATTR_FILE_DIR_MASK)) - { - return -1; - } - - cid = (dir->ch << 16) | dir->cl; // upper part of cluster id + lower part of cluster id - - if (dir->attr & ATTR_ARCHIVE) - { - type = FAT_FILE; - } - else - { - type = FAT_DIR; - } - - node = _create_vnode(dir_node, component_name, type, cid, dir->size); - - *target = node; - - return 0; -} - -int _writefile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block) -{ - struct fat_file_block_t *entry; - struct list_head *head; - - head = &data->file->list; - - if (list_empty(head)) - { - return -1; - } - - list_for_each_entry(entry, head, list) - { - *block = entry; - if (foid == entry->oid) - { // offset match - return 0; - } - } - - return -1; -} - -int _writefile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block) -{ - struct fat_info_t *info; - unsigned int curoid, curcid; - - info = data->fat; - - // block is from cache - if (*block) - { - curoid = (*block)->oid; - curcid = (*block)->cid; - - if (curoid == foid) - { // offset match - return 0; - } - - curoid++; - curcid = get_next_cluster(info->fat_lba, curcid); - } - else - { - curoid = 0; - curcid = fcid; - } - - // create new block in cache - while (1) - { - struct fat_file_block_t *newblock; - - newblock = kmalloc(sizeof(struct fat_file_block_t)); - - newblock->oid = curoid; - newblock->cid = curcid; - newblock->bufIsUpdated = 0; - newblock->isDirty = 1; - - list_add_tail(&newblock->list, &data->file->list); - - *block = newblock; - - if (curoid == foid) - { - return 0; - } - - curoid++; - curcid = get_next_cluster(info->fat_lba, curcid); - } -} - -int _writefile_cache(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block) -{ - int wsize; - - // if cache block is not updated yet, read from sdcard - if (!block->bufIsUpdated) - { - // read the data from sdcard - struct fat_info_t *info; - int lba; - - info = data->fat; - lba = info->cluster_lba + (block->cid - 2) * info->bs.sector_per_cluster; - - readblock(lba, block->buf); - - block->bufIsUpdated = 1; - } - - wsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; - memcpy((void *)&block->buf[bckoff], (void *)&buf[bufoff], wsize); - - return wsize; -} - -int _writefile_fat32(struct fat32_inode *data, unsigned long long bckoff, const unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid) -{ - struct list_head *head; - struct fat_info_t *info; - struct fat_file_block_t *block; - int lba; - int wsize; - - head = &data->file->list; - info = data->fat; - - block = kmalloc(sizeof(struct fat_file_block_t)); - - wsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; - // read the address from sdcard and write it - if (cid >= INVALID_CID) - { - memset(block->buf, 0, BLOCK_SIZE); - } - else - { - lba = info->cluster_lba + (cid - 2) * info->bs.sector_per_cluster; - - readblock(lba, block->buf); - } - - memcpy((void *)&block->buf[bckoff], (void *)&buf[bufoff], wsize); - - block->oid = oid; - block->cid = cid; - block->bufIsUpdated = 1; - block->isDirty = 1; // wait for sync - - list_add_tail(&block->list, head); - - return wsize; -} - -int _writefile(const void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len) -{ - struct fat_file_block_t *block; - struct list_head *head; - unsigned int foid; // first block id - unsigned int coid; // current block id - unsigned int cid; // target cluster id - unsigned long long bufoff, result; - int ret; - - block = NULL; - head = &data->file->list; - foid = fileoff / BLOCK_SIZE; - coid = 0; - cid = data->cid; - bufoff = 0; - result = 0; - - // Seek, find the particular offset - ret = _writefile_seek_cache(data, foid, &block); - - if (ret < 0) - { - ret = _writefile_seek_fat32(data, foid, cid, &block); - } - - if (ret < 0) - { - return 0; - } - - // Write - while (len) - { - unsigned long long bckoff; - - bckoff = (fileoff + result) % BLOCK_SIZE; - - if (&block->list != head) - { - // cache has the blocks to be written - ret = _writefile_cache(data, bckoff, buf, bufoff, len, block); - cid = block->cid; - block = list_first_entry(&block->list, struct fat_file_block_t, list); - } - else - { - // Read block from sdcard, create cache, then write it - cid = get_next_cluster(data->fat->fat_lba, cid); - ret = _writefile_fat32(data, bckoff, buf, bufoff, len, coid, cid); - } - - if (ret < 0) - { - break; - } - - bufoff += ret; - result += ret; - coid += 1; - len -= ret; - } - - return result; -} - -int _readfile_seek_cache(struct fat32_inode *data, unsigned int foid, struct fat_file_block_t **block) -{ - struct fat_file_block_t *entry; - struct list_head *head; - - // check the cache list - head = &data->file->list; - - // if cache is none, return not found - if (list_empty(head)) - { - return -1; - } - - // find that offset in cache - list_for_each_entry(entry, head, list) - { - *block = entry; - if (foid == entry->oid) - { - return 0; - } - } - - return -1; -} - -int _readfile_seek_fat32(struct fat32_inode *data, unsigned int foid, unsigned int fcid, struct fat_file_block_t **block) -{ - struct fat_info_t *info; - unsigned int curoid, curcid; - - info = data->fat; - - // if block found in cache, change to that offset in fat32 - if (*block) - { - curoid = (*block)->oid; - curcid = (*block)->cid; - - if (curoid == foid) - { - return 0; - } - - curoid++; - curcid = get_next_cluster(info->fat_lba, curcid); - - if (curcid >= INVALID_CID) - { - return -1; - } - } - else - { - curoid = 0; - curcid = fcid; - } - - while (1) - { - // add new offset block to cache - struct fat_file_block_t *newblock; - - newblock = kmalloc(sizeof(struct fat_file_block_t)); - - newblock->oid = curoid; - newblock->cid = curcid; - newblock->bufIsUpdated = 0; - newblock->isDirty = 0; - - list_add_tail(&newblock->list, &data->file->list); - - *block = newblock; - - if (curoid == foid) - { - return 0; - } - - curoid++; - curcid = get_next_cluster(info->fat_lba, curcid); - - if (curcid >= INVALID_CID) - { - return -1; - } - } -} - -int _readfile_cache(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned long long bufoff, unsigned int size, struct fat_file_block_t *block) -{ - int rsize; - - if (!block->bufIsUpdated) - { - // read the data from sdcard - struct fat_info_t *info; - int lba; - - info = data->fat; - lba = info->cluster_lba + (block->cid - 2) * info->bs.sector_per_cluster; - readblock(lba, block->buf); - - block->bufIsUpdated = 1; - } - - // if the size is overflow, resize it - rsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; - - memcpy((void *)&buf[bufoff], (void *)&block->buf[bckoff], rsize); - - return rsize; -} - -int _readfile_fat32(struct fat32_inode *data, unsigned long long bckoff, unsigned char *buf, unsigned int bufoff, unsigned int size, unsigned int oid, unsigned int cid) -{ - struct list_head *head; - struct fat_info_t *info; - struct fat_file_block_t *block; - int lba; - int rsize; - - head = &data->file->list; - info = data->fat; - - block = kmalloc(sizeof(struct fat_file_block_t)); - - rsize = size > BLOCK_SIZE - bckoff ? BLOCK_SIZE - bckoff : size; - lba = info->cluster_lba + (cid - 2) * info->bs.sector_per_cluster; - - // read from fat32 - readblock(lba, block->buf); - - memcpy((void *)&buf[bufoff], (void *)&block->buf[bckoff], rsize); - - block->oid = oid; - block->cid = cid; - block->bufIsUpdated = 1; - - list_add_tail(&block->list, head); - - return rsize; -} - -int _readfile(void *buf, struct fat32_inode *data, unsigned long long fileoff, unsigned long long len) -{ - struct fat_file_block_t *block; - struct list_head *head; - unsigned int foid; // first block id - unsigned int coid; // current block id - unsigned int cid; // target cluster id - unsigned long long bufoff, result; - int ret; - - block = NULL; - head = &data->file->list; - foid = fileoff / BLOCK_SIZE; - coid = 0; - cid = data->cid; - bufoff = 0; - result = 0; - - // Seek, find the particular offset - ret = _readfile_seek_cache(data, foid, &block); - if (ret < 0) - { - ret = _readfile_seek_fat32(data, foid, cid, &block); - } - - if (ret < 0) - { - return 0; - } - - // Read - while (len) - { - unsigned long long bckoff; - - bckoff = (fileoff + result) % BLOCK_SIZE; - - if (&block->list != head) - { - // cache found - ret = _readfile_cache(data, bckoff, buf, bufoff, len, block); - - cid = block->cid; - block = list_first_entry(&block->list, struct fat_file_block_t, list); - } - else - { - // Read block from sdcard, create cache - cid = get_next_cluster(data->fat->fat_lba, cid); - - if (cid >= INVALID_CID) - { - break; - } - - ret = _readfile_fat32(data, bckoff, buf, bufoff, len, coid, cid); - } - - if (ret < 0) - { - break; - } - - bufoff += ret; - result += ret; - coid += 1; - len -= ret; - } - - return result; -} - -void _do_sync_dir(struct vnode *dirnode) -{ - struct fat32_inode *data, *entry; - struct list_head *head; - struct dir_t *dir; - struct long_dir_t *ldir; - unsigned int cid; - int lba, idx, lfnidx; - unsigned char buf[BLOCK_SIZE]; - - data = dirnode->internal; - head = &data->dir->list; - cid = data->cid; - idx = 0; - lfnidx = 1; - - if (cid >= INVALID_CID) - { - uart_sendlinek("fat32 _do_sync_dir: invalid dirnode->data->cid"); - } - - // get the buf from dirnode's offset - lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; - readblock(lba, buf); - - list_for_each_entry(entry, head, list) - { - struct dir_t *origindir; - const char *name; - const char *ext; - int lfn, namelen, extpos, i, buflba; - unsigned char lookupbuf[BLOCK_SIZE]; - - name = entry->name; - - // If entry is a old file, update its size - origindir = __lookup_fat32(dirnode, name, lookupbuf, &buflba); - - if (origindir) - { - if (entry->type == FAT_FILE) - { - origindir->size = entry->file->size; - writeblock(buflba, lookupbuf); - } - continue; - } - - // Else if entry is a new file - ext = NULL; - extpos = -1; - - do - { - - namelen = strlen(name); - if (namelen >= 13) - { - lfn = 1; - break; - } - for (i = 0; i < namelen; ++i) - { - // get idx of extension name - if (name[namelen - 1 - i] == '.') - { - break; - } - } - if (i < namelen) - { - ext = &name[namelen - i]; - extpos = namelen - 1 - i; - } - if (i >= 4) - { - lfn = 1; - break; - } - if (namelen - 1 - i > 8) - { - // SFN: 8.3 - lfn = 1; - break; - } - - lfn = 0; - } while (0); - - // Seek idx to the end of dir - while (1) - { - dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * idx]); - - if (dir->name[0] == 0) - { - break; - } - - idx += 1; - - if (idx >= 16) - { // if idx is over Directory Entry, create a new one - unsigned int newcid; - - writeblock(lba, buf); - - newcid = get_next_cluster(data->fat->fat_lba, cid); - if (newcid >= INVALID_CID) - { - newcid = alloc_cluster(data->fat, cid); - } - - cid = newcid; - - lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; - - readblock(lba, buf); - idx = 0; - } - } - - // Write LFN - if (lfn) - { - int ord; - int first; - - ord = ((namelen - 1) / 13) + 1; - first = 0x40; // LAST_LONG_ENTRY flag in LFN LDIR_Ord - - for (; ord > 0; --ord) - { - int end; - ldir = (struct long_dir_t *)(&buf[sizeof(struct long_dir_t) * idx]); - - ldir->order = first | ord; - ldir->attr = ATTR_LFN; - ldir->type = 0; - // TODO: Calculate checksum, SFN + LFN - ldir->checksum = 0; - ldir->fstcluslo = 0; - - first = 0; - end = 0; - - for (i = 0; i < 10; i += 2) - { - if (end) - { // padding 0xff if filename end - ldir->name1[i] = 0xff; - ldir->name1[i + 1] = 0xff; - } - else - { - ldir->name1[i] = name[(ord - 1) * 13 + i / 2]; - ldir->name1[i + 1] = 0; - if (ldir->name1[i] == 0) - { - end = 1; - } - } - } - for (i = 0; i < 12; i += 2) - { - if (end) - { - ldir->name2[i] = 0xff; - ldir->name2[i + 1] = 0xff; - } - else - { - ldir->name2[i] = name[(ord - 1) * 13 + 5 + i / 2]; - ldir->name2[i + 1] = 0; - if (ldir->name2[i] == 0) - { - end = 1; - } - } - } - for (i = 0; i < 4; i += 2) - { - if (end) - { - ldir->name3[i] = 0xff; - ldir->name3[i + 1] = 0xff; - } - else - { - ldir->name3[i] = name[(ord - 1) * 13 + 11 + i / 2]; - ldir->name3[i + 1] = 0; - if (ldir->name3[i] == 0) - { - end = 1; - } - } - } - - idx += 1; - - if (idx >= 16) - { - unsigned int newcid; - - writeblock(lba, buf); - - newcid = get_next_cluster(data->fat->fat_lba, cid); - if (newcid >= INVALID_CID) - { - newcid = alloc_cluster(data->fat, cid); - } - - cid = newcid; - - lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; - readblock(lba, buf); - - idx = 0; - } - } - } - - // Write SFN - dir = (struct dir_t *)(&buf[sizeof(struct dir_t) * idx]); - - // TODO: Set these properties properly - dir->ntres = 0; - dir->crttimetenth = 0; - dir->crttime = 0; - dir->crtdate = 0; - dir->lstaccdate = 0; - dir->wrttime = 0; - dir->wrtdate = 0; - - if (entry->type == FAT_DIR) - { - dir->attr = ATTR_DIRECTORY; - dir->size = 0; - } - else - { - dir->attr = ATTR_ARCHIVE; - dir->size = entry->file->size; - } - - if (entry->cid >= INVALID_CID) - { - entry->cid = alloc_cluster(data->fat, 0); - } - - dir->ch = (entry->cid >> 16) & 0xffff; - dir->cl = entry->cid & 0xffff; - - if (lfn) - { - int lfni; - - // Creating SFN body - // TODO: handle lfnidx - for (i = 7, lfni = lfnidx; i >= 0 && lfni;) - { - dir->name[i--] = '0' + lfni % 10; - lfni /= 10; - } - - lfnidx++; - // numeric-tail: ~n (1 <= n <= 6) - dir->name[i--] = '~'; - - // TODO: handle letter case - memcpy((void *)dir->name, name, i + 1); - } - else - { - // TODO: handle letter case - for (i = 0; i != extpos && name[i]; ++i) - { - dir->name[i] = name[i]; - } - - for (; i < 8; ++i) - { - dir->name[i] = ' '; // in SFN, each part is padded with space - } - } - - // SFN format: 8.3 - // TODO: handle letter case - for (i = 0; i < 3 && ext[i]; ++i) - { - dir->name[8 + i] = ext[i]; - } - - for (; i < 3; ++i) - { - dir->name[8 + i] = ' '; - } - - idx += 1; - - if (idx >= 16) - { - int newcid; - - writeblock(lba, buf); - - newcid = get_next_cluster(data->fat->fat_lba, cid); - if (newcid >= INVALID_CID) - { - newcid = alloc_cluster(data->fat, cid); - } - - cid = newcid; - - lba = data->fat->cluster_lba + (cid - 2) * data->fat->bs.sector_per_cluster; - - // TODO: Cache data block of directory - readblock(lba, buf); - - idx = 0; - } - } - - if (idx) - { - writeblock(lba, buf); - } -} - -void _do_sync_file(struct vnode *filenode) -{ - struct fat_file_block_t *entry; - struct fat32_inode *data; - struct list_head *head; - unsigned int cid; - - data = filenode->internal; - head = &data->file->list; - cid = data->cid; - - if (cid >= INVALID_CID) - { - // uart_sendlinek("fat32 _do_sync_file: invalid cid"); - return; - } - - list_for_each_entry(entry, head, list) - { - int lba; - - if (entry->oid == 0) - { - // cache is valid but not sync'd, just an informational warning - if (!(entry->cid >= INVALID_CID) && data->cid != entry->cid) - { - uart_sendlinek("_do_sync_file: cid isn't sync"); - } - - entry->cid = data->cid; - } - - if (entry->cid >= INVALID_CID) - { - entry->cid = alloc_cluster(data->fat, cid); - } - - // if the file is sync'd, pass - if (!entry->isDirty) - { - continue; - } - - // cache buf is not updated, initialize it to avoid error - if (!entry->bufIsUpdated) - { - memset(entry->buf, 0, BLOCK_SIZE); - entry->bufIsUpdated = 1; - } - - // sync to fat32 fs - lba = data->fat->cluster_lba + (entry->cid - 2) * data->fat->bs.sector_per_cluster; - writeblock(lba, entry->buf); - - entry->isDirty = 0; - - cid = entry->cid; - } -} - -void _sync_dir(struct vnode *dirnode) -{ - struct fat32_inode *data, *entry; - struct list_head *head; - - // Init: dirnode is mounted fs - data = dirnode->internal; - head = &data->dir->list; - - _do_sync_dir(dirnode); - - list_for_each_entry(entry, head, list) - { - if (entry->type == FAT_DIR) - { - _sync_dir(entry->node); // recursive to next dirnode - } - else - { - _do_sync_file(entry->node); - } - } -} - -int fat32_op_deny() -{ - return -1; -} - -void fat32_dump(struct vnode *vnode, int level) -{ -} - -void fat32_ls(struct vnode *vnode) -{ - uart_sendlinek("in fat32_ls\n"); - struct fat32_inode *inode = (struct fat32_inode *)vnode->internal; - int child_idx = 0; - for (; child_idx <= 16; child_idx++) - { - if (!inode->entry[child_idx]) - { - // break; - } - vnode = inode->entry[child_idx]; - uart_sendlinek("%s\n", ((struct fat32_inode *)vnode->internal)->name); - } -} \ No newline at end of file