From f585cf0b409ec94f6a3fe30701fd8b8aa6b31287 Mon Sep 17 00:00:00 2001 From: "ivan.pavlovic" <ivan.pavlovic@hes-so.ch> Date: Sat, 11 Jan 2025 16:53:09 +0100 Subject: [PATCH] Keyboard done --- guest/guest.bin | Bin 3501 -> 3637 bytes guest/guest_main.c | 30 +- guest/guest_main.o | Bin 1912 -> 2072 bytes guest/idt.c | 10 + guest/idt.d | 2 +- guest/idt.o | Bin 1512 -> 1676 bytes guest/idt_asm.o | Bin 624 -> 640 bytes guest/idt_asm.s | 5 + shared/hypercall_params.h | 4 + vmm/peripheriques/disk/disk.c | 8 +- vmm/peripheriques/disk/disk.o | Bin 5448 -> 4912 bytes vmm/peripheriques/gfx_init/gfx_init.c | 2 +- vmm/peripheriques/gfx_init/gfx_init.o | Bin 2832 -> 2528 bytes vmm/peripheriques/keyboard/keyboard.c | 13 + vmm/peripheriques/keyboard/keyboard.d | 4 + vmm/peripheriques/keyboard/keyboard.h | 17 ++ vmm/peripheriques/keyboard/keyboard.o | Bin 0 -> 1336 bytes vmm/peripheriques/peripheriques.c | 53 +++- vmm/peripheriques/peripheriques.d | 5 +- vmm/peripheriques/peripheriques.h | 3 +- vmm/peripheriques/peripheriques.o | Bin 4752 -> 4616 bytes .../sprites/content/sprite_content.c | 4 +- .../sprites/content/sprite_content.o | Bin 3664 -> 3256 bytes .../sprites/position/sprite_position.c | 4 +- .../sprites/position/sprite_position.o | Bin 2880 -> 2472 bytes .../sprites/visibility/sprite_visibility.c | 4 +- .../sprites/visibility/sprite_visibility.o | Bin 2656 -> 2272 bytes vmm/peripheriques/state_machine.h | 1 + vmm/peripheriques/timer/timer.c | 2 +- vmm/peripheriques/timer/timer.o | Bin 2280 -> 2072 bytes vmm/vmm | Bin 35376 -> 35680 bytes vmm/vmm.c | 260 ++++++++++++------ vmm/vmm.d | 5 +- vmm/vmm.o | Bin 12456 -> 13528 bytes 34 files changed, 318 insertions(+), 118 deletions(-) create mode 100644 vmm/peripheriques/keyboard/keyboard.c create mode 100644 vmm/peripheriques/keyboard/keyboard.d create mode 100644 vmm/peripheriques/keyboard/keyboard.h create mode 100644 vmm/peripheriques/keyboard/keyboard.o diff --git a/guest/guest.bin b/guest/guest.bin index 759ecaeecba1bf277b968267be9c0982f1802b7f..3aeb9ac215e6ea70448c7764cd5014a429ca2b56 100755 GIT binary patch delta 1073 zcmZ20y;WvHKI7eq1>(ZjIT#q4j|g<Tax}l;2*`4Hahqe}fANVMC7GHyCjOV7_*#g` zpJU>G%X$%r!U-o2hju<~epB%xjh%tv#kYU||2Mzk$+*GE!0^KP|NsBZM+BPRaAZti zWMIgMU}9i+kpK}q?)rs+fq~(*|3U{o1_s*&ZHx>h&R}*x#tTjchOCrc*9ieHE;ECj z)BJ`9%>4*5{)oUr2fj!KhUOpArR>LDzc4Z|FdSzE83Qt<x%LY~$?6FZcXhjREEeGd zNlWlCFo>RwW<Sm<!^gm|G2@=qaaILB28JcolbI&Og8UHN{6?f(RDy5v9!5V;kn)8f zl?NZNb{+z=3@<DO34qxLU$A2neISM=s=zlnm?_Q*<b>TI?=qecyw&OYp)>SLx9f-Q z&@Y`A3@?El*zNjZF~~U}2QV;z?O;5#P=RmqYo>O_iIa<&br~ZjFJu-ob7TbvNVhA; z!5<v_+YW$YDFYM)FVvA_1Yj~>85tN}@Ul*R%PhzEb}|o(2IG;*rYyRQD<&ti6f>#t zZN9<6&B*v=^ApxsruybL9L=>HjHN=&Z+Nm2Uff~;TeTPzvXJ0xej|}~oHap=f#E;< zjs!jihQ&!@3=GY0STYzm7#Ok`GC*Q4GJb)heb)?528LeO4<N%BviO3sI09Y>f+JrB z;`zlO)t#a#d<+b`=5R7FSfeR^3XW`;;tW0phECBOK9GGp86Y>j@PIgQ!pXyFllOD@ zFtcPaPUhlNW;*+CvOcG1eQ-%)QHergT3TjuMq+v@gLi7Bm4a#t7bqfZ*%%m>voSC{ zVkZyhLiI8r>5pP(U=RTr&cMLHSQRw+Jf|qrov)Lhamq0r{yLeBOOEO6*U4&Ja!l90 zPIlvxV|wv*avGN$)9<g7+qmR}#lHRjKOLmok&mO5$%&VhY4YUL+^USFlkalLGd52C z%cab?V6q~&Jmcocj@;&q+a_0X%QNnqJd<0VQFHQ6Zga-S$sf7pmG1ud|6dc?oYbQ{ zEG!HR3JeSkF$@e0&wflc;;~|sn4HTaZ(R5L|9?ef#jy~@GEl|!zyJTAjV#YJee!;u FcK{3(Wz+xw delta 925 zcmdlgvsQXSKBMo%0&yXC4hDwiBLdy79L;Yy0<s)lcu)K%F>#|L(<k<c|K%sX7Gm1Z zKJmY0eG5BS-Gq~eLpz@~zu|cCosEIv#kYU||2Mzk$#CIhV0hvD|NsByBLX0P!?YO; zFSro=aFDz*gby*I+m&N+4=)45an=dE3=E=YquGzMPT^%>*qCw8>Nx8RUIvCG)svYf z#Dc5~Zhpfm(k(iHcd`JJpC?HDLXgsf4_G@7fmwzZ7J~%9?1L}Zv57tqLld3BJ9#-% zoE69oyBQc57#L3o-s*Jy&>8xr+x0_t=$Fn5hL^xD>~{UI7~~$10~i><b}$}VID>bx zJ##x_=;Y(fx)L(1;K1p2<>23T02GcHpBWh#Ua(H)VUd)1%>t7=_(K3D{}m*Ek!7+Y ziyY&|$q6hPj2)9ZS#%k5CU0jcW}3shS%;OIkuhhp1zRjrJtP#G-$<k#XFVXw!0?}a z#{pgjhQ)_O85o-1uw*cBFfe2>WPrq8H2(re!Y&R@28LeO56y3QvKX@Xg0eUQUg&_s zUk2j6#URz4qDOc^M(|{SjC~Qz0CwqwlZVqLAmD__0i52G=W{C6^Zx(;KZ1WH|3Y^8 z*!Z}p$modXBP{0`97{@4^GZ?`Qc@KR4M2d4!Lgv|@QPxEM2L){A{QuxU$QbV1hX+P z^s$qN#U!Dc*Fb5IL2T@k?{O<JrF@&5$0f(){cUm|mmE{*x5?|c<e1{VO+LpZ$5ilb z@;fd$rsi*x`MBkT=6(DB-x=f_M?Q{LCMRCj`pLJr)fiV!PUV(o+&a0HTbb#~_sQ?L zq}Uo57#N;^pUlTCHu(X!0^_U6j6Cv;pC&8v$TP-HcH}W<?44Z6BhMuGbMiVavB?{F zIGCh<PTs|1#ppBnE04VKrr-bnvmsmLbd-mMg@Hkafq@~0fq`Mh@Bjbvk>#1PC%f~$ F0|4e%K0p8f diff --git a/guest/guest_main.c b/guest/guest_main.c index 33bc27d..3611921 100644 --- a/guest/guest_main.c +++ b/guest/guest_main.c @@ -1,4 +1,5 @@ #include <stdint.h> +#include <stdio.h> #include "idt.h" #include "utils.h" #include "pmio.h" @@ -15,6 +16,8 @@ #define timer_sleep timer_sleep_phys #endif +extern uint32_t key; + void timer_sleep_pv(int usec) { hyper_timer_sleep_params_t *timer_sleep_params = (hyper_timer_sleep_params_t*)(SHARED_STORAGE_ADDRESS); timer_sleep_params->us = usec; @@ -66,8 +69,29 @@ void guest_main() { // console_pv("Débloquage du display!\n"); // affichage_pv(400, 300); - console_pv("Attente de 100000\n"); + //console_pv("Attente de 100000\n"); // timer_sleep(10000000); - timer_sleep_phys(10000000); - console_pv("Après attente!!\n"); + //timer_sleep_phys(10000000); + //console_pv("Après attente!!\n"); + + console_pv("Start affichage"); + affichage_pv(600, 400); + + int quit = 0; + + while (quit == 0) + { + if (key != 100000){ + char buffer[100]; + snprintf(buffer, 100, "Key: %d\n", key); + console_pv(buffer); + + if( key == 27){ + quit = 1; + } + + key = 100000; + } + } + } diff --git a/guest/guest_main.o b/guest/guest_main.o index cbc944be68e926c84b77b2cf92e4683f2d3acae0..d0161fb98f957fe75efcbfdb35053beac7cb5745 100644 GIT binary patch delta 447 zcmeytH$z~80^^H~ib9O_6)*n$|NsBRw}1ctH^1S@U|?Wi0E;vq5omtHkuiahfgvM; z2_bmg^$SSNYyX8H%635;BSVQZm>rNIz`($emD1}vApl_n4>A|5uK9;_Df@BPFN_Qf z49B%tLB@bgX|DakP_lZ$gp-GZOA?Dp6cW?YGLthB(^DC|Q!A|$R8uxjVboz1o(@v) z$j8yj<iyL$H2EkG3(MroOg9;)PhQI`E?5DQg<_CvY9?=GZs*TVtz;<9D=5m$D@kKu zV3=&p;%TSB$iTqF&A?#E$iTqJ&%odcrM*Ek3j;$KNM3+}Ar(Y(F)-wU#Q7N*>cRBn zSuC#@Cr)l<Rc777!obimc`d6l<I%|%S=GU$_+$Y#0oJ383=EQ!RoRpo?@jh(Q)m1& zxsXkr@z3O$Z0bxZOp_0>sWI8GPJYFv#wNqez#zalS&UtYRfmOvp>?t?yRt+HD+5Cj M)Gr_k6kZ@200<j?xc~qF delta 297 zcmbOs@PluH0;9)9MIpvSju(Ia|NsBu+rR(+o8RzcFfcGMfJK^*2!Qwv(`KOXg^}bZ zoILDUQj(filB$rBs$ggU0$dD^1x1Hf6e}b`WE2%Q-(l2Y6m|v~?8wK_%H+h$T7Q&> zg@s|VH1kbPkhl;7BSZdVS(f(6TUb2Alo=TqnAjN@^cWc!7+Dw?j6r;^$yThd7;Pu3 zvMICLurM$rO!j3{W-Ods$fgb^#V2oI6JRZ5WMEL8tjH`p`39Q+<Fv^y+0+>~O%`NV zXWTN`l3ktY4&&q`b~UCsER(y~)!42uF)(~!n7oZ$iS-CG149K^;|F#D)+;Ow3`HOw E0O|x@82|tP diff --git a/guest/idt.c b/guest/idt.c index f49386d..2677ac4 100644 --- a/guest/idt.c +++ b/guest/idt.c @@ -2,9 +2,14 @@ #include "utils.h" #include "descriptors.h" #include "x86.h" +#include "pmio.h" #define GDT_KERNEL_CODE_SELECTOR 0x08 +// My test +uint32_t key; +// -------- + // Structure of an IDT descriptor. There are 3 types of descriptors: // task-gates, interrupt-gates, trap-gates. // See 5.11 of Intel 64 & IA32 architectures software developer's manual for more details. @@ -53,9 +58,13 @@ static idt_entry_t idt_build_entry(uint16_t selector, uint32_t offset, uint8_t t // Low level handler defined in idt_asm.s void _irq0(); +void _irq1(); // IRQ handler void irq_handler(uint32_t irq_number) { + if (irq_number == 1){ + key = ind(0x60); + } } void idt_init() { @@ -66,6 +75,7 @@ void idt_init() { memset(idt, 0, sizeof(idt)); idt[0] = idt_build_entry(GDT_KERNEL_CODE_SELECTOR, (uint32_t)_irq0, TYPE_INTERRUPT_GATE, DPL_KERNEL); + idt[1] = idt_build_entry(GDT_KERNEL_CODE_SELECTOR, (uint32_t)_irq1, TYPE_INTERRUPT_GATE, DPL_KERNEL); idt_load(&idt_ptr); } diff --git a/guest/idt.d b/guest/idt.d index 65b389d..b6670f0 100644 --- a/guest/idt.d +++ b/guest/idt.d @@ -1 +1 @@ -idt.o: idt.c idt.h utils.h descriptors.h x86.h +idt.o: idt.c idt.h utils.h descriptors.h x86.h pmio.h diff --git a/guest/idt.o b/guest/idt.o index 43d2c0acb517a821f18afa93c9c2cfe0ab72afb9..49136b163198f4506c134f23c97b4a027fc214c0 100644 GIT binary patch delta 638 zcmaFC-NQRUfvJUMqS9>V<~JP8wH%D4Ld|b@vJzhW`Tzfa^AUl?3=9km6HXou?R?t& zMk4Jvs{#iD!+-W23JeSki<LMS7@FU(WH4|rFk~@gC`^1RFChrlC)4fvp*!@;Vvw>< zQ56OThKV0UWS{;6nF*8AU|?YA6xCq>nZc8xFj<jNa<U_1yS^gGN=H79RwgH2*4U#w zEG!HRG7Jn1F$@e0%NZCLW+TfpO`rUo(Nhp)56Bga3@i-X3=9kklLMLL>p==x7#J7? z8CV$985kJa7#J8prVBAJG8ls-p;&-{fx#TfbdbCQR1QRe<lR9GC<gI;p==NZ;s=8m zPz>TTWTs5s&!kYFom$C|SyULGk(if~lUl@(nU}(lnNkv;nU`6@keixYoLa&VpIKCB z045E=ayj{lDGW0h7#Ns185kBYFfcH(Gcarb(aa1C+oALxD191AUjV7+W?;Ah;`1;t z`~=a=1`G`U!3+il7DfgJMqUO6RS?b0z@QDKjiIy!BLf2y-{dIfLrhMLljT^HSUZ>* z7%C>avM4i_O@7ECKDmKKfVF{<fkAEZR2F5%hRHiw)EVbYeh4NxS=AYjOg3ayXJTNP o9L1`}YQx09@L_T*t1_z&GXq1+WJV_8$p=^kSS45(7_vY-0NiVS?EnA( delta 493 zcmeC-eZf6Jf$0JBM5Wmp6JigCc0O%>BawETm4SnS;XnHh1_lO(#Y`Lw49#y?GC*Qk z3>gfQ80C$0{{R2qd_<<(^+R{)m&G7uouVuZAay)obua#a6$nf?c^D+gz`!uMjB%1a z8;Ik`$I;5<#LMb*l!t|dfkB3Wfgy&0fuV<ifgvARo+*2>Ig_U#NC;##BLfQqH;6NN zB9pvr8v_Fa$TT4aMh1N(-5|aNNEH+dFfcIKL)jn-#CM%6%WPDiSyULGk(if~lUl@( znNkv;nU`6@keixYoLa&VpIKCB02a;3PfTH8V3^9lz`)4Nz%U0&FND$?p!8M-1_mZh z28O*LJ{JSSJrK>z!0-f0zk$*pLF%{}7!(*LGqLPr{5{!`NqF)V76DcsW(J0U$uC)y z8TBXgvZ}K>FfuT(O}1oJW^|Yw%c{;4!#LTFNo?{QRsqJC$!l5FSz8zx7%C=jWEGzL rhE;$mhI#ToRyEc?j0_A1CTp@Ov+iMHVDOt9$fnF%!py*s1+oVKBTHpO diff --git a/guest/idt_asm.o b/guest/idt_asm.o index fcb2a94a593a069eb5c5140768dbe5ef8bbfb6f6..075cc50f013c0946efde3f60635984055d3ac14d 100644 GIT binary patch delta 98 zcmeys(!e^QhS7autv_SK#Iwq*222bL4impBGZsviWK?2i$zq&r#ppb_kujcChk=1X rVDeK&eO?|02oPXkWKfta$fU^{pIKCBIN6d(QNWOafq{t~A`c<~q6HG5 delta 80 zcmZo*{lGGzhS7Oqtv_SI#Iwq*3QP<PRujJ}GbT)yWK^1L&*(I{mNA)Cje&uIXYx}< a{mCj!YLf$)6vP<7K$n4mfr$;w1QP&VdJpOV diff --git a/guest/idt_asm.s b/guest/idt_asm.s index bfd31a8..1f0519f 100644 --- a/guest/idt_asm.s +++ b/guest/idt_asm.s @@ -15,6 +15,11 @@ _irq0: push 0 ; put irq number on the stack jmp irq_handler_wrapper +global _irq1 +_irq1: + push 1 ; put irq number on the stack + jmp irq_handler_wrapper + extern irq_handler irq_handler_wrapper: diff --git a/shared/hypercall_params.h b/shared/hypercall_params.h index 4dace22..c009169 100644 --- a/shared/hypercall_params.h +++ b/shared/hypercall_params.h @@ -39,4 +39,8 @@ typedef struct { int32_t y ; // y position } __attribute__((packed)) hyper_sprite_position_params_t; +typedef struct { + uint32_t key ; // code of the pressed key +} __attribute__((packed)) hyper_keyboard_params_t; + #endif diff --git a/vmm/peripheriques/disk/disk.c b/vmm/peripheriques/disk/disk.c index bdba16d..a3a51fc 100644 --- a/vmm/peripheriques/disk/disk.c +++ b/vmm/peripheriques/disk/disk.c @@ -48,14 +48,14 @@ void disk_store_sector_4(void *addr) { } void disk_store_data(void *addr) { - printf("Storring on id=%ld\n", data_index); + //printf("Storring on id=%ld\n", data_index); buffer_16[data_index] = *(uint16_t *)addr; data_index++; if (data_index == SECTOR_SIZE/2) { stop_loop = true; - printf("Stopping loop after id=%ld\n", data_index); + //printf("Stopping loop after id=%ld\n", data_index); } } @@ -63,7 +63,7 @@ void disk_conclude(void *addr){ hyper_disk_params_t* tmp_params = addr == NULL ? &disk_params : (hyper_disk_params_t*) addr; - printf("Mem: %d\n", mem); + //printf("Mem: %d\n", mem); // Pv not working for some reason // Wrong data writen @@ -95,5 +95,5 @@ void disk_conclude(void *addr){ } fclose(disk); - printf("Storing data\n"); + //printf("Storing data\n"); } \ No newline at end of file diff --git a/vmm/peripheriques/disk/disk.o b/vmm/peripheriques/disk/disk.o index f85163d96494c7e0bc36af65822977ce741f47f3..a66604d41d53db9c4038ced2b648bfd317b5df8c 100644 GIT binary patch delta 913 zcmX@1wLxuy29p8*M6FlMowYwETQb^lu^(e)U|?WioDe&CKBJm^bL|O+QZA2f*Bc() z4lJ*QJi0|e(lCKdOw5dvg_y-AFJR%G?7*VH$THcJS$%Q>3&-RNW(6?407{>L(2U<E zFJzWyWSK0;;y+n{g=2CCi^AlE!s3$y1dS$hu_jKgV3nIZgY}AWAjlp^K7lqSXI?fY zA0BoN1_l`h28KN#aRvqkFGdCi2ADjvD<cm($K;7Dl9LOVSvK!sb77PO8^FN8Fo}VI zL5P8oK>?%zq;aw&$8^R=lQ(j>Gk%-g$RR#ifK!5zd9ov?_~Zi4dy_-Cbl4$wh)iC{ zCBAt9mja{YEr<vM69WSS3j+hg5~yJhCm-Y%XZ!&oCoAwsFmg>+<Pm3-nB2%C&S*3F zA&+=s1XLwRCn)Ux{D**QBylkY1_qdTKaw~oD*i&0|DO&O2iY!;q<-Gyi@f6XOQEtL zTR^%bq3+!P6$j~(K+<&xDh^XG3srv#Dh^T)G6UwSPe|fYNap;7h)-V5E6B(?nUPQ2 zQxIe%G?b)~RO%s#BfH-jDh{GRE_Z^u#2aLqYB)$3i)qQo;+tLhvl$r`CT|q@&X_fM zrJy<23QmYA6PPEz5;S94#WZ;$i`e7>W{$}YLJCX=m?kF)*@37<LUv3RyptaZ*>M(t zyv)GBkTf}wS$wjCuma~LsE7<$q(NAL=^YE)oCCrNoFAYH3??hG3s3$dtiq@;Sy9BE wNq}#1l87DW50G~l7#J2zUMXVEIfDb@BrZ_;pUfdD!MT7BBGL&q-+`F}06&M`X#fBK delta 1327 zcmdm>c0y}{29t;2M6Fk<&2I!eI%|J;bh9!rFfe#@9`ophvX1WniM#+2lf@bBG*pj) zB^dE5op5q;JfoU5UgJEPYfmtgazYJyE$GoL3bF;t-@Js8nUNjpjLGwv<R(90)|mW( zNnx^r0LNqrW(e&7r86Kj<G0C<%<_|1I4194_LwZd%rTjRMPc#=W{$}gES8fGFmYG} zm*f`}W#*+T<mV}5rr4_Hq;N3=m*f`|fW&h0^9vLb(@Ii{;BvmHxmF6QDO{5aSdw@^ znnCJP5=#;%Uu2P={Ep?C@kEfL9r*;>n4Edpn0k2FIT#pZ7#JA#fW#RX7)lu#7#Lvk z%ms`*>>QH~StK_Luz4^_f;BTRFic`#U=U(pWJmxh25FjH$UdF%>Ewg#;*%9P3>d#p z4&=~hWSQK^A<oDJCIu%qa(rbgD9X$$Nt;~CsmoDNT2jowz#uaDAgB1|1DpzsjQ1uB za*G>+qmF@rfr){E0TgwA|3ko6sQXwL7#KhS{|6%c|Ig%yT;hz(lO4Im8KuCaDwxy( zk&;$W2ZBr!W?*3W4b|lYk~Q=}k_Fi%2(=>;DvoYf&E!IEamMz^3%SKTCqmVLOa|%I zh3cIL6-U>*1}Y9x53>iPWh=<E`aL*guOo?zGcYi~eEk|p9Avv0$S4K|hR;xOknIvk z>VHASLADDai8F!(KyeA8K?Vgu4dR(Rkw@H64kU~e8DUUaHK;hq8Yv{>{3a{%iq}U% zWkD3k%zUV>M34Xj0|UCQTqJQ&QiOT33rQT=GxMS1APQuDHPrm&AOQx3Gz<$iLnOfB z$QJC!A$|-h4x&I7Oov)<4kQ5efb3>n-fTw3gvm4czB68(Jdxj=tAh)o?gY!^OZ;X` zqRf*wGKo!A5YS*!V4mzHU<abQ1nigs_$Qwdu;aV{3I_%Th82?q1<jc%SSNc4+A&RG z1#4O$sKGRYb@C}eJH``}Ifd+*Gz2Dl3E6QjV1rn3Ve&*FbIt-z2v2PCMIm#}9Rd(u J=VU<vc>t&iJAwcJ diff --git a/vmm/peripheriques/gfx_init/gfx_init.c b/vmm/peripheriques/gfx_init/gfx_init.c index afc4a6e..ced67f4 100644 --- a/vmm/peripheriques/gfx_init/gfx_init.c +++ b/vmm/peripheriques/gfx_init/gfx_init.c @@ -30,7 +30,7 @@ void gfx_init_conclude(void *addr){ display_width = tmp_params->width; display_height = tmp_params->height; - printf("Initialising display!!! Width: %d, Height: %d\n", display_width, display_height); + //printf("Initialising display!!! Width: %d, Height: %d\n", display_width, display_height); sem_post(&display_sem); } \ No newline at end of file diff --git a/vmm/peripheriques/gfx_init/gfx_init.o b/vmm/peripheriques/gfx_init/gfx_init.o index 73bd6e495105bbe4a8bbbd2bc7db3a95f116bbb1..c2a61831039f091a68e922550ab0a62173e3f8ed 100644 GIT binary patch delta 483 zcmbOr_CR=ohPVP70~|PjSq=>R415#qb0(gZo%ljwaswmhWI;xGMyAPzjOtL5b#f!4 z{p9zI3X=txrU?0iv^nw#v@tpJvN3t_uyagqWR#kGfyrR91akzV|KvjEddB&a4>F5S zR$!T|l#*Fokds&$U!0oDP@I|@Uyxs1!XN-LgMop8iGhKEWAa@VaY+uS2#E3m5pY>v zR`JPqSa=xICnvIsGv-Y;WEE#Dn>>+KeDV!ep2<3FJiIfY>KPdr7+5F&Wfh<Nhn0u* z21s=BMRwuI7Hs{K&$BILtesrQZZ7D-0+L{0SOK9JcqZ>;*Js>2xsg$P5{CxkfytU2 z_KXK6XL8sJet;@XKq%#qpDe*Cz_?(tCZ{^1|KvbUai%?tlN%YuCO5DPFvd@w$SKZw z0OSw`1_p!4h8*&Y<&!URh;x2`idBHciY8BF7Z(j+g_!FBp%{1=7#O%F+j41(W`F{Q nfq}sSs*9I_fq{8)EtfXu0%nNf6_Yn|nRCv7n$S48kX;@Cxusrh delta 724 zcmaDLJV9)NhPVJb0~|PjSq=;W4Ez)AbL6^3LHur35ZQUmqZiEZ=sdmyB=BP5a>a?K z<QSPJzEqz)fsJ#rB%?fxo_IrGasi`(o@ZWWNoHbBW^ra-x<X23aY0UErJ|yuLU?9M zNrshzYKo46M`~tzMhS?`HF-Xx;^h5|Q-uma<~#BUv@tpJvN7fGuyagKWR#lRz+^DF zfRTlnnSp)se5Ops!pWS>^^CJ7J2HziE(4L17cftjD=5m$D@kL3+7@4&n#)j}nj2q` zUtGe#ATW6%i#V@3$b1F{1||ju2F}U3EaH>ru<-CkA&GKLp35RW`3wsWWA5aGEaLUW z$Z`w}41fMZKn;>OGm>~GRGfu@fq@4}d;(M)WHT?4_zb8xNIf5tcmYJ5je(JYfq`}M zUl#GnI;=dr2Oz>=QTEBYtm2dZu<%R{VC`os%1=owNt}F_bur`o$&GC0f)_wWGB7Z3 zfJ|UuVBnp6l1-oS{^UeP@yP=08jKGnTe90TKA2p|ZZCKP9Kj3>2~gvCC!b`OpS*%Y zfb#%UxBg^Dc6mm>$q(7Z8Q)L-$*#^AK3S1NoQa!haw4PH<Oys7jOmjTIm9^yKt5z( zU@!n{sGq!$L!8qADpmm&tD3x!O<dH14PuuEgkk^%3io7QPHoX0P}Lbwt3koSGTE0? Yn^OVmrS+2=In6m6peA%qZe)`O0K8hOg8%>k diff --git a/vmm/peripheriques/keyboard/keyboard.c b/vmm/peripheriques/keyboard/keyboard.c new file mode 100644 index 0000000..661d996 --- /dev/null +++ b/vmm/peripheriques/keyboard/keyboard.c @@ -0,0 +1,13 @@ +#include "keyboard.h" + +state_t keyboard_states[] = { + {WRITE_KEY, 0x60, 0, 4, NULL}, + {EMULATE, 0, 0, 0, NULL} +}; + +state_machine_t keyboard_state_machine = { + .current_state = 0, + .states = keyboard_states +}; + +hyper_keyboard_params_t keyboard_params; \ No newline at end of file diff --git a/vmm/peripheriques/keyboard/keyboard.d b/vmm/peripheriques/keyboard/keyboard.d new file mode 100644 index 0000000..b0dee24 --- /dev/null +++ b/vmm/peripheriques/keyboard/keyboard.d @@ -0,0 +1,4 @@ +peripheriques/keyboard/keyboard.o: peripheriques/keyboard/keyboard.c \ + peripheriques/keyboard/keyboard.h \ + peripheriques/keyboard/../state_machine.h \ + peripheriques/keyboard/../../../shared/hypercall_params.h diff --git a/vmm/peripheriques/keyboard/keyboard.h b/vmm/peripheriques/keyboard/keyboard.h new file mode 100644 index 0000000..7e0e3ae --- /dev/null +++ b/vmm/peripheriques/keyboard/keyboard.h @@ -0,0 +1,17 @@ +#ifndef KEYBOARD_H +#define KEYBOARD_H + +#include <stdint.h> +#include <stdio.h> +#include <unistd.h> +#include "../state_machine.h" +#include "../../../shared/hypercall_params.h" + +extern state_t keyboard_states[]; +extern state_machine_t keyboard_state_machine; +extern hyper_keyboard_params_t keyboard_params; + +void timer_store(void *addr); +void timer_conclude(void *addr); + +#endif \ No newline at end of file diff --git a/vmm/peripheriques/keyboard/keyboard.o b/vmm/peripheriques/keyboard/keyboard.o new file mode 100644 index 0000000000000000000000000000000000000000..c679dbac3a8d9ca8e5f3203200c200d62756fd74 GIT binary patch literal 1336 zcmb<-^>JfjWMqH=Mg}_u1P><4z+l0IU^{@B4h%dD+;FuCU@-*2f?$GKtYDH1!rj@~ zN<qWjFH}>(&_vHj&rre0z{teF($D~G7|0$41_lO@`R;z93``7+2S8$ANd^W6MkpVf zpI~Z0G)SI>;p2Z08yWL3Ffa%*AUq!cm6QRCBWx0YiW`H)nV~!e2Dpms)XJp%#G(|v zWCj>BzPKc@B()fgAD^3;oROKAiV!YHEK1BRh8W2Kp}^sea1{dsgI;lEZb@PigI;k- z5rocwu}V@aN*MG~5=#;p^pc8;8T5)$a}vRP5KAv7KRGdnK`%K!H#aq}gh4Maza&-9 z-7i$PxFj(-8_G}5E7dC~$}dPQDyf7zfg(y895)OMY-pxH(iWN^R4uZoB2)|!(hymg zepoy~L>U-BX#~aw(drBg44|+?*FOOy$$%7ZP(CPqK$&355QqIR{jl@^R?NV_fX>%} z+5vMfOx*^kMG{Z}PN+JNTR}oFaYv~AkX!(gf#3xYiUE{9p-eCZH5Qz1KmuM+{UA0n z-h<3RV#D;qgrXQ27}yyYka7k@<^Y6ZKzA3+{ZMJJJ5bUuRN@1au7J{9P&;7yVg3h& q3wqpvv}8aX>I~u_VW==%M38}j0h|64P=&d0l@JD07{Xy-U;qG_GFO@a literal 0 HcmV?d00001 diff --git a/vmm/peripheriques/peripheriques.c b/vmm/peripheriques/peripheriques.c index 0e02a86..8b24ed0 100644 --- a/vmm/peripheriques/peripheriques.c +++ b/vmm/peripheriques/peripheriques.c @@ -8,25 +8,45 @@ state_machine_t* state_machines[NB_STATE_MACHINE] = { &disk_state_machine, &sprite_content_state_machine, &sprite_visibility_state_machine, - &sprite_position_state_machine + &sprite_position_state_machine, + &keyboard_state_machine }; void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value){ - printf("Checking... addr: 0x%lX, size: %d, value: %d\n", addr, size, value); + //printf("Checking... addr: 0x%lX, size: %d, value: %d\n", addr, size, value); for (int i = 0; i < NB_STATE_MACHINE; i++){ - printf("State machine n°%d\n", i); - printf("State machine state: %d\n", state_machines[i]->current_state); + //printf("State machine n°%d\n", i); + //printf("State machine state: %d\n", state_machines[i]->current_state); state_t tmp_state = state_machines[i]->states[state_machines[i]->current_state]; switch (tmp_state.act) { case WRITE: - printf("WRITE\n"); + //printf("WRITE\n"); if(tmp_state.address == addr && tmp_state.size == size){ - printf("Test OK\n"); + //printf("Test OK\n"); *((uint32_t *)addr_p) = (uint32_t)tmp_state.value; - printf("Wrote %ld on 0x%lX\n", tmp_state.value, addr); + //printf("Wrote %ld on 0x%lX\n", tmp_state.value, addr); + state_machines[i]->current_state += 1; + + if(tmp_state.callback != NULL){ + tmp_state.callback(addr_p); + } + } + else{ + state_machines[i]->current_state = 0; + } + break; + case WRITE_KEY: + //printf("WRITE_KEY\n"); + if(tmp_state.address == addr && tmp_state.size == size){ + printf("Test OK\n"); + *((uint32_t *)addr_p) = (uint32_t)keyboard_params.key; + printf("Wrote %d on 0x%lX\n", keyboard_params.key, addr); + + usleep(100000); + state_machines[i]->current_state += 1; if(tmp_state.callback != NULL){ @@ -38,10 +58,10 @@ void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value){ } break; case STORE: - printf("STORE\n"); + //printf("STORE\n"); if(tmp_state.address == addr && tmp_state.size == size){ - printf("Test OK\n"); + //printf("Test OK\n"); tmp_state.callback(addr_p); state_machines[i]->current_state += 1; } @@ -50,10 +70,10 @@ void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value){ } break; case STORE_LOOP: - printf("STORE_LOOP\n"); + //printf("STORE_LOOP\n"); if(tmp_state.address == addr && tmp_state.size == size){ - printf("Test OK\n"); + //printf("Test OK\n"); tmp_state.callback(addr_p); if (stop_loop){ state_machines[i]->current_state += 1; @@ -64,9 +84,9 @@ void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value){ } break; case EQUALS: - printf("EQUALS\n"); + //printf("EQUALS\n"); if(tmp_state.address == addr && tmp_state.size == size && tmp_state.value == value){ - printf("Test OK\n"); + //printf("Test OK\n"); state_machines[i]->current_state += 1; } else{ @@ -77,10 +97,13 @@ void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value){ break; } - printf("State machine state: %d\n", state_machines[i]->current_state); + //cprintf("State machine state: %d\n", state_machines[i]->current_state); if (state_machines[i]->states[state_machines[i]->current_state].act == EMULATE){ - state_machines[i]->states[state_machines[i]->current_state].callback(NULL); + if(state_machines[i]->states[state_machines[i]->current_state].callback != NULL){ + state_machines[i]->states[state_machines[i]->current_state].callback(NULL); + } + state_machines[i]->current_state = 0; } } diff --git a/vmm/peripheriques/peripheriques.d b/vmm/peripheriques/peripheriques.d index c4936e7..9695e32 100644 --- a/vmm/peripheriques/peripheriques.d +++ b/vmm/peripheriques/peripheriques.d @@ -14,4 +14,7 @@ peripheriques/peripheriques.o: peripheriques/peripheriques.c \ peripheriques/sprites/visibility/sprite_visibility.h \ peripheriques/sprites/visibility/../sprites.h \ peripheriques/sprites/position/sprite_position.h \ - peripheriques/sprites/position/../sprites.h + peripheriques/sprites/position/../sprites.h \ + peripheriques/keyboard/keyboard.h \ + peripheriques/keyboard/../state_machine.h \ + peripheriques/keyboard/../../../shared/hypercall_params.h diff --git a/vmm/peripheriques/peripheriques.h b/vmm/peripheriques/peripheriques.h index 6aadffa..afdc737 100644 --- a/vmm/peripheriques/peripheriques.h +++ b/vmm/peripheriques/peripheriques.h @@ -10,8 +10,9 @@ #include "sprites/content/sprite_content.h" #include "sprites/visibility/sprite_visibility.h" #include "sprites/position/sprite_position.h" +#include "keyboard/keyboard.h" -#define NB_STATE_MACHINE 6 +#define NB_STATE_MACHINE 7 void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value); diff --git a/vmm/peripheriques/peripheriques.o b/vmm/peripheriques/peripheriques.o index 9ca211e7e4f8933ade41de2a099d26236cb756f3..b045dc7a1c7766b669542cf895b2918bdb76a653 100644 GIT binary patch delta 1544 zcmbQB+MzN*L;M6U0~|PjSq=<>3<4AFrMQl}?g0tBT*@*zfyH~WB%_W83x7KgGXq2C z0gqmhR*<AeFDr=ZW?}M};n6D!VtX)N`2WD8+x3KprR$2)6#i|lH!NJ|ltz1WyI$x# z<k9WApi^M7AdAH056tqDMVQQ!qnH>NUWPI;Fu*kNw=QI0V1R1mZ=J%xzyP(!qx1L+ zkR9C+o4{sugI(a!9lE0P7(&?&kTS5^{R`R{C&#eJ!R(W1W@KP^S;vU5uQUj1SE=XZ zRwh>_CC14KEK-x@SlJ9-{s&nO^Gp;>U7$yID9DcsJUWm6zr?={?1YvBC6Q2%DKIKb z7G#lEs(xJw^HixHOtY&;cj$#~*BKs`he|D>8lomwv6!;3^0ywD9M9sz>Cx?=;L&=Z zBm^vdiY1YSjlVB&vOcTh<N#JSsgTs-5(R&6hVY{Nl2irN6ovde1%nFJoCvPTj;!L7 z+1cbLYp{g~-C<#1U~uFUXk&8bWpiz2X1+AJk8Kj8#bibH*^^z^MI>)AFfa%)FoJ># zjKLZh7#N;Sc4QZ4d<`algGg2;Mg|6f$&RcdlNmV<`DLe8Cgmp<rNkGPB$lMc=O!j+ zWagzZBxj^1XG6po3Q9|g8Q|&)5{nXZix~=vGV@B(7)pzCQd0}SHZm|Um`--&6lV+s zk%sG_f=mny49pA+3=&ZOE+~yI{t2Xuk!NxumpG#%h?Fdc`Ua-*&wmK0pL~&1yuKAl zmY;!v0VX>Uhxj}sagcjJ0Sa=;YN$AfFMwpuRwQvjB=M6F@yY32f{c$r?qrmh{E<tX zF#$|gfyp@_Qt}eW;S3B6APQtU%!RK&vWzT~H*$+JDuc-sFj)sC=Yq+7VDc826q>w{ zN1Ra)Os0Uz1~9n;L{3iNoltK8@(2S1IQn^@Y!D>_BA_k+x#BRCuK=Y%Vjvs~@e_jz znz#i>l7WFi15JE4R9pul&JFe=NX(Ua@+;m1=G2_T$sT;olP~ZoFy5K`k<VQ41_wl` z0VwDh7#R2_Tk`8O$*@j#WEGp-z^}n71Il-kFA4}xKESWRsQ}_JFfdq5{>X2x$pQ7# z3WymDd<+Z>AO%n};YrJNa-g7u21tg1fdLjKP(2Kw7=W=sw8LaUesRqWP@^kALLhfB zFfgz)FfgDS?K^p*fH+eJ>*Q4eYK&o%FA9h=ErB^+fH7^dprAPC3Yg843kBpE>m~;Z zh;!b6iaAU+6jYup!Y?AK0WGCr`2pk^p2>R!wFM>EAdc7ojSc?EKLzzgPk@}mz`(!> W6$PsS2ULKN1g8Vkw2sMz{PF-67+Ht_ literal 4752 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 PLIwtgX1GcS16@A=SBjY4 diff --git a/vmm/peripheriques/sprites/content/sprite_content.c b/vmm/peripheriques/sprites/content/sprite_content.c index a06e216..c0af462 100644 --- a/vmm/peripheriques/sprites/content/sprite_content.c +++ b/vmm/peripheriques/sprites/content/sprite_content.c @@ -55,7 +55,5 @@ void sprite_content_store_data(void *addr){ void sprite_content_conclude(void *addr){ - printf("Showing sprite SLOT: %d, WIDTH: %d, HEIGHT: %d\n", sprite_content_params.slot, sprite_content_params.width, sprite_content_params.height); - - usleep(10000000); + //printf("Showing sprite SLOT: %d, WIDTH: %d, HEIGHT: %d\n", sprite_content_params.slot, sprite_content_params.width, sprite_content_params.height); } \ No newline at end of file diff --git a/vmm/peripheriques/sprites/content/sprite_content.o b/vmm/peripheriques/sprites/content/sprite_content.o index e9e2e02761a9eb7a82a11bd22ef6f425f3c630d9..801b11bc51fe37d49bee9156f6a780495c4072f7 100644 GIT binary patch delta 669 zcmca0vqN%%hWHN-1~_m4vm6-s8TcmJpJ3~({V^f-@Z?4&*~wXqa*QmKI~mm(Stf5} zRG%EcBr(~6Ndt^OFbYiGz{oK<f=Pjqb#fq=#pH)fp9Q%=W;yZ+v@tpJvbpiFb4+ez zlAgrkF*$*ygOPjkOP2c0GguiJbwJ7(7#IYhG!p{@14!$i{}7;oEI#=xo46!MmJ=%K z3Z+51cqad46PM&=U|{$G(fU6eNtSQ2F1xrS4+8@O%;aJuS)R$UXtFIRvc2r$lVjL< z7^hDTWEY=&f}IEK3Rb9^#ZVgL3hv2oA!-G8A&K%aFfja{ypcm#5T*wtc>qLAp2#IU z`2`2h<U1TZyaJ3MAqEBz#W9(eQ+zTHCl9X&h|2&GWtnWtd1^90*Fwg#lMT7$Ctu)_ z5PShOv;nG)XYx-jeI{PU$$^YwlO4D<7zHM0a@#X1OkT-tFPOm&v0?&*V&IwllUsgr z1djk?!Q@OHbw>Zm6M4j$dYGV^1sLNeU*r*IoG@9FN1d^JvLKH*=K+vM85kILOg7|^ zXDph0kxN|k2h`XKn6V5D3|y0Id9_6=m?1(LP}hNCh-LC#UTw|?ED#yS$sc*mISZf( Iu@U4i09cNP%m4rY delta 1041 zcmdlXc|m4^hIjxM0~|PjSq=;W4Ez)APdGHc5%B1&{n5<}67CiSk^I|OA=H7+V;;R= zwnyjj9U!q6AYy;Rv>6Ow)`XLXCp$7JPu60Tn=HV@F*$%y0ZdmgDomch%rf~1qY4^r zGg*U4U~&N?$7Baaj!B#v`oS6b<(YZu3dIFQnI)+T!9M;WRtl;qItt;QE+HNeriZJi zy9Zd9YjQr*S0PuBD;)U*+L)Yq*_a%7*f}OUGD%II!0a*EfQf~dnSmXo0D>o9WbS8l zot(&0&&tTiz#uSLkWrYG1IiLv{E&rFpr9x-uOyA3v^Xa<wSa*^aPmYpab69Gb_ON} z1_qwVylmo<JPZsBoKR7)3m6!{vb>XR*~BIJ7#J9S{D**Ws49?N{>iy);*<Zd@h}!o z{>Uaic?BB}h{xN4q=t9$S*QtrAO`%OjwH)B`7hLVa8xibFf2xr<(aI@E*=W99j12| zk}N+11H*5qnHP}6k^OQFO&n&+T~IhUzC@B`VPIf@+42o44iXbU5@%q9NPxrzLE@7W z*@Y+fu=DU9fJlH9uutw~7nkIKihw8qs6G(IIe9O;xFk}VW$*wAGcbVlvQB=>eu}Lq zKP9mwaq?D<#Z2sslcPAz1Xr+u%wb><00lb(0|W2mg`E0~?vpQa+A{`B7UZ&LOqd+V zWiPk`YV8Dwa*#SMc|oWqs2BsohRK24>XLp?I}PCC5XOVa7rE3~K=C~JBBu!BpUHyU z>Rjmz4B(W<#4wqWNo;Ziw}N6lR6n}u2Fwt1c1(`sme;LfU|;}+7bI&!WI&_`G`UrP zI3OP}FfedWe#)&a_yVeb12kOtCNJa?pKQS+!8rpOef*OndCWNvKuzeJ+{i3ES%--S E06Y!GDF6Tf diff --git a/vmm/peripheriques/sprites/position/sprite_position.c b/vmm/peripheriques/sprites/position/sprite_position.c index 006319c..c26f799 100644 --- a/vmm/peripheriques/sprites/position/sprite_position.c +++ b/vmm/peripheriques/sprites/position/sprite_position.c @@ -29,7 +29,5 @@ void sprite_position_store_y(void *addr){ } void sprite_position_conclude(void *addr){ - printf("Showing sprite SLOT: %d, X: %d, Y: %d\n", sprite_position_params.slot, sprite_position_params.x, sprite_position_params.y); - - usleep(10000000); + //printf("Showing sprite SLOT: %d, X: %d, Y: %d\n", sprite_position_params.slot, sprite_position_params.x, sprite_position_params.y); } \ No newline at end of file diff --git a/vmm/peripheriques/sprites/position/sprite_position.o b/vmm/peripheriques/sprites/position/sprite_position.o index f1ee2bb632834dd7f877f619cae4c6eac68171de..9da0a592db38edc142945ab2c8ca888d4ab3b155 100644 GIT binary patch delta 498 zcmX>gwnBJ<hWHCs1~_m4vm6-s8TcmJ`-pYc{+JMZ7%YY$SSCJHXJnbo$*9iAG}#c1 zWS#8DZZVmINq({h(-uK)kS<3)fi@;*UN$!#c8<v#8Koy1FtSYMVb+-(z+Aw{J^3KB z`D6{2!$KgX41!>ifq{vEfq`=}FRQpGCj$e+-~SL`k1Wf;z`zLQ7eHwcp9RVWQ8PdU zR2}Q&zpUbu|FH7#zCaRXpRCI!KAD4qXL11B^2z_%7BU7-UdV1P=m0gw1FDv1@=JDo z#)*?ZGD%PF;N+R?z#+jnV{#;iJ>!DOGdb)9JD}<-5b8PPCwp)TFfCx59L1@|=s&rU zQ=DlJ<K&HuVv{$p3oyn{KFBG~c>v^O1_lO$$%!2DjOCLVImJ0YK*eT&#fl~$WS8en zfSJp{z`!**mrGl;0~ACI3=AKjGQ12749t_)a%po`Fhhh6PkzW{&Y1v>-Nwla+2sM5 CEm;@< delta 905 zcmZ1>d_Zi1hPVSe0~|PjSq=;W4Ez)AeH@zK2zYeX{^;ff33rQvNd9fC5b8kZF^^s_ z+oSXN4v^Rj5V5~u+6)FTYr@IHlM5L|8JQ<8RA*$Kcv5}x0w$J;UsO=3i3>O;9^jb# zfmK5-I3vG2GcR4CxS%MrBvm2U$3MhMK{Z83Ap$~0f+()Z^BEN<?`Pa9<jTOnz~IOy z(8lD<%f{ru!_G0ekWp�w#mW4U8<z%na<4_cJvzx=wavHfKG|z`!6dxsXwq^%RsP zGP#oZkWxWWW?o4eLuqkNYH9(<KoAxL5ey6rObiSRT$6oS#Ot{j7#RNkhX8wISq26M zMkqf7N`rMFiASM{!^}xU6aND-{(ml#I5PtS!=L~E&A?JsPze?W1_o}31X#QUNt_2s zykPP|7IEGgP+5>O*(R@L5ubdAg@+d$Lr_O@Ouow^&d4(PE6XOfqWqM^lEleNSr;>Q zPoBsmJlU6>dvZFP<m3Y!9Go|xM)6Lb$fnPDdh$Uwd&Ucs8QJX_A53;+w->wtP7VwV z6$o|g@{*wNfC_-A2OyU)Ffgc3=46*w^n*IW04#?f*rD2Fz^=H%&chPUz`!t>kwb(@ znQ3w%qZlX|fn2A=kj}us07}D99dI)=paKS9i|U~kK?UKeBA@~@K&o^>VGIgiNJfAw zVhCV^uoEB@11LvuPrk~bE&2hf-va6_J_ZH`mdT==+MF67gBTbXE`q%P4oFT(&J9qL JI$@%W3;+|kxLE)I diff --git a/vmm/peripheriques/sprites/visibility/sprite_visibility.c b/vmm/peripheriques/sprites/visibility/sprite_visibility.c index 896bdab..90e20cd 100644 --- a/vmm/peripheriques/sprites/visibility/sprite_visibility.c +++ b/vmm/peripheriques/sprites/visibility/sprite_visibility.c @@ -24,7 +24,5 @@ void sprite_visibility_store_toggle(void *addr){ } void sprite_visibility_conclude(void *addr){ - printf("Showing sprite SLOT: %d, VISIBILITY: %d\n", sprite_visibility_params.slot, sprite_visibility_params.toggle); - - usleep(10000000); + //printf("Showing sprite SLOT: %d, VISIBILITY: %d\n", sprite_visibility_params.slot, sprite_visibility_params.toggle); } \ No newline at end of file diff --git a/vmm/peripheriques/sprites/visibility/sprite_visibility.o b/vmm/peripheriques/sprites/visibility/sprite_visibility.o index 4105482dbfb26854589a9df0d65c21e8f5db8f21..f5ec981653ac8bc6357b95cecb080f09f42f3c85 100644 GIT binary patch delta 441 zcmaDL@<4EchPVPN0~|PjSq=>R415#q&3HO%e@uuy3>IUVcu;+E0wc%74+@M-lLZ;o z!KC=)07d~u*2#&C_LEOC%1?gII8~4vq~4KFppD6ym(7ibonvw$qx56}MwZEIm~<w8 zV2WVmp6tnNK6wN4K7IxUL6B+&1_mYu1_qAFy)5Fa91IK$e<v%l3Qw+K<>8$Hm1ksN zU|^l>%PKzEhn0u*21s<WBD?V94%Yt3@@xwkttTI3GZ#F-43c1AFn~}DJd-)u^%<)t zPh^swyn=&gass;qYc)u2@<LAG$rIQ$7#k+<WVaXm0M(ZOl4D>1>En=}oWUW$m@v7L zL!Hro@<I-ArW(e{iHu^CFR%$P#!r68A<o$VauovugTZ7+4td7%$%-7}oExBG6=1QV z$q(7YMFUtM=6XOV1|9|m2Cm7yoZ6xqAb&G3Fn~S8z`(%Ez`(#f`7Eb4Cj-<;`zAAT PnRCv7n$S4;Ae%e@Q2SBh delta 733 zcmaDL_&{WWhIj%S0~|PjSq=;W4Ez)A&3u~Q2zYeX{@~xn3KHkvb^*>h(0R<G7cA=0 zd3*;*_63O8-!N?k1DG}8<YABi95YXBRA*$KxKe%c1XhlTHxwY0z+?eNfr&E&CL1ss zXar~EmuKdsD-;(LWtOBW1pD}hSShHc=qQAF275Yr`gn#!g7{pM;~5nuH!w~SbY@^+ zU~uFUXk&8bWvk<1=a{U>C_UMM$zZYpBMUP#1N-E7rc6fX$tRi2S@$t8FbGUmWE5sS z3T25*W@O$gUr>~pSCYn1TAY)bS^zSSK@dzbFfcJNFmO&j%Pd~c$-uzy_df*KBg-O* zd!mW|fhhkUiX_g=z`y_#PlAfGFfcH1A&KW8iE~55g}_EZ9LK=G$iTqBI{7cN_+%Xx z9^L~`<seb^$+|4!lm9UDOb%e_XDiB2Ni0d6e3xZ0WAWrhR&&7ykW~x}3@e~ocqgA^ z)o0v1S&>nEvH+U~>t>MnWJM0)$pLH{j0YxHve^r2fTNg!Aps=Ez`(#e`6QeC<Q41! zoC`oUGB7Y`PHtqEXY`x=kWHNN<m8`h>Wtx&71_m^o-$5WWE7h`fmMJpeR3kZIOB`S zmF((_^^+H}i*rhV!j^%7p#rSAYVtx>anTN_RUR;_7#JA1C-ZV>i%x*5R)AW`$H2hA fGTE0yn{xvwL>U+u&P;CPFz37gHKB8IBda_BQg*Nv diff --git a/vmm/peripheriques/state_machine.h b/vmm/peripheriques/state_machine.h index 11c0fd6..4d4d7c6 100644 --- a/vmm/peripheriques/state_machine.h +++ b/vmm/peripheriques/state_machine.h @@ -7,6 +7,7 @@ typedef enum t_action_t { WRITE, + WRITE_KEY, STORE, STORE_LOOP, EQUALS, diff --git a/vmm/peripheriques/timer/timer.c b/vmm/peripheriques/timer/timer.c index fcc8978..180c370 100644 --- a/vmm/peripheriques/timer/timer.c +++ b/vmm/peripheriques/timer/timer.c @@ -20,6 +20,6 @@ void timer_store(void *addr){ void timer_conclude(void *addr){ hyper_timer_sleep_params_t* tmp_params = addr == NULL ? &timer_params : (hyper_timer_sleep_params_t*) addr; - printf("\nTime: %d\n", tmp_params->us); + // printf("\nTime: %d\n", tmp_params->us); usleep(tmp_params->us); } \ No newline at end of file diff --git a/vmm/peripheriques/timer/timer.o b/vmm/peripheriques/timer/timer.o index 84284c1e7d0cdeab224af08a1a65de8800d67c67..c998ddc48f6a3977b0dd715af3d190061ca4a6fc 100644 GIT binary patch delta 474 zcmaDMI7489#^eJW9Q+In3=9q+g291-pMh_pz4OF*a+4T2CZ14WWSaO=oso6&Ll%e0 zF^n>d43o<k%LGk8iXHg`+L)Yq+46bVIVKA-N>7$xGMJpe<iKb$c_EYkWDe$_@Y3R( z)YJlyVh|Pp5ey6rObiSR><kPHfBr*&F%EGTs5lD)0|N(=dXLG1EaH=YF!M})!_33m z0aeAwz`(#fS(c?~@^Y4ijNX$yS<M9nm?4rL5Q>3k@<djB#_q`nS?w9SCo{6yGcK6y z$Yw7XfvJv7UeExl3q~1CW@J}q@n>LQnC!?d!ss*EkzJiN9^{$HYuThHcd#o+mNPIg zfE)tyB1{{IZkT+KU0t_`fq?<!8Aw=z#36VA)OwhOJPZsBT$4pPv_)@#3}awmxB*ef ezzg<dD2F!Z2B;O0lRG)gIWIs>Xq@cHDh~k4E?4CM delta 606 zcmbOs@Ir8chWHB>1~_m4vm6)%82BgJJBuFk=w$_ocyu1$0is`kh>6vzlNebTnI|q( zpZtN5W#So?i4O!OF&c1jg=FTYS}CZea81@{l$#vDSRxbv(%{G^(8lD<%f{r*!_G1B zqtxUNj0Te!S(up_*eCNd1u_OqPGs_Djbvb85SaK;Wb#I)K<R>_%)F8`hSK7k)YJk7 z0gx#S3=B*R3=ABTWtqi2IT#oi{``jkHzZkRB=KOVILLdPNa6`d;#`w`nZ+m9F!S&h zKt&lD7#P?l*D{MUvP_=J+{9LtpORRTI9ZfsF=P7Vhm69L&#<TnW`OKrU|^_#YT}*D z$g0n{e6k^{J>&Apg{=0B2PSW1wHJH<Rp)_F$0k2{0h<IPH`FX1Nk0Y#29Tu&P&F_r zda@y#I!ibM1H<G(HW9}1$%Sm{lIaW#4D8U5fGGsg6_YozsY}*FjRJ)eNEC)wO#aBG zu3N>xzyJyhNF2lD7#K7_f(#4{FbD85FfedWc4gNV1qV1N%t7vBU|`?_nJ~GPU7M2w U>ahffH`rA;BcP^qLPS`20O+K1L;wH) diff --git a/vmm/vmm b/vmm/vmm index 97e079146cc757008d6e95c24a2090587129cae2..e8276973c100f06f69b8301a73bf605f2f5b4172 100755 GIT binary patch delta 12339 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 NG-o>AG?}YQ4FIB6H#z_S delta 12302 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 PX6!a+n%p?qs#^^JzNt6c diff --git a/vmm/vmm.c b/vmm/vmm.c index 6ba03fc..a74227c 100644 --- a/vmm/vmm.c +++ b/vmm/vmm.c @@ -20,30 +20,36 @@ #define SECTOR_SIZE 512 -typedef struct t_guest_os_t { - uint8_t* code; +typedef struct t_guest_os_t +{ + uint8_t *code; long codeSize; } guest_os_t; -guest_os_t* readByteCode(char* filePath){ +guest_os_t *readByteCode(char *filePath) +{ FILE *file = fopen(filePath, "rb"); - if (file == NULL) { + if (file == NULL) + { err(1, "fopen"); } - guest_os_t* guest_os = malloc(sizeof(guest_os_t)); + guest_os_t *guest_os = malloc(sizeof(guest_os_t)); fseek(file, 0, SEEK_END); guest_os->codeSize = ftell(file); fseek(file, 0, SEEK_SET); guest_os->code = malloc(guest_os->codeSize); - - fread(guest_os->code, 1, guest_os->codeSize, file); - if (ferror(file)) { + fread(guest_os->code, 1, guest_os->codeSize, file); + + if (ferror(file)) + { err(1, "Error reading file."); - } else { + } + else + { printf("File read successfully.\n"); } @@ -52,13 +58,16 @@ guest_os_t* readByteCode(char* filePath){ return guest_os; } -void write_sector(uint32_t sector_number, const uint8_t *data) { - if (sector_number > MAX_SECTOR_NUM) { +void write_sector(uint32_t sector_number, const uint8_t *data) +{ + if (sector_number > MAX_SECTOR_NUM) + { fprintf(stderr, "Sector number out of range\n"); } - + FILE *disk = fopen(disk_filename, "r+b"); - if (!disk) { + if (!disk) + { perror("Failed to open disk file"); } @@ -66,14 +75,16 @@ void write_sector(uint32_t sector_number, const uint8_t *data) { uint64_t offset = (uint64_t)sector_number * SECTOR_SIZE; // Seek to the sector position - if (fseek(disk, offset, SEEK_SET) != 0) { + if (fseek(disk, offset, SEEK_SET) != 0) + { perror("Seek failed"); fclose(disk); } // Write 512 bytes to the specified sector size_t bytes_written = fwrite(data, 1, SECTOR_SIZE, disk); - if (bytes_written != SECTOR_SIZE) { + if (bytes_written != SECTOR_SIZE) + { perror("Failed to write full sector"); fclose(disk); } @@ -90,47 +101,55 @@ sem_t display_sem; uint32_t display_width, display_height; -static uint32_t read_data(uint8_t *addr, uint8_t size) { +static uint32_t read_data(uint8_t *addr, uint8_t size) +{ uint32_t value; - switch (size) { - case 1: - value = *(uint8_t *)addr; + switch (size) + { + case 1: + value = *(uint8_t *)addr; break; - case 2: - value = *(uint16_t *)addr; + case 2: + value = *(uint16_t *)addr; break; - case 4: - value = *(uint32_t *)addr; + case 4: + value = *(uint32_t *)addr; break; - default: - errx(1, "Unsupported size trying to retrieve data.\n"); + default: + errx(1, "Unsupported size trying to retrieve data.\n"); break; } return value; } -void* vcpu_thread_func(void* args){ - while (1) { - if (ioctl(vcpufd, KVM_RUN, NULL) == -1){ +void *vcpu_thread_func(void *args) +{ + while (1) + { + if (ioctl(vcpufd, KVM_RUN, NULL) == -1) + { err(1, "KVM_RUN"); } - - switch (run->exit_reason) { + + switch (run->exit_reason) + { case KVM_EXIT_HLT: puts("KVM_EXIT_HLT"); return 0; case KVM_EXIT_IO: - printf("KVM_EXIT_IO\n"); - if (run->io.direction == KVM_EXIT_IO_OUT){ - uint32_t value = read_data((uint8_t*) run + run->io.data_offset, run->io.size); - if(run->io.size == 1 && run->io.port == 0xABBA){ - printf("HYPERCALL!!\n"); + // printf("KVM_EXIT_IO\n"); + if (run->io.direction == KVM_EXIT_IO_OUT) + { + uint32_t value = read_data((uint8_t *)run + run->io.data_offset, run->io.size); + if (run->io.size == 1 && run->io.port == 0xABBA) + { + // printf("HYPERCALL!!\n"); switch (value) { case 1: - hyper_console_params_t console_params = *(hyper_console_params_t*)shared_mem; + hyper_console_params_t console_params = *(hyper_console_params_t *)shared_mem; printf("%s", (char *)mem + console_params.msg); break; case 2: @@ -151,10 +170,10 @@ void* vcpu_thread_func(void* args){ gfx_init_conclude(shared_mem); break; case 4: - hyper_disk_params_t disk_params = *(hyper_disk_params_t*)shared_mem; - uint8_t *data_addr = (uint8_t*) mem + disk_params.data; + hyper_disk_params_t disk_params = *(hyper_disk_params_t *)shared_mem; + uint8_t *data_addr = (uint8_t *)mem + disk_params.data; write_sector(disk_params.sector_idx, data_addr); - + disk_conclude(shared_mem); break; case 5: @@ -167,22 +186,26 @@ void* vcpu_thread_func(void* args){ break; } } - else{ - check_state(run->io.port, (uint8_t*) run + run->io.data_offset, run->io.size, value); + else + { + check_state(run->io.port, (uint8_t *)run + run->io.data_offset, run->io.size, value); } } - else if (run->io.direction == KVM_EXIT_IO_IN) { - check_state(run->io.port, (uint8_t*) run + run->io.data_offset, run->io.size, 0); + else if (run->io.direction == KVM_EXIT_IO_IN) + { + check_state(run->io.port, (uint8_t *)run + run->io.data_offset, run->io.size, 0); } break; case KVM_EXIT_MMIO: - printf("KVM_EXIT_MMIO\n"); - if (run->mmio.is_write) { + // printf("KVM_EXIT_MMIO\n"); + if (run->mmio.is_write) + { uint32_t value = read_data((uint8_t *)run->mmio.data, run->mmio.len); check_state(run->mmio.phys_addr, run->mmio.data, run->mmio.len, value); } - else if (!run->mmio.is_write) { + else if (!run->mmio.is_write) + { check_state(run->mmio.phys_addr, run->mmio.data, run->mmio.len, 0); } break; @@ -197,100 +220,135 @@ void* vcpu_thread_func(void* args){ } } -int main(int argc, char **argv){ +int main(int argc, char **argv) +{ - guest_os_t* guest_os = readByteCode(argv[1]); + guest_os_t *guest_os = readByteCode(argv[1]); disk_filename = argv[2]; printf("Disk filename: %s\n", disk_filename); int kvmfd = open("/dev/kvm", O_RDWR | O_CLOEXEC); - if(kvmfd == -1){ + if (kvmfd == -1) + { err(1, "/dev/kvm"); } int version = ioctl(kvmfd, KVM_GET_API_VERSION, NULL); - if(version == -1){ - err (1 , "KVM_GET_API_VERSION") ; - } - if(version != KVM_API_VERSION){ + if (version == -1) + { + err(1, "KVM_GET_API_VERSION"); + } + if (version != KVM_API_VERSION) + { err(1, "Unsupported version of the KVM API"); } int vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0); - if(vmfd == -1){ - err(1, "KVM_CREATE_VM"); + if (vmfd == -1) + { + err(1, "KVM_CREATE_VM"); } uint64_t ram_size = 512 * 4096; - mem = mmap(NULL, ram_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0) ; - if(!mem){ + mem = mmap(NULL, ram_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (!mem) + { err(1, "Allocating guest memory"); } printf("Size: %ld\n", guest_os->codeSize); memcpy(mem, guest_os->code, guest_os->codeSize); - struct kvm_userspace_memory_region memreg = { + struct kvm_userspace_memory_region memreg = { .slot = 0, .guest_phys_addr = 0, .memory_size = ram_size, .userspace_addr = (uint64_t)mem, - .flags = 0 - }; - if(ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg) == -1){ - err(1 , "KVM_SET_USER_MEMORY_REGION"); + .flags = 0}; + if (ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg) == -1) + { + err(1, "KVM_SET_USER_MEMORY_REGION"); } uint64_t shared_size = 4096; - shared_mem = mmap(NULL, shared_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0) ; - if(!shared_mem ){ + shared_mem = mmap(NULL, shared_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (!shared_mem) + { err(1, "Allocating guest memory"); } - struct kvm_userspace_memory_region shared_memreg = { - .slot = 1 , + struct kvm_userspace_memory_region shared_memreg = { + .slot = 1, .guest_phys_addr = 3ULL * 1024 * 1024 * 1024, .memory_size = shared_size, - .userspace_addr = (uint64_t)shared_mem, - .flags = 0 + .userspace_addr = (uint64_t)shared_mem, + .flags = 0}; + if (ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &shared_memreg) == -1) + { + err(1, "KVM_SET_USER_MEMORY_REGION 2"); + } + + if (ioctl(vmfd, KVM_CREATE_IRQCHIP, NULL) < 0) + { + err(1, "KVM_GET_IRQCHIP"); + } + + struct kvm_irqchip irqchip = { + .chip_id = 0, // 0 = PIC1 , 1 = PIC2 , 2 = IOAPIC }; - if(ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &shared_memreg) == -1){ - err(1 , "KVM_SET_USER_MEMORY_REGION 2"); + + // Retrieve the PIC registers + if (ioctl(vmfd, KVM_GET_IRQCHIP, &irqchip) < 0) + { + err(1, "KVM_GET_IRQCHIP 1"); + } + + irqchip.chip.pic.auto_eoi = 1; + + if (ioctl(vmfd, KVM_SET_IRQCHIP, &irqchip) < 0) + { + err(1, "KVM_SET_IRQCHIP 2"); } vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0); - if(vcpufd < 0){ + if (vcpufd < 0) + { err(1, "KVM_CREATE_VCPU"); } int vcpu_mmap_sz = ioctl(kvmfd, KVM_GET_VCPU_MMAP_SIZE, NULL); - if(vcpu_mmap_sz == -1){ + if (vcpu_mmap_sz == -1) + { err(1, "KVM_GET_VCPU_MMAP_SIZE"); } - if(vcpu_mmap_sz < sizeof(struct kvm_run)){ + if (vcpu_mmap_sz < sizeof(struct kvm_run)) + { err(1, "KVM_GET_VCPU_MMAP_SIZE unexpectedly small"); } run = mmap(NULL, vcpu_mmap_sz, PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0); - if(!run){ + if (!run) + { err(1, "mmap vcpu"); } - struct kvm_sregs sregs ; - if(ioctl(vcpufd, KVM_GET_SREGS, &sregs) == -1){ + struct kvm_sregs sregs; + if (ioctl(vcpufd, KVM_GET_SREGS, &sregs) == -1) + { err(1, "KVM_GET_SREGS"); } sregs.cs.base = 0; sregs.cs.selector = 0; - sregs.ds.base = 0; + sregs.ds.base = 0; sregs.ds.selector = 0; sregs.es.base = 0; sregs.es.selector = 0; sregs.ss.base = 0; sregs.ss.selector = 0; - if(ioctl(vcpufd, KVM_SET_SREGS, &sregs) == -1){ + if (ioctl(vcpufd, KVM_SET_SREGS, &sregs) == -1) + { err(1, "KVM_SET_SREGS"); } @@ -300,8 +358,9 @@ int main(int argc, char **argv){ regs.rip = 0; regs.rsp = ram_size; regs.rflags = 0x2; - - if(ioctl(vcpufd, KVM_SET_REGS, ®s) == -1){ + + if (ioctl(vcpufd, KVM_SET_REGS, ®s) == -1) + { err(1, "KVM_SET_REGS"); } @@ -317,7 +376,46 @@ int main(int argc, char **argv){ gfx_context_t *ctxt = gfx_create("Display", display_width, display_height); - if(pthread_join(vcpu_thread, NULL)==-1){ + bool quit = false; + + while (!quit) + { + SDL_Keycode key = gfx_keypressed(); + + if (key != 0) + { + keyboard_params.key = key; + + struct kvm_irq_level irq_level; + irq_level.irq = 1; + + irq_level.level = 1; + if (ioctl(vmfd, KVM_IRQ_LINE, &irq_level) < 0) + { + err(1, "KVM_GET_IRQCHIP UP"); + } + + irq_level.level = 0; + if (ioctl(vmfd, KVM_IRQ_LINE, &irq_level) < 0) + { + err(1, "KVM_GET_IRQCHIP DOWN"); + } + + printf("Stored Key: %d\n", keyboard_params.key); + // sleep(10); + // usleep(10000000); + + if (key == SDLK_ESCAPE) + { + quit = true; + } + } + } + + pthread_cancel(vcpu_thread); + + if (pthread_join(vcpu_thread, NULL) == -1) + { err(1, "pthread_join"); } gfx_destroy(ctxt); diff --git a/vmm/vmm.d b/vmm/vmm.d index 9aaecd3..39fc2c3 100644 --- a/vmm/vmm.d +++ b/vmm/vmm.d @@ -14,4 +14,7 @@ vmm.o: vmm.c ../shared/hypercall_params.h gfx/gfx.h \ peripheriques/sprites/visibility/sprite_visibility.h \ peripheriques/sprites/visibility/../sprites.h \ peripheriques/sprites/position/sprite_position.h \ - peripheriques/sprites/position/../sprites.h + peripheriques/sprites/position/../sprites.h \ + peripheriques/keyboard/keyboard.h \ + peripheriques/keyboard/../state_machine.h \ + peripheriques/keyboard/../../../shared/hypercall_params.h diff --git a/vmm/vmm.o b/vmm/vmm.o index 4c48b43b41dd8dc4eb5610e5d1083e00fac67519..778c71c6720e4ea5ca446543501f6e961982c3bf 100644 GIT binary patch delta 4824 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 BN?ZT{ delta 4024 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 -- GitLab