aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNic Gaffney <gaffney_nic@protonmail.com>2023-12-10 09:48:53 -0600
committerNic Gaffney <gaffney_nic@protonmail.com>2023-12-10 09:48:53 -0600
commit8fcd0cf7d6a2c891422c7101840778043207a60d (patch)
tree5527b605fdaee1ad4404bef6418f1a5e34e31d52
parent87d1e83a0ea5e20e535e3378e57f1fe0e9818a64 (diff)
downloadgftos-8fcd0cf7d6a2c891422c7101840778043207a60d.tar.gz
Changed to the based ASM syntax and implemented a rudementary GDT
-rw-r--r--.clang-format5
-rw-r--r--Makefile2
-rw-r--r--README.md30
-rw-r--r--compile_flags.txt1
-rw-r--r--src/header/boot.s156
-rw-r--r--src/header/crti.s17
-rw-r--r--src/header/crtn.s8
-rw-r--r--src/include/gdt.h32
-rw-r--r--src/kernel/gdt.c51
-rw-r--r--src/kernel/gen_gdt.c11
-rw-r--r--src/kernel/kernel.c28
-rw-r--r--src/utils/str.c38
-rw-r--r--tests/compile_flags.txt1
-rwxr-xr-xtests/testbin0 -> 20752 bytes
-rw-r--r--tests/test_gdt.c21
15 files changed, 245 insertions, 156 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..11212cb
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,5 @@
+---
+BasedOnStyle: LLVM
+IndentWidth: 4
+TabWidth: 4
+...
diff --git a/Makefile b/Makefile
index 258638f..2d16e10 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ C := $(sort $(shell find $(SRC) -name '*.c'))
INCLUDE_DIR = $(SRC)/include
INCLUDES := -I$(INCLUDE_DIR)
-ASSEMBLER = $(TARGET)-as
+ASSEMBLER = nasm -felf32
CC = $(TARGET)-gcc
CFLAGS = $(INCLUDES) -std=gnu99 -ffreestanding -O2 -Wall -Wextra
diff --git a/README.md b/README.md
index bbc4689..f3d7d49 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,33 @@
# Basic setup for OSdev
These files are well commented and are meant to remind you how to actually develop an OS. read from osdev.org to learn more.
+## quickstart
+```sh
+mkdir -p $HOME/.local/opt
+mkdir -p $HOME/.local/opt/cross
+mkdir -p $HOME/.local/src
+export PREFIX="$HOME/.local/opt/cross"
+export TARGET=i686-elf
+export PATH="$PREFIX/bin:$PATH"
+
+cd $HOME/.local/src
+mkdir build-binutils
+cd build-binutils
+curl https://ftp.gnu.org/gnu/binutils/binutils-2.41.tar.xz | tar -xJ
+../binutils-2.41/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror
+make
+make install
+
+cd $HOME/.local/src
+which -- $TARGET-as || echo $TARGET-as is not in the PATH
+curl https://ftp.gnu.org/gnu/gcc/gcc-13.2.0/gcc-13.2.0.tar.xz | tar -xJ
+mkdir build-gcc
+cd build-gcc
+../gcc-13.2.0/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers
+make all-gcc
+make all-target-libgcc
+make install-gcc
+make install-target-libgcc
+
+export PATH="$HOME/.local/opt/cross/bin:$PATH"
+```
diff --git a/compile_flags.txt b/compile_flags.txt
new file mode 100644
index 0000000..cec6042
--- /dev/null
+++ b/compile_flags.txt
@@ -0,0 +1 @@
+-I src/include/
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 <stdint.h>
+#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 <stdint.h>
+
+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 <stddef.h>
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;
}
diff --git a/tests/compile_flags.txt b/tests/compile_flags.txt
new file mode 100644
index 0000000..f8a2c60
--- /dev/null
+++ b/tests/compile_flags.txt
@@ -0,0 +1 @@
+-I../src/include/
diff --git a/tests/test b/tests/test
new file mode 100755
index 0000000..f2cb106
--- /dev/null
+++ b/tests/test
Binary files differ
diff --git a/tests/test_gdt.c b/tests/test_gdt.c
new file mode 100644
index 0000000..938e709
--- /dev/null
+++ b/tests/test_gdt.c
@@ -0,0 +1,21 @@
+#include "gdt.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+int main() {
+
+ uint16_t code_info = make_code(0, 0, 1);
+ uint16_t data_info = make_data(0, 0, 1);
+ Segment_Descriptor_t null = make_descriptor(0, 0, 0);
+ Segment_Descriptor_t code = make_descriptor(0, 0xFFFFF, code_info);
+ Segment_Descriptor_t data = make_descriptor(0, 0xFFFFF, data_info);
+ GDT_t *table = malloc(sizeof(GDT_t));
+ *table = (GDT_t){null, code, data};
+ GDTR_t gdtr = {(table + sizeof(GDT_t) - table - 1), (uint32_t)table};
+
+ printf("%zu\n", sizeof(GDT_t));
+ printf("0x%.16llX\n", null);
+ printf("0x%.16llX\n", code);
+ printf("0x%.16llX\n", data);
+ printf("0x%.24llX\n", table);
+}