tasking: fix ELF file execution
This commit is contained in:
Executable
BIN
Binary file not shown.
@@ -0,0 +1,15 @@
|
|||||||
|
section .text
|
||||||
|
global _start ;must be declared for using gcc
|
||||||
|
_start: ;tell linker entry point
|
||||||
|
mov edx, len ;message length
|
||||||
|
mov ecx, msg ;message to write
|
||||||
|
mov ebx, 1 ;file descriptor (stdout)
|
||||||
|
mov eax, 4 ;system call number (sys_write)
|
||||||
|
int 0x80 ;call kernel
|
||||||
|
mov eax, 1 ;system call number (sys_exit)
|
||||||
|
int 0x80 ;call kernel
|
||||||
|
|
||||||
|
section .data
|
||||||
|
|
||||||
|
msg db 'Hello, world!',0xa ;our dear string
|
||||||
|
len equ $ - msg ;length of our dear string
|
||||||
Binary file not shown.
+1
-1
@@ -60,7 +60,7 @@ typedef struct Process
|
|||||||
struct Process* next; // Следующий процесс
|
struct Process* next; // Следующий процесс
|
||||||
} Process;
|
} Process;
|
||||||
|
|
||||||
Process* task_create(uint32_t func, void** args, uint32_t arg_count, uint32_t ring, uint32_t* pagedir);
|
Process* task_create(uint32_t func, uint32_t user_esp, uint32_t ring, uint32_t* pagedir);
|
||||||
void scheduler_init();
|
void scheduler_init();
|
||||||
void schedule();
|
void schedule();
|
||||||
void scheduler_lock();
|
void scheduler_lock();
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
|
|
||||||
#define DivRoundUp(number, divisor) ((number + divisor - 1) / divisor)
|
#define DivRoundUp(number, divisor) ((number + divisor - 1) / divisor)
|
||||||
|
|
||||||
|
#define USER_STACK_TOP 0xBFFFFFF0//0xC0000000 // Top of user space memory
|
||||||
|
#define USER_STACK_SIZE 0x4000 // 16KB stack (4 pages)
|
||||||
|
#define USER_STACK_BOTTOM (USER_STACK_TOP - USER_STACK_SIZE)
|
||||||
|
|
||||||
disk_ops_t ops1 =
|
disk_ops_t ops1 =
|
||||||
{
|
{
|
||||||
.read = ata_read,
|
.read = ata_read,
|
||||||
@@ -19,16 +23,16 @@ static fat_t g_fat;
|
|||||||
int read_file(const char* path, uint8_t** buffer)
|
int read_file(const char* path, uint8_t** buffer)
|
||||||
{
|
{
|
||||||
file_t file;
|
file_t file;
|
||||||
int err = fat_fopen(&file, path, "r");
|
int err = fat_fopen(&file, path, "r");
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
uint32_t file_size = fat_fsize(&file);
|
uint32_t file_size = fat_fsize(&file);
|
||||||
printf("file_size: %X\n", file_size);
|
printf("file_size: %X\n", file_size);
|
||||||
|
|
||||||
uint8_t buf[512];
|
uint8_t buf[512];
|
||||||
//memset(buf, 0, 512);
|
//memset(buf, 0, 512);
|
||||||
printf("heh\n");
|
printf("heh\n");
|
||||||
|
|
||||||
*buffer = (uint8_t*)malloc(file_size);
|
*buffer = (uint8_t*)malloc(file_size);
|
||||||
//memset(*buffer, 0, file_size);
|
//memset(*buffer, 0, file_size);
|
||||||
@@ -36,35 +40,35 @@ int read_file(const char* path, uint8_t** buffer)
|
|||||||
printf("eeee\n");
|
printf("eeee\n");
|
||||||
|
|
||||||
|
|
||||||
int cnt = fat_fread(&file, *buffer, file_size);
|
int cnt = fat_fread(&file, *buffer, file_size);
|
||||||
|
|
||||||
/*for (;;)
|
/*for (;;)
|
||||||
{
|
{
|
||||||
int cnt = fat_fread(&file, buf, 512);
|
int cnt = fat_fread(&file, buf, 512);
|
||||||
if (cnt < 0)
|
if (cnt < 0)
|
||||||
return cnt;
|
return cnt;
|
||||||
|
|
||||||
|
//printf("%s\n", buf);
|
||||||
|
memcpy(current, buf, 512);
|
||||||
|
current += 512;
|
||||||
|
|
||||||
|
if (cnt < 512)
|
||||||
|
break;
|
||||||
|
}*/
|
||||||
|
|
||||||
//printf("%s\n", buf);
|
|
||||||
memcpy(current, buf, 512);
|
|
||||||
current += 512;
|
|
||||||
|
|
||||||
if (cnt < 512)
|
|
||||||
break;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
return fat_fclose(&file);
|
return fat_fclose(&file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void exec_from_file(const char* filename)
|
void exec_from_file(const char* filename)
|
||||||
{
|
{
|
||||||
asm volatile("cli");
|
asm volatile("cli");
|
||||||
int err, cnt;
|
int err, cnt;
|
||||||
err = fat_mount(&ops1, 0, &g_fat, "ebalo");
|
err = fat_mount(&ops1, 0, &g_fat, "ebalo");
|
||||||
|
|
||||||
uint8_t* file;
|
uint8_t* file;
|
||||||
|
|
||||||
int result = read_file("/ebalo/testfile", &file);
|
int result = read_file("/ebalo/aaa", &file);
|
||||||
printf("result: %X\n", result);
|
printf("result: %X\n", result);
|
||||||
printf("buffer: %s\n", file);
|
printf("buffer: %s\n", file);
|
||||||
|
|
||||||
@@ -86,47 +90,74 @@ void exec_from_file(const char* filename)
|
|||||||
|
|
||||||
for(int i = 0; i < program_header_table_entry_count; i++)
|
for(int i = 0; i < program_header_table_entry_count; i++)
|
||||||
{
|
{
|
||||||
Elf32_Phdr *elf_phdr = (Elf32_Phdr *)((uint32_t)file + elf_ehdr->e_phoff +
|
Elf32_Phdr *elf_phdr = (Elf32_Phdr *)((uint32_t)file + elf_ehdr->e_phoff +
|
||||||
i * elf_ehdr->e_phentsize);
|
i * elf_ehdr->e_phentsize);
|
||||||
|
|
||||||
printf("HEADER %X, type: 0x%X, vaddr: 0x%X, paddr: 0x%X, memsz: 0x%X\n", i, elf_phdr->p_type, elf_phdr->p_vaddr, elf_phdr->p_paddr, elf_phdr->p_memsz);
|
printf("HEADER %X, type: 0x%X, vaddr: 0x%X, paddr: 0x%X, memsz: 0x%X\n", i, elf_phdr->p_type, elf_phdr->p_vaddr, elf_phdr->p_paddr, elf_phdr->p_memsz);
|
||||||
if(elf_phdr->p_type != PT_LOAD)
|
if(elf_phdr->p_type != PT_LOAD)
|
||||||
{
|
{
|
||||||
printf("not PT_LOAD, skipping...\n");
|
printf("not PT_LOAD, skipping...\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int pages_needed = (elf_phdr->p_memsz / 0x1000) + 1;
|
|
||||||
printf("pages needed: %X\n", pages_needed);
|
|
||||||
|
|
||||||
for(int j = 0; j < pages_needed; j++)
|
int pages_needed = DivRoundUp(elf_phdr->p_memsz, 0x1000);//(elf_phdr->p_memsz / 0x1000) + 1;
|
||||||
{
|
printf("pages needed: %X\n", pages_needed);
|
||||||
uint32_t vaddr = (elf_phdr->p_vaddr & ~0xFFF) + j * 0x1000;
|
|
||||||
void* phys_addr = alloc_page();
|
|
||||||
|
|
||||||
printf("mapping 0x%X -> 0x%X\n", phys_addr, vaddr);
|
for(int j = 0; j < pages_needed; j++)
|
||||||
//map_page_in_directory(proc_pd, phys_addr, (void*)vaddr, PAGE_PRESENT | PAGE_RW | PAGE_USER);
|
{
|
||||||
map_page(phys_addr, (void*)vaddr, PAGE_PRESENT | PAGE_RW | PAGE_USER);
|
uint32_t vaddr = (elf_phdr->p_vaddr & ~0xFFF) + j * 0x1000;
|
||||||
}
|
void* phys_addr = alloc_page();
|
||||||
|
|
||||||
|
printf("mapping 0x%X -> 0x%X\n", phys_addr, vaddr);
|
||||||
|
map_page(phys_addr, (void*)vaddr, PAGE_PRESENT | PAGE_RW | PAGE_USER);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy((void*)elf_phdr->p_vaddr, file+elf_phdr->p_offset, elf_phdr->p_filesz);
|
memcpy((void*)elf_phdr->p_vaddr, file+elf_phdr->p_offset, elf_phdr->p_filesz);
|
||||||
|
|
||||||
|
if (elf_phdr->p_memsz > elf_phdr->p_filesz) {
|
||||||
|
uint32_t bss_start = elf_phdr->p_vaddr + elf_phdr->p_filesz;
|
||||||
|
uint32_t bss_end = elf_phdr->p_vaddr + elf_phdr->p_memsz;
|
||||||
|
memset((void*)bss_start, 0, bss_end - bss_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("p_filesz: 0x%X (%X)\n", elf_phdr->p_filesz, elf_phdr->p_filesz);
|
||||||
|
printf("================================\n\n\n\n");
|
||||||
uint32_t file_start = (elf_phdr->p_vaddr & ~0xFFF) + elf_phdr->p_filesz;
|
|
||||||
uint32_t file_end = (elf_phdr->p_vaddr & ~0xFFF) + pages_needed * 0x1000;
|
|
||||||
memset((void*)file_start, 0, file_end - file_start);
|
|
||||||
|
|
||||||
printf("p_filesz: 0x%X (%X)\n", elf_phdr->p_filesz, elf_phdr->p_filesz);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
printf("================================\n\n\n\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_page_dir(curr_pd_phys);
|
printf("setting up the user stack...\n");
|
||||||
Process* p_task1 = task_create(elf_ehdr->e_entry, NULL, 0, 3, proc_pd);
|
|
||||||
|
//TODO: i think this thing allocates more pages than needed
|
||||||
asm volatile("sti");
|
for (uint32_t vaddr = USER_STACK_BOTTOM; vaddr <= USER_STACK_TOP; vaddr += PAGE_SIZE) {
|
||||||
|
void* phys_addr = alloc_page();
|
||||||
|
if(!phys_addr)
|
||||||
|
{
|
||||||
|
printf("error allocating user stack page, aborting...\n");
|
||||||
|
set_page_dir(curr_pd_phys);
|
||||||
|
//TODO: free previously allocated pages
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
map_page(phys_addr, (void*)(vaddr & ~0xFFF), PAGE_PRESENT | PAGE_RW | PAGE_USER);
|
||||||
|
printf("mapping stack 0x%X -> 0x%X (0x%X)\n", (uint32_t)phys_addr, vaddr, (vaddr & ~0xFFF));
|
||||||
|
memset((void*)(vaddr & ~0xFFF), 0, PAGE_SIZE); // Add this
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
uint32_t user_esp = USER_STACK_TOP;
|
||||||
|
|
||||||
|
// envp (environment pointer array) = NULL terminator
|
||||||
|
user_esp -= 4;
|
||||||
|
*(uint32_t*)user_esp = 0;
|
||||||
|
|
||||||
|
// argv (argument pointer array) = NULL terminator
|
||||||
|
user_esp -= 4;
|
||||||
|
*(uint32_t*)user_esp = 0;
|
||||||
|
|
||||||
|
// argc (argument count) = 0
|
||||||
|
user_esp -= 4;
|
||||||
|
*(uint32_t*)user_esp = 0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
set_page_dir(curr_pd_phys);
|
||||||
|
Process* p_task1 = task_create(elf_ehdr->e_entry, USER_STACK_TOP, 3, proc_pd);
|
||||||
|
|
||||||
|
asm volatile("sti");
|
||||||
}
|
}
|
||||||
@@ -16,10 +16,27 @@ sys_exit_handler:
|
|||||||
mov fs, ax
|
mov fs, ax
|
||||||
mov gs, ax
|
mov gs, ax
|
||||||
|
|
||||||
|
mov eax, [esp+44] ; System call number
|
||||||
|
mov ebx, [esp+32] ; Arg1
|
||||||
|
mov ecx, [esp+40] ; Arg2
|
||||||
|
mov edx, [esp+36] ; Arg3
|
||||||
|
mov esi, [esp+28] ; Arg4
|
||||||
|
mov edi, [esp+24] ; Arg5
|
||||||
|
|
||||||
|
; Print debug information
|
||||||
|
push edi ; arg5
|
||||||
|
push esi ; arg4
|
||||||
|
push edx ; arg3
|
||||||
|
push ecx ; arg2
|
||||||
|
push ebx ; arg1
|
||||||
|
push eax ; syscall number
|
||||||
|
push syscall_debug_fmt
|
||||||
|
|
||||||
; Выполняем действие
|
; Выполняем действие
|
||||||
push sys_exit_msg
|
;push sys_exit_msg
|
||||||
call printf
|
call printf
|
||||||
add esp, 4
|
;add esp, 4
|
||||||
|
add esp, 28
|
||||||
|
|
||||||
; Восстанавливаем сегменты Ring 3
|
; Восстанавливаем сегменты Ring 3
|
||||||
pop gs
|
pop gs
|
||||||
@@ -47,3 +64,4 @@ heh:
|
|||||||
|
|
||||||
section .data
|
section .data
|
||||||
sys_exit_msg: db "Returned from Ring 3", 0
|
sys_exit_msg: db "Returned from Ring 3", 0
|
||||||
|
syscall_debug_fmt: db "Syscall #%x, args: 0x%x 0x%x 0x%x 0x%x 0x%x", 10, 0
|
||||||
+7
-6
@@ -22,7 +22,7 @@ extern Process* current;
|
|||||||
extern uint32_t pid_counter;
|
extern uint32_t pid_counter;
|
||||||
extern uint32_t task_count;
|
extern uint32_t task_count;
|
||||||
|
|
||||||
Process* task_create(uint32_t func, void** args, uint32_t arg_count, uint32_t ring, uint32_t* pagedir)
|
Process* task_create(uint32_t func, uint32_t user_esp, uint32_t ring, uint32_t* pagedir)
|
||||||
{
|
{
|
||||||
void *p_physical = alloc_page();
|
void *p_physical = alloc_page();
|
||||||
Process* p = (Process*)((uint32_t)p_physical+0xC0000000);
|
Process* p = (Process*)((uint32_t)p_physical+0xC0000000);
|
||||||
@@ -60,14 +60,15 @@ Process* task_create(uint32_t func, void** args, uint32_t arg_count, uint32_t ri
|
|||||||
|
|
||||||
if(ring == 3)
|
if(ring == 3)
|
||||||
{
|
{
|
||||||
void* user_stack_physical = alloc_page();
|
/*void* user_stack_physical = alloc_page();
|
||||||
|
|
||||||
uint32_t user_stack_virtual_top = 0xBFFFF000 - ((p->pid -1) * (USTACKSIZE + 4096)); // Уникальный верх стека для каждого процесса
|
uint32_t user_stack_virtual_top = 0xBFFFF000 - ((p->pid -1) * (USTACKSIZE + 4096)); // Уникальный верх стека для каждого процесса
|
||||||
uint32_t user_stack_virtual_base = user_stack_virtual_top - USTACKSIZE;
|
uint32_t user_stack_virtual_base = user_stack_virtual_top - USTACKSIZE;
|
||||||
|
|
||||||
map_page_in_directory(p->pagedir, user_stack_physical, (void*)user_stack_virtual_base, PAGE_PRESENT | PAGE_RW | PAGE_USER); // Флаги 0x7
|
map_page_in_directory(p->pagedir, user_stack_physical, (void*)user_stack_virtual_base, PAGE_PRESENT | PAGE_RW | PAGE_USER); // Флаги 0x7
|
||||||
|
*/
|
||||||
|
|
||||||
p->tf->usermode_esp = user_stack_virtual_top;
|
p->tf->usermode_esp = user_esp;//user_stack_virtual_top;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +146,7 @@ void scheduler_init()
|
|||||||
{
|
{
|
||||||
uint32_t* kernel_tasks_pagedir = (uint32_t*)create_page_dir();
|
uint32_t* kernel_tasks_pagedir = (uint32_t*)create_page_dir();
|
||||||
|
|
||||||
task_create((uint32_t)idle, NULL, 0, 0, kernel_tasks_pagedir);
|
task_create((uint32_t)idle, 0, 0, kernel_tasks_pagedir);
|
||||||
|
|
||||||
/*void* args1[] = {(void*)42, (void*)"ebalo"};
|
/*void* args1[] = {(void*)42, (void*)"ebalo"};
|
||||||
task_create((uint32_t)task1, args1, 2, 0, kernel_tasks_pagedir);
|
task_create((uint32_t)task1, args1, 2, 0, kernel_tasks_pagedir);
|
||||||
@@ -195,7 +196,7 @@ void jump_usermode2(void) {
|
|||||||
|
|
||||||
uint32_t* proc_pd = create_page_dir();
|
uint32_t* proc_pd = create_page_dir();
|
||||||
uint32_t* proc2_pd = create_page_dir();
|
uint32_t* proc2_pd = create_page_dir();
|
||||||
Process* p_task1 = task_create(0x400000, NULL, 0, 3, proc_pd);
|
/*Process* p_task1 = task_create(0x400000, NULL, 3, proc_pd);
|
||||||
Process* p_task2 = task_create(0x400000, NULL, 0, 3, proc2_pd);
|
Process* p_task2 = task_create(0x400000, NULL, 0, 3, proc2_pd);
|
||||||
|
|
||||||
if (map_page_in_directory(p_task1->pagedir,
|
if (map_page_in_directory(p_task1->pagedir,
|
||||||
@@ -216,6 +217,6 @@ void jump_usermode2(void) {
|
|||||||
printf("jump_usermode2: Failed to map user code into task's PD for PID %d\n", p_task2->pid);
|
printf("jump_usermode2: Failed to map user code into task's PD for PID %d\n", p_task2->pid);
|
||||||
// TODO: Terminate/cleanup p_task1, free code_phys_task1
|
// TODO: Terminate/cleanup p_task1, free code_phys_task1
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
scheduler_unlock();
|
scheduler_unlock();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user