From fbd17924e096144de653fe6bb707ce4e7781e0b8 Mon Sep 17 00:00:00 2001 From: c0repwn3r Date: Fri, 13 May 2022 21:33:49 -0400 Subject: [PATCH] Rewrite finished --- Makefile | 83 ++++++++------- bin/shade.bin | Bin 1056296 -> 15184 bytes bin/shade.iso | Bin 26591232 -> 26597376 bytes bin/shade.iso.lock | 0 include/shade/platform/ports.h | 4 + {src/kernel => include/shade}/print.h | 0 {src/kernel => include/shade}/util.h | 0 {src/kernel => include}/strings.h | 0 obj/kernel/kernel.o | Bin 3272 -> 3160 bytes obj/kernel/print.o | Bin 4984 -> 3952 bytes obj/kernel/strings.o | Bin 1848 -> 0 bytes obj/kernel/util.o | Bin 1472 -> 1616 bytes src/boot/entry.asm | 141 ++++++++++++++++++++++++++ src/boot/entry64.asm | 17 ++++ src/boot/mb2_header.asm | 16 +++ src/iso/boot/grub/grub.cfg | 7 ++ src/iso/grub.cfg | 6 -- src/kernel/kernel.c | 7 +- src/kernel/platform/ports.c | 26 +++++ src/kernel/print.c | 12 +-- src/kernel/util.c | 2 +- src/{kernel => libc}/strings.c | 2 +- src/linker.ld | 33 +++--- 23 files changed, 290 insertions(+), 66 deletions(-) delete mode 100644 bin/shade.iso.lock create mode 100644 include/shade/platform/ports.h rename {src/kernel => include/shade}/print.h (100%) rename {src/kernel => include/shade}/util.h (100%) rename {src/kernel => include}/strings.h (100%) delete mode 100644 obj/kernel/strings.o create mode 100644 src/boot/entry.asm create mode 100644 src/boot/entry64.asm create mode 100644 src/boot/mb2_header.asm create mode 100644 src/iso/boot/grub/grub.cfg delete mode 100644 src/iso/grub.cfg create mode 100644 src/kernel/platform/ports.c rename src/{kernel => libc}/strings.c (97%) diff --git a/Makefile b/Makefile index 1d7164b..fbf99ed 100644 --- a/Makefile +++ b/Makefile @@ -1,54 +1,67 @@ -ASM ?= nasm +ASM := nasm + CC := x86_64-elf-gcc -GDB := gdb +CCFLAGS := + LD := x86_64-elf-ld +LDFLAGS := -C_FILES = $(shell find src/ -type f -name '*.c') -CO_FILES = $(patsubst src/%.c, obj/%.o, $(C_FILES)) -ASM_FILES = $(shell find src/kernel/ -type f -name '*.asm') -AO_FILES = $(patsubst src/kernel/%.asm, obj/kernel/%.o, $(ASM_FILES)) +INCLUDE := include/ -KERNEL_O_FILES = ${CO_FILES} ${AO_FILES} +# Target: kernel, type: C ASM +kernel_c_source_files = $(shell find src/kernel/ -type f -name *.c) +kernel_c_object_files = $(patsubst src/%.c,obj/%.o,$(kernel_c_source_files)) +kernel_asm_source_files = $(shell find src/kernel/ -type f -name *.asm) +kernel_asm_object_files = $(patsubst src/%.asm,obj/%.o,$(kernel_asm_source_files)) +kernel_source_files = $(kernel_c_source_files) $(kernel_asm_object_files) +kernel_object_files = $(kernel_c_object_files) $(kernel_asm_object_files) -BOOT_O_FILES = obj/entry.o obj/entry64.o obj/mb2.o obj/vga-print.o -BOOT_SRC_FILES = obj/entry.asm obj/entry64.asm obj/mb2.asm obj/vga-print.asm +# Target: libc, type: C ASM +libc_c_source_files = $(shell find src/libc/ -type f -name *.c) +libc_c_object_files = $(patsubst src/%.c,obj/%.o,$(libc_c_source_files)) +libc_asm_source_files = $(shell find src/libc/ -type f -name *.asm) +libc_asm_object_files = $(patsubst src/%.asm,obj/%.o,$(libc_c_object_files)) +libc_source_files = $(libc_c_source_files) $(libc_asm_source_files) +libc_object_files = $(libc_c_object_files) $(libc_asm_object_files) -iso: bin/shade.iso +# Target: sboot, type: ASM +# Override: 32-bit +sboot_asm_source_files = $(shell find src/boot/ -type f -name *.asm) +sboot_asm_object_files = $(patsubst src/%.asm,obj/%.o,$(sboot_asm_source_files)) +sboot_source_files = $(sboot_asm_source_files) +sboot_object_files = $(sboot_asm_object_files) -bin/shade.bin: ${BOOT_O_FILES} ${KERNEL_O_FILES} - mkdir -p bin - $(LD) -T src/linker.ld $^ -o $@ - grub-file --is-x86-multiboot2 bin/shade.bin +shade_bin_ldfile = src/linker.ld + +default: run bin/shade.iso: bin/shade.bin - mkdir -p isodir/boot/grub - cp bin/shade.bin isodir/boot/shade.bin - cp src/iso/grub.cfg isodir/boot/grub/grub.cfg - grub-mkrescue -o bin/shade.iso isodir - rm -rf isodir + cp bin/shade.bin src/iso/boot/shade.bin + grub-mkrescue src/iso/ -o $@ + rm src/iso/boot/shade.bin +bin/shade.bin: $(sboot_object_files) $(kernel_object_files) $(libc_object_files) + mkdir -p "$(@D)" + $(LD) $(LDFLAGS) -n -T $(shade_bin_ldfile) $^ -o $@ + grub-file --is-x86-multiboot2 $@ + +# Generics +# Source file types: C ASM + +# C obj/%.o: src/%.c mkdir -p "$(@D)" - $(CC) -ffreestanding -O2 -Wall -Wextra -c $< -o $@ + $(CC) $(CCFLAGS) -I $(INCLUDE) -ffreestanding -c $< -o $@ +# ASM obj/%.o: src/%.asm mkdir -p "$(@D)" - $(ASM) -f elf64 $< -o $@ - + $(ASM) -felf64 $< -o $@ +# Other run: clean bin/shade.iso - qemu-system-x86_64 -hdd bin/shade.iso -d int -no-reboot - -debug: clean bin/shade.iso bin/shade.bin - qemu-system-x86_64 -s -S -hdd bin/shade.iso -d int -no-reboot & - ${GDB} os-image.bin -ex "set arch i386:x86-64" -ex "symbol-file bin/shade.bin" -ex "target remote localhost:1234" - + qemu-system-x86_64 -drive file=bin/shade.iso,index=0,media=disk,format=raw clean: - find obj -type f -name '*.o' -exec rm {} + - find obj -type f -name '*.bin' -exec rm {} + - find bin -type f -name '*.o' -exec rm {} + - find bin -type f -name '*.bin' -exec rm {} + - find . -type f -name '*.dis' -exec rm {} + - rm -f kernel.elf - rm -rf isodir \ No newline at end of file + rm -rf bin/* + rm -rf obj/* \ No newline at end of file diff --git a/bin/shade.bin b/bin/shade.bin index 8b749dbc91fb333cb008057da5bdd20cb51ee8a5..fe77f8c73c9ada11d2a13d69c1d8bcbeea9e683e 100755 GIT binary patch literal 15184 zcmeHNac~sX8Gm==AfRvu1C~~57j!Iifan0>$~gssK!lk>&&y?#oZQ`BclUtU zM5(cwotselhpp6Tk=EM&q4-Bdv5QG}%)XiIe((4DzVE&Fdv9N|FZ*C<)wjGJ53`Dw-N~pXu>gmb3ZieJFmPMS7Q$yK z8^^|S-!Vj)?heBQJQ5(3%Dw#N@Dp|S<|^PS;40uM;40uM;40uM;40uM;40uM;40uM z@P#XIdhNO#H8K@HllDLNC9*5=|UZ4^=tr~1P$d(3J`-xG%U{wLQuN4)5FT;xxNbJ(v<5>b zm$A&dM-Nhrf5sWVG|+xR^3ND}c_(At{_62`T;Z?sOWorUw$neO`{;2W+j$)e)vl{O z?yG>cu68l3N?1~@RJ(5+jN!(hrAFiKMl`&uZ`YY!-Ma>M<#H=37#pq&8}EhNhpLRW z{_ye81xk1Gi)9I@f4;+d*)@MWK<_KV*I1eTuPcUB7YKIG+0k#<%;`qoTopm3IP?fz=Cz0+0SO zTA}D%cFHu0_I(9cp5QD5C?=4s?jH9IKS@1=t`yt3wvhF`17uO}1Cz79GqBpbJ%;ZM z7-z{54I>d7Y&;&y+`?F8ja97^s+tYdBxPA?=x;i0rHjr`POGk z2DFdh(Y2mTl2x13! zWPM)5@%}98dtjVNy$#BLAT-nwx`+w<`!t%sOWY^xd!vhHuP^I63BxhQyg7RpF?(6x z^WeBz&%nq|d4jIKJ-G4?Hlz7s2g62NPD~=i3CH@d6mnrtpZ@?_{bXm`CrqE{KOFi5 z!<{K6ckr~BKjUNLLPy<5M<|c(=6ePzj9wU6R2{yrPs1#4v6hKsv<(@VoHau^nxP?2 zpAi~4JORBq^5!TgQh;#iLQlTZf1ukqcH|U+9{@b;w|)L*`Zye31>#&z7!H=imG4N$ zLIo_6%eCK@7=Vjg0OZ+WWMW4sU+#8{Cfpgi62{2RLvfSB>Sj5~q%ITnrcLoEpGjRL z>Sa(|E!fY&7Tq{f6~KPgWyfI{EcZI9N0t!LZWBD=Z;4n=#C>Fi$hy~dA$4*;CSnT_ zD{X?u?m*RCGS82|B}Oi{*e*P_j$#!euCoaqyTp!F5nG(9fVEi7#FIgq%AhAKcUx(a zOIMJ+gR-~U=`O=M@&aLdh|Q7pBeIrGg!MyM*6PXQi5$X~Gi3B)ty_JdMb&87tIGdU z-N-r7J;M>v_zy&Xis(%_x-ALnkYg||rVIwnO)b(2%*3BiWJzIyRe=?k{ z8wh(&($eR9AY5(_^|zkd?MP!>FzN<6LhqUrAIcBj04pEvTFWn1$zT zsJ(57J@^ye@(ou>aE#5i^`L~u%AelB)DCtAMM3tAMM3tH2kjz~d6bpQren(Jb_$ zMz4cZEPJDzh$%@~(iMrVZ;m#|Z2CB+kx{!|+A6ClIU#M6RV}WhBvuuy4py^unN%vC zYLW=yp0gX|ZE`|MC*_oGW@qfKR9ufo6Y=}y2B{&gr4!K>Nz24yvZgg=5{Z^^!m&n4 zx2W-^W?h;Yng1zEz90Bz@Np;a zZLsr?0DlJjqb2-9Ha`tIT>sBP;ddqc0h?a}{#o$J6295yH-jGr&kwyU{nl}s>(dH; z5d4kK_t;MbZgCZG6>t@B6>t@B6>t@B6>t@B75LvO;9pr&vsjwBa!uVV zX>N6JZm{a}+s7*jt6(1%%Dv2U0%EPx1Ji@Q`{Cd2Q_JwV*T}Pihk4lQGXM1guPej( zyD#!@F2mb|f4U5RLg3rW@cjaRtPKCN!1t8l?+N^18BXu4_}?%)RfdlvX@E0)Dd8*u zj{6vWvEVE>S@_aY{5A_;TZ%8X@Ow+~l@`9Y6u+C}ctNvId(751a{R*reFNew_X&Uc z+{0OR0KeLL=)4C07;q0h)0igm;QI+)o)WlJhClls^2{vrxANRphQDx)JoM?w)%t(r z8aVyOdlE)4d90}efA_@*`UHN;YvNCfanb+G$^S($@5==Kp1>~(oS(sf`v`ad{`5tS zvs@AWki7Q6X$0q;BFE4&&HTIKQjP6 zOW-R+f6V8Nv3bC$pAxRla)kiV_yN&Rb6;R=1MrE=$1247wARBW;Xfe8 z%g;EFM;7?61kTS!fF}e#>@)kr&vbyd2zFW`p-9uo7y&%A)o0Z#hR zXINA$eVC@k=F}^SJ||gU9ch+v0ILS0T9TP&MAM_HZdK$|L(w0Hu4)T+jWx@$tr3c+ zM69$LBs`_)oRb>_8%t;6C3cV_kxWXZk|TPw zJ|S!DGe|I@C}}3Ah$c@QD>GSD6_pjkB8mAWwRt7AY6fL6>Uu@jm87WXNZQn(FPLv$ zgE6H+j%acdKcMDBFs;N>x~!JTxL`gPGOdCP#@L#=)sdRoRqMI2u6E;kW}b+HB5gF> zGkQFMo2DbAi2zu!bPMAtBC+PE%3=vQsz#!TgaA|W_C!1-W7wFu2vlQ9Ia!QB0!pIF z+eB-T?dBOhi|a~MWK)&xR{X*Ryv-E)MBTsI??9<+$sr zd2hBXUEZOypsF-P^(YI<&5=eN;L9v%*6THmVYZUa|0M9oYoGRO%4x?}nGPNiUzs-Z*w?c7J3&wz!rgYW;wRaNX;}Sn-phu_ z9jA(fd$AQ#p*~I*cdAdN3kpq--FJ?dmxK5amC9>n$*p!xmiF4K$3MK#^ss*KTK?tn F{{~@<&YJ)L delta 7345 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 delta 66718 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

-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 diff --git a/bin/shade.iso.lock b/bin/shade.iso.lock deleted file mode 100644 index e69de29..0000000 diff --git a/include/shade/platform/ports.h b/include/shade/platform/ports.h new file mode 100644 index 0000000..d616f0e --- /dev/null +++ b/include/shade/platform/ports.h @@ -0,0 +1,4 @@ +unsigned char port_byte_in(unsigned short port); +void port_byte_out(unsigned short port, unsigned char data); +unsigned short port_word_in(unsigned short port); +void port_word_out(unsigned short port, unsigned short data); \ No newline at end of file diff --git a/src/kernel/print.h b/include/shade/print.h similarity index 100% rename from src/kernel/print.h rename to include/shade/print.h diff --git a/src/kernel/util.h b/include/shade/util.h similarity index 100% rename from src/kernel/util.h rename to include/shade/util.h diff --git a/src/kernel/strings.h b/include/strings.h similarity index 100% rename from src/kernel/strings.h rename to include/strings.h diff --git a/obj/kernel/kernel.o b/obj/kernel/kernel.o index 3f1f6737f73ea2ea0a58e4411d1304157666cd5d..66bfda775dcffa94bce1fa61453a1d4d4684619e 100644 GIT binary patch literal 3160 zcmbtV-)me&6h52Owzf$dt6;QMrWGVbdz-9?_ygIvY?DGvLbjnQ$a-^kx_impxy#Jm zBwG-Jg6La(@x}kZCm%!v!4~=;zUg03Uj!cn5qzj1)N}5gvpY_9AJhYLXU=!N^PTx| z@7(ulD_15;C15MTt1$E!1(^u-VU1*&Yu87gSEQYmRiX~>_~0mR0)_5%0U@6dP>ErB?!rxmzr`% zCTX`LRYsE}yQ<H-Vx=Gjaz$>7OWQP))mi9k<$@yvrckMndtFR6 zBGn@9bdwkvyP?*h%KC2FK=@i)3Ywru;z%kZMHDKrg;?4{!7vk-P2XHzxmvBQR%^5c z8BGMSOm?V9Fo?wzlftAu9pV0JDXGX(wfd5nTUy<`C>F}WLNIUl;RyBu+XL7z3KLMe zO&D9r`ur_CVgsd{8&KMtDV?1 z=8?=AQJSReE4iD*O2T$0j1@$Q40R(+5-`N;X_M+kH#MxXaSa)p^0KX> z`}|D@ck908>Ck&Z)+o9|^H&b;>g+i<{epOZ-nBTd>t*Y|@9^FI`NY9p{ZBoeCF_6Y z@LiqH9o*IV(!t$%{^;N*am@4o$-$=_{5J=8_5ZLqulF76|LO3jam@OY_Tr-RI_luZ zEzUY0+5BmT@2>ZZ$G>g)kB;G=^Z2vYKR<>qtlk9n)YvL^z&PI*5SV@^3%9V(bkVnY zq-7EYncT}DXogt`!Im))=(KR~x10Yk1C?enXsKR+zq78?Ssyu+Dcg-3_;-^$h5ywH z%%&yN-n&+@&Yay3j(IMe#Q>dMg$cG_rymyDJY6nmbdHou?+V#$(ZSQ$6K-i11!(() zY{ZA3MVvJMYyJY}lBRp6=nm@ddIfp@#36eT8&UXwO&Hl-D@gw@*I17G*Dy%$v0wk5 z1$$}Y4S54&uKD?NFOE9DeM{u}bbbVJKA+#H+Ej1f)?c>^r8|Y*F+ZQ~ iAph(Tf*)v7X#4qd_~3nGkq@FQc1Ct)NAUTP3P5Jy^7yqZ^2*ZWZvL>-MtmbuV2+a`>Yo{3T% zGRkTcq=6p>d#0`1flESvpk2S!GR|%G!*FmqPg9LJ8Q7rHP4#^1f;JaZ~w5(&`ZJq zGIo4x{U{yCvLW$$*JvD|4uh77oY5^m(i?!qeIWExz32vR@ycpr`D$YsmmtM~0G65_ zHt~kB0AohGxNlpqzSbCQa=FoXMbBTpdh>#=*1W1$p>;R`TEp`YJP=i7RXRY7r9?iT z^(QD$+PkhwyK|*8QzuV-1i?ALpXC^7^tsPxh%L>`y(D8H{oG z>M{5&z_ITEXq0SSK;MOD98c#MeES$&<#)?#sdm5D8#Ghn(k9#=J4oUHu2CLt?&Q}~ zB^JP@OD$U_ZMNbtWB9tn(-El4Cj~& zt~0*+Se_vR&)`XT?jPoIUf^(ahWPV@GtU(H6_GD_UKP0HSt{`G_%4Zj$@4}b|4H(B zzl!6(BY0$AzreFV{-(&6eXYPH&p_b#3F38on{ZyAi{!s2@+JR=0+;-s6nI`I|5K4K zc|I4on6!(3ylqWF%SCs!HY0Q`VHAVSF9!>dW(D<;tNCxBlj#w|?2VCH}K`-?; zln0kO*Il-(34Jd$yQ%Wpe(Ec4!#U;I7#&QndesNrmy`z|@$B>KMR97pPSp3{izOt-lS-%7*%|EJbak4uDmD5Xx$9IYS6csO5$~A;(S=@Vo)VDY&kbAir{_?sp@F*B#>#5Nm JCz3AK{|!X1`*r{T diff --git a/obj/kernel/print.o b/obj/kernel/print.o index 91008f8053ab6de309d5a400d30db65035fe9234..99394ea7f4e2c60ca10842cf60a5ffebeae36ebf 100644 GIT binary patch literal 3952 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 diff --git a/obj/kernel/util.o b/obj/kernel/util.o index 7cc7d31061c7e69ba365c60d0867e9ba4c16aec9..7032cdd476eae9121859a242ab2c19aedca5c371 100644 GIT binary patch delta 680 zcmZuvL2DC16rMMms*c820WNOSQ{^vwlvW&WG+fCixe#gg_IsVcnB!%63Rl! zV+kw_2)zjT2VU%<7k4Yvkkcx75PH}{gkblOo2%sD%x1R-@xgoV+wa@=&D&w!DSz52 zHXV&zL?uQQGDWTugX0g5=73`(K;!H)8!7Spw#`O-%jY&5aPVzIKJ>V41RQ$VBhsQ4 z8-aXfg`MqvbDYgjsSOU%2wJQk4haPrN@AyIwS}pP=sr6nt=X4}0jh`J!B_ zy$+~WR{P79ee7+wa?)HeJ732(KMVN9`%MqAtNX}8%M3~LZG3e8KMtql?!}EL$5TS& zSCd+`x?CvMo)~(ebbq0=uqbBW1`wgcy=OP&J*reuQ{~~c+ySl5T%wPrFJBpJtBRMg ztV*gkVmY3Du6P;8s-!yoAl|_(;X?%{27yt14qC-DkUx9>98i-fg9l8sm19|aYE2eNbhI5%UaKuKYJn1HbuSF;G0EXgw arc9Tpn44IGuGp9;Pc9|@bAWq-Mm+;F0~|PjSq==`3|tJYm+E9Zk}nw^;FoUz3G;8`VejB!^JqT6=wW%N z^uyt_G(CR#7O)O}c?Y2S63Na>9=$B$Y5ejo3=AI4#~B?u%Kv*<9xwfTIBh~`=P$?3 zU!I+xzu)rg{NT9r?3puX_&u(t8UFX^d>YIz&(L|H^J3?3PoVjp{Ob<_b$c9qq1n3fr^9}7%@x|gNg@$OaX$d$p@L-HBBHK z1|}d4!Z7Ktqrl{s vEcToZj1UbOlMPwT851UFvf4APV4S>))sE3(@=I2G&J`f5fgpUcA&Wc!E5&_( diff --git a/src/boot/entry.asm b/src/boot/entry.asm new file mode 100644 index 0000000..fe7a356 --- /dev/null +++ b/src/boot/entry.asm @@ -0,0 +1,141 @@ + + +global entry_x86 +extern entry_x64 + +section .text +bits 32 +entry_x86: + mov esp, stack_top + + call check_mb2_boot + call check_cpuid + call check_x64_supported + + call setup_page_tables + call enable_paging + + lgdt [gdt64.pointer] + jmp gdt64.code_segment:entry_x64 ; Jump into 64 bit entry + + hlt + +check_mb2_boot: + cmp eax, 0x36d76289 ; compare eax to mb2 magic number + jne .mb2_not_booted + ret +.mb2_not_booted: + mov al, "B" ; err code B - boot error + jmp error + +check_cpuid: + pushfd ; Put flags on stack so we can mess with them + pop eax ; then put the stack into EAX so we can easily modify it + mov ecx, eax ; Make a copy of eax in ecx for comparison + xor eax, 1 << 21 ; Attempt to flip the CPUID bit which is bit 21 + push eax ; Put eax back onto stack + popfd ; Write flags back + pushfd ; Copy flags onto stack so we can check if the bit did flip + pop eax ; Put stack into EAX for comparison + push ecx ; Put original flags into stack so we can make sure they remain unchanged + popfd; Push original flags back onto the flags register + cmp eax, ecx ; Compare the modifided? flags to the original flags + je .cpuid_unsupported ; Flags were not changed, cpuid not supported + ret + +.cpuid_unsupported: + mov al, "C" ; err code C - cpuid unsupported + jmp error + +check_x64_supported: + mov eax, 0x80000000 ; Magic code that i dont understand + cpuid ; Magic code that i dont understand + cmp eax, 0x80000001 ; Magic code that i dont undetstand + jb .x64_unsupported ; Something went wrong so x64 isnt supported + + mov eax, 0x80000001 ; Set magic value 0x80000001 into EAX for cpuid + cpuid ; Get "extended features list" from CPU info + test edx, 1 << 29 ; Check if x64 is supported by checking bit 29 + jz .x64_unsupported ; If zero, x64 unsupported so jump to no x64 + + ret +.x64_unsupported: + mov al, "L" ; err code L, long mode/x64 unsupported + jmp error + +; Magic paging code that I don't understand +setup_page_tables: + mov eax, page_table_l3 + or eax, 0b11 ; present, writable + mov [page_table_l4], eax + + mov eax, page_table_l2 + or eax, 0b11 ; present, writable + mov [page_table_l3], eax + + mov ecx, 0 ; counter +.loop: + + mov eax, 0x200000 ; 2MiB + mul ecx + or eax, 0b10000011 ; present, writable, huge page + mov [page_table_l2 + ecx * 8], eax + + inc ecx ; increment counter + cmp ecx, 512 ; checks if the whole table is mapped + jne .loop ; if not, continue + + ret + +enable_paging: + ; pass page table location to cpu + mov eax, page_table_l4 + mov cr3, eax + + ; enable PAE + mov eax, cr4 + or eax, 1 << 5 + mov cr4, eax + + ; enable long mode + mov ecx, 0xC0000080 + rdmsr + or eax, 1 << 8 + wrmsr + + ; enable paging + mov eax, cr0 + or eax, 1 << 31 + mov cr0, eax + + ret + +error: + ; print "ERR: X" where X is the error code + mov dword [0xb8000], 0x4f524f45 + mov dword [0xb8004], 0x4f3a4f52 + mov dword [0xb8008], 0x4f204f20 + mov byte [0xb800a], al + hlt + +section .bss +align 4096 +page_table_l4: + resb 4096 +page_table_l3: + resb 4096 +page_table_l2: + resb 4096 +stack_bottom: + resb 4096 * 4 +stack_top: + +section .rodata +gdt64: + dd 0 ; zero entry + dd 0 +.code_segment: equ $ - gdt64 + dq (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) ; code segment +.pointer: + dw $ - gdt64 - 1 ; length + dq gdt64 ; address \ No newline at end of file diff --git a/src/boot/entry64.asm b/src/boot/entry64.asm new file mode 100644 index 0000000..2d10b51 --- /dev/null +++ b/src/boot/entry64.asm @@ -0,0 +1,17 @@ +global entry_x64 +extern kmain + +section .text +bits 64 +entry_x64: + ; Nullify all data registers + mov ax, 0 + mov ss, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + call kmain ; Jump into C kernel entry + + hlt \ No newline at end of file diff --git a/src/boot/mb2_header.asm b/src/boot/mb2_header.asm new file mode 100644 index 0000000..5eabae1 --- /dev/null +++ b/src/boot/mb2_header.asm @@ -0,0 +1,16 @@ +section .mb2_header +header_start: + ; https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html for more information, section 3.1.1 + dd 0xe85250d6 ; multiboot2 magic number + + dd 0 ; i386 protected 32 bit mode + + dd header_end - header_start ; Header length + + dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) ; Checksum, total is 0 + + ; Ending tag + dw 0 + dw 0 + dd 8 +header_end: \ No newline at end of file diff --git a/src/iso/boot/grub/grub.cfg b/src/iso/boot/grub/grub.cfg new file mode 100644 index 0000000..9c6aeb4 --- /dev/null +++ b/src/iso/boot/grub/grub.cfg @@ -0,0 +1,7 @@ +set timeout=5 +set default=0 + +menuentry "shadeOS Development Build" { + multiboot2 /boot/shade.bin + boot +} \ No newline at end of file diff --git a/src/iso/grub.cfg b/src/iso/grub.cfg deleted file mode 100644 index 1fdb214..0000000 --- a/src/iso/grub.cfg +++ /dev/null @@ -1,6 +0,0 @@ -set timeout=0 -set default=0 - -menuentry "shadeOS Dev Build" { - multiboot /boot/shade.bin -} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index dbb52be..84b5789 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,7 +1,5 @@ -#include "./platform/ports.h" -#include "print.h" - -void dummy_test_entrypoint() {} +#include +#include void kernel_welcome() { print_str("Welcome to "); @@ -44,4 +42,5 @@ void kmain() { print_str("Copyright (c) e3team 2022. All rights reserved.\n"); print_str("This program is provided \"as-is\" and no express or implied warranty is provided.\n"); print_str("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n"); + } \ No newline at end of file diff --git a/src/kernel/platform/ports.c b/src/kernel/platform/ports.c new file mode 100644 index 0000000..34a48db --- /dev/null +++ b/src/kernel/platform/ports.c @@ -0,0 +1,26 @@ +/* + * Read 1 byte from specified port + */ +unsigned char port_byte_in(unsigned short port) { + unsigned char result; + // source and dest are backwards. + // "=a (result)" set the C variable to the value of register e'a'x + // '"d" (port) map the C variable port into e'd'x register + __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); +} + +void port_byte_out(unsigned short port, unsigned char data) { + // both regs are C vars, nothing is returned, so no '=' in asm syntax + // comma because two vars in input area and none in return area + __asm__("out %%al, %%dx" : : "a" (data), "d" (port)); +} + +unsigned short port_word_in(unsigned short port) { + unsigned short result; + __asm__("in %%dx, %%ax" : "=a" (result) : "d" (port)); + return result; +} + +void port_word_out(unsigned short port, unsigned short data) { + __asm__("out %%ax, %%dx" : : "a" (data), "d" (port)); +} \ No newline at end of file diff --git a/src/kernel/print.c b/src/kernel/print.c index 85bde11..0ee30b7 100644 --- a/src/kernel/print.c +++ b/src/kernel/print.c @@ -1,5 +1,5 @@ -#include "print.h" -#include "./platform/ports.h" +#include +#include int row = 0; int col = 0; @@ -87,10 +87,10 @@ void print_set_color(char foreground, char background) { void set_cursor_pos(int col, int row) { int offset = col + NUM_COLS * row; - outb(REG_SCREEN_CTRL, 14); - outb(REG_SCREEN_DATA, (unsigned char)(offset >> 8)); - outb(REG_SCREEN_CTRL, 15); - outb(REG_SCREEN_DATA, (unsigned char)(offset & 0xff)); + port_byte_out(REG_SCREEN_CTRL, 14); + port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset >> 8)); + port_byte_out(REG_SCREEN_CTRL, 15); + port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset & 0xff)); } void kernel_msg_ok(char* msg) { diff --git a/src/kernel/util.c b/src/kernel/util.c index e945d94..5063a05 100644 --- a/src/kernel/util.c +++ b/src/kernel/util.c @@ -1,4 +1,4 @@ -#include "util.h" +#include void memcpy(char *source, char *dest, int nbytes) { int i; diff --git a/src/kernel/strings.c b/src/libc/strings.c similarity index 97% rename from src/kernel/strings.c rename to src/libc/strings.c index eef8e40..d148672 100644 --- a/src/kernel/strings.c +++ b/src/libc/strings.c @@ -1,4 +1,4 @@ -#include "strings.h" +#include #include void itoa(int n, char str[]) { diff --git a/src/linker.ld b/src/linker.ld index f5b8dcd..289a33b 100644 --- a/src/linker.ld +++ b/src/linker.ld @@ -1,23 +1,30 @@ - ENTRY(entry_x86) -SECTIONS -{ - . = 1M; +SECTIONS { + . = 1M; - .boot : + .text BLOCK(4K) : ALIGN(4K) + { + *(.mb2_header) + *(.text) + } + + /* Read-only data. */ + .rodata BLOCK(4K) : ALIGN(4K) { - KEEP(*(.mb2_header)) + *(.rodata) } - - .text : + + /* Read-write data (initialized) */ + .data BLOCK(4K) : ALIGN(4K) { - *(.text) + *(.data) } - - .idt BLOCK(0x1000) : ALIGN(0x1000) + + /* Read-write data (uninitialized) and stack */ + .bss BLOCK(4K) : ALIGN(4K) { - _idt = .; - . = . + 0x1000; + *(COMMON) + *(.bss) } } \ No newline at end of file