From 8fcd0cf7d6a2c891422c7101840778043207a60d Mon Sep 17 00:00:00 2001 From: Nic Gaffney Date: Sun, 10 Dec 2023 09:48:53 -0600 Subject: Changed to the based ASM syntax and implemented a rudementary GDT --- src/header/boot.s | 156 ++++++++++++++++----------------------------------- src/header/crti.s | 17 +++--- src/header/crtn.s | 8 +-- src/include/gdt.h | 32 +++++++++++ src/kernel/gdt.c | 51 +++++++++++++++++ src/kernel/gen_gdt.c | 11 ++++ src/kernel/kernel.c | 28 ++++----- src/utils/str.c | 38 ++++++------- 8 files changed, 186 insertions(+), 155 deletions(-) create mode 100644 src/include/gdt.h create mode 100644 src/kernel/gdt.c create mode 100644 src/kernel/gen_gdt.c (limited to 'src') diff --git a/src/header/boot.s b/src/header/boot.s index 2276e3d..5eaa794 100644 --- a/src/header/boot.s +++ b/src/header/boot.s @@ -1,117 +1,55 @@ -/* multiboot header constants */ -.set ALIGN, 1<<0 /* Align loaded modules on page boundries */ -.set MEMINFO, 1<<1 /* Provide memory map*/ -.set FLAGS, ALIGN | MEMINFO /* Multiboot flag field*/ -.set MAGIC, 0x1BADB002 /*Lets bootloader find header*/ -.set CHECKSUM, -(MAGIC + FLAGS) /* Proves we are multiboot via checksum*/ - -/* - * Declare a multiboot header that marks the program as a kernel. - * These are magic values that are docymented in the multiboot standard. - * The bootloader will search fot this signature in the first 8KiB of - * the kernel file, aligned at a 32-bit boundry. - * The signature is in its own section so the header can be forced to be - * within the first 8KiB of the kernel file. - */ -.section .multiboot -.align 4 -.long MAGIC -.long FLAGS -.long CHECKSUM - -/* - * The multiboot standard doesn't define the value of the "stack pointer register," - * or esp, as it is up to the kernel to provide a stack. - * This allocates room for a small stack through a few steps: - * 1. Create a symbol at the bottom of the stack - * 2. Allocate 16 KiB for the stack - * 3. Create a symbol at the top of the stack. - * The stack grows DOWN on x86. - * Since the stack is in its own section*, it can be marked "nobits" - * which means the kernel file is smaller since it doesn't contain - * an uninitialized stack. - * On x86, the stack must be 16-byte aligned** according to System V ABI standard - * and de-facto extentions. - * The compiler assumes the stack is properly aligned, so failure to align will - * result in UB. - */ -.section bss -.align 16 -.stack_bottom: -.skip 16384 -stack_top: - -/* - * Our linker script specifies _start as te entry point to the kernel. - * The bootloader will jump here once the kernel is loaded. - * We won't return, since the bootloader would be gone at that point - */ -.section .text -.global _start -.type _start, @function +MBALIGN equ 1<<0 ; Align loaded modules on page boundries */ +MBMEMINFO equ 1<<1 ; Provide memory map*/ +MBFLAGS equ MBALIGN | MBMEMINFO ; Multiboot flag field*/ +MAGIC equ 0x1BADB002 ;Lets bootloader find header*/ +CHECKSUM equ -(MAGIC + MBFLAGS) ; Proves we are multiboot via checksum*/ + + +section .multiboot +align 4 + dd MAGIC + dd MBFLAGS + dd CHECKSUM + +section .bss +align 16 +stack_bottom: +resb 16384 +stack_top: + +section .text +global _start:function (_start.end - _start) _start: - /* - * The bootloader loads us into 32-bit mode on x86 machines. - * Interrupts and paging are disabled. - * The multiboot standard defines our current processor state. - * The kernel has full control over the CPU - * The kernel can only use two things - * 1. hardware features - * 2. its own code - * No printing is available (Unless we make it). - * No security restrictions, safeguards, or debugging mechanisms. - * We only have what the kernel provides. - * ABSOLUTE POWER OVER THE MACHINE!! - */ + mov esp, stack_top - /* - * To setup a stack, make the esp register point to the top of the stack. - * We have to do this in assembly since C wont even function without the stack. - */ - mov $stack_top, %esp + extern get_gdtr + call get_gdtr + extern gdtr + mov [gdtr], eax + cli + lgdt [gdtr] - /* - * This is a good point to initialize crucial processor state before our - * high level kernel is entered. - * It's best to minize early environment where crucial features are offline. - * The processor is not fully initialized yet, therefore - * features such as floating point instructions and instruction set extentions - * are ALSO not initialized. - * The GDT (global descriptor table) should be loaded here. - * Paging should be enabled here. - */ - /* - * Enter our high level kernel. - * the ABI (?) requres the stack is 16-byte aligned at the time of - * the call instruction (which afterward will push the return pointer - * of size 4 bytes). - * The stack was 16-byte aligned above, and we have pushed a multiple of - * 16 bytes to the stack (we have pushed zero bytes so far), so - * the alignment is preserved, and the call is well defined. - */ + call reloadSegments ; this motherfucker is what is causing so many issues + + [bits 32] + extern kernel_main call kernel_main - /* - * If the system has nothing else to do, we will infinitely loop. - * To do this, we must: - * 1. Disable interrupts with `cli` - * (clear interrupt enable in eflags.) - * They are already disabled by the bootloader, so we can skip this. - * Keep in mind, we may have to do this later AND return from main - * (for some nonsensical reason) - * 2. wait for the next interrupt to arrive with `hlt` (halt instruction) - * Since interrupts are disabled, this locks up the computer (yay!) - * 3. jump to the `hlt` instruction if it ever wakes up due to a - * non-maskable interrupt occuring or due to a system management mode. - */ - cli -1: hlt - jmp 1 -/* - * Set the size of _start to { current_location - (start of _start) } - * This is useful for debugging or for call tracing later on. - */ -.size _start, . - _start + cli +.hang: hlt + jmp .hang +.end: + + reloadSegments: + JMP 0x0008:.reload_CS ; should def define a CODESEG +.reload_CS: + MOV AX, 0x0010 + MOV DS, AX + MOV ES, AX + MOV FS, AX + MOV GS, AX + MOV SS, AX + RET diff --git a/src/header/crti.s b/src/header/crti.s index 91e86fa..26d677a 100644 --- a/src/header/crti.s +++ b/src/header/crti.s @@ -1,12 +1,11 @@ -.section .init -.global _init -.type _init @function +section .init +global _init:function _init: - push %ebp - movl %esp, %ebp + push ebp + mov ebp, esp, -.section .fini -.global _fini +section .fini +global _fini _fini: - push %ebp - movl %esp, %ebp + push ebp + mov ebp, esp diff --git a/src/header/crtn.s b/src/header/crtn.s index 4874122..46f8de6 100644 --- a/src/header/crtn.s +++ b/src/header/crtn.s @@ -1,7 +1,7 @@ -.section .init - popl %ebp +section .init + pop ebp ret -.section .fini - popl %ebp +section .fini + pop ebp ret diff --git a/src/include/gdt.h b/src/include/gdt.h new file mode 100644 index 0000000..05f426e --- /dev/null +++ b/src/include/gdt.h @@ -0,0 +1,32 @@ +#pragma once +#include +#define FLAG 0b1100 +typedef struct Segment_Descriptor { + uint16_t lim_low; + uint16_t base_low; + uint8_t base_mid; + uint8_t access; + uint8_t lim_flag; + uint8_t base_high; +} __attribute__((packed)) Segment_Descriptor_t; + +typedef struct GDTR { + uint16_t size; + uint32_t offset; +} __attribute__((packed)) GDTR_t; + +typedef struct GDT { + Segment_Descriptor_t nulldesc; + Segment_Descriptor_t codedesc; + Segment_Descriptor_t datadesc; +} __attribute__((packed)) GDT_t; + +uint8_t make_access(uint8_t DPL, uint8_t type, uint8_t exec, uint8_t direction, + uint8_t read_write); + +uint16_t make_code(uint8_t priv, uint8_t dc, uint8_t rw); +uint16_t make_data(uint8_t priv, uint8_t dc, uint8_t rw); + +Segment_Descriptor_t make_descriptor(uint32_t base, uint32_t limit, + uint16_t access_flag); +void get_gdtr(); diff --git a/src/kernel/gdt.c b/src/kernel/gdt.c new file mode 100644 index 0000000..cf0f487 --- /dev/null +++ b/src/kernel/gdt.c @@ -0,0 +1,51 @@ +#include "gdt.h" +#include + +uint8_t make_access(uint8_t DPL, uint8_t type, uint8_t exec, uint8_t direction, + uint8_t read_write) { + uint8_t access = 0; + access |= (1 << 7); + access |= (DPL << 5); + access |= (type << 4); + access |= (exec << 3); + access |= (direction << 2); + access |= (read_write << 1); // 10 + return access; +} + +uint16_t make_code(uint8_t priv, uint8_t dc, uint8_t rw) { + uint16_t access = 0; + access |= (1 << 7); + access |= (priv << 5); + access |= (0b11 << 3); + access |= (dc << 2); + access |= (rw << 1); // 10 + access <<= 8; + access |= FLAG; + return access; +} + +uint16_t make_data(uint8_t priv, uint8_t dc, uint8_t rw) { + uint16_t access = 0; + access |= (1 << 7); + access |= (priv << 5); + access |= (0b10 << 3); + access |= (dc << 2); + access |= (rw << 1); // 10 + access <<= 8; + access |= FLAG; + return access; +} + +Segment_Descriptor_t make_descriptor(uint32_t base, uint32_t limit, + uint16_t access_flag) { + uint16_t lim_low = limit; + uint16_t base_low = base; + uint8_t base_mid = (base >> 16); + uint8_t access_byte = access_flag >> 8; + uint8_t lim_flag = ((access_flag << 4) | (limit >> 16)); + uint8_t base_high = (base >> 24); + return (Segment_Descriptor_t){ + lim_low, base_low, base_mid, access_byte, lim_flag, base_high, + }; +} diff --git a/src/kernel/gen_gdt.c b/src/kernel/gen_gdt.c new file mode 100644 index 0000000..05eedaa --- /dev/null +++ b/src/kernel/gen_gdt.c @@ -0,0 +1,11 @@ +#include "gdt.h" + +GDT_t *table = 0x0; +GDTR_t gdtr = {0, 0}; +void get_gdtr() { + *table = (GDT_t){make_descriptor(0, 0, 0), + make_descriptor(0x0000, 0xFFFFF, make_code(0, 0, 1)), + make_descriptor(0x0000, 0xFFFFF, make_data(0, 0, 1))}; + gdtr.size = sizeof(Segment_Descriptor_t) * 3 - 1; + gdtr.offset = 0x0; +} diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 40438ec..01c017b 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -10,20 +10,20 @@ #error "Must use ix86-elf compiler" #endif -// Color Constants - void kernel_main(void) { - print_clear(); - for (int r = 0; r < 24; r++) { - for (int c = 0; c < 80; c += 3) { - int color = (r + c) % 15 + 1; - print_set_color(color, PRINT_COLOR_BLACK); - printf(":3 "); + print_clear(); + for (int r = 0; r < 24; r++) { + for (int c = 0; c < 80; c += 3) { + int color = (r + c) % 15 + 1; + print_set_color(color, PRINT_COLOR_BLACK); + printf(":3 "); + } + printf("%n"); } - printf("%n"); - } - print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK); - printf("printf\n\tint: %d\n\tstring: %s\n\tchar: %c\n\tpercent: " - "%%\n\tnothing: %n", - 99, "World! ", 't'); + print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK); + printf("printf\n\tint: %d\n\tstring: %s\n\tchar: %c\n\tpercent: " + "%%\n\tnothing: %n", + 99, "World! ", 't'); + + // printf("\n0x%d\n", *((int *)(0x0010))); } diff --git a/src/utils/str.c b/src/utils/str.c index 499f781..e0903c4 100644 --- a/src/utils/str.c +++ b/src/utils/str.c @@ -2,32 +2,32 @@ #include size_t strlen(const char *str) { - size_t size = 0; - for (; (str[size]) != '\0'; size++) { - } - return size; + size_t size = 0; + for (; (str[size]) != '\0'; size++) { + } + return size; } char *str_reverse(char *str) { - char *str_ptr = str; - size_t size = strlen(str); - char return_str[size]; + char *str_ptr = str; + size_t size = strlen(str); + char return_str[size]; - for (size_t i = 0; i < size; i++) - return_str[size - i - 1] = str[i]; + for (size_t i = 0; i < size; i++) + return_str[size - i - 1] = str[i]; - for (size_t i = 0; i < size; i++) - *str_ptr++ = return_str[i]; + for (size_t i = 0; i < size; i++) + *str_ptr++ = return_str[i]; - return str; + return str; } char *itoa(int num, char *str) { - char *str_ptr = str; - for (; num;) { - *str_ptr++ = num % 10 + 48; - num /= 10; - } - str_reverse(str); - return str; + char *str_ptr = str; + for (; num;) { + *str_ptr++ = num % 2 + 48; + num /= 2; + } + str_reverse(str); + return str; } -- cgit v1.2.3