lots of in progress stuff
This commit is contained in:
		
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,8 +1,8 @@
 | 
			
		||||
objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o gdt.o\
 | 
			
		||||
		  paging.o fault.o tests.o kbd.o helper.o disk.o file.o fs.o dosfs/dosfs.o fs_dos.o\
 | 
			
		||||
		  progs.o hexedit.o textedit.o
 | 
			
		||||
CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding\
 | 
			
		||||
		 -march=i686 -fno-stack-protector -Wno-int-conversion -nostdlib -c
 | 
			
		||||
CFLAGS = -target "i386-elf" -m32 -mgeneral-regs-only -ffreestanding\
 | 
			
		||||
		 -march=i386 -fno-stack-protector -Wno-int-conversion -nostdlib -c
 | 
			
		||||
LFLAGS = -Wl,--gc-sections -Wl,--print-gc-sections -m32 -nostartfiles -nostdlib
 | 
			
		||||
 | 
			
		||||
ifeq ($(OUTFILE),)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								fault.nasm
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								fault.nasm
									
									
									
									
									
								
							@@ -70,10 +70,13 @@ jmp _fault_coda
 | 
			
		||||
_gpf_old_ds: dw 0
 | 
			
		||||
extern get_key
 | 
			
		||||
extern get_scancode
 | 
			
		||||
extern get_key_no_wait
 | 
			
		||||
extern get_scancode_no_wait
 | 
			
		||||
extern task_ptr
 | 
			
		||||
extern _enter_v86_internal_no_task
 | 
			
		||||
extern return_prev_task
 | 
			
		||||
extern v86Interrupt
 | 
			
		||||
extern TIMERVAL
 | 
			
		||||
gpf_handler_32:
 | 
			
		||||
push eax
 | 
			
		||||
mov eax, dword [esp+8] ; EIP
 | 
			
		||||
@@ -91,9 +94,25 @@ jne .s1
 | 
			
		||||
call get_key
 | 
			
		||||
jmp .return_to_offender
 | 
			
		||||
.s1: cmp al, 0x01 ; get scancode
 | 
			
		||||
jne .s86
 | 
			
		||||
jne .s2
 | 
			
		||||
call get_scancode
 | 
			
		||||
jmp .return_to_offender
 | 
			
		||||
.s2: cmp al, 0x02 ; get key no wait
 | 
			
		||||
jne .s3
 | 
			
		||||
call get_key_no_wait
 | 
			
		||||
jmp .return_to_offender
 | 
			
		||||
.s3: cmp al, 0x03 ; get scancode no wait
 | 
			
		||||
jne .s4
 | 
			
		||||
call get_scancode_no_wait
 | 
			
		||||
jmp .return_to_offender
 | 
			
		||||
.s4: cmp al, 0x04 ; get timer
 | 
			
		||||
jne .s5
 | 
			
		||||
mov eax, dword [TIMERVAL]
 | 
			
		||||
jmp .return_to_offender
 | 
			
		||||
.s5: cmp al, 0x05 ; short wait (hlt)
 | 
			
		||||
jne .s86
 | 
			
		||||
hlt
 | 
			
		||||
jmp .return_to_offender
 | 
			
		||||
.s86: cmp al, 0x86 ; v86 interrupt call
 | 
			
		||||
je .v86int
 | 
			
		||||
cmp ax, 0x86D8 ; get v86 data pointer
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										73
									
								
								handler.nasm
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								handler.nasm
									
									
									
									
									
								
							@@ -1,71 +1,38 @@
 | 
			
		||||
oldscancodesToAscii: db 0, 0 ; 0x00 - 0x01
 | 
			
		||||
db "1234567890" ; 0x02 - 0x0B
 | 
			
		||||
db "-=" ; 0x0C - 0x0D
 | 
			
		||||
db 0, 0 ; 0x0E - 0x0F
 | 
			
		||||
db "qwertyuiop[]" ; 0x10 - 0x1B
 | 
			
		||||
db 0, 0 ; 0x1C - 0x1D
 | 
			
		||||
db "asdfghjkl;'`" ; 0x1E - 0x29
 | 
			
		||||
db 0 ; 0x2A
 | 
			
		||||
db "\zxcvbnm,./" ; 0x2B - 0x35
 | 
			
		||||
db 0 ; 0x36
 | 
			
		||||
db '*' ; 0x37
 | 
			
		||||
db 0 ; 0x38
 | 
			
		||||
db ' ' ; 0x39
 | 
			
		||||
db 'C'
 | 
			
		||||
scancodesToAsciiEnd:
 | 
			
		||||
cursorCurrent: dd 0xb8000 + (80*6*2)
 | 
			
		||||
global oldkeyboardHandler
 | 
			
		||||
oldkeyboardHandler:
 | 
			
		||||
push eax
 | 
			
		||||
push ebx
 | 
			
		||||
push ds
 | 
			
		||||
mov ax, 0x10
 | 
			
		||||
mov ds, ax
 | 
			
		||||
xor eax, eax
 | 
			
		||||
in al, 0x60
 | 
			
		||||
cmp eax, 0x3A
 | 
			
		||||
jg .done
 | 
			
		||||
mov al, [oldscancodesToAscii+eax]
 | 
			
		||||
test al, al
 | 
			
		||||
jz .done
 | 
			
		||||
mov ebx, [cursorCurrent]
 | 
			
		||||
mov byte [ebx], al
 | 
			
		||||
add dword [cursorCurrent], 2
 | 
			
		||||
mov byte [KBDWAIT], 1
 | 
			
		||||
.done:
 | 
			
		||||
mov al, 0x20
 | 
			
		||||
out 0x20, al
 | 
			
		||||
pop ds
 | 
			
		||||
pop ebx
 | 
			
		||||
pop eax
 | 
			
		||||
iret
 | 
			
		||||
 | 
			
		||||
KBDWAIT: db 0
 | 
			
		||||
oldkbd_wait:
 | 
			
		||||
mov byte [KBDWAIT], 0
 | 
			
		||||
.loop:
 | 
			
		||||
hlt
 | 
			
		||||
movzx eax, byte [KBDWAIT]
 | 
			
		||||
test eax, eax
 | 
			
		||||
jz .loop
 | 
			
		||||
ret
 | 
			
		||||
global PROC_SWITCH
 | 
			
		||||
PROC_SWITCH: dw 0
 | 
			
		||||
 | 
			
		||||
global TIMERVAL
 | 
			
		||||
global TIMERVAL_FRAC
 | 
			
		||||
TIMERVAL: dd 0
 | 
			
		||||
TIMERVAL_FRAC: dd 0
 | 
			
		||||
global timerHandler
 | 
			
		||||
timerHandler:
 | 
			
		||||
push eax
 | 
			
		||||
push ds
 | 
			
		||||
mov ax, 0x10
 | 
			
		||||
mov ds, ax
 | 
			
		||||
;inc byte [(0xb8000 + (80*8*2))]
 | 
			
		||||
inc dword [TIMERVAL]
 | 
			
		||||
; Value from PITPgrm
 | 
			
		||||
add dword [TIMERVAL_FRAC], 0xfffdb8d0
 | 
			
		||||
adc dword [TIMERVAL], 0
 | 
			
		||||
mov al, 0x20
 | 
			
		||||
out 0x20, al
 | 
			
		||||
; Check task switch
 | 
			
		||||
movzx eax, word [PROC_SWITCH]
 | 
			
		||||
test eax, eax
 | 
			
		||||
jnz task_switch
 | 
			
		||||
pop ds
 | 
			
		||||
pop eax
 | 
			
		||||
iret
 | 
			
		||||
 | 
			
		||||
extern save_current_task_int
 | 
			
		||||
task_switch:
 | 
			
		||||
mov word [PROC_SWITCH], 0
 | 
			
		||||
pop ds
 | 
			
		||||
pop eax
 | 
			
		||||
call save_current_task_int
 | 
			
		||||
iret
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
global picInit
 | 
			
		||||
picInit:
 | 
			
		||||
mov al, 0x11  ; initialization sequence
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								kbd.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								kbd.c
									
									
									
									
									
								
							@@ -1,6 +1,11 @@
 | 
			
		||||
#include "interrupt.h"
 | 
			
		||||
#include "kbd.h"
 | 
			
		||||
 | 
			
		||||
extern uint16_t PROC_SWITCH;
 | 
			
		||||
__attribute__((__noreturn__))
 | 
			
		||||
__attribute__((__no_caller_saved_registers__))
 | 
			
		||||
extern void ret_current_task_int();
 | 
			
		||||
 | 
			
		||||
uint8_t scancodesToAscii[0x3B] =
 | 
			
		||||
"\0\0" // 0x00 - 0x01
 | 
			
		||||
"1234567890" // 0x02 - 0x0B
 | 
			
		||||
@@ -69,6 +74,8 @@ void keyboardHandler(struct interrupt_frame *frame) {
 | 
			
		||||
        "mov %%ax, %%ds\n"
 | 
			
		||||
        ::"a"(old_ds)
 | 
			
		||||
    );
 | 
			
		||||
    if (key == KEY_F12) PROC_SWITCH = 1;
 | 
			
		||||
    if (key == KEY_F11) ret_current_task_int();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
@@ -106,3 +113,18 @@ uint16_t get_scancode() {
 | 
			
		||||
    return k;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
uint8_t get_key_no_wait() {
 | 
			
		||||
    uint8_t k = _LSTKEY_ASCII;
 | 
			
		||||
    _LSTKEY_ASCII = 0;
 | 
			
		||||
    return k;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
uint16_t get_scancode_no_wait() {
 | 
			
		||||
    uint16_t k = _LSTKEY_SCAN | (_LSTKEY_ASCII << 8);
 | 
			
		||||
    _LSTKEY_SCAN = 0;
 | 
			
		||||
    _LSTKEY_ASCII = 0;
 | 
			
		||||
    return k;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										72
									
								
								kernel.c
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								kernel.c
									
									
									
									
									
								
							@@ -190,9 +190,11 @@ Protected Only (1MB+)
 | 
			
		||||
280000 - 300000 Disk Cache (512kB)
 | 
			
		||||
300000 - 310000 Task Stack (64kB)
 | 
			
		||||
310000 - 320000 Interrupt Stack (64kB)
 | 
			
		||||
320000 - 400000 Kernel Stack (896kB)
 | 
			
		||||
400000 - 700000 Usermode Code (3mB)
 | 
			
		||||
700000 - 800000 Usermode Stack (1mB)
 | 
			
		||||
320000 - 400000 Free (896kB)
 | 
			
		||||
400000 - 700000 Free (3mB)
 | 
			
		||||
700000 - 800000 Kernel Stack (1mB)
 | 
			
		||||
 800000 -  F00000 Usermode Code (7mB)
 | 
			
		||||
 F00000 - 1000000 Usermode Stack (1mB)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
void DrawScreen(uint16_t *vga) {
 | 
			
		||||
@@ -247,13 +249,8 @@ void RestoreVGA() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t fileCount, fileOffset;
 | 
			
		||||
// We store dir entries in usermode space,
 | 
			
		||||
// which is nice because there's nothing after,
 | 
			
		||||
// but it does mean we need to reload the dir
 | 
			
		||||
// after every task called. This might be fine,
 | 
			
		||||
// since the task might have modified the directory.
 | 
			
		||||
extern char _USERMODE;
 | 
			
		||||
dirent *const DirEntries = (dirent*)&_USERMODE;
 | 
			
		||||
dirent *const DirEntries = (dirent*)0x400000;
 | 
			
		||||
#define MAXDISPFILES 16
 | 
			
		||||
void PrintFileList(uint16_t *vga) {
 | 
			
		||||
    uint16_t *vga_text = &((uint16_t *)vga)[80*6+3];
 | 
			
		||||
@@ -377,7 +374,20 @@ void FileSelect() {
 | 
			
		||||
                for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
 | 
			
		||||
                    current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
 | 
			
		||||
                current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
 | 
			
		||||
                create_child(GetFreeStack(), (uintptr_t)HexEditor, 1, current_path);
 | 
			
		||||
                {
 | 
			
		||||
                    // Give userspace mem (8MB)
 | 
			
		||||
                    uintptr_t process_page0 = add_pages(4|2|1);
 | 
			
		||||
                    uintptr_t process_page1 = add_pages(4|2|1);
 | 
			
		||||
                    asm("xchg %bx,%bx");
 | 
			
		||||
                    // Page blocks are 4MB
 | 
			
		||||
                    move_pages(process_page0 >> 22, (uintptr_t)&_USERMODE >> 22);
 | 
			
		||||
                    move_pages(process_page1 >> 22, ((uintptr_t)&_USERMODE >> 22) + 1);
 | 
			
		||||
                    asm("xchg %bx,%bx");
 | 
			
		||||
                    create_child(GetFreeStack(), (uintptr_t)HexEditor, 1, current_path);
 | 
			
		||||
                    // Free userspace mem
 | 
			
		||||
                    free_pages(process_page0 >> 22);
 | 
			
		||||
                    free_pages(process_page1 >> 22);
 | 
			
		||||
                }
 | 
			
		||||
                current_path[current_path_end] = 0;
 | 
			
		||||
                RestoreVGA();
 | 
			
		||||
                reload = 1;
 | 
			
		||||
@@ -388,7 +398,18 @@ void FileSelect() {
 | 
			
		||||
                for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
 | 
			
		||||
                    current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
 | 
			
		||||
                current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
 | 
			
		||||
                create_child(GetFreeStack(), (uintptr_t)TextViewTest, 1, current_path);
 | 
			
		||||
                {
 | 
			
		||||
                    // Give userspace mem (8MB)
 | 
			
		||||
                    uintptr_t process_page0 = add_pages(4|2|1);
 | 
			
		||||
                    uintptr_t process_page1 = add_pages(4|2|1);
 | 
			
		||||
                    // Page blocks are 4MB
 | 
			
		||||
                    move_pages(process_page0 >> 22, (uintptr_t)&_USERMODE >> 22);
 | 
			
		||||
                    move_pages(process_page1 >> 22, ((uintptr_t)&_USERMODE >> 22) + 1);
 | 
			
		||||
                    create_child(GetFreeStack(), (uintptr_t)TextViewTest, 1, current_path);
 | 
			
		||||
                    // Free userspace mem
 | 
			
		||||
                    free_pages(process_page0 >> 22);
 | 
			
		||||
                    free_pages(process_page1 >> 22);
 | 
			
		||||
                }
 | 
			
		||||
                current_path[current_path_end] = 0;
 | 
			
		||||
                RestoreVGA();
 | 
			
		||||
                reload = 1;
 | 
			
		||||
@@ -455,6 +476,34 @@ void FileSelect() {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO Move this somewhere else, maybe configurable & with timer handler
 | 
			
		||||
void PITPgrm() {
 | 
			
		||||
    const uint32_t base_clk = 3579545;
 | 
			
		||||
    const uint16_t reload_v = 1194;
 | 
			
		||||
    // (base_clk / 3) / reload_v = ~999.31463Hz
 | 
			
		||||
 | 
			
		||||
    // 32.32 Fixed point
 | 
			
		||||
    const uint64_t irq_ms = (uint64_t)reload_v * 3000LL * ((1LL << 42) / (uint64_t)base_clk / (1LL << 10));
 | 
			
		||||
    // irq_ms = 4294818000 (0xfffdb8d0)
 | 
			
		||||
    // We don't actually use this here, but in handler.nasm
 | 
			
		||||
    // for now, eventually this should be in C
 | 
			
		||||
 | 
			
		||||
    asm volatile(
 | 
			
		||||
        "cli\n"
 | 
			
		||||
        "movb $0b00110100, %%al\n"
 | 
			
		||||
        "outb %%al, $0x43\n"
 | 
			
		||||
        :::"%eax"
 | 
			
		||||
    );
 | 
			
		||||
    uint32_t clobber_eax;
 | 
			
		||||
    asm volatile(
 | 
			
		||||
        "outb %%al, $0x40\n"
 | 
			
		||||
        "movb %%ah, %%al\n"
 | 
			
		||||
        "outb %%al, $0x40\n"
 | 
			
		||||
        "sti\n"
 | 
			
		||||
        :"=a"(clobber_eax):"a"(reload_v)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int MakeSystemVolume(uint8_t sysPartition);
 | 
			
		||||
void MakeMBRPartitions();
 | 
			
		||||
void SystemRun(uint8_t sysPartition) {
 | 
			
		||||
@@ -463,6 +512,7 @@ void SystemRun(uint8_t sysPartition) {
 | 
			
		||||
    DrawScreen((uint16_t*)0xb8000);
 | 
			
		||||
 | 
			
		||||
    InitDisk();
 | 
			
		||||
    PITPgrm();
 | 
			
		||||
 | 
			
		||||
    // Check for FAT partition
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										95
									
								
								paging.c
									
									
									
									
									
								
							
							
						
						
									
										95
									
								
								paging.c
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
#include "paging.h"
 | 
			
		||||
 | 
			
		||||
uint32_t page_directory[1024] __attribute__((aligned(4096)));
 | 
			
		||||
uint32_t page_tables[4][1024] __attribute__((aligned(4096)));
 | 
			
		||||
uint32_t page_tables[128][1024] __attribute__((aligned(4096)));
 | 
			
		||||
 | 
			
		||||
void enable_paging() {
 | 
			
		||||
    asm(
 | 
			
		||||
@@ -21,7 +21,6 @@ void map_pages(uintptr_t page, uintptr_t num_pages, uintptr_t phy_address, char
 | 
			
		||||
 | 
			
		||||
    // Each page is 4K, Each page table is 4M
 | 
			
		||||
    uintptr_t page_dir_entry = page >> 10;
 | 
			
		||||
    if (page_dir_entry >= 4) return;
 | 
			
		||||
    uintptr_t page_index = page & 0x3ff;
 | 
			
		||||
    if (page_index + num_pages > 1024) return;
 | 
			
		||||
 | 
			
		||||
@@ -32,11 +31,93 @@ void map_pages(uintptr_t page, uintptr_t num_pages, uintptr_t phy_address, char
 | 
			
		||||
        page_tables[page_dir_entry][page_index + i] = phy_address + (i * 0x1000) | access_flags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Marks a 4MB page directory index unused, *without* freeing physical memory
 | 
			
		||||
void mark_pages_unused(uint16_t page_dir_idx) {
 | 
			
		||||
    if (page_dir_idx >= 1024) return;
 | 
			
		||||
    // Supervisor, R/W, Not Present
 | 
			
		||||
    page_directory[page_dir_idx] = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bitmap of physical memory usage
 | 
			
		||||
uint8_t PhyMapArr[1024/8];
 | 
			
		||||
 | 
			
		||||
// Marks a 4MB page directory index unused, along with underlying physical memory
 | 
			
		||||
void free_pages(uint16_t page_dir_idx) {
 | 
			
		||||
    // Get first entry of page table
 | 
			
		||||
    uint32_t *page_table = (uint32_t*)(page_directory[page_dir_idx] != 2 ? (uintptr_t)page_directory[page_dir_idx] & 0xfffff000 : 0);
 | 
			
		||||
    if (!page_table) return;
 | 
			
		||||
 | 
			
		||||
    // Free physical memory
 | 
			
		||||
    uint32_t phy_address = page_table[0] & 0xfffff000;
 | 
			
		||||
    uint32_t phy_address_4mb = phy_address >> 22;
 | 
			
		||||
    uint32_t map_idx = phy_address_4mb >> 3;
 | 
			
		||||
    uint32_t bit_idx = phy_address_4mb & 7;
 | 
			
		||||
    // Clear bit
 | 
			
		||||
    PhyMapArr[map_idx] &= ~(1 << bit_idx);
 | 
			
		||||
 | 
			
		||||
    // Mark unused
 | 
			
		||||
    mark_pages_unused(page_dir_idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Gets an unused 4MB page directory index. Return -1 if no free pages.
 | 
			
		||||
uint16_t get_unused_pages() {
 | 
			
		||||
    for (int i = 0; i < 1024; i++)
 | 
			
		||||
        if (page_directory[i] == 2) return i;
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Gets physical address of 4MB unused area of physical memory. This will have to be mapped to virtual memory space to be used.
 | 
			
		||||
uint32_t get_phy_mem() {
 | 
			
		||||
    for (int i = 0; i < sizeof(PhyMapArr); i++) {
 | 
			
		||||
        // Fully used
 | 
			
		||||
        if (PhyMapArr[i] == 0xff) continue;
 | 
			
		||||
        // At least one bit must be free
 | 
			
		||||
        uint8_t bits = PhyMapArr[i];
 | 
			
		||||
        for (int j = 0; j < 8; j++)
 | 
			
		||||
            if (!(bits & (1 << j))) return (i << 25) + (j << 22);
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// User, R/W, Present
 | 
			
		||||
#define USERACCESS (4|2|1)
 | 
			
		||||
// Supervisor, R/W, Present
 | 
			
		||||
#define SUPERACCESS (2|1)
 | 
			
		||||
 | 
			
		||||
// Returns a pointer to a newly mapped 4MB memory chunk
 | 
			
		||||
uintptr_t add_pages(char access_flags) {
 | 
			
		||||
    // Get free physical space
 | 
			
		||||
    uint32_t phy_mem = get_phy_mem();
 | 
			
		||||
    if (phy_mem == -1) return -1;
 | 
			
		||||
 | 
			
		||||
    // Get free virtual space
 | 
			
		||||
    uint16_t free_ent = get_unused_pages();
 | 
			
		||||
    if ((int16_t)free_ent == -1) return -1;
 | 
			
		||||
    uintptr_t page = free_ent << 10;
 | 
			
		||||
 | 
			
		||||
    // Mark page directory entry present, pointing to page table
 | 
			
		||||
    page_directory[free_ent] = ((uintptr_t)&page_tables[free_ent]) | USERACCESS;
 | 
			
		||||
    
 | 
			
		||||
    // Map pages to physical address
 | 
			
		||||
    map_pages(page, 1024, phy_mem, access_flags);
 | 
			
		||||
 | 
			
		||||
    // Mark physical memory used
 | 
			
		||||
    uint32_t phy_address_4mb = phy_mem >> 22;
 | 
			
		||||
    uint32_t map_idx = phy_address_4mb >> 3;
 | 
			
		||||
    uint32_t bit_idx = phy_address_4mb & 7;
 | 
			
		||||
    // Set bit
 | 
			
		||||
    PhyMapArr[map_idx] |= 1 << bit_idx;
 | 
			
		||||
 | 
			
		||||
    // Return virtual address
 | 
			
		||||
    return page << 12;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Copies 4MB groups of pages
 | 
			
		||||
void move_pages(uint16_t src_page_dir_idx, uint16_t dest_page_dir_idx) {
 | 
			
		||||
    if (src_page_dir_idx >= 1024 || dest_page_dir_idx >= 1024) return;
 | 
			
		||||
    page_directory[dest_page_dir_idx] = page_directory[src_page_dir_idx];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_paging() {
 | 
			
		||||
    for (int i = 0; i < 1024; i++)
 | 
			
		||||
        // Supervisor, R/W, Not Present
 | 
			
		||||
@@ -51,13 +132,15 @@ void init_paging() {
 | 
			
		||||
    // Next 4MB: Kernel
 | 
			
		||||
    map_pages(0x00400000 >> 12, 1024, 0x00400000, SUPERACCESS);
 | 
			
		||||
 | 
			
		||||
    // Next 8MB: Usermode
 | 
			
		||||
    map_pages(0x00800000 >> 12, 1024, 0x00800000, USERACCESS);
 | 
			
		||||
    map_pages(0x00C00000 >> 12, 1024, 0x00C00000, USERACCESS);
 | 
			
		||||
 | 
			
		||||
    // We aren't using page directory permissions
 | 
			
		||||
    for (int i = 0; i < 4; i++)
 | 
			
		||||
        page_directory[i] = ((uintptr_t)&page_tables[i]) | USERACCESS;
 | 
			
		||||
 | 
			
		||||
    // Mark all physical memory free TODO Check memory size
 | 
			
		||||
    for (int i = 0; i < sizeof(PhyMapArr); i++)
 | 
			
		||||
        PhyMapArr[i] = 0;
 | 
			
		||||
    // Mark lowest 8MB as used
 | 
			
		||||
    PhyMapArr[0] = 3;
 | 
			
		||||
 | 
			
		||||
    enable_paging();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								paging.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								paging.h
									
									
									
									
									
								
							@@ -1,3 +1,6 @@
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
void free_pages(uint16_t page_dir_idx);
 | 
			
		||||
uintptr_t add_pages(char access_flags);
 | 
			
		||||
void move_pages(uint16_t src_page_dir_idx, uint16_t dest_page_dir_idx);
 | 
			
		||||
void init_paging();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								progs.c
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								progs.c
									
									
									
									
									
								
							@@ -1,21 +1,23 @@
 | 
			
		||||
#include "progs.h"
 | 
			
		||||
#include "paging.h"
 | 
			
		||||
#include "file.h"
 | 
			
		||||
 | 
			
		||||
extern char _USERMODE, _USERMODE_END;
 | 
			
		||||
static uintptr_t USERMODE_STACK = (uintptr_t)&_USERMODE_END - 0x100000;
 | 
			
		||||
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
 | 
			
		||||
void ProgramLoadTest(char *path) {
 | 
			
		||||
void programLoadTestInner(char *path) {
 | 
			
		||||
    uint16_t *vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
    for (int i = 0; i < 80*25; i++)
 | 
			
		||||
        vga_text[i] = 0x0f00;
 | 
			
		||||
    uint32_t successcount;
 | 
			
		||||
 | 
			
		||||
    uint8_t *diskReadBuf = (uint8_t *)&_USERMODE;
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t err;
 | 
			
		||||
        dirent de;
 | 
			
		||||
        err = path_getinfo(path, &de);
 | 
			
		||||
        if (de.size > 0x300000 || err) {
 | 
			
		||||
        if (de.size > 0xE00000 || err) {
 | 
			
		||||
            vga_text += printStr("File too large or error.", vga_text);
 | 
			
		||||
            kbd_wait();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        FILE file;
 | 
			
		||||
@@ -45,7 +47,8 @@ void ProgramLoadTest(char *path) {
 | 
			
		||||
    vga_text = nextLine(vga_text,(uint16_t*)0xb8000);
 | 
			
		||||
    vga_text += printStr("Press any key to run.", vga_text);
 | 
			
		||||
    kbd_wait();
 | 
			
		||||
    uint32_t res = create_user_child((uintptr_t)&_USERMODE_END, (uintptr_t)&_USERMODE, 0);
 | 
			
		||||
    uint32_t res = create_user_child(USERMODE_STACK, (uintptr_t)&_USERMODE, 0);
 | 
			
		||||
 | 
			
		||||
    union V86Regs_t regs;
 | 
			
		||||
    regs.w.ax = 3; // text mode
 | 
			
		||||
    V8086Int(0x10, ®s); 
 | 
			
		||||
@@ -57,5 +60,18 @@ void ProgramLoadTest(char *path) {
 | 
			
		||||
    vga_text += printStr(" (0x", vga_text);
 | 
			
		||||
    vga_text += printDword(res, vga_text);
 | 
			
		||||
    vga_text += printStr("). Press any key to exit.", vga_text);
 | 
			
		||||
    kbd_wait();
 | 
			
		||||
}
 | 
			
		||||
void ProgramLoadTest(char *path) {
 | 
			
		||||
    // Get free memory (8MB)
 | 
			
		||||
    uintptr_t process_page0 = add_pages(4|2|1);
 | 
			
		||||
    uintptr_t process_page1 = add_pages(4|2|1);
 | 
			
		||||
    // Map usermode memory
 | 
			
		||||
    move_pages(process_page0 >> 22, (uintptr_t)&_USERMODE >> 22);
 | 
			
		||||
    move_pages(process_page1 >> 22, ((uintptr_t)&_USERMODE >> 22) + 1);
 | 
			
		||||
    // Inner program
 | 
			
		||||
    programLoadTestInner(path);
 | 
			
		||||
    kbd_wait();
 | 
			
		||||
    // Free process memory
 | 
			
		||||
    free_pages(process_page0 >> 22);
 | 
			
		||||
    free_pages(process_page1 >> 22);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										98
									
								
								task.nasm
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								task.nasm
									
									
									
									
									
								
							@@ -5,9 +5,8 @@ ltr ax
 | 
			
		||||
ret
 | 
			
		||||
 | 
			
		||||
global task_ptr
 | 
			
		||||
task_ptr: equ (0x310000-4)
 | 
			
		||||
task_ptr: equ (0x310000)
 | 
			
		||||
 | 
			
		||||
; TODO Is varargs too compiler dependent?
 | 
			
		||||
; extern void create_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
 | 
			
		||||
global create_child
 | 
			
		||||
create_child:
 | 
			
		||||
@@ -60,6 +59,101 @@ push 0x18 | 3
 | 
			
		||||
push eax
 | 
			
		||||
iret
 | 
			
		||||
 | 
			
		||||
; save task
 | 
			
		||||
; stack contains caller, eip, cs, eflags(, esp, ss)
 | 
			
		||||
global save_current_task_new
 | 
			
		||||
save_current_task_new:
 | 
			
		||||
push ds
 | 
			
		||||
push ebx
 | 
			
		||||
push eax
 | 
			
		||||
push 0x10
 | 
			
		||||
pop ds
 | 
			
		||||
; 0 eax, 4 ebx, 8 ds, 12 caller, 16 eip, 20 cs, 24 eflags(, 28 esp, 32 ss)
 | 
			
		||||
; location to save task
 | 
			
		||||
mov ebx, dword [0x318000]
 | 
			
		||||
; code & stack
 | 
			
		||||
mov eax, dword [esp+16]
 | 
			
		||||
mov dword [ebx+0], eax  ; eip
 | 
			
		||||
mov eax, dword [esp+20]
 | 
			
		||||
mov dword [ebx+4], eax  ; cs
 | 
			
		||||
cmp ax, 0x08
 | 
			
		||||
; if we're not in code segment, save stack info
 | 
			
		||||
je .curr_stack
 | 
			
		||||
mov eax, dword [esp+24]
 | 
			
		||||
mov dword [ebx+8], eax  ; eflags
 | 
			
		||||
mov eax, dword [esp+28]
 | 
			
		||||
mov dword [ebx+12], eax ; esp
 | 
			
		||||
mov eax, dword [esp+32]
 | 
			
		||||
mov dword [ebx+16], eax ; ss
 | 
			
		||||
jmp .seg_regs
 | 
			
		||||
; if we're in code segment, we save current info, minus interrupt stack
 | 
			
		||||
.curr_stack:
 | 
			
		||||
mov eax, dword [esp+24]
 | 
			
		||||
mov dword [ebx+8], eax  ; eflags
 | 
			
		||||
lea eax, [esp+28]
 | 
			
		||||
mov dword [ebx+12], eax ; esp before interrupt
 | 
			
		||||
mov eax, ss
 | 
			
		||||
mov dword [ebx+16], eax
 | 
			
		||||
; segment regs
 | 
			
		||||
.seg_regs:
 | 
			
		||||
mov eax, dword [esp+8]
 | 
			
		||||
mov dword [ebx+20], eax ; ds
 | 
			
		||||
mov eax, es
 | 
			
		||||
mov dword [ebx+24], eax
 | 
			
		||||
mov eax, fs
 | 
			
		||||
mov dword [ebx+28], eax
 | 
			
		||||
mov eax, gs
 | 
			
		||||
mov dword [ebx+32], eax
 | 
			
		||||
; general regs besides esp
 | 
			
		||||
mov eax, dword [esp+0]
 | 
			
		||||
mov dword [ebx+36], eax ; eax
 | 
			
		||||
mov eax, dword [esp+4]
 | 
			
		||||
mov dword [ebx+40], eax ; ebx
 | 
			
		||||
mov dword [ebx+44], ecx
 | 
			
		||||
mov dword [ebx+48], edx
 | 
			
		||||
mov dword [ebx+52], esi
 | 
			
		||||
mov dword [ebx+56], edi
 | 
			
		||||
mov dword [ebx+60], ebp
 | 
			
		||||
pop eax
 | 
			
		||||
pop ebx
 | 
			
		||||
pop ds
 | 
			
		||||
xchg bx,bx
 | 
			
		||||
ret
 | 
			
		||||
 | 
			
		||||
; return to current task
 | 
			
		||||
global ret_current_task
 | 
			
		||||
ret_current_task:
 | 
			
		||||
xchg bx,bx
 | 
			
		||||
push 0x10
 | 
			
		||||
pop ds
 | 
			
		||||
; location to get task
 | 
			
		||||
mov ebx, dword [0x318000]
 | 
			
		||||
mov ebp, [ebx+60]
 | 
			
		||||
mov edi, [ebx+56]
 | 
			
		||||
mov esi, [ebx+52]
 | 
			
		||||
mov edx, [ebx+48]
 | 
			
		||||
mov ecx, [ebx+44]
 | 
			
		||||
mov gs, [ebx+32]
 | 
			
		||||
mov fs, [ebx+28]
 | 
			
		||||
mov es, [ebx+24]
 | 
			
		||||
mov ds, [ebx+20]
 | 
			
		||||
mov eax, [ebx+4] ; cs
 | 
			
		||||
cmp ax, 0x08
 | 
			
		||||
je .restore_stack 
 | 
			
		||||
mov eax, [ebx+36]
 | 
			
		||||
mov esp, ebx
 | 
			
		||||
mov ebx, [ebx+40]
 | 
			
		||||
iret
 | 
			
		||||
.restore_stack:
 | 
			
		||||
mov esp, [ebx+12]
 | 
			
		||||
mov ss, [ebx+16]
 | 
			
		||||
mov eax, [ebx+36]
 | 
			
		||||
push dword [ebx+8]
 | 
			
		||||
push dword [ebx+4]
 | 
			
		||||
push dword [ebx]
 | 
			
		||||
mov ebx, [ebx+40]
 | 
			
		||||
iret
 | 
			
		||||
 | 
			
		||||
; return address in EAX
 | 
			
		||||
; return stack in ECX
 | 
			
		||||
; we can modify EAX, ECX, EDX
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								tests.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								tests.c
									
									
									
									
									
								
							@@ -1,4 +1,5 @@
 | 
			
		||||
#include "tests.h"
 | 
			
		||||
#include "paging.h"
 | 
			
		||||
 | 
			
		||||
extern char *user_test();
 | 
			
		||||
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
 | 
			
		||||
@@ -26,8 +27,17 @@ void ReloadUser() {
 | 
			
		||||
        *d++ = *s++;
 | 
			
		||||
}
 | 
			
		||||
char TestUser() {
 | 
			
		||||
    // Get free memory (8MB)
 | 
			
		||||
    uintptr_t process_page0 = add_pages(4|2|1);
 | 
			
		||||
    uintptr_t process_page1 = add_pages(4|2|1);
 | 
			
		||||
    // Map usermode memory
 | 
			
		||||
    move_pages(process_page0 >> 22, (uintptr_t)&_USERMODE >> 22);
 | 
			
		||||
    move_pages(process_page1 >> 22, ((uintptr_t)&_USERMODE >> 22) + 1);
 | 
			
		||||
    ReloadUser();
 | 
			
		||||
    char *vga = (char *)(uintptr_t)create_user_child((uintptr_t)&_USERMODE_END, (uintptr_t)&_USERMODE, 0);
 | 
			
		||||
    char *vga = (char *)(uintptr_t)create_user_child((uintptr_t)&_USERMODE_END - 0x100000, (uintptr_t)&_USERMODE, 0);
 | 
			
		||||
    // Free process memory
 | 
			
		||||
    free_pages(process_page0 >> 22);
 | 
			
		||||
    free_pages(process_page1 >> 22);
 | 
			
		||||
    if ((uintptr_t)vga != 0xA0000) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								tss.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								tss.c
									
									
									
									
									
								
							@@ -41,8 +41,8 @@ void write_tss() {
 | 
			
		||||
    tss_data->iomap_base = 0x80;
 | 
			
		||||
 | 
			
		||||
    // not technically TSS but set up task pointer
 | 
			
		||||
    uint32_t *current_task_ptr = (uint32_t*)(0x310000-4);
 | 
			
		||||
    *current_task_ptr = 0x310000-(20*4); // each task is 12 dwords, plus 1 for pointer
 | 
			
		||||
    uint32_t *current_task_ptr = (uint32_t*)(0x310000);
 | 
			
		||||
    *current_task_ptr = 0x310000-(1*4); // each task is 12 dwords, plus 1 for pointer
 | 
			
		||||
    /* TODO setup null recovery task at start */
 | 
			
		||||
}
 | 
			
		||||
extern void flushTSS();
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,8 @@ mov dword [0xb8000+800], 0x0f000f00 | 'g' | ':' << 16
 | 
			
		||||
mov dword [0xb8004+800], 0x0f000f00 | ' ' | '#' << 16
 | 
			
		||||
mov dword [0xb8008+800], 0x0f000f00 | 'G' | 'P' << 16
 | 
			
		||||
mov dword [0xb800C+800], 0x0f000f00 | 'F' | ' ' << 16
 | 
			
		||||
.busy:
 | 
			
		||||
jmp .busy
 | 
			
		||||
mov eax, 0 ; command = 00h, get key
 | 
			
		||||
int 0x21 ; OS call
 | 
			
		||||
cmp al, 'd'
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user