diff --git a/i386/loader/src-asm/entry.asm b/i386/loader/src-asm/entry.asm index 290482a..9f9bc9f 100755 --- a/i386/loader/src-asm/entry.asm +++ b/i386/loader/src-asm/entry.asm @@ -4,12 +4,12 @@ ; If something has to be included, include it at the bottom! STACK_SIZE equ 32768 -UPPER_STACK_POINTER equ 0x100000 +UPPER_STACK_POINTER equ 0x20000 LOWER_STACK_POINTER equ (UPPER_STACK_POINTER - STACK_SIZE) bits 16 -org 0x0000 -entry: +org 0xa000 +stage_2_setup_entry: mov ebx, LOWER_STACK_POINTER mov ss, ebx mov esp, STACK_SIZE @@ -17,6 +17,10 @@ entry: push dx cli + mov ah, 0x00 + mov al, 0x03 ;0x13 + int 0x10 + .check_a20: push ebp mov ebp, esp @@ -30,46 +34,37 @@ entry: .a20_is_enabled: - ; Reset Display - mov ah, 0x00 - mov al, 0x03 - int 0x10 - - mov ah, 0x0b - mov bh, 0x00 - mov bl, 0 - int 0x10 - mov edi, ebp mov esi, esp push ebp mov ebp, esp - push .flat_gdt_loaded + ; push dword after_gdt_loaded call load_flat_gdt mov esp, ebp pop ebp -.flat_gdt_loaded: - mov ebp, edi - mov esp, esi - - ; push ebp - ; mov ebp, esp - ; call setup_drivers - ; mov esp, ebp - ; pop ebp cli hlt + some_text: db "This is some text.", 0x00 ; Utilities -%include "utility/math.asm" -%include "utility/memory.asm" - ; Memory Management %include "memory/a20.asm" %include "memory/gdt.asm" + + +bits 32 +stage2_true_entry: + mov [dword 0xb8000], byte 'X' + mov [dword 0xb8000 + 1], byte 0x31 + cli + hlt + +%include "utility/math.asm" +%include "utility/memory.asm" + ; Driver Manager ; %include "drivers/manager.asm" diff --git a/i386/loader/src-asm/memory/gdt.asm b/i386/loader/src-asm/memory/gdt.asm new file mode 100755 index 0000000..a0b5c99 --- /dev/null +++ b/i386/loader/src-asm/memory/gdt.asm @@ -0,0 +1,414 @@ + +GDT_MEMORY_AREA equ 0x7e00 +GDT_ENTRY_COUNT equ 3 + +; Arguments (note: all arguments are 4-byte padded): +; [Furthest from EBP] +; +; 4. uint32 privilege_level +; - Only 0 to 3; 0 being kernel and 3 being userland. +; Everything above 3 is an error. +; +; 3 uint32 num_pages +; - Only 20 bits are usable. Everything above will +; be cut off to be written to the segment descriptor. +; +; 2. ptr32 base_address +; +; 1. uint32 segment_index +; Note: +; - Zero is NOT usable and will throw an error. +; the highest theoretical value for this is 8191, +; but generally, one should stick to GDT_ENTRY_COUNT. +; +; [Nearest to EBP] +make_regular_data_segment_in_gdt: +.prolog: + push esi + add esp, 64 + mov esi, esp + + mov [esi + (64 - 4)], eax + mov [esi + (64 - 8)], ebx + mov [esi + (64 - 12)], ecx + mov [esi + (64 - 16)], edx + mov [esi + (64 - 20)], edi + +.get_arguments: + mov eax, [ebp - 4] ; segment_index + mov ebx, [ebp - 8] ; base_address + mov ecx, [ebp - 12] ; num_pages + mov edx, [ebp - 16] ; privilege_level + + mov [esi + 16], eax ; segment_index + mov [esi + 20], ebx ; base_address + mov [esi + 24], ecx ; num_pages + mov [esi + 28], edx ; privilege_level + +.validate_arguments: + cmp eax, 8191 + ja .segment_index_too_tall + cmp eax, 0 + je .segment_index_is_zero + + cmp edx, 3 + ja .privilege_level_too_large + +.calculate_work_address: + shl eax, 3 ; Entry offset from table start + add eax, GDT_MEMORY_AREA ; Entry address + mov [esi + 12], eax + +.write_segment_limit: + mov [eax], cx + shr ecx, 16 + and ecx, 0x0f + mov [eax + 6], cl + +.write_base_address: + mov [eax + 2], bx + shr bx, 16 + mov [eax + 4], bl + mov [eax + 7], bh + +.set_default_flags: + or [eax + 6], byte (0b1100 << 4) + +.set_data_segment_specific_access_byte: + mov al, 0b1001 + ; OR the privilege level into the access byte + mov dl, [ebp - 16] + shl dl, 1 + and dl, 0b0110 + or al, dl + shl al, 4 ; Move the 4 bits of general flags to their place + + ; Data-segment specific part + or al, 0b0010 ; DATA | HEAP | READ_WRITE | NOT_ACCESSED + + mov ebx, [esi + 12] + mov [ebx + 5], al ; Write to the final destination + +.epilog: + mov edi, [esi + (64 - 20)] + mov edx, [esi + (64 - 16)] + mov ecx, [esi + (64 - 12)] + mov ebx, [esi + (64 - 8)] + mov eax, [esi + (64 - 4)] + + sub esp, 64 + pop esi + ret + +.segment_index_too_tall: +.segment_index_is_zero: +.privilege_level_too_large: + ; todo(logs): Write debug message. + cli + hlt + + + +; Arguments (note: all arguments are 4-byte padded): +; [Furthest from EBP] +; +; 4. uint32 privilege_level +; - Only 0 to 3; 0 being kernel and 3 being userland. +; Everything above 3 is an error. +; +; 3 uint32 num_pages +; - Only 20 bits are usable. Everything above will +; be cut off to be written to the segment descriptor. +; +; 2. ptr32 base_address +; +; 1. uint32 segment_index +; Note: +; - Zero is NOT usable and will throw an error. +; the highest theoretical value for this is 8191, +; but generally, one should stick to GDT_ENTRY_COUNT. +; +; [Nearest to EBP] +; COMMENTED OUT DUE TO BEING BUGGY! +; make_stack_segment_in_gdt: +; .prolog: +; push esi +; add esp, 64 +; mov esi, esp + +; mov [esi + (64 - 4)], eax +; mov [esi + (64 - 8)], ebx +; mov [esi + (64 - 12)], ecx +; mov [esi + (64 - 16)], edx +; mov [esi + (64 - 20)], edi + +; .get_arguments: +; mov eax, [ebp - 4] ; segment_index +; mov ebx, [ebp - 8] ; base_address +; mov ecx, [ebp - 12] ; num_pages +; mov edx, [ebp - 16] ; privilege_level + +; mov [esi + 16], eax ; segment_index +; mov [esi + 20], ebx ; base_address +; mov [esi + 24], ecx ; num_pages +; mov [esi + 28], edx ; privilege_level + +; .validate_arguments: +; cmp eax, 8191 +; ja .segment_index_too_tall +; cmp eax, 0 +; je .segment_index_is_zero + +; cmp edx, 3 +; ja .privilege_level_too_large + +; .calculate_work_address: +; shl eax, 3 ; Entry offset from table start +; add eax, GDT_MEMORY_AREA ; Entry address +; mov [esi + 12], eax + +; .write_segment_limit: +; mov [eax], cx +; shr ecx, 16 +; and ecx, 0x0f +; mov [eax + 6], cl + +; .write_base_address: +; mov [eax + 2], bx +; shr bx, 16 +; mov [eax + 4], bl +; mov [eax + 7], bh + +; .set_default_flags: +; or [eax + 6], word (0b1100 << 4) + +; .set_stack_specific_access_byte: +; mov al, 0b1001 +; ; OR the privilege level into the access byte +; mov dl, [ebp - 16] +; shl dl, 1 +; and dl, 0b0110 +; or al, dl +; shl al, 4 ; Move the 4 bits of general flags to their place + +; ; Stack specific part +; or al, 0b0110 ; DATA | STACK | READ_WRITE | NOT_ACCESSED + +; mov ebx, [esi + 12] +; mov [ebx + 5], al ; Write to the final destination + +; .epilog: +; mov edi, [esi + (64 - 20)] +; mov edx, [esi + (64 - 16)] +; mov ecx, [esi + (64 - 12)] +; mov ebx, [esi + (64 - 8)] +; mov eax, [esi + (64 - 4)] + +; sub esp, 64 +; pop esi +; ret + +; .segment_index_too_tall: +; .segment_index_is_zero: +; .privilege_level_too_large: +; ; todo(logs): Write debug message. +; cli +; hlt + + + +; Arguments (note: all arguments are 4-byte padded): +; [Furthest from EBP] +; +; 4. uint32 privilege_level +; - Only 0 to 3; 0 being kernel and 3 being userland. +; Everything above 3 is an error. +; +; 3 uint32 num_pages +; - Only 20 bits are usable. Everything above will +; be cut off to be written to the segment descriptor. +; +; 2. ptr32 base_address +; +; 1. uint32 segment_index +; Note: +; - Zero is NOT usable and will throw an error. +; the highest theoretical value for this is 8191, +; but generally, one should stick to GDT_ENTRY_COUNT. +; +; [Nearest to EBP] +make_code_segment_in_gdt: +.prolog: + push esi + add esp, 64 + mov esi, esp + + mov [esi + (64 - 4)], eax + mov [esi + (64 - 8)], ebx + mov [esi + (64 - 12)], ecx + mov [esi + (64 - 16)], edx + mov [esi + (64 - 20)], edi + +.get_arguments: + mov eax, [ebp - 4] ; segment_index + mov ebx, [ebp - 8] ; base_address + mov ecx, [ebp - 12] ; num_pages + mov edx, [ebp - 16] ; privilege_level + + mov [esi + 16], eax ; segment_index + mov [esi + 20], ebx ; base_address + mov [esi + 24], ecx ; num_pages + mov [esi + 28], edx ; privilege_level + +.validate_arguments: + cmp eax, 8191 + ja .segment_index_too_tall + cmp eax, 0 + je .segment_index_is_zero + + cmp edx, 3 + ja .privilege_level_too_large + +.calculate_work_address: + shl eax, 3 ; Entry offset from table start + add eax, GDT_MEMORY_AREA ; Entry address + mov [esi + 12], eax + +.write_segment_limit: + mov [eax], cx + shr ecx, 16 + and ecx, 0x0f + mov [eax + 6], cl + +.write_base_address: + mov [eax + 2], bx + shr bx, 16 + mov [eax + 4], bl + mov [eax + 7], bh + +.set_default_flags: + or [eax + 6], word (0b1100 << 4) + +.set_code_segment_specific_access_byte: + mov al, 0b1001 + ; OR the privilege level into the access byte + mov dl, [ebp - 16] + shl dl, 1 + and dl, 0b0110 + or al, dl + shl al, 4 ; Move the 4 bits of general flags to their place + + ; Code-segment specific part + or al, 0b1010 ; CODE | NON-CONFORMING | READABLE | NOT_ACCESSED + + mov ebx, [esi + 12] + mov [ebx + 5], al ; Write to the final destination + +.epilog: + mov edi, [esi + (64 - 20)] + mov edx, [esi + (64 - 16)] + mov ecx, [esi + (64 - 12)] + mov ebx, [esi + (64 - 8)] + mov eax, [esi + (64 - 4)] + + sub esp, 64 + pop esi + ret + +.segment_index_too_tall: +.segment_index_is_zero: +.privilege_level_too_large: + ; todo(logs): Write debug message. + cli + hlt + + +; [Furthest to EBP] +; 1) Return Address +; [Nearest to EBP] +load_flat_gdt: +.prolog: + push esi + add esp, 64 + mov esi, esp + + mov [esi + (64 - 4)], eax + mov [esi + (64 - 8)], ebx + mov [esi + (64 - 12)], ecx + mov [esi + (64 - 16)], edx + mov [esi + (64 - 20)], edi + + ; mov eax, [ebp - 4] + ; mov [esi], eax + +.set_segments: + push ebp + mov ebp, esp + push dword 2 ; Segment Index + push dword 0 ; Start Offset + push dword 0xfffff ; Page Count + push dword 0 ; Required privilege level + call make_regular_data_segment_in_gdt + mov esp, ebp + pop ebp + + ; COMMENTED OUT DUE TO BEING BUGGY + ; push ebp + ; mov ebp, esp + ; push dword 3 ; Segment Index + ; push dword LOWER_STACK_POINTER ; Start Offset + ; push dword 0xfffff ; Page Count + ; push dword 0 ; Required privilege level + ; call make_stack_segment_in_gdt + ; mov esp, ebp + ; pop ebp + + push ebp + mov ebp, esp + push dword 1 ; Segment Index + push dword 0x0000 ; Start Offset + push dword 0xfffff ; Page Count + push dword 0 ; Required privilege level + call make_code_segment_in_gdt + mov esp, ebp + pop ebp + + mov bx, 0 + mov ds, bx + lgdt [.gdtr] + + mov bx, (2 << 3) + mov ds, bx + mov es, bx + mov fs, bx + mov gs, bx + ; mov bx, (3 << 3) + mov ss, bx + + mov ebx, cr0 + or ebx, 1 + mov cr0, ebx + + jmp dword 0x08:.epilog + +bits 32 +.epilog: + mov edi, [esi + (64 - 20)] + mov edx, [esi + (64 - 16)] + mov ecx, [esi + (64 - 12)] + mov ebx, [esi + (64 - 8)] + mov eax, [esi + (64 - 4)] + + add esp, 64 + pop esi + jmp stage2_true_entry + ; jmp after_gdt_loaded + +align 16 +.gdtr: +.gdtr.length: + dw 23 +.gdtr.pointer: + dd GDT_MEMORY_AREA + +align 1