commit 884d0f4c7d80af81e0db072060347ff11ff97912 Author: rami Date: Mon May 20 05:59:07 2024 -0400 init diff --git a/.cache/clangd/index/acpi.h.DEF797BDB8217123.idx b/.cache/clangd/index/acpi.h.DEF797BDB8217123.idx new file mode 100644 index 0000000..db9abac Binary files /dev/null and b/.cache/clangd/index/acpi.h.DEF797BDB8217123.idx differ diff --git a/.cache/clangd/index/kmain.c.9B04FE5F8A3537CE.idx b/.cache/clangd/index/kmain.c.9B04FE5F8A3537CE.idx new file mode 100644 index 0000000..0e86f2c Binary files /dev/null and b/.cache/clangd/index/kmain.c.9B04FE5F8A3537CE.idx differ diff --git a/.cache/clangd/index/multiboot.h.DC0E53CEA67FC33F.idx b/.cache/clangd/index/multiboot.h.DC0E53CEA67FC33F.idx new file mode 100644 index 0000000..405d3c3 Binary files /dev/null and b/.cache/clangd/index/multiboot.h.DC0E53CEA67FC33F.idx differ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b807197 --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +CC = i686-elf-gcc +INCLUDE = -I./ +CFLAGS = -Wall -Wextra -Werror -ffreestanding $(INCLUDE) +LDFLAGS = -T kernel.ld -ffreestanding -O3 -nostdlib -lgcc -mpreferred-stack-boundary=4 + +BUILDDIR = build + +KERNELSRC := $(shell find . -name '*.c' -o -name '*.asm') +KERNELOBJ := $(addprefix $(BUILDDIR)/, \ + $(notdir \ + $(patsubst %.c,%.o,\ + $(patsubst %.asm,%.o,$(KERNELSRC))))) + +LIBSRC := $(shell find ./lib -name '*.c') +LIBOBJ := $(addprefix $(BUILDDIR)/, \ + $(notdir \ + $(patsubst %.c,%.o,$(LIBSRC)))) + +KERNELIMG := $(BUILDDIR)/kernel.bin + +QEMUFLAGS = -d int -s \ + -kernel $(KERNELIMG) + +.PHONY: all kernel qemu clean docs + +all: qemu + +qemu: kernel + +kernel: $(KERNELIMG) + +$(KERNELIMG): $(KERNELOBJ) $(LIBOBJ) + $(CC) $^ -o $@ $(LDFLAGS) +$(BUILDDIR)/%.o: %.c + $(CC) $(CFLAGS) -c $^ -o $@ +$(BUILDDIR)/%.o: %.asm + nasm -felf32 $^ -o $@ + +qemu: kernel + qemu-system-i386 $(QEMUFLAGS) + +iso: kernel + cp $(BUILDDIR)/kernel.bin iso/boot/kernel.bin + grub-mkrescue -o $(BUILDDIR)/andewOS.iso iso/ + +clean: + rm -rf build/*.o build/*.bin iso/boot/*.bin +docs: + doxygen diff --git a/acpi.c b/acpi.c new file mode 100644 index 0000000..419a004 --- /dev/null +++ b/acpi.c @@ -0,0 +1,39 @@ +#include + +struct rsdp *acpi_search_for_rsdp() { + char *ptr = (char *)BIOS_START; + char *str = RSDP_SIG; + + while ((uint32_t)ptr <= (uint32_t)BIOS_END - RSDP_SIG_LEN) { + int i; + for (i = 0; i < RSDP_SIG_LEN; i++) { + if (ptr[i] != str[i]) + break; + } + if (i == RSDP_SIG_LEN) { + return (struct rsdp *)ptr; + } + ptr++; + } + + return 0; +} + +int acpi_validate_rsdp_checksum(struct rsdp *s) { + uint8_t *bytes = (uint8_t *)s; + uint8_t sum = 0; + for (int i = 0; i < RSDP_SIZE; i++) { + sum += bytes[i]; + } + + return (sum & 0x0F) == 0; +} + +int acpi_validate_sdt_checksum(struct ACPISDTHeader *s) { + uint8_t sum = 0; + for (uint32_t i = 0; i < s->Length; i++) { + sum += ((char *)s)[i]; + } + + return sum == 0; +} diff --git a/acpi.h b/acpi.h new file mode 100644 index 0000000..ba29712 --- /dev/null +++ b/acpi.h @@ -0,0 +1,45 @@ +#ifndef ACPI_H_ +#define ACPI_H_ + +#include + +#define BIOS_START 0x000E0000 +#define BIOS_END 0x000FFFFF +#define RSDP_SIG "RSD PTR " +#define RSDP_SIG_LEN 8 +#define RSDP_SIZE 20 + +#define ACPI_VER_1 0 +#define ACPI_VER_OTHER 2 + +struct rsdp { + char Signature[RSDP_SIG_LEN]; + uint8_t Checksum; + char OEMID[6]; + uint8_t Revision; + uint32_t RsdtAddress; +} __attribute__ ((packed)); + +struct ACPISDTHeader { + char Signature[4]; + uint32_t Length; + uint8_t Revision; + uint8_t Checksum; + char OEMID[6]; + char OEMTableID[8]; + uint32_t OEMRevision; + uint32_t CreatorID; + uint32_t CreatorRevision; +}; + +struct rsdt { + struct ACPISDTHeader h; + uint32_t other_sdt[]; +}; + +struct rsdp *acpi_search_for_rsdp(); +int acpi_validate_rsdp_checksum(struct rsdp *s); +int acpi_validate_sdt_checksum(struct ACPISDTHeader *s); +struct ACPISDTHeader *acpi_find_table(struct rsdt *root, const char *signature); + +#endif diff --git a/build/acpi.o b/build/acpi.o new file mode 100644 index 0000000..5294589 Binary files /dev/null and b/build/acpi.o differ diff --git a/build/io.o b/build/io.o new file mode 100644 index 0000000..653e94b Binary files /dev/null and b/build/io.o differ diff --git a/build/kernel.bin b/build/kernel.bin new file mode 100755 index 0000000..54f6ac4 Binary files /dev/null and b/build/kernel.bin differ diff --git a/build/kmain.o b/build/kmain.o new file mode 100644 index 0000000..da54399 Binary files /dev/null and b/build/kmain.o differ diff --git a/build/multiboot.o b/build/multiboot.o new file mode 100644 index 0000000..2587208 Binary files /dev/null and b/build/multiboot.o differ diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 0000000..bb46126 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,7 @@ +[ + { + "directory": "/home/rami/rk", + "file": "kmain.c", + "command": "i686-elf-gcc -Wall -Wextra -Werror -ffreestanding -I./ -c kmain.c -o build/kmain.o" + } +] diff --git a/io.c b/io.c new file mode 100644 index 0000000..e3dc4ad --- /dev/null +++ b/io.c @@ -0,0 +1,17 @@ +#include + +uint8_t inportb(uint16_t port) { + uint8_t result; + + asm volatile ("in %%dx, %%al" + : "=a" (result) + : "d" (port)); + + return result; +} + +void outportb(uint16_t port, uint8_t byte) { + asm volatile ("out %%al, %%dx" + : // no output + : "a" (byte), "d" (port)); +} diff --git a/io.h b/io.h new file mode 100644 index 0000000..62474ca --- /dev/null +++ b/io.h @@ -0,0 +1,9 @@ +#ifndef IO_H_ +#define IO_H_ + +#include + +uint8_t inportb(uint16_t port); +void outportb(uint16_t port, uint8_t byte); + +#endif diff --git a/kernel.ld b/kernel.ld new file mode 100644 index 0000000..d6ca5c9 --- /dev/null +++ b/kernel.ld @@ -0,0 +1,28 @@ +ENTRY(_start) + +SECTIONS +{ + . = 1M; + + .text BLOCK(4K) : ALIGN(4K) + { + *(.multiboot) + *(.text) + } + + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } +} diff --git a/kmain.c b/kmain.c new file mode 100644 index 0000000..b9e2580 --- /dev/null +++ b/kmain.c @@ -0,0 +1,81 @@ +#include +#include + +struct kernel_context { + struct rsdp *rsdp; + struct xsdp *xsdp; + + struct rsdt *rsdt; +}; + +struct kernel_context ctx = {0}; + +int strncmp( const char * s1, const char * s2, int n ) +{ + while ( n && *s1 && ( *s1 == *s2 ) ) + { + ++s1; + ++s2; + --n; + } + if ( n == 0 ) + { + return 0; + } + else + { + return ( *(unsigned char *)s1 - *(unsigned char *)s2 ); + } +} + +void *findFACP(void *RootSDT) +{ + struct rsdt *rsdt = (struct rsdt *) RootSDT; + int entries = (rsdt->h.Length - sizeof(rsdt->h)) / 4; + + for (int i = 0; i < entries; i++) + { + struct ACPISDTHeader *h = (struct ACPISDTHeader *) rsdt->other_sdt[i]; + if (!strncmp(h->Signature, "FACP", 4)) + return (void *) h; + } + + // No FACP found + return 0; +} + +void kmain(struct multiboot_info *info) { + // Check if the bootloader gave us the upper and lower memory + if (!(info->flags & 0x1)) goto halt; + + char *vmem = (char *)0xb8000; + + struct rsdp *found_rsdp = acpi_search_for_rsdp(); + if (!found_rsdp) goto halt; + if (found_rsdp->Revision == ACPI_VER_1) { + // ACPI v1.0 is being used + if (!acpi_validate_rsdp_checksum(found_rsdp)) goto halt; + ctx.rsdp = found_rsdp; + ctx.xsdp = 0; + + if (!acpi_validate_sdt_checksum((struct ACPISDTHeader *)found_rsdp->RsdtAddress)) + goto halt; + + ctx.rsdt = (struct rsdt*)found_rsdp->RsdtAddress; + + } else if (found_rsdp->Revision == ACPI_VER_OTHER) { + // ACPI v2.0+ is being used + // not supported yet.... + goto halt; + } else goto halt; + + void *fadt = findFACP(ctx.rsdt); + if (!fadt) goto halt; + char *next_sig = (char *)fadt; + vmem[0] = next_sig[0]; + vmem[2] = next_sig[1]; + vmem[4] = next_sig[2]; + vmem[6] = next_sig[3]; +halt: + for (;;) {} +} diff --git a/multiboot.asm b/multiboot.asm new file mode 100644 index 0000000..510a1ed --- /dev/null +++ b/multiboot.asm @@ -0,0 +1,71 @@ +%define MAGIC 0x1BADB002 +%define FLAGS 0 + +; Multiboot v1 Specification +; https://www.gnu.org/software/grub/manual/multiboot/multiboot.html +section .multiboot +align 4 +dd MAGIC +dd FLAGS +dd -(MAGIC + FLAGS) + +section .text +global _start +_start: + cli + + ; Check if EAX contains the multiboot magic number the bootloader is supposed to give us + cmp eax, 0x2BADB002 + jne halt + + lgdt [gdtp] + mov ax, 0x10 ; Offset to kernel data descriptor + mov es, ax + mov ds, ax + mov fs, ax + mov gs, ax + mov ss, ax + jmp 0x8:.use_code_seg ; Offset to kernel code descriptor +.use_code_seg: + mov esp, stack_bottom + push ebx + extern kmain + call kmain + +; If the kernel function somehow returns, disable interrupts and hang + cli +halt: + hlt + jmp halt + +; GDT for a flat memory layout +; We get access to all memory and can utilize paging +gdt_start: +gdt_null: + dq 0 +gdt_kern_code: + dw 0xffff + dw 0x0000 + db 0x00 + db 0b10011010 + db 0b11001111 + db 0x00 +gdt_kern_data: + dw 0xffff + dw 0x0000 + db 0x00 + db 0b10010010 + db 0b11001111 + db 0x00 +gdt_end: + +gdtp: + dw gdt_end - gdt_start - 1 + dd gdt_start + +; Reserve 16KiB of kernel stack space +section .bss +align 4 +stack_top: + resb 16384 +stack_bottom: diff --git a/multiboot.h b/multiboot.h new file mode 100644 index 0000000..aca2ecf --- /dev/null +++ b/multiboot.h @@ -0,0 +1,31 @@ +#ifndef MULTIBOOT_H_ +#define MULTIBOOT_H_ + +#include + +#define MULTIBOOT_MAGIC 0x2BADB002 + +struct multiboot_info { + uint32_t flags; //required + uint32_t memLower; //if bit 0 in flags are set + uint32_t memUpper; //if bit 0 in flags are set + uint32_t bootDevice; //if bit 1 in flags are set + uint32_t commandLine; //if bit 2 in flags are set + uint32_t moduleCount; //if bit 3 in flags are set + uint32_t moduleAddress; //if bit 3 in flags are set + uint32_t syms[4]; //if bits 4 or 5 in flags are set + uint32_t memMapLength; //if bit 6 in flags is set + uint32_t memMapAddress; //if bit 6 in flags is set + uint32_t drivesLength; //if bit 7 in flags is set + uint32_t drivesAddress; //if bit 7 in flags is set + uint32_t configTable; //if bit 8 in flags is set + uint32_t apmTable; //if bit 9 in flags is set + uint32_t vbeControlInfo; //if bit 10 in flags is set + uint32_t vbeModeInfo; //if bit 11 in flags is set + uint32_t vbeMode; // all vbe_* set if bit 12 in flags are set + uint32_t vbeInterfaceSeg; + uint32_t vbeInterfaceOff; + uint32_t vbeInterfaceLength; +}; + +#endif