diff --git a/partt3/Makefile b/partt3/Makefile new file mode 100644 index 0000000..be3763e --- /dev/null +++ b/partt3/Makefile @@ -0,0 +1,39 @@ +kernel_source_files := $(shell find src/impl/kernel -name *.c) +kernel_object_files := $(patsubst src/impl/kernel/%.c, build/kernel/%.o, $(kernel_source_files)) + +x86_64_c_source_files := $(shell find src/impl/x86_64 -name *.c) +x86_64_c_object_files := $(patsubst src/impl/x86_64/%.c, build/x86_64/%.o, $(x86_64_c_source_files)) + +x86_64_asm_source_files := $(shell find src/impl/x86_64 -name *.asm) +x86_64_asm_object_files := $(patsubst src/impl/x86_64/%.asm, build/x86_64/%.o, $(x86_64_asm_source_files)) + +x86_64_object_files := $(x86_64_c_object_files) $(x86_64_asm_object_files) + +$(kernel_object_files): build/kernel/%.o : src/impl/kernel/%.c + mkdir -p $(dir $@) && \ + x86_64-elf-gcc -c -I src/intf -ffreestanding $(patsubst build/kernel/%.o, src/impl/kernel/%.c, $@) -o $@ + +$(x86_64_c_object_files): build/x86_64/%.o : src/impl/x86_64/%.c + mkdir -p $(dir $@) && \ + x86_64-elf-gcc -c -I src/intf -ffreestanding $(patsubst build/x86_64/%.o, src/impl/x86_64/%.c, $@) -o $@ + +$(x86_64_asm_object_files): build/x86_64/%.o : src/impl/x86_64/%.asm + mkdir -p $(dir $@) && \ + nasm -f elf64 $(patsubst build/x86_64/%.o, src/impl/x86_64/%.asm, $@) -o $@ + +.PHONY: build +build: $(kernel_object_files) $(x86_64_object_files) + sudo mkinitramfs -o targets/x86_64/iso/boot/grub/initrd.img + mkdir -p dist/x86_64 && \ + x86_64-elf-ld -n -o dist/x86_64/kernel.bin -T targets/x86_64/linker.ld $(kernel_object_files) $(x86_64_object_files) && \ + cp dist/x86_64/kernel.bin targets/x86_64/iso/boot/kernel.bin && \ + dd if=/dev/zero of=dist/x86_64/kernel.iso bs=1M count=50 + sudo mkfs.fat -F32 dist/x86_64/kernel.iso + sudo fatlabel dist/x86_64/kernel.iso 9BAR-DEF0 + grub-mkrescue /usr/lib/grub/i386-pc -o dist/x86_64/kernel.iso targets/x86_64/iso + +clean: + rm -rf build + rm -rf dist + cd targets/x86_64/iso/boot/grub/ + rm -f initrd.img diff --git a/partt3/Readme.md b/partt3/Readme.md new file mode 100644 index 0000000..233af23 --- /dev/null +++ b/partt3/Readme.md @@ -0,0 +1,2 @@ +#Os dev part 1 +initrd: sudo mkinitramfs -o targets/x86_64/iso/boot/grub/initrd.img \ No newline at end of file diff --git a/partt3/run.sh b/partt3/run.sh new file mode 100644 index 0000000..bbe8394 --- /dev/null +++ b/partt3/run.sh @@ -0,0 +1,2 @@ +make clean && make && make build +qemu-system-x86_64 dist/x86_64/kernel.iso \ No newline at end of file diff --git a/partt3/src/impl/kernel/main.c b/partt3/src/impl/kernel/main.c new file mode 100644 index 0000000..f968c52 --- /dev/null +++ b/partt3/src/impl/kernel/main.c @@ -0,0 +1,20 @@ +#include "print.h" +/*#include +#include */ +#include "types.h" + +void kernel_main() { + + int x = 6; + int y = 3; + int o = x * y; + + print_clear(); + print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_LIGHT_GREEN); + print_str("Welcome to our 64-bit kernel!\n"); + print_str("This is the FAT FILE SYSTEM\n"); + // print_str(name); + //printf("this is a %c\n", name); + //print_int(ma); + printf("output %d", o); +} diff --git a/partt3/src/impl/x86_64/boot/header.asm b/partt3/src/impl/x86_64/boot/header.asm new file mode 100644 index 0000000..4cfa18e --- /dev/null +++ b/partt3/src/impl/x86_64/boot/header.asm @@ -0,0 +1,16 @@ +section .multiboot_header +header_start: + ; magic number + dd 0xe85250d6 ; multiboot2 + ; architecture + dd 0 ; protected mode i386 + ; header length + dd header_end - header_start + ; checksum + dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) + + ; end tag + dw 0 + dw 0 + dd 8 +header_end: diff --git a/partt3/src/impl/x86_64/boot/main.asm b/partt3/src/impl/x86_64/boot/main.asm new file mode 100644 index 0000000..8ffe7e6 --- /dev/null +++ b/partt3/src/impl/x86_64/boot/main.asm @@ -0,0 +1,136 @@ +global start +extern long_mode_start + +section .text +bits 32 +start: + mov esp, stack_top + + call check_multiboot + call check_cpuid + call check_long_mode + + call setup_page_tables + call enable_paging + + lgdt [gdt64.pointer] + jmp gdt64.code_segment:long_mode_start + + hlt + +check_multiboot: + cmp eax, 0x36d76289 + jne .no_multiboot + ret +.no_multiboot: + mov al, "M" + jmp error + +check_cpuid: + pushfd + pop eax + mov ecx, eax + xor eax, 1 << 21 + push eax + popfd + pushfd + pop eax + push ecx + popfd + cmp eax, ecx + je .no_cpuid + ret +.no_cpuid: + mov al, "C" + jmp error + +check_long_mode: + mov eax, 0x80000000 + cpuid + cmp eax, 0x80000001 + jb .no_long_mode + + mov eax, 0x80000001 + cpuid + test edx, 1 << 29 + jz .no_long_mode + + ret +.no_long_mode: + mov al, "L" + jmp error + +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: + dq 0 ; zero entry +.code_segment: equ $ - gdt64 + dq (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) ; code segment +.pointer: + dw $ - gdt64 - 1 ; length + dq gdt64 ; address diff --git a/partt3/src/impl/x86_64/boot/main64.asm b/partt3/src/impl/x86_64/boot/main64.asm new file mode 100644 index 0000000..8d623c2 --- /dev/null +++ b/partt3/src/impl/x86_64/boot/main64.asm @@ -0,0 +1,16 @@ +global long_mode_start +extern kernel_main + +section .text +bits 64 +long_mode_start: + ; load null into all data segment registers + mov ax, 0 + mov ss, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + call kernel_main + hlt diff --git a/partt3/src/impl/x86_64/ports.c b/partt3/src/impl/x86_64/ports.c new file mode 100644 index 0000000..f9a2d81 --- /dev/null +++ b/partt3/src/impl/x86_64/ports.c @@ -0,0 +1,13 @@ +#include + +// Read a byte from the specified port +static inline uint8_t inportb(uint16_t port) { + uint8_t result; + __asm__ volatile ("inb %1, %0" : "=a"(result) : "dN"(port)); // we don't care asm code AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaaaaaaaa + return result; +} + +// Write a byte to the specified port +static inline void outportb(uint16_t port, uint8_t data) { + __asm__ volatile ("outb %0, %1" : : "a"(data), "dN"(port)); +} diff --git a/partt3/src/impl/x86_64/print.c b/partt3/src/impl/x86_64/print.c new file mode 100644 index 0000000..8b8ea7c --- /dev/null +++ b/partt3/src/impl/x86_64/print.c @@ -0,0 +1,175 @@ +#include "print.h" + + +const static size_t NUM_COLS = 80; +const static size_t NUM_ROWS = 25; + +struct Char { + uint8_t character; + uint8_t color; +}; + +struct Char* buffer = (struct Char*) 0xb8000; +size_t col = 0; +size_t row = 0; +uint8_t color = PRINT_COLOR_WHITE | PRINT_COLOR_BLACK << 4; + +void clear_row(size_t row) { + struct Char empty = (struct Char) { + character: ' ', + color: color, + }; + + for (size_t col = 0; col < NUM_COLS; col++) { + buffer[col + NUM_COLS * row] = empty; + } +} + +void print_clear() { + for (size_t i = 0; i < NUM_ROWS; i++) { + clear_row(i); + } +} + +void print_newline() { + col = 0; + + if (row < NUM_ROWS - 1) { + row++; + return; + } + + for (size_t row = 1; row < NUM_ROWS; row++) { + for (size_t col = 0; col < NUM_COLS; col++) { + struct Char character = buffer[col + NUM_COLS * row]; + buffer[col + NUM_COLS * (row - 1)] = character; + } + } + + clear_row(NUM_COLS - 1); +} + +void print_char(char character) { + if (character == '\n') { + print_newline(); + return; + } + + if (col > NUM_COLS) { + print_newline(); + } + + buffer[col + NUM_COLS * row] = (struct Char) { + character: (uint8_t) character, + color: color, + }; + + col++; +} + +void print_str(char* str) { + for (size_t i = 0; 1; i++) { + char character = (uint8_t) str[i]; + + if (character == '\0') { + return; + } + + print_char(character); + } + + +} + + +void print_int(int value) { + if (value < 0) { + print_char('-'); + value = -value; + } + + char buffer[11]; // Buffer to hold the largest int value (-2147483648) + '\0' + int pos = 10; + buffer[pos] = '\0'; + + do { + buffer[--pos] = (value % 10) + '0'; + value /= 10; + } while (value != 0); + + print_str(&buffer[pos]); +} + +void print_float(float value) { + // Handle negative values + if (value < 0) { + print_char('-'); + value = -value; + } + + // Extract the integer part + int integer_part = (int)value; + print_int(integer_part); + + // Print the decimal point + print_char('.'); + + // Extract and print the fractional part + float fractional_part = value - (float)integer_part; + + // Handle precision up to 6 decimal places + for (int i = 0; i < 6; i++) { + fractional_part *= 10; + int digit = (int)fractional_part; + print_char(digit + '0'); + fractional_part -= digit; + } +} + +void print_set_color(uint8_t foreground, uint8_t background) { + color = foreground + (background << 4); +} + + +void printf(const char* format, ...) { + va_list args; + va_start(args, format); + + for (size_t i = 0; format[i] != '\0'; i++) { + if (format[i] == '%' && format[i + 1] != '\0') { + i++; // Move past '%' + switch (format[i]) { + case 'c': { + char c = (char) va_arg(args, int); // `char` is promoted to `int` in varargs + print_char(c); + break; + } + case 's': { + char* s = va_arg(args, char*); + print_str(s); + break; + } + case 'd': { + int d = va_arg(args, int); + print_int(d); + break; + } + case 'f': { + float f = (float) va_arg(args, double); // `float` is promoted to `double` in varargs + print_float(f); + break; + } + default: + // If an unknown specifier is encountered, just print it as-is + print_char('%'); + print_char(format[i]); + break; + } + } else { + // Print any character that's not part of a format specifier + print_char(format[i]); + } + } + + va_end(args); +} \ No newline at end of file diff --git a/partt3/src/intf/ports.h b/partt3/src/intf/ports.h new file mode 100644 index 0000000..6264af9 --- /dev/null +++ b/partt3/src/intf/ports.h @@ -0,0 +1,6 @@ +#include + +// Read a byte from the specified port +static inline uint8_t inportb(uint16_t port); +// Write a byte to the specified port +static inline void outportb(uint16_t port, uint8_t data); \ No newline at end of file diff --git a/partt3/src/intf/print.h b/partt3/src/intf/print.h new file mode 100644 index 0000000..02493e2 --- /dev/null +++ b/partt3/src/intf/print.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include + +enum { + PRINT_COLOR_BLACK = 0, + PRINT_COLOR_BLUE = 1, + PRINT_COLOR_GREEN = 2, + PRINT_COLOR_CYAN = 3, + PRINT_COLOR_RED = 4, + PRINT_COLOR_MAGENTA = 5, + PRINT_COLOR_BROWN = 6, + PRINT_COLOR_LIGHT_GRAY = 7, + PRINT_COLOR_DARK_GRAY = 8, + PRINT_COLOR_LIGHT_BLUE = 9, + PRINT_COLOR_LIGHT_GREEN = 10, + PRINT_COLOR_LIGHT_CYAN = 11, + PRINT_COLOR_LIGHT_RED = 12, + PRINT_COLOR_PINK = 13, + PRINT_COLOR_YELLOW = 14, + PRINT_COLOR_WHITE = 15, +}; + +void print_clear(); +void print_char(char character); +void print_str(char* string); +void print_int(int value); +void print_float(float value); + +void print_set_color(uint8_t foreground, uint8_t background); +void printf(const char* format, ...); \ No newline at end of file diff --git a/partt3/src/intf/types.h b/partt3/src/intf/types.h new file mode 100644 index 0000000..42cc2b5 --- /dev/null +++ b/partt3/src/intf/types.h @@ -0,0 +1,32 @@ +#include +#include + +#ifndef TYPES_H +#define TYPES_H + +typedef signed char int8; +typedef unsigned char uint8; + +typedef signed short int16; +typedef unsigned short uint16; + +typedef signed int int32; +typedef unsigned int uint32; + +typedef signed long long int64; +typedef unsigned long long uint64; + +typedef char *string; //cs50 + +//unsigned int size_t; error +typedef __SIZE_TYPE__ size_t; + +//we dont care +// typedef int bool; + +#define low_16(address) (uint16)((address) & 0xFFFF) +#define high_16(address) (uint16)(((address) >> 16) & 0xFFFF) + + + +#endif \ No newline at end of file diff --git a/partt3/targets/x86_64/iso/boot/grub/grub.cfg b/partt3/targets/x86_64/iso/boot/grub/grub.cfg new file mode 100644 index 0000000..b801946 --- /dev/null +++ b/partt3/targets/x86_64/iso/boot/grub/grub.cfg @@ -0,0 +1,10 @@ +set timeout=0 +set default=0 + +menuentry "MITHUOS" { + multiboot2 /boot/kernel.bin + boot + initrd initrd.img + insmod fat + search --no-floppy --fs-uuid --set=root 9BAR-DEF0 +} \ No newline at end of file diff --git a/partt3/targets/x86_64/iso/boot/kernel.bin b/partt3/targets/x86_64/iso/boot/kernel.bin new file mode 100644 index 0000000..d9aed91 Binary files /dev/null and b/partt3/targets/x86_64/iso/boot/kernel.bin differ diff --git a/partt3/targets/x86_64/linker.ld b/partt3/targets/x86_64/linker.ld new file mode 100644 index 0000000..0cf372d --- /dev/null +++ b/partt3/targets/x86_64/linker.ld @@ -0,0 +1,16 @@ +ENTRY(start) + +SECTIONS +{ + . = 1M; + + .boot : + { + KEEP(*(.multiboot_header)) + } + + .text : + { + *(.text) + } +}