From 982287d730c16203357f4d0998c713f1c5aa6f74 Mon Sep 17 00:00:00 2001 From: xiaoyi1212 Date: Sat, 20 Apr 2024 02:43:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0syscall?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- boot/io.asm | 32 +++++++++++++++- driver/keyboard.c | 56 ++++++++++++++++++++++++++- include/io.h | 2 + include/keyboard.h | 2 + include/memory.h | 2 + include/pcat.h | 13 +++++++ include/syscall.h | 58 ++++++++++++++++++++++++++++ kernel/kernel.c | 2 + kernel/page.c | 96 ++++++++++++++++++++++++++++++++-------------- kernel/syscall.c | 29 ++++++++++++++ kernel/task.c | 6 +-- sysapp/pcat.c | 40 +++++++++++++++++++ sysapp/shell.c | 23 ++++++++++- 13 files changed, 325 insertions(+), 36 deletions(-) create mode 100644 include/pcat.h create mode 100644 include/syscall.h create mode 100644 kernel/syscall.c create mode 100644 sysapp/pcat.c diff --git a/boot/io.asm b/boot/io.asm index 76aa6b2..1b713f2 100644 --- a/boot/io.asm +++ b/boot/io.asm @@ -5,10 +5,40 @@ global io_in8, io_in16, io_in32 global io_out8, io_out16, io_out32 global io_load_eflags, io_store_eflags global load_gdtr, load_idtr -global tss_flush, gdt_flush, switch_to +global tss_flush, gdt_flush, switch_to, copy_page_physical section .text +[GLOBAL copy_page_physical] +copy_page_physical: + push ebx ; According to __cdecl, we must preserve the contents of EBX. + pushf ; push EFLAGS, so we can pop it and reenable interrupts + ; later, if they were enabled anyway. + cli ; Disable interrupts, so we aren't interrupted. + ; Load these in BEFORE we disable paging! + mov ebx, [esp+12] ; Source address + mov ecx, [esp+16] ; Destination address + + mov edx, cr0 ; Get the control register... + and edx, 0x7fffffff ; and... + mov cr0, edx ; Disable paging. + + mov edx, 1024 ; 1024*4bytes = 4096 bytes + +.loop: + mov eax, [ebx] ; Get the word at the source address + mov [ecx], eax ; Store it at the dest address + add ebx, 4 ; Source address += sizeof(word) + add ecx, 4 ; Dest address += sizeof(word) + dec edx ; One less word to do + jnz .loop + + mov edx, cr0 ; Get the control register again + or edx, 0x80000000 ; and... + mov cr0, edx ; Enable paging. + + popf ; Pop EFLAGS back. + pop ebx ; Get the original value of EBX back. switch_to: mov eax, [esp+4] diff --git a/driver/keyboard.c b/driver/keyboard.c index aacfae9..ab1de30 100644 --- a/driver/keyboard.c +++ b/driver/keyboard.c @@ -4,7 +4,7 @@ #include "../include/queue.h" #include "../include/io.h" -static KEY_STATUS *key_status; +KEY_STATUS *key_status; Queue *key_char_queue; struct key_listener* head_listener; @@ -122,6 +122,7 @@ void init_keyboard(){ key_char_queue = create_queue(); head_listener = (struct key_listener*) kmalloc(sizeof(struct key_listener)); head_listener->func = default_handle; + head_listener->lid = 0; register_interrupt_handler(0x21,handle_keyboard_input); } @@ -142,6 +143,59 @@ int handle_keyboard_input(){ return 0; } +static void found_listener(int lid,struct key_listener *head,struct key_listener *base,struct key_listener **argv,int first){ + struct key_listener *t = base; + if(t == NULL){ + argv = NULL; + return; + } + if(t->lid == lid){ + *argv = t; + return; + } else{ + if(!first) + if(head->lid == t->lid){ + argv = NULL; + return; + } + found_listener(lid,head,t->next,argv,0); + } +} + +struct key_listener* found_listener_id(int lid){ + struct task_struct *argv = NULL; + found_listener(lid,head_listener,head_listener,&argv,1); + if(argv == NULL){ + printf("Cannot found key listener id:[%d].\n",lid); + return NULL; + } + return argv; +} + +void remove_listener(int lid){ + struct key_listener *argv = found_listener_id(lid); + if(argv == NULL){ + printf("Cannot found listener id:[%d].\n",lid); + return; + } + if(argv->lid == 0){ + printf("[\033driver\036]: Cannot remove default listener.\n"); + return; + } + + kfree(argv); + struct key_listener *head = head_listener; + struct key_listener *last = NULL; + while (1){ + if(head->lid == argv->lid){ + last->next = argv->next; + return; + } + last = head; + head = head->next; + } +} + void add_listener(struct key_listener* listener){ if(listener == NULL) return; diff --git a/include/io.h b/include/io.h index bb26d1e..685f6c7 100644 --- a/include/io.h +++ b/include/io.h @@ -36,6 +36,8 @@ void load_idtr(int limit, int addr); uint16_t inw(uint16_t port); +void copy_page_physical(uint32_t,uint32_t); + extern char read_port(unsigned short port); static inline void outb(uint16_t port, uint8_t data) { diff --git a/include/keyboard.h b/include/keyboard.h index 2a3b576..c716187 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -18,6 +18,7 @@ typedef struct { }KEY_MAP; typedef struct key_listener{ + int lid; void (*func)(uint32_t key,int release,char c); struct key_listener *next; }kl_t; @@ -25,5 +26,6 @@ typedef struct key_listener{ void init_keyboard(); int handle_keyboard_input(); void add_listener(struct key_listener* listener); +void remove_listener(int lid); #endif //CRASHPOWEROS_KEYBOARD_H diff --git a/include/memory.h b/include/memory.h index af5e5ad..c12c813 100644 --- a/include/memory.h +++ b/include/memory.h @@ -63,6 +63,8 @@ uint32_t first_frame(); void page_fault(registers_t *regs); +page_directory_t *clone_directory(page_directory_t *src); + void flush_tlb(); void *ksbrk(int incr); diff --git a/include/pcat.h b/include/pcat.h new file mode 100644 index 0000000..b813978 --- /dev/null +++ b/include/pcat.h @@ -0,0 +1,13 @@ +#ifndef CRASHPOWEROS_PCAT_H +#define CRASHPOWEROS_PCAT_H + +#include "task.h" +#include "fat16.h" + +struct pcat_process{ + uint8_t is_e; +}; + +void pcat_launch(struct task_struct *father,struct File *file); + +#endif diff --git a/include/syscall.h b/include/syscall.h new file mode 100644 index 0000000..0c973d9 --- /dev/null +++ b/include/syscall.h @@ -0,0 +1,58 @@ +#ifndef CRASHPOWEROS_SYSCALL_H +#define CRASHPOWEROS_SYSCALL_H + +#include + +#define SYSCALL_NUM 10 + +#define DEFN_SYSCALL0(fn, num) \ +int syscall_##fn() \ +{ \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num)); \ + return a; \ +} + +#define DEFN_SYSCALL1(fn, num, P1) \ +int syscall_##fn(P1 p1) \ +{ \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1)); \ + return a; \ +} + +#define DEFN_SYSCALL2(fn, num, P1, P2) \ +int syscall_##fn(P1 p1, P2 p2) \ +{ \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1), "c" ((int)p2)); \ + return a; \ +} + +#define DEFN_SYSCALL3(fn, num, P1, P2, P3) \ +int syscall_##fn(P1 p1, P2 p2, P3 p3) \ +{ \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1), "c" ((int)p2), "d"((int)p3)); \ + return a; \ +} + +#define DEFN_SYSCALL4(fn, num, P1, P2, P3, P4) \ +int syscall_##fn(P1 p1, P2 p2, P3 p3, P4 p4) \ +{ \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1), "c" ((int)p2), "d" ((int)p3), "S" ((int)p4)); \ + return a; \ +} + +#define DEFN_SYSCALL5(fn, num) \ +int syscall_##fn(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) \ +{ \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1), "c" ((int)p2), "d" ((int)p3), "S" ((int)p4), "D" ((int)p5)); \ + return a; \ +} + +void syscall_install(); + +#endif diff --git a/kernel/kernel.c b/kernel/kernel.c index 2ae915c..c416d36 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -11,6 +11,7 @@ #include "../include/shell.h" #include "../include/date.h" #include "../include/acpi.h" +#include "../include/syscall.h" extern uint32_t end; extern int status; @@ -60,6 +61,7 @@ void kernel_main(multiboot_t *multiboot) { init_keyboard(); printf("[\035kernel\036]: Keyboard driver load success!\n"); + syscall_install(); print_cpu_id(); io_sti(); diff --git a/kernel/page.c b/kernel/page.c index 357512b..563f2c5 100644 --- a/kernel/page.c +++ b/kernel/page.c @@ -46,14 +46,14 @@ uint32_t first_frame() { } } } - return (uint32_t) -1; + return (uint32_t) - 1; } void alloc_frame(page_t *page, int is_kernel, int is_writable) { if (page->frame) return; else { uint32_t idx = first_frame(); - if (idx == (uint32_t) -1) { + if (idx == (uint32_t) - 1) { printf("FRAMES_FREE_ERROR: Cannot free frames!\n"); asm("cli"); for (;;)io_hlt(); @@ -110,57 +110,95 @@ void page_fault(registers_t *regs) { printf("[ERROR]: Page fault |"); if (present) { - printf("Type: present;\n\taddress: %x ", faulting_address); - if(current->pid == 0){ - printf(" ======= Kernel Error ======= "); + printf("Type: present;\n\taddress: %x \n", faulting_address); + if (current->pid == 0) { + printf(" ======= Kernel Error ======= \n"); while (1) io_hlt(); - } else{ + } else { current->state = TASK_ZOMBIE; - printf("Taskkill process PID:%d Name:%s",current->pid,current->name); + printf("Taskkill process PID:%d Name:%s\n", current->pid, current->name); } - } - else if (rw) { + } else if (rw) { printf("Type: read-only;\n\taddress: %x", faulting_address); - if(current->pid == 0){ + if (current->pid == 0) { printf(" ======= Kernel Error ======= "); while (1) io_hlt(); - } else{ + } else { current->state = TASK_ZOMBIE; - printf("Taskkill process PID:%d Name:%s",current->pid,current->name); + printf("Taskkill process PID:%d Name:%s", current->pid, current->name); } - } - else if (us) { + } else if (us) { printf("Type: user-mode;\n\taddres: %x", faulting_address); - if(current->pid == 0){ + if (current->pid == 0) { printf(" ======= Kernel Error ======= "); while (1) io_hlt(); - } else{ + } else { current->state = TASK_ZOMBIE; - printf("Taskkill process PID:%d Name:%s",current->pid,current->name); + printf("Taskkill process PID:%d Name:%s", current->pid, current->name); } - } - else if (reserved) { + } else if (reserved) { printf("Type: reserved;\n\taddress: %x", faulting_address); - if(current->pid == 0){ + if (current->pid == 0) { printf(" ======= Kernel Error ======= "); while (1) io_hlt(); - } else{ + } else { current->state = TASK_ZOMBIE; - printf("Taskkill process PID:%d Name:%s",current->pid,current->name); + printf("Taskkill process PID:%d Name:%s", current->pid, current->name); } - } - else if (id) { - printf("Type: decode address;\n\taddress: %x", faulting_address); - if(current->pid == 0){ - printf(" ======= Kernel Error ======= "); + } else if (id) { + printf("Type: decode address;\n\taddress: %x\n", faulting_address); + if (current->pid == 0) { + printf(" ======= Kernel Error ======= \n"); while (1) io_hlt(); - } else{ + } else { current->state = TASK_ZOMBIE; - printf("Taskkill process PID:%d Name:%s",current->pid,current->name); + printf("Taskkill process PID:%d Name:%s\n", current->pid, current->name); } } } +static page_table_t *clone_table(page_table_t *src, uint32_t *physAddr) { + page_table_t *table = (page_table_t *) kmalloc_ap(sizeof(page_table_t), physAddr); + memset(table, 0, sizeof(page_directory_t)); + + int i; + for (i = 0; i < 1024; i++) { + if (!src->pages[i].frame) + continue; + alloc_frame(&table->pages[i], 0, 0); + if (src->pages[i].present) table->pages[i].present = 1; + if (src->pages[i].rw) table->pages[i].rw = 1; + if (src->pages[i].user) table->pages[i].user = 1; + if (src->pages[i].accessed)table->pages[i].accessed = 1; + if (src->pages[i].dirty) table->pages[i].dirty = 1; + copy_page_physical(src->pages[i].frame * 0x1000, table->pages[i].frame * 0x1000); + } + return table; +} + +page_directory_t *clone_directory(page_directory_t *src) { + uint32_t phys; + page_directory_t *dir = (page_directory_t *) kmalloc_ap(sizeof(page_directory_t), &phys); + memset(dir, 0, sizeof(page_directory_t)); + + uint32_t offset = (uint32_t) dir->tablesPhysical - (uint32_t) dir; + dir->physicalAddr = phys + offset; + int i; + for (i = 0; i < 1024; i++) { + if (!src->tables[i]) + continue; + if (kernel_directory->tables[i] == src->tables[i]) { + dir->tables[i] = src->tables[i]; + dir->tablesPhysical[i] = src->tablesPhysical[i]; + } else { + uint32_t phys; + dir->tables[i] = clone_table(src->tables[i], &phys); + dir->tablesPhysical[i] = phys | 0x07; + } + } + return dir; +} + void init_page() { uint32_t mem_end_page = 0xFFFFFFFF; // 4GB Page diff --git a/kernel/syscall.c b/kernel/syscall.c new file mode 100644 index 0000000..24b9028 --- /dev/null +++ b/kernel/syscall.c @@ -0,0 +1,29 @@ +#include "../include/syscall.h" +#include "../include/isr.h" + +void syscall_handler(registers_t *regs){ + if (regs->eax >= SYSCALL_NUM) + return; + + void *location = NULL;//syscalls[regs->eax]; + + int ret; + asm volatile (" \ + push %1; \ + push %2; \ + push %3; \ + push %4; \ + push %5; \ + call *%6; \ + pop %%ebx; \ + pop %%ebx; \ + pop %%ebx; \ + pop %%ebx; \ + pop %%ebx; \ + " : "=a" (ret) : "r" (regs->edi), "r" (regs->esi), "r" (regs->edx), "r" (regs->ecx), "r" (regs->ebx), "r" (location)); + regs->eax = ret; +} + +void syscall_install(){ + register_interrupt_handler(0x80,syscall_handler); +} \ No newline at end of file diff --git a/kernel/task.c b/kernel/task.c index 529b9df..f6a419c 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -95,7 +95,7 @@ struct task_struct* found_task_pid(int pid){ found_task(pid,running_proc_head,running_proc_head,&argv,1); if(argv == NULL){ printf("Cannot found task Pid:[%d].\n",pid); - return; + return NULL; } return argv; } @@ -167,7 +167,7 @@ void change_task_to(struct task_struct *next) { struct task_struct *prev = current; current = next; - //switch_page_directory(current->pgd_dir); + switch_page_directory(current->pgd_dir); switch_to(&(prev->context), &(current->context)); } @@ -183,7 +183,7 @@ int32_t kernel_thread(int (*fn)(void *), void *arg,char* name) { new_task->state = TASK_RUNNABLE; new_task->stack = current; new_task->pid = now_pid++; - new_task->pgd_dir = (page_directory_t *) kmalloc_a(sizeof(page_directory_t)); + new_task->pgd_dir = kernel_directory; new_task->name = name; diff --git a/sysapp/pcat.c b/sysapp/pcat.c new file mode 100644 index 0000000..f52905b --- /dev/null +++ b/sysapp/pcat.c @@ -0,0 +1,40 @@ +#include "../include/pcat.h" +#include "../include/keyboard.h" +#include + +struct task_struct *father_pcat; +struct pcat_process *this_process; +uint32_t pid_pcat; +extern KEY_STATUS *key_status; + +void pcat_key_listener(uint32_t key,int release,char c){ + +} + +void start_pcat_thread(){ + this_process = (struct pcat_process*) kmalloc(sizeof(struct pcat_process)); + struct key_listener *listener = (struct key_listener*) kmalloc(sizeof(struct key_listener)); + listener->func = pcat_key_listener; + listener->func = 2; + add_listener(listener); + while (1){ + if(key_status->is_ctrl){ + if(this_process->is_e){ + kfree(this_process); + start_task(father_pcat); + task_kill(get_current()); + } + } + + + } +} + +void pcat_launch(struct task_struct *father,struct File *file){ + father_pcat = father; + pid_pcat = kernel_thread(start_pcat_thread,NULL,"CPOS-PCAT"); + wait_task(father); + while (1){ + if(father->state != TASK_SLEEPING) break; + } +} \ No newline at end of file diff --git a/sysapp/shell.c b/sysapp/shell.c index 40f8f3a..1d184f1 100644 --- a/sysapp/shell.c +++ b/sysapp/shell.c @@ -5,8 +5,7 @@ #include "../include/task.h" #include "../include/cmos.h" #include "../include/fat16.h" -#include "../include/timer.h" -#include "../include/io.h" +#include "../include/pcat.h" extern Queue *key_char_queue; @@ -211,6 +210,23 @@ void cmd_debug(){ printf("ESI: 0x%08x | EDI 0x%08x | EBP 0x%08x | EFLAGS 0x%08x\n",esi,edi,ebp,get_current()->context.eflags); } +void cmd_pcat(int argc,char **argv){ + if (argc == 1) { + + return; + } + char name[8] = {0}; + char ext[3] = {0}; + analyse_fullname(argv[1], name, ext); + int isfind = find_file(name, ext, 0); + struct File* file; + if(isfind){ + file = open_file(argv[1]); + } else file = create_file(argv[1]); + + pcat_launch(get_current(),file); +} + void setup_shell(){ vga_clear(); printf("%s for x86 [Version %s] \n",OS_NAME, OS_VERSION); @@ -256,6 +272,8 @@ void setup_shell(){ cmd_shutdown(); else if (!strcmp("debug", argv[0])) cmd_debug(); + else if (!strcmp("pcat", argv[0])) + cmd_pcat(argc,argv); else if (!strcmp("help", argv[0]) || !strcmp("?", argv[0]) || !strcmp("h", argv[0])) { vga_writestring("-=[\037CrashPowerShell Helper\036]=-\n"); vga_writestring("help ? h \032Print shell help info.\036\n"); @@ -271,6 +289,7 @@ void setup_shell(){ vga_writestring("reset \032Reset OS.\036\n"); vga_writestring("shutdown exit \032Shutdown OS.\036\n"); vga_writestring("debug \032Print os debug info.\036\n"); + vga_writestring("pcat [filename] \032Launch pcat application.\036\n"); } else printf("\033[Shell]: Unknown command '%s'.\036\n", argv[0]); } }