From da6cb6c86d3ea720fbeb325e1779a00d23b39473 Mon Sep 17 00:00:00 2001 From: xamidev Date: Sun, 14 Jul 2024 16:58:35 +0200 Subject: [PATCH] Add: IDT implementation without ISRs --- idt.c | 42 ++++++++++++++++++++++++++++++++++++++++++ idt.h | 8 ++++++++ iso/boot/kernel.elf | Bin 14564 -> 14760 bytes kernel.elf | Bin 14564 -> 14760 bytes kmain.c | 2 ++ loader.s | 7 +++++++ makefile | 2 +- os.iso | Bin 491520 -> 491520 bytes system.c | 8 ++++++++ system.h | 8 ++++++++ 10 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 idt.c create mode 100644 idt.h create mode 100644 system.c create mode 100644 system.h diff --git a/idt.c b/idt.c new file mode 100644 index 0000000..02f13fe --- /dev/null +++ b/idt.c @@ -0,0 +1,42 @@ +#include "idt.h" +#include "system.h" + +struct idt_entry +{ + unsigned short base_lo; + unsigned short sel; + unsigned char always0; + unsigned char flags; + unsigned short base_hi; +} __attribute__((packed)); + +struct idt_ptr +{ + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + +struct idt_entry idt[256]; +struct idt_ptr idtp; + +extern void idt_load(); + +void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags) +{ + idt[num].base_lo = (base & 0xFFFF); + idt[num].base_hi = (base >> 16) & 0xFFFF; + + idt[num].sel = sel; + idt[num].always0 = 0; + idt[num].flags = flags; +} + +void idt_install() +{ + idtp.limit = (sizeof (struct idt_entry)*256) - 1; + idtp.base = (unsigned int)&idt; + + memset(&idt, 0, sizeof(struct idt_entry)*256); + + idt_load(); +} diff --git a/idt.h b/idt.h new file mode 100644 index 0000000..2d28f8f --- /dev/null +++ b/idt.h @@ -0,0 +1,8 @@ +#ifndef IDT_H +#define IDT_H + +void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags); + +void idt_install(); + +#endif diff --git a/iso/boot/kernel.elf b/iso/boot/kernel.elf index 4fafbb55e0a28451e849db49d5488045d35bf9e3..37b93083e6094b2aa4cec9a8fbcee2f813abce40 100755 GIT binary patch delta 2729 zcma);e^69a6vyv-?6Qk4zPBqNu)wZpil&GLLI{N78kLlzFf}R>siY*P12{TbJM^g7 zS(d~*=}b+jnWZ!7XpU$NmAWdU=D1E)<{u5y_+!--cLiZ}$k+GozLl5bAHA9T<8#ir z=bn4+z3;s%Yj)RfN{SOil1&KNo{I`kHn9>-`{Yp*WPuP?v`i`z!m-xM`T&&0Q6y9} z?PX?uPR4=SwZdjG#*Pt9?x2Mb?-~QD*J4qX#}Fd<^tDkgDR^6!=Xtr|5S$R1jCV;1 zJxq3cm|B(@lKmN$dADNnE?ZwZX7953H==P#g|Kkgd~%~-ZtRmAeJ-gK5-N%5iJ`Hx zH4%Ty-wepIOWM;ze-zDOrEy4^ZF+ddC7tP^e$lMkJ%WYrrzYdrH!kQx4ur$D{+eT6 zz0h$K@y=WR8`kYT6xOi?2+J=r$<86`|5!T1@=eal!PD*v$5qLv@s7tV+PCQzV^(wk z`O)UkUyND$!{|1-I=wpnv zbkKBN=Rs1N+==w&$ls#}kT~rOdMYkk_dU8zZjN&C&v89;X8dig=irot37l?`o+)-7 ztQwWcajmp1aTIrlex10K3P}ZAG@Y9?4YfU~m($YvOBI9cF;tKvr_LY6P*=tEtSCgX`{<^V&mugo!oY0!-ZGZpO?tT~a{?E`!b` zv1uGq5eO#B2{KrVqsXN5yx3HBsJ%t%HAucVZ$D12HlHoQW@xeboHo6~Hh62K(>Cau z$2lqn5u>j~l9k%u- z*gr|edsMMV+rq}!m;;C(`hQP$yz;9iCvE9!ET z{eC*%lFpj~^mS_jZMEq6rvr40C5XU{s(sTE}8J(Eg2qa#>aO0WHfodpMGS z+N>L5GkC5_Zv}5u@l)Uq6;A~Js^Tf&^U*{8*rz35#m^EljYuj%5e)9BxCH#Fic7(J zsB!8d`)c$ekA?)~^$|eJ_SXBYph{0M|9*GxQ!DDRz^(7Xb;-P7?JcT`~dCNVInD3 zScd~=hMqkl?1zJ&87`8&ie3N@;7(NHL@<8|;BxHHL9}2y8H*0PbI}-J#5Efa#x;Ay zlfVtJB4NjbImiRI7(~L3ALA4_{s|LA0-g=M2!Dx+zf!OP%&sEy|1$Wfk_QuSk0MJU zIL?dM$gsmY@Rbpf0UTKeCe{c?lMUc5WGG_a4DQB?*?nOFwKGI9pFJM zfZYv~9Rv13(1!qgioqdp=c5RDauzJAQtSb*z!qdG_J4zaMuylOVFBC#4=CeV*muEO z;D3^$e*pF>0osiiK#)Q`BK%M>Fo3(GMDmxyMsP7w$UYD(h4J7&5Wr$ZKN{>&O_%}J zt5Ti`zO2&cf!S%n8+2SKV)l(G!3rZOwSk*4zz8!IU>Tj9z22~5X+!1`Qop{wVObsB znSDTnU^PKiwPIC$L-op)bU{unv#P3J)=>3Ub;B~+nUf>bEvo~E>{h;0y_EWMtWhwc z!t{HT%T442nw)FVVzy2TEy^9ENAD)RAY_cH)h(knYJFqfNjc=|{}xzk!ta?EnA( delta 2150 zcma);ZERCj7{|}OecjmB+iflD%GOd)kU-s_8w>{wSQQfyf-F&CQIwDYA(70@sD!dq zk-2nkJVp|Y1cJt?DT+e`0%TfV6cd4jw}6@ZFkF>(bfwM?2G{?&?H&EV2k&-Xe*g2F z=Q-y&=eF%??BCpBE6kIahcWhhB`Q1~=46`A8RN4eX2y8Yb#AhYZs&pbn@ycP&Ye=0 zFORX7P}0FzcykV_7qS@hM~oXZ0e>QToVI+Ym{s8>`cwAXuT;dyh~v0 zj5pyz^fTVr7Bm6>JXo}PBXUzrZc4~ak$``RGH1P(Q9vs3C{U|aoi@BOB+CK+mx??? zm9-7GP6T@!?w{ozk4C9ivQAPg?r4;WZC+zr{pc^Dy4D-d`6GqlU@qU;KQ!JvS-4Eq zW_#^XgBoFjso^4Kg}YLU=?Cwy=}-^$xV+&K*E>>rhw9KD(T1nPpYApK#9XEyMy7Og z>4Le;cnsZ^khYYv@;miYxW1A03>YpUQ7xeox>ayl zKZRvnEE!aAdPyb10TiwAn zZ!EAxXk8jJ9s00f+aP^iv{tvS1Ak<)RSP>s9apApz*__xZ>rYG;o zaB`Yj94no;VK?ua1k2PKiLE;(_{PPla-{S|&lRLD`1H;EF1b6ZJ}z?jd^7=@Kn*+UhJ7-ErEDrY24&oG#aq zxGYcS)~e5jQ`{Y!0BIEE6t}ic<2V7KufRNl{+PKKR_vXSsxiLrHZ7Xy66+HPWu+|> zjbd|xwnO=5n7*1g&6>FPV0qkUKjyreM2KR&R%EOxN!c!!=p7+9nq?!j0?oz|YIc>1 zUyRU4pt3u36m<9wU2_#5_|B3?LfK2cxQ-`)KLWF&wi+I=9sE?rxD)(F20sEmkipZy zzh&^_;IsM%{`e8Tq_%kw>uUgZHp7?E$uMp3WyiIA< zYDnIW?)_ye`cuk~`~mN%D}nu9;8om@)T3oVbohNy`5;Bh9ljrdT4zcXn1NjZw+a%& z!dX5N_6ORgEQux3d=u@iY)QFKd^`!ZW1K${nBR+8<0K^-ALsvZt;Fhaf}9QDWjKIt zv|t~zpu=yr9uv*X$cn%_awPUTm`}J4J^}~of+m9{*cYYkr-F09{9^O@Zg5X}oB5)K z)q;xsS0|w3j7l?piWo|?!%6{(hfFr9&;eDx4{Y6f0`a| z0pCJE{wnYd>;NAdTad_hgC#X%J{atSupTLOrzd<5?t}yW>Tw6h!QqU6A+QDk`32zP z=fKxB66;O#Mer5)Tb<@U@cHxt_%;W?#&pKKJY`V`*D?(L1@qJ7pC>%PJ+zClVl^ZD zZF~pz_>x8uSPlg}Z&F3Yeo9oVrwx@J+F$9Q3zZ4_dA3E!qu$vLBg~JL;;K=3SpgNz z$>l=Nm{5}vPC}SPb#olqNem}J36ZwWY0h=4*A@}ABvfHFIB$GWu@YKZW!F{Xy|dA# Os!6&!{G51?2l)>~hGbg+ diff --git a/kernel.elf b/kernel.elf index 4fafbb55e0a28451e849db49d5488045d35bf9e3..37b93083e6094b2aa4cec9a8fbcee2f813abce40 100755 GIT binary patch delta 2729 zcma);e^69a6vyv-?6Qk4zPBqNu)wZpil&GLLI{N78kLlzFf}R>siY*P12{TbJM^g7 zS(d~*=}b+jnWZ!7XpU$NmAWdU=D1E)<{u5y_+!--cLiZ}$k+GozLl5bAHA9T<8#ir z=bn4+z3;s%Yj)RfN{SOil1&KNo{I`kHn9>-`{Yp*WPuP?v`i`z!m-xM`T&&0Q6y9} z?PX?uPR4=SwZdjG#*Pt9?x2Mb?-~QD*J4qX#}Fd<^tDkgDR^6!=Xtr|5S$R1jCV;1 zJxq3cm|B(@lKmN$dADNnE?ZwZX7953H==P#g|Kkgd~%~-ZtRmAeJ-gK5-N%5iJ`Hx zH4%Ty-wepIOWM;ze-zDOrEy4^ZF+ddC7tP^e$lMkJ%WYrrzYdrH!kQx4ur$D{+eT6 zz0h$K@y=WR8`kYT6xOi?2+J=r$<86`|5!T1@=eal!PD*v$5qLv@s7tV+PCQzV^(wk z`O)UkUyND$!{|1-I=wpnv zbkKBN=Rs1N+==w&$ls#}kT~rOdMYkk_dU8zZjN&C&v89;X8dig=irot37l?`o+)-7 ztQwWcajmp1aTIrlex10K3P}ZAG@Y9?4YfU~m($YvOBI9cF;tKvr_LY6P*=tEtSCgX`{<^V&mugo!oY0!-ZGZpO?tT~a{?E`!b` zv1uGq5eO#B2{KrVqsXN5yx3HBsJ%t%HAucVZ$D12HlHoQW@xeboHo6~Hh62K(>Cau z$2lqn5u>j~l9k%u- z*gr|edsMMV+rq}!m;;C(`hQP$yz;9iCvE9!ET z{eC*%lFpj~^mS_jZMEq6rvr40C5XU{s(sTE}8J(Eg2qa#>aO0WHfodpMGS z+N>L5GkC5_Zv}5u@l)Uq6;A~Js^Tf&^U*{8*rz35#m^EljYuj%5e)9BxCH#Fic7(J zsB!8d`)c$ekA?)~^$|eJ_SXBYph{0M|9*GxQ!DDRz^(7Xb;-P7?JcT`~dCNVInD3 zScd~=hMqkl?1zJ&87`8&ie3N@;7(NHL@<8|;BxHHL9}2y8H*0PbI}-J#5Efa#x;Ay zlfVtJB4NjbImiRI7(~L3ALA4_{s|LA0-g=M2!Dx+zf!OP%&sEy|1$Wfk_QuSk0MJU zIL?dM$gsmY@Rbpf0UTKeCe{c?lMUc5WGG_a4DQB?*?nOFwKGI9pFJM zfZYv~9Rv13(1!qgioqdp=c5RDauzJAQtSb*z!qdG_J4zaMuylOVFBC#4=CeV*muEO z;D3^$e*pF>0osiiK#)Q`BK%M>Fo3(GMDmxyMsP7w$UYD(h4J7&5Wr$ZKN{>&O_%}J zt5Ti`zO2&cf!S%n8+2SKV)l(G!3rZOwSk*4zz8!IU>Tj9z22~5X+!1`Qop{wVObsB znSDTnU^PKiwPIC$L-op)bU{unv#P3J)=>3Ub;B~+nUf>bEvo~E>{h;0y_EWMtWhwc z!t{HT%T442nw)FVVzy2TEy^9ENAD)RAY_cH)h(knYJFqfNjc=|{}xzk!ta?EnA( delta 2150 zcma);ZERCj7{|}OecjmB+iflD%GOd)kU-s_8w>{wSQQfyf-F&CQIwDYA(70@sD!dq zk-2nkJVp|Y1cJt?DT+e`0%TfV6cd4jw}6@ZFkF>(bfwM?2G{?&?H&EV2k&-Xe*g2F z=Q-y&=eF%??BCpBE6kIahcWhhB`Q1~=46`A8RN4eX2y8Yb#AhYZs&pbn@ycP&Ye=0 zFORX7P}0FzcykV_7qS@hM~oXZ0e>QToVI+Ym{s8>`cwAXuT;dyh~v0 zj5pyz^fTVr7Bm6>JXo}PBXUzrZc4~ak$``RGH1P(Q9vs3C{U|aoi@BOB+CK+mx??? zm9-7GP6T@!?w{ozk4C9ivQAPg?r4;WZC+zr{pc^Dy4D-d`6GqlU@qU;KQ!JvS-4Eq zW_#^XgBoFjso^4Kg}YLU=?Cwy=}-^$xV+&K*E>>rhw9KD(T1nPpYApK#9XEyMy7Og z>4Le;cnsZ^khYYv@;miYxW1A03>YpUQ7xeox>ayl zKZRvnEE!aAdPyb10TiwAn zZ!EAxXk8jJ9s00f+aP^iv{tvS1Ak<)RSP>s9apApz*__xZ>rYG;o zaB`Yj94no;VK?ua1k2PKiLE;(_{PPla-{S|&lRLD`1H;EF1b6ZJ}z?jd^7=@Kn*+UhJ7-ErEDrY24&oG#aq zxGYcS)~e5jQ`{Y!0BIEE6t}ic<2V7KufRNl{+PKKR_vXSsxiLrHZ7Xy66+HPWu+|> zjbd|xwnO=5n7*1g&6>FPV0qkUKjyreM2KR&R%EOxN!c!!=p7+9nq?!j0?oz|YIc>1 zUyRU4pt3u36m<9wU2_#5_|B3?LfK2cxQ-`)KLWF&wi+I=9sE?rxD)(F20sEmkipZy zzh&^_;IsM%{`e8Tq_%kw>uUgZHp7?E$uMp3WyiIA< zYDnIW?)_ye`cuk~`~mN%D}nu9;8om@)T3oVbohNy`5;Bh9ljrdT4zcXn1NjZw+a%& z!dX5N_6ORgEQux3d=u@iY)QFKd^`!ZW1K${nBR+8<0K^-ALsvZt;Fhaf}9QDWjKIt zv|t~zpu=yr9uv*X$cn%_awPUTm`}J4J^}~of+m9{*cYYkr-F09{9^O@Zg5X}oB5)K z)q;xsS0|w3j7l?piWo|?!%6{(hfFr9&;eDx4{Y6f0`a| z0pCJE{wnYd>;NAdTad_hgC#X%J{atSupTLOrzd<5?t}yW>Tw6h!QqU6A+QDk`32zP z=fKxB66;O#Mer5)Tb<@U@cHxt_%;W?#&pKKJY`V`*D?(L1@qJ7pC>%PJ+zClVl^ZD zZF~pz_>x8uSPlg}Z&F3Yeo9oVrwx@J+F$9Q3zZ4_dA3E!qu$vLBg~JL;;K=3SpgNz z$>l=Nm{5}vPC}SPb#olqNem}J36ZwWY0h=4*A@}ABvfHFIB$GWu@YKZW!F{Xy|dA# Os!6&!{G51?2l)>~hGbg+ diff --git a/kmain.c b/kmain.c index b15b916..a9712ba 100644 --- a/kmain.c +++ b/kmain.c @@ -1,11 +1,13 @@ #include "stdio.h" #include "serial.h" #include "gdt.h" +#include "idt.h" int kmain(int retvalue) { gdt_install(); + idt_install(); // serial testing diff --git a/loader.s b/loader.s index bdf1dd1..25aa675 100644 --- a/loader.s +++ b/loader.s @@ -38,6 +38,13 @@ gdt_flush: flush2: ret +global idt_load +extern idtp + +idt_load: + lidt [idtp] + ret + section .bss align 4 kernel_stack: diff --git a/makefile b/makefile index 2f40e62..f663857 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -OBJECTS = loader.o kmain.o stdio.o io.o string.o serial.o gdt.o +OBJECTS = loader.o kmain.o stdio.o io.o string.o serial.o gdt.o idt.o system.o CC = gcc CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -Wall -Wextra -c LDFLAGS = -T link.ld -melf_i386 diff --git a/os.iso b/os.iso index 33455f4aead94dfba949c0068f2dfcf3ee780010..b19cf325f0773de7434a4114fc757d0b2d2540fc 100644 GIT binary patch delta 3000 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 z