From 35d08c3a9c9526d48eed1bd76540272fc11b4136 Mon Sep 17 00:00:00 2001 From: c0repwn3r Date: Fri, 13 May 2022 17:00:50 -0400 Subject: [PATCH] it wont work goddammit --- Makefile | 6 +- bin/shade.bin | Bin 9828 -> 11224 bytes bin/shade.iso | Bin 26591232 -> 26593280 bytes bin/shade.iso.lock | 0 bochsrc.txt | 57 ++++++++++ obj/boot.o | Bin 864 -> 1296 bytes obj/kernel/kernel.o | Bin 1860 -> 1900 bytes obj/kernel/platform/interrupts/int.o | Bin 0 -> 1200 bytes obj/kernel/platform/interrupts/int_lowlevel.o | Bin 0 -> 2240 bytes old/src/boot/protected/gdt.asm | 1 + old/src/kernel/platform/gdt.h | 28 +++++ src/boot.asm | 14 +++ src/gdt.asm | 33 ++++++ src/iso/grub.cfg | 3 + src/kernel/kernel.c | 9 +- src/kernel/platform/interrupts/int.c | 35 ++++++ src/kernel/platform/interrupts/int.h | 43 ++++++++ .../platform/interrupts/int_lowlevel.asm | 101 ++++++++++++++++++ src/kernel/platform/types.h | 18 ---- src/kernel/strings.c | 2 +- 20 files changed, 323 insertions(+), 27 deletions(-) create mode 100644 bin/shade.iso.lock create mode 100644 bochsrc.txt create mode 100644 obj/kernel/platform/interrupts/int.o create mode 100644 obj/kernel/platform/interrupts/int_lowlevel.o create mode 100644 old/src/kernel/platform/gdt.h create mode 100644 src/gdt.asm create mode 100644 src/kernel/platform/interrupts/int.c create mode 100644 src/kernel/platform/interrupts/int.h create mode 100644 src/kernel/platform/interrupts/int_lowlevel.asm delete mode 100644 src/kernel/platform/types.h diff --git a/Makefile b/Makefile index 6cd758c..3e8a13a 100644 --- a/Makefile +++ b/Makefile @@ -37,11 +37,11 @@ obj/%.o: src/%.asm run: clean bin/shade.iso - qemu-system-x86_64 -hdd 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 & - ${GDB} os-image.bin -ex "symbol-file bin/shade.bin" -ex "target remote localhost:1234" + 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" clean: diff --git a/bin/shade.bin b/bin/shade.bin index b755599e508652d9deabe4b8bf1d930f97afbf8e..bc273ebae2a62cff654d3369d75f11dfaf4cb632 100755 GIT binary patch delta 3432 zcmZ9Pe{2-j5y$83!!hoe+kkD%598zPa|*b&?+mGNlEzW714-N(9H?<>FNbdr>>hW{ z-I}yg&?2m)wk%xJjgkr}RU_J}KNM9Zjq9p^grBu&oA{(OD*d4lDFqz~jSNB!A%W|6 z-tN0wyw=RkXWqOwZ{M4@yZ+Bp7r!;-E7-dJnBQMyloA=G$DUYOR82&_p5G4r+PnU? z*HvDrDD+V+DO60+8HFY)f)&=BsY>9G~y?PM_kSgmJ!?b&?a z+*N)RJ=-cav^-lNd*=3_AFljlyFlZ89<0?w-xss(#k@@yuC|&dDq1nb`xP6YOO`i6 zw=O@l!so$OG~LZ+u|qUen9*R)x@+q_W_o#fAjGW&mTME+|GQ&HF3D`L+?^h?q;lno zZf-rBZ@mQ*1ONUn%U(urohJvA$h^ySQ+c z%TWHAZ&hwFMz59af0lctzsP2H{sGlW)JpGZ< zH|9AXfXS{p{Qk*(z7{`(v1b=mz~Z=>?0rPh6J;=ir;h%v4#QG(YNG6gpL|InkpCmS-;0F7%^9Zx*^) z=&uO=+i>~ zQRp{?{*BPT6#9hFuL}K&(8pMRP@>Qk$Ti3f$SufSh#QMn0#P6pkkt@B5+>w5M@ z7&4mZdiDoke$ZN%i(bPMnOYo<*U|EjgJ+cvI*wulKf*ZSDNHsfw}4=8`E%b2};KqFqfm` zcfeellK%&8xT_6B+{>oUjuH4iRmz0|E$0 zBf$=v>%m=^K$*=CgZbM9Z*{sKr=|@&j0yAeK#T`&L&C4wyoVX>^)~MV&liguHbe&< z4j(#r?SKctYw)1K3L=4CVz-|JA4b9fn`gj# zaD%I;-J0=Ra17%Pci92&fYablY+eiIPdItU{{}Z90jI&pp~WMXLrV=L2Z!}UlD_`UE$wP|`{T6bv8NvshBZP%Qi~8gyh0I?@Imd4rC`AxGknBXP))IOIqiawHDr6RRPSx5Zk#kRx%(kvQZ?-0Vo) z95hok2bN;v)WP_mP6IJ5oK%yE=gj$9qjKi{K;)c^nh delta 1451 zcmZ9MYe-XJ7{{MoTyv&7>bzeXYneNfHt2%gXdhC#h-s$Hm78W-*+tP=1ci}dN<_*_ zANmsYK`JV+0wF3W7MOjKuqX@>Dw-8FDqv06tjr{|j z5@Y|!{+Ak};9^LX-Uj3TVNOXPpSw)4^nk0{YKhKgo^pE{;--f@d8gH65yaql6cKV& zdLzkRLGrn0l05^tJtElyKwA4#>3rSKU0z>RpuFotS^F35xdOehKbBZ=qRZjsckFo!0iBkIjlt|$Hupg>W{A;YxKt1Laf!fs=osTdcIAA<1z~*uR)4`$#%Tu6bIg(l#^+r(bx*-zo{wg5H)Cm zb?6Rgt)HS$|pGKm0!heYN3Ve&;=bRTv7^#dOLrYlXm4ZK_4Mj<`PVfZU zF-*`a_&2^!eMoR!2n&$Oi~;<^ynuzAQ2?JA=VUPEOL2mEp?#RZcEMJ#Qzwy0@Cq=$ zsyM_HPf?T)ZbE@agkR7G!37~t2u0w>`pAqb!6C3w_{+c~DSkZC?gJ0OpD75pgT}xH zG5$2T8oXO@C)kC8GXy&>Kqx`QeDC=TFN6EQUj-+C`5#EkfN65Jvfi9+x>o;zL(6K} zjoiah?V-AwW?ysTG4i$eYnuHm*JfjTZI;-k#%8~7&vAd9ud&t7uG{k2ciRcpB%9Qu z(X2zxj^xc~-If>W_z`!evlp_gQn5*Su})>i-_*r&>=p={?Mq`#5FX=l;?GL) d?4&(IH;kijOT{kREvcuhL}f5$9uz+P{0CtCUu6IQ diff --git a/bin/shade.iso b/bin/shade.iso index 080a0abb6cdddb524180342fad1571cc763b5adb..f81d3d4079165a311388768fac65bef80830f776 100644 GIT binary patch delta 65295 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 Ipq0x12e(P33IG5A delta 63313 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 delta 383 zcmbQh^?+@H0W${!%S1=@i2;0*Cor*0%;8~dm{_UKIAP*K`Fb`62$;agz`zG(gD3$g zTO3F;L)jo|0Z^Sa5+BF~14SUo1Z9J$2OtR`2AK~smj#GHW@-X4l6mzE4}iMzfPydp zGtdwyzzGus(g8qSAOl!|7-Rs*Kn@^g+OSp{#Q*Id^aMyT>|tiV~?jn&L(mS}C;=R78lbO325A4CITM3Di{=L1+j{ z_U?4&T8b`&NQwOm{((XfH|_+5c+Sjw&fvxach3Dd@7=j?-t2BZxMx|G7+8{!C=$sf z!pe<+^0FwWj5OfV@M!Qo+oXT|dp4VuJ}$r=9xd%}E{sa4#xOO_ATfHFZVa>2G~CbM z(%XBf=~=i;odbVKPO~66Xp9f%Pr#w>!|Ws!ZDRZX0_PjkiIso6c>>2}J^N~hkkUFo@yls(iSD0{YFuG?PCb$Wg`OgS9~ zi#->bezojZsx4b;-G0YsE6!)(uB5g=rim0mRiE_IPs4l32s9Lw( zw!_h|W literal 0 HcmV?d00001 diff --git a/obj/kernel/platform/interrupts/int_lowlevel.o b/obj/kernel/platform/interrupts/int_lowlevel.o new file mode 100644 index 0000000000000000000000000000000000000000..98f9819729ccd5f2ab8a6c189699a2d00e5536fb GIT binary patch literal 2240 zcmdUxJ7^U_7=>q&7$ZcuQHuyZNrd}mH7#Eh^T}uB9+|HOnw>9|N^k$)pLm4w z9@K(Mpn7N()Cg^WTA@y;2igYhg!V!QphM6AGy;WC1WiDvp)=5V=pu9lx(?lj?m-Ws zC(v_9HOIk3teT6X#W;#HgK(2sL*^(5%{_AWUuE}8E>x)>CHDq7xqa>cvV3=Y=42=P zk>%MtIT&JdCV~DXmVz$oiPl>MV?`l__0*URgJruffO~n$qenjI5_AtscY3 z+M3epC5)`IDXm_^$eNqd>H~~CgDI`Pz{p;h(&{^m?29R_e!~nf$@4D2g2{fF(y9(w z_Ri*&$g+<%uSb?WwYdXX_SfdE$g%UQDd0do0Vl?Sx)>?JS-J;U{Bj-{|3su&Hm91Wse5VjP;Ogxg0 zvMpn|IEbS0LR=J^4)Z6%;5d$9rkGX1#86O($MU)KXeKut29X*oM(JWaKA3Jzte03n zv2BTMPi#kGI}_WL*zUw`PORs)bNYEsL(l2xIW0Y>r{^^FoUWeJ)^qy$PG8^Y>pOjY zr?2ny^_{-H)7N+U`c7Zp>D%V?ZFBnKWf2D4QS)xDXi!T2ZU`5XOG$bE%lK+?9VvfP zWL(aRu#4P6_K~~DedIy%Fqt8bkXf=wPLflkyg#Jh1@aPkmApaTA@7rq$fx8BavIbX zO1&ay$T#FW@;&*H{6u~xzml`$H*${rN&X_|N%@tM{#9fRSxctKWn?|Mf?Pv3l1=0$ PQvOen`P<2EvWNTwb}hQ# literal 0 HcmV?d00001 diff --git a/old/src/boot/protected/gdt.asm b/old/src/boot/protected/gdt.asm index db35b41..df7bfe2 100644 --- a/old/src/boot/protected/gdt.asm +++ b/old/src/boot/protected/gdt.asm @@ -1,3 +1,4 @@ + gdt_start: ; use labels to compute sizes and jumps ; gdt starts with 8 byte null dd 0x0 diff --git a/old/src/kernel/platform/gdt.h b/old/src/kernel/platform/gdt.h new file mode 100644 index 0000000..5545747 --- /dev/null +++ b/old/src/kernel/platform/gdt.h @@ -0,0 +1,28 @@ +#ifndef GDT_H +#define GDT_H + +#include + +// the GDT descriptor format makes literally no sense, who came up with this +typedef struct { + uint16_t limit_low16; // Low 16 bits of limit + uint16_t base_low16; // Low 16 bits of base + uint8_t base_mid8; // Middle 8 bits of base + uint8_t access; // 7: present, 6-5: priv level, 4: type, 3: executable, 2: dc, 1: rw, 0: accessed (zero) + uint8_t limit_flags; // High 4 bits of limit AND flags (?? why). flags: 3: granularity, 2: size, 1: long, 0: reserved + uint8_t base_high8; // High 8 bits of base +} __attribute__((packed)) gdt_entry_t; + +typedef struct { + uint16_t size; // GDT size (bytes) - 1 + uint32_t offset; // Address of element 0 of the GDT +} __attribute__((packed)) gdt_ptr_t; + +static gdt_entry_t gdt[8192]; +static gdt_ptr_t gdtr; + +void init_gdt(); +void gdt_set_segment(int limit, int base, int access); +void load_gdt(); + +#endif \ No newline at end of file diff --git a/src/boot.asm b/src/boot.asm index a265974..c4eac95 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -18,6 +18,8 @@ stack_bottom: resb 16384 stack_top: +%include "src/gdt.asm" + ; _start = entry to kernel ; Since the bootloader will be gone, it doesn't make sense to return from this section .text @@ -27,6 +29,18 @@ _start: ; 32bit protected mode, no int, no paging mov esp, stack_top ; Initialize stack + cli ; Disable interrupts + lgdt [gdt_descriptor] ; load the GDT + jmp CODE_SEG:.reload_seg ; far jump into a different segment + +.reload_seg: ; now in 32bit + mov ax, DATA_SEG ; update segment registers + mov ds, ax + mov ss, ax + mov es, ax + mov fs, ax + mov gs, ax + extern kmain call kmain diff --git a/src/gdt.asm b/src/gdt.asm new file mode 100644 index 0000000..94a1299 --- /dev/null +++ b/src/gdt.asm @@ -0,0 +1,33 @@ +section .data + +gdt_start: ; use labels to compute sizes and jumps + ; gdt starts with 8 byte null + dd 0x0 + dd 0x0 + +; GDT for code segment, base = 0x00000000, length = 0xfffff +gdt_code: + dw 0xffff ; segment length + dw 0x0 ; segment base + db 0x0 ; segment base + db 10011010b ; flags + db 11001111b ; flags + segment length + db 0x0 ; segment base + +; GDT for data segment +gdt_data: + dw 0xffff ; segment length + dw 0x0 ; segment base + db 0x0 ; segment base + db 10010010b ; flags + db 11001111b ; flags + segment length + db 0x0 ; segment base + +gdt_end: + +gdt_descriptor: + dw gdt_end - gdt_start - 1 ; size, always 1 less than what it actually is + dd gdt_start ; address + +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start \ No newline at end of file diff --git a/src/iso/grub.cfg b/src/iso/grub.cfg index d6d553e..1fdb214 100644 --- a/src/iso/grub.cfg +++ b/src/iso/grub.cfg @@ -1,3 +1,6 @@ +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 33df331..3002fb1 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,7 +1,6 @@ #include "./platform/drivers/ports.h" #include "print.h" -#include "./platform/types.h" -//#include "./platform/interrupts/int.h" +#include "./platform/interrupts/int.h" void dummy_test_entrypoint() {} @@ -46,10 +45,10 @@ 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"); -/* + idt_init(); - kernel_msg_ok("Interrupts initialized"); __asm__ __volatile__("int $2"); -*/ + + //kernel_msg_ok("Interrupts working"); } \ No newline at end of file diff --git a/src/kernel/platform/interrupts/int.c b/src/kernel/platform/interrupts/int.c new file mode 100644 index 0000000..7474267 --- /dev/null +++ b/src/kernel/platform/interrupts/int.c @@ -0,0 +1,35 @@ +#include "int.h" +#include "../../print.h" + +#include +#include +#include + +int count = 0; + +void exception_handler() { + print_str("I"); +} + +void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags) { + idt_entry_t* descriptor = &idt[vector]; + + descriptor->isr_low = (uint32_t)isr & 0xFFFF; + descriptor->kernel_cs = 0x08; // this value can be whatever offset your kernel code selector is in your GDT + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)isr >> 16; + descriptor->reserved = 0; +} + +void idt_init() { + idtr.base = (uint32_t)&idt[0]; + idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1; + + for (uint8_t vector = 0; vector < 32; vector++) { + idt_set_descriptor(vector, isr_stub_table[vector], 0x8E); + isr_stub_table[vector] = true; + } + + __asm__ volatile ("lidt %0" : : "m"(idtr)); // load the new IDT + __asm__ volatile ("sti"); // set the interrupt flag +} \ No newline at end of file diff --git a/src/kernel/platform/interrupts/int.h b/src/kernel/platform/interrupts/int.h new file mode 100644 index 0000000..f2a0d01 --- /dev/null +++ b/src/kernel/platform/interrupts/int.h @@ -0,0 +1,43 @@ +#ifndef INT_H +#define INT_H + +#include "../../util.h" +#include +#include +#include + +typedef struct { + uint16_t isr_low; // The lower 16 bits of the ISR's address + uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR + uint8_t reserved; // Set to zero + uint8_t attributes; // Type and attributes; see the IDT page + uint16_t isr_high; // The higher 16 bits of the ISR's address +} __attribute__((packed)) idt_entry_t; + +__attribute__((aligned(0x10))) +static idt_entry_t idt[256]; // Create an array of IDT entries; aligned for performance + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) idtr_t; + +static idtr_t idtr; + +typedef struct { + uint32_t ds; /* Data segment selector */ + uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */ + uint32_t int_no, err_code; /* Interrupt number and error code (if applicable) */ + uint32_t eip, cs, eflags, useresp, ss; /* Pushed by the processor automatically */ +} registers_t; + +__attribute__((noreturn)) +void exception_handler(); + +void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags); + +extern void* isr_stub_table[]; + +void idt_init(void); + +#endif \ No newline at end of file diff --git a/src/kernel/platform/interrupts/int_lowlevel.asm b/src/kernel/platform/interrupts/int_lowlevel.asm new file mode 100644 index 0000000..a030f48 --- /dev/null +++ b/src/kernel/platform/interrupts/int_lowlevel.asm @@ -0,0 +1,101 @@ +%macro isr_err_stub 1 +isr_stub_%+%1: + ;push byte %1 ; Push interrupt no to stack + + ; 1. Save CPU state + ;pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax + ;mov ax, ds ; Lower 16-bits of eax = ds. + ;push eax ; save the data segment descriptor + ;mov ax, 0x10 ; kernel data segment descriptor + ;mov ds, ax + ;mov es, ax + ;mov fs, ax + ;mov gs, ax + + ; 2. Call C handler + call exception_handler + + ; 3. Restore state + ;pop eax + ;mov ds, ax + ;mov es, ax + ;mov fs, ax + ;mov gs, ax + ;popa + ;add esp, 8 ; Cleans up the pushed error code and pushed ISR number + iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP +%endmacro +; if writing for 64-bit, use iretq instead +%macro isr_no_err_stub 1 +isr_stub_%+%1: + ;push byte 0 ; No error occured + ;push byte %1 ; Push interrupt no to stack + + ; 1. Save CPU state + ;pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax + ;mov ax, ds ; Lower 16-bits of eax = ds. + ;push eax ; save the data segment descriptor + ;mov ax, 0x10 ; kernel data segment descriptor + ;mov ds, ax + ;mov es, ax + ;mov fs, ax + ;mov gs, ax + + ; 2. Call C handler + call exception_handler + + ; 3. Restore state + ;pop eax + ;mov ds, ax + ;mov es, ax + ;mov fs, ax + ;mov gs, ax + ;popa + ;add esp, 8 ; Cleans up the pushed error code and pushed ISR number + ;sti + iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP +%endmacro + +extern exception_handler + +isr_no_err_stub 0 +isr_no_err_stub 1 +isr_no_err_stub 2 +isr_no_err_stub 3 +isr_no_err_stub 4 +isr_no_err_stub 5 +isr_no_err_stub 6 +isr_no_err_stub 7 +isr_err_stub 8 +isr_no_err_stub 9 +isr_err_stub 10 +isr_err_stub 11 +isr_err_stub 12 +isr_err_stub 13 +isr_err_stub 14 +isr_no_err_stub 15 +isr_no_err_stub 16 +isr_err_stub 17 +isr_no_err_stub 18 +isr_no_err_stub 19 +isr_no_err_stub 20 +isr_no_err_stub 21 +isr_no_err_stub 22 +isr_no_err_stub 23 +isr_no_err_stub 24 +isr_no_err_stub 25 +isr_no_err_stub 26 +isr_no_err_stub 27 +isr_no_err_stub 28 +isr_no_err_stub 29 +isr_err_stub 30 +isr_no_err_stub 31 + +global isr_stub_table +isr_stub_table: +%assign i 0 +%rep 32 + dd isr_stub_%+i ; use DQ instead if targeting 64-bit +%assign i i+1 +%endrep + diff --git a/src/kernel/platform/types.h b/src/kernel/platform/types.h deleted file mode 100644 index e18f414..0000000 --- a/src/kernel/platform/types.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef TYPES_H -#define TYPES_H - -typedef unsigned int u32; -typedef int i32; -typedef unsigned short u16; -typedef short i16; -typedef unsigned char u8; -typedef char i8; - -#define high16(i32) (i32 & 0xffff) -#define low16(i32) ((i32>>16) & 0xffff) - -#define TRUE 1 -#define FALSE 0 -#define NULL 0 - -#endif \ No newline at end of file diff --git a/src/kernel/strings.c b/src/kernel/strings.c index 79897f8..eef8e40 100644 --- a/src/kernel/strings.c +++ b/src/kernel/strings.c @@ -1,5 +1,5 @@ #include "strings.h" -#include "./platform/types.h" +#include void itoa(int n, char str[]) { int i, sign;