diff --git a/DEBUG b/DEBUG new file mode 100644 index 0000000..59ee97a --- /dev/null +++ b/DEBUG @@ -0,0 +1,7 @@ +DEBUGGING MP3 +=============== + +The only steps that need to be taken on the virtual machine for debugging +using qemu is to perform a "sudo make debug" (after "make dep"). This will build the disk image needed for QEMU and gdb. + +Refer to the handout for instructions on starting QEMU and gdb. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..90c3320 --- /dev/null +++ b/INSTALL @@ -0,0 +1,17 @@ +ECE391 MP3 - Operating System Project +===================================== + +To get this skeleton OS running on QEMU, you must do the following steps: + +"make dep" +"sudo make" + +to build the OS (it is called bootimg) and the QEMU disk image (mp3.img) + +You can then follow the instructions in Appendix G to setup your +debug.bat batch script. + +If you would like to run MP3 without having to connect gdb (When you are done +and have removed all your bugs for example), you can duplicate the debug.bat +batch script and remove the -s and -S options in the QEMU command. This is +will stop QEMU from waiting for GDB to connect. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fc2a68b --- /dev/null +++ b/Makefile @@ -0,0 +1,42 @@ + +# Makefile for OS project +# To build, first `make dep`, them `make`. Everything should be automatic. +# Will compile all *.c and *.S files in the current directory. + + +# Flags to use when compiling, preprocessing, assembling, and linking +CFLAGS += -Wall -fno-builtin -fno-stack-protector -nostdlib +ASFLAGS += +LDFLAGS += -nostdlib -static +CC=gcc + +#If you have any .h files in another directory, add -I to this line +CPPFLAGS +=-nostdinc -g + +# This generates the list of source files +SRC = $(wildcard *.S) $(wildcard *.c) + +# This generates the list of .o files. The order matters, boot.o must be first +OBJS = boot.o +OBJS += $(filter-out boot.o,$(patsubst %.S,%.o,$(filter %.S,$(SRC)))) +OBJS += $(patsubst %.c,%.o,$(filter %.c,$(SRC))) + + +bootimg: Makefile $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) -Ttext=0x400000 -o bootimg + ./debug.sh + +dep: Makefile.dep + +Makefile.dep: $(SRC) + $(CC) -MM $(CPPFLAGS) $(SRC) > $@ + +.PHONY: clean +clean: + rm -f *.o Makefile.dep bootimg + +ifneq ($(MAKECMDGOALS),dep) +ifneq ($(MAKECMDGOALS),clean) +include Makefile.dep +endif +endif diff --git a/Makefile.dep b/Makefile.dep new file mode 100644 index 0000000..6778188 --- /dev/null +++ b/Makefile.dep @@ -0,0 +1,25 @@ +boot.o: boot.S multiboot.h x86_desc.h types.h +page.o: page.S +stub_handler.o: stub_handler.S +x86_desc.o: x86_desc.S x86_desc.h types.h +file_system.o: file_system.c file_system.h types.h lib.h task.h \ + file_desc.h +i8259.o: i8259.c i8259.h types.h lib.h task.h file_desc.h +idt_handler.o: idt_handler.c lib.h types.h task.h file_desc.h \ + idt_handler.h i8259.h terminal.h rtc.h +irq0.o: irq0.c irq0.h lib.h types.h task.h file_desc.h i8259.h +kernel.o: kernel.c multiboot.h types.h x86_desc.h lib.h task.h \ + file_desc.h i8259.h debug.h idt_handler.h sys_call.h stub_handler.h \ + page.h rtc.h terminal.h file_system.h test.h +lib.o: lib.c lib.h types.h task.h file_desc.h +rtc.o: rtc.c rtc.h lib.h types.h task.h file_desc.h +sys_call.o: sys_call.c sys_call.h types.h file_op_table.h lib.h task.h \ + file_desc.h idt_handler.h rtc.h file_system.h terminal.h page.h +table.o: table.c task.h types.h file_desc.h lib.h table.h +task.o: task.c task.h types.h file_desc.h page.h x86_desc.h file_system.h \ + lib.h i8259.h irq0.h +terminal.o: terminal.c terminal.h types.h lib.h task.h file_desc.h \ + table.h +test.o: test.c test.h types.h lib.h task.h file_desc.h multiboot.h \ + x86_desc.h i8259.h debug.h idt_handler.h page.h rtc.h terminal.h \ + file_system.h diff --git a/boot.S b/boot.S new file mode 100644 index 0000000..53fff06 --- /dev/null +++ b/boot.S @@ -0,0 +1,56 @@ +# boot.S - start point for the kernel after GRUB gives us control +# vim:ts=4 noexpandtab + +#define ASM 1 + +#include "multiboot.h" +#include "x86_desc.h" + +.text + + # Multiboot header (required for GRUB to boot us) + .long MULTIBOOT_HEADER_MAGIC + .long MULTIBOOT_HEADER_FLAGS + .long -(MULTIBOOT_HEADER_MAGIC+MULTIBOOT_HEADER_FLAGS) + +# Entrypoint to the kernel +.globl start, _start + +.align 4 +start: +_start: + # Make sure interrupts are off + cli + jmp continue + +continue: + # Load the GDT + lgdt gdt_desc + # Load CS with the new descriptor value + ljmp $KERNEL_CS, $keep_going + +keep_going: + # Set up ESP so we can have an initial stack + movl $0x800000, %esp + + # Set up the rest of the segment selector registers + movw $KERNEL_DS, %cx + movw %cx, %ss + movw %cx, %ds + movw %cx, %es + movw %cx, %fs + movw %cx, %gs + + # Push the parameters that entry() expects (see kernel.c): + # eax = multiboot magic + # ebx = address of multiboot info struct + pushl %ebx + pushl %eax + + # Jump to the C entrypoint to the kernel. + call entry + + # We'll never get back here, but we put in a hlt anyway. +halt: + hlt + jmp halt diff --git a/boot.o b/boot.o new file mode 100644 index 0000000..3de94cf Binary files /dev/null and b/boot.o differ diff --git a/bootimg b/bootimg new file mode 100644 index 0000000..30905d0 Binary files /dev/null and b/bootimg differ diff --git a/debug-gdb.lnk b/debug-gdb.lnk new file mode 100644 index 0000000..285c40c Binary files /dev/null and b/debug-gdb.lnk differ diff --git a/debug.h b/debug.h new file mode 100644 index 0000000..ba1bb24 --- /dev/null +++ b/debug.h @@ -0,0 +1,33 @@ +/* debug.h - Useful macros for debugging + * vim:ts=4 noexpandtab + */ + +#ifndef _DEBUG_H +#define _DEBUG_H + +#ifndef ASM + +#ifdef DEBUG + +#define ASSERT(EXP) \ +do { \ + if(!(EXP)) { \ + printf(__FILE__ ":%u: Assertion `" #EXP "\' failed.\n", __LINE__); \ + } \ +} while(0) + +#define debugf(...) \ +do { \ + printf(__FILE__ ":%u: ", __LINE__); \ + printf(__VA_ARGS__); \ +} while(0) + +#else +#define ASSERT(EXP) \ + while(0) +#define debugf(...) \ + while(0) +#endif + +#endif +#endif /* _DEBUG_H */ diff --git a/debug.lnk b/debug.lnk new file mode 100644 index 0000000..09d6d84 Binary files /dev/null and b/debug.lnk differ diff --git a/debug.sh b/debug.sh new file mode 100644 index 0000000..845b28f --- /dev/null +++ b/debug.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +if [ -d /mnt/tmpmp3 ]; then +rmdir /mnt/tmpmp3 +fi + +if [ -d /tmp/mp3 ]; then +rm -rf /tmp/mp3 +fi + +mkdir /mnt/tmpmp3 +mkdir /tmp/mp3 +cp ./bootimg /tmp/mp3/ +cp ./filesys_img /tmp/mp3/ +cp ./mp3.img /tmp/mp3/ +mount -o loop,offset=32256 /tmp/mp3/mp3.img /mnt/tmpmp3 +cp -f /tmp/mp3/bootimg /mnt/tmpmp3/ +cp -f /tmp/mp3/filesys_img /mnt/tmpmp3/ +umount /mnt/tmpmp3 +cp -f /tmp/mp3/mp3.img ./ +rm -rf /tmp/mp3 +rmdir /mnt/tmpmp3 + diff --git a/devel machine.lnk b/devel machine.lnk new file mode 100644 index 0000000..abfc74f Binary files /dev/null and b/devel machine.lnk differ diff --git a/file_desc.h b/file_desc.h new file mode 100644 index 0000000..7227b21 --- /dev/null +++ b/file_desc.h @@ -0,0 +1,21 @@ +#ifndef _FILE_DESC_H +#define _FILE_DESC_H + +typedef struct filedescriptor{ + void* file_operations_pointer; + uint32_t inode_pointer; + uint32_t file_position; + uint32_t flags; + }filedescriptor_t; + + +typedef struct file_type_op_action{ + int32_t (*open)(filedescriptor_t*,void*); + int32_t (*read)(filedescriptor_t* , void*, uint32_t); + int32_t (*write)(filedescriptor_t* , const void*, uint32_t); + }file_type_op_action_t; + + +#endif + + diff --git a/file_op_table.h b/file_op_table.h new file mode 100644 index 0000000..f90ace5 --- /dev/null +++ b/file_op_table.h @@ -0,0 +1,155 @@ +#ifndef _FILE_OP_TABLE_H +#define _FILE_OP_TABLE_H +#include "lib.h" +#include "idt_handler.h" +#include "rtc.h" +#include "file_system.h" +#include "terminal.h" +#include "file_desc.h" +#define debug_fread_f_d 0 +#define debug_fread_f_d_freq 51 +#if debug_fread_f_d +static int32_t debug_fread_f_d_k=debug_fread_f_d_freq; +#endif + +static int32_t fopen_f_d(filedescriptor_t* fdstruct,void* buf) +{ + return -1; +} + +static int32_t fread_f_d(filedescriptor_t* fdstruct, void* buf, uint32_t n_bytes) +{ + + + //char buff[n_bytes]; + //char * pointer =(char *) buf; + //int32_t h; + uint32_t temp; + //uint32_t temp2; + //uint32_t inode = fdstruct->inode_pointer; + //uint32_t n_bytes1 = n_bytes; + //printf("indoe %d",fdstruct->inode_pointer); + //printf("fb %x",(uint32_t)*(uint32_t*)(fdstruct->inode_pointer)); + if(fdstruct->inode_pointer == 0) + { + //printf( "directory: %d",fdstruct->file_position); + temp = read_data(fdstruct->inode_pointer, fdstruct->file_position, (uint8_t*) buf, n_bytes); + fdstruct->file_position += n_bytes; + + } + else + { + temp = read_data(fdstruct->inode_pointer, fdstruct->file_position, (uint8_t*) buf, n_bytes); + fdstruct->file_position += temp; + if(temp == 0) + { + //printf( "cao ni ma quan jia "); + + } + + } + // don grep excutebe file + if(*(uint32_t*) buf == 0x464c457f ) + return 0; + //temp2 = fdstruct->file_position; + // if(temp == -1) + // fdstruct->file_position = 0; + // for(h = temp; h < strlen((uint8_t*)buf); h++) + // pointer[h]=0; + //printf( "%c",*pointer); +#if debug_fread_f_d + debug_fread_f_d_k--; + if (debug_fread_f_d_k==0) { + printf("Buf is %s\n",buf); + printf("return data byte read:%d\n",temp); + while(1); + } +#endif + //printf( "\n %s ",buf); + return temp; + +} + +static int32_t fwrite_f_d(filedescriptor_t* fdstruct, const void* buf, uint32_t n_bytes) +{ + return -1; +} + +static int32_t fopen_rtc(filedescriptor_t* fdstruct,void* buf) +{ +return 0; +} + +static int32_t fread_rtc(filedescriptor_t* fdstruct, void* buf, uint32_t n_bytes) +{ +sti(); +read_rtc(); +cli(); +return 0; +} + +static int32_t fwrite_rtc(filedescriptor_t* fdstruct, const void* buf, uint32_t n_bytes) +{ + + // printf( "fwrite_rtc %d",(int)*(int*)buf); + // char *type = NULL; + // char temp =*type; + cli(); + write_rtc((int)*(int*)buf); + sti(); +return 0; +} + +static int32_t termin_read(filedescriptor_t* fdstruct, void* buf, uint32_t n_bytes) +{ +sti(); +return r_terminal(0x00,(uint8_t*) buf, n_bytes); + + +} + +static int32_t termin_open(filedescriptor_t* fdstruct,void* buf) +{ +open_terminal(0x00); +return 0; +} + +static int32_t termin_write(filedescriptor_t* fdstruct, const void* buf, uint32_t n_bytes) +{ + +printf( "%s",buf); +return 0; +} + + +//no +file_type_op_action_t RTC_type_op = { +.open =&fopen_rtc, +.write= &fwrite_rtc, +.read= &fread_rtc}; + + + +//DIRECTORY +file_type_op_action_t directry_type_op = { +.open = &fopen_f_d, +.write= &fwrite_f_d, +.read = &fread_f_d}; + + + +//REGULER FILE +file_type_op_action_t file_type_op = { +.open = &fopen_f_d, +.write= &fwrite_f_d, +.read = &fread_f_d}; + +file_type_op_action_t terminal_type_op = { +.open = &termin_open, +.write= &termin_write, +.read = &termin_read}; + + +#endif + + diff --git a/file_system.c b/file_system.c new file mode 100644 index 0000000..7412b99 --- /dev/null +++ b/file_system.c @@ -0,0 +1,242 @@ +#include "file_system.h" +#include "lib.h" +#include "types.h" +#define debug_file_system 0 +#define debug_get_inode_by_name 0 +#define debug_set_start 0 +#define debug_read_dentry_by_name 0 +#define debug_read_data 0 +#define debug_check_name 0 +static uint32_t filestart; +static int checkname(const uint8_t * fname, uint8_t * cname); + +extern uint32_t sizeofinode(uint32_t inode) +{ +return *(uint32_t*)(filestart + FILE_BLOCK_SIZE*(inode + 1)); +}; +/* + * get_inode_by_name + * Description: obtain the node + * INPUTS: fname -- file name which need to access + * OUTPUTS: N/A + * RETURN VALUE: return inode if succeed or -1 if failed + * SIDE EFFECTS: N/A + */ +int32_t get_inode_by_name(uint8_t* fname){ + dentry_t copy; +#if debug_get_inode_by_name +printf("get_inode_by_name:center get_inode_by_name %s ", fname); +#endif + if(read_dentry_by_name((uint8_t *)fname, ©) == -1) + return -1; +#if debug_get_inode_by_name +printf("get_inode_by_name:copy.inode :%x:",copy.inode); +#endif + return copy.inode; +} + +/* + * setstart + * Description: set the starting addr + * INPUTS: start -- starting addr + * OUTPUTS: N/A + * RETURN VALUE: N/A + * SIDE EFFECTS: N/A + */ +void setstart(uint32_t start) +{ + filestart=start; +#if debug_set_start +printf("0x%x ", (uint32_t)*(uint32_t *)(filestart+4)); +#endif +} + +/* + * read_dentry_by_name + * Description: Search the file by name + * INPUTS: dentry -- pointer points to the struct that we + * need to construct for the name comparing + * info + * fname -- the file name that need to be found + * OUTPUTS: none + * RETURN VALUE: 0 on success, -1 on failure + * SIDE EFFECTS: reconstruct the dentry every time failed to + * find the name. + */ +int32_t read_dentry_by_name(const uint8_t * fname, dentry_t *dentry) +{ + /*Indicating the number of directory entries. */ + uint32_t numinde = (uint32_t)*(uint32_t*)(filestart+4); + int i; + int end = 0; + int h; + uint32_t address; + /*Search the entries one by one*/ + for( i = 1; i<=numinde; i++) + { + /*If we failed to find the file name, reconstruct the dentry */ + if(checkname(fname, (uint8_t*)(filestart + 64*i))) + { + for( h = 0; h<32; h++){ + /*construct the name buffer bit by bit for 32 times since it's 32bits*/ + dentry->name[h] = (uint8_t)*(uint8_t*) (filestart + 64*i + h);} + /*the addr of type is 32bit after the name*/ + dentry->type = (uint32_t) *(uint32_t*)(filestart + 64*i + 32); + /*the addr of inode is 4bit after the type*/ + dentry->inode = (uint32_t) *(uint32_t*)(filestart + 64*i + 36); + /* calculate the address of the inode pointer*/ + address = (filestart + FILE_BLOCK_SIZE*(i+1)); + end = 1; +#if debug_read_dentry_by_name + printf("read_dentry_by_name '%s' ",(uint8_t*)(filestart + 64*i)); + printf("read_dentry_by_name '%s' ",fname); +#endif + break; + } +#if debug_read_dentry_by_name + printf("read_dentry_by_name '%s'",(uint8_t*)(filestart + 64*i)); +#endif + } + if(end == 1) + { +#if debug_read_dentry_by_name + printf("read_dentry_by_name: success on looking for '%s' ",fname); +#endif + return address;//return inode pointer + } + else + { + // printf("failure on looking for'%s' ",fname); + return -1; + } + +}; +/* + * checkname + * Description: check the name + * INPUTS: fname -- file name need to access + * cname -- expected name + * OUTPUTS: N/A + * RETURN VALUE: return 0 if fail or 1 if succeed + * SIDE EFFECTS: N/A + */ +int checkname(const uint8_t * fname, uint8_t * cname) +{ + int h; + /*If the string length doesn't match, return 0*/ + if(strlen((int8_t*)cname) < strlen((int8_t*)fname)) + return 0; + /*Compare the bits one by one*/ + for( h = 0; h < strlen((int8_t*)cname); h++) + if(fname[h] != cname[h]) + /*If not match, return 0*/ + return 0; + +#if debug_check_name + printf("checkname1 '%s' ",fname); + printf("checkname2 '%s' ",cname); +#endif + return 1; + +}; +/* + * read_dentry_by_index + * Description: Search the file by index + * INPUTS: dentry -- pointer points to the struct that we + * need to construct for the index comparing + * info + * index -- the file index that need to be found + * OUTPUTS: none + * RETURN VALUE: 0 on success, -1 on failure + * SIDE EFFECTS: none + */ +int32_t read_dentry_by_index(uint32_t index, dentry_t *dentry) +{ + uint32_t numinde = (uint32_t)*(uint32_t*)(filestart+4); + int i; + int end = 0; + int h; + for( i = 1; i<=numinde; i++) + { + /*We only need to identify the unsigned integer which is index*/ + if((uint32_t) *(uint32_t*)(filestart + 64*i + 36) == index) + { + /*If not find, do the same thing as read by name*/ + for( h = 0; h<32; h++) + dentry->name[h] = (uint8_t) * (uint8_t*)(filestart + 64*i + h); + dentry->type = (uint32_t) * (uint32_t*)(filestart + 64*i + 32); + dentry->inode = (uint32_t) * (uint32_t*)(filestart + 64*i + 36); + + end = 1; + break; + } + } + if(end == 1) + { + //printf("can find in "); + return 0; + } + else + {//printf("cannot find in "); + return -1; + } + +} +/* + * read_data + * Description: Search the file by name + * INPUTS: inode -- the exact index node that we need access + * offset -- the starting point start to access + * buf -- pointer to the buffer which store the accessed data + * length -- the length of the data need to copied + * OUTPUTS: none + * RETURN VALUE: the length of the data read or -1 on failure + * SIDE EFFECTS: none + */ + +int32_t read_data(uint32_t inode, uint32_t offset, uint8_t* buf, uint32_t length) +{ + /* Obtain the total number of inodes */ + uint32_t total_inodes =(uint32_t ) *(uint32_t*) (filestart + 4); + /* get the addr of the inode of the file */ + uint32_t * dentry_ptr = (uint32_t*)(filestart + FILE_BLOCK_SIZE*(inode + 1)); + /* obtain offset in the block */ + uint32_t charoffset = offset % FILE_BLOCK_SIZE ; + /* pointer to the data block */ + uint8_t * block_pointer; + /* data block index */ + uint32_t block_num; + uint32_t i; + if(inode > total_inodes) /* offset > total # of bytes Or inode > total inodes */ // offset > total # of bytes Or inode > total inodes + return -1; + + if(inode != 0) + { + if(offset >= *dentry_ptr) + return 0; + for(i = 0; i < length; i++) /* copy length blocks to the buffer in order */ + { + if(i + offset > *dentry_ptr) /* if it reaches the end of the block, then break */ + break; + block_num = *(dentry_ptr+1+(i+charoffset)/FILE_BLOCK_SIZE); + block_pointer = (uint8_t*) (filestart + (1+total_inodes + block_num) * FILE_BLOCK_SIZE); + buf[i] = (uint8_t) *(block_pointer+(i+charoffset)%FILE_BLOCK_SIZE); + + } + return i; + } + else + { + strncpy((int8_t *)buf,((int8_t*) (filestart + 64*(offset / length + 1))),length); + return strlen((int8_t*) (filestart + 64*(offset / length + 1))); + + } +#if debug_read_data + printf(" read success%s",buf); +#endif + + +} + + + diff --git a/file_system.h b/file_system.h new file mode 100644 index 0000000..e5450c4 --- /dev/null +++ b/file_system.h @@ -0,0 +1,21 @@ +#include "types.h" +#ifndef _FILE_SYSTEM_H +#define _FILE_SYSTEM_H + +#define FILE_BLOCK_SIZE 4096 + +typedef struct dentry{ + uint8_t name[32]; + uint32_t type; + uint32_t inode; + }dentry_t; + +extern void setstart(uint32_t filestart); +extern uint32_t sizeofinode(uint32_t inode); +extern int32_t get_inode_by_name(uint8_t* fname); +extern int32_t read_dentry_by_name(const uint8_t * fname, dentry_t *dentry ); +extern int32_t read_dentry_by_index(uint32_t index, dentry_t *dentry); +extern int32_t read_data(uint32_t inode, uint32_t offset, uint8_t* buf, uint32_t length); +#endif + + diff --git a/file_system.o b/file_system.o new file mode 100644 index 0000000..dbff2b1 Binary files /dev/null and b/file_system.o differ diff --git a/filesys_img b/filesys_img new file mode 100644 index 0000000..96d9bbc Binary files /dev/null and b/filesys_img differ diff --git a/i8259.c b/i8259.c new file mode 100644 index 0000000..3c772e4 --- /dev/null +++ b/i8259.c @@ -0,0 +1,92 @@ +/* i8259.c - Functions to interact with the 8259 interrupt controller + * vim:ts=4 noexpandtab + */ + +#include "i8259.h" +#include "lib.h" +#define PIC1_DATA (MASTER_8259_PORT+1) +#define PIC2_DATA (SLAVE_8259_PORT+1) +/* Interrupt masks to determine which interrupts + * are enabled and disabled */ +uint8_t master_mask; /* IRQs 0-7 */ +uint8_t slave_mask; /* IRQs 8-15 */ + +void +i8259_init(void) +{ + /*INITIALIZE*/ + master_mask = 0xff; + slave_mask = 0xff; + + outb(master_mask,PIC1_DATA); + outb(slave_mask,PIC2_DATA); + + outb(ICW1,MASTER_8259_PORT); + /* ICW2: Master PIC vector offset */ + outb(ICW2_MASTER,PIC1_DATA); + /* ICW3: tell Master PIC that there is a slave PIC at IRQ2 */ + outb(ICW3_MASTER,PIC1_DATA); + outb(ICW4,PIC1_DATA); + + outb(ICW1,SLAVE_8259_PORT); + /* ICW2: Slave PIC vector offset */ + outb(ICW2_SLAVE,PIC2_DATA); + /* ICW3: tell Slave PIC its cascade identity */ + outb(ICW3_SLAVE,PIC2_DATA); + outb(ICW4,PIC2_DATA); + + /*restore the IRQ mask*/ + outb(master_mask,PIC1_DATA); + outb(slave_mask,PIC2_DATA); + +} + +/* Enable (unmask) the specified IRQ */ +void +enable_irq(uint32_t irq_num) +{ + uint16_t port; + uint8_t value; + if(irq_num < 8) { + port = PIC1_DATA; + } else { + port = PIC2_DATA; + irq_num -= 8; + } + value = inb(port) & ~ (1 << irq_num); + outb(value,port); + +} + +/* Disable (mask) the specified IRQ */ +void +disable_irq(uint32_t irq_num) +{ + uint16_t port; + uint8_t value; + if(irq_num < 8) { + port = PIC1_DATA; + } else { + port = PIC2_DATA; + irq_num -= 8; + } + value = inb(port) | (1 << irq_num); + outb(value,port); + +} + +/* Send end-of-interrupt signal for the specified IRQ */ +void +send_eoi(uint32_t irq_num) +{ + unsigned long flags; + cli_and_save(flags); + if(irq_num >= 8) { + outb((0x02 | EOI),MASTER_8259_PORT); + outb((uint16_t) ((irq_num-8) | EOI),SLAVE_8259_PORT); + } + else + outb((irq_num | EOI),MASTER_8259_PORT); + restore_flags(flags); +} + diff --git a/i8259.h b/i8259.h new file mode 100644 index 0000000..6bc38bb --- /dev/null +++ b/i8259.h @@ -0,0 +1,41 @@ +/* i8259.h - Defines used in interactions with the 8259 interrupt + * controller + * vim:ts=4 noexpandtab + */ + +#ifndef _I8259_H +#define _I8259_H + +#include "types.h" + +/* Ports that each PIC sits on */ +#define MASTER_8259_PORT 0x20 +#define SLAVE_8259_PORT 0xA0 + +/* Initialization control words to init each PIC. + * See the Intel manuals for details on the meaning + * of each word */ +#define ICW1 0x11 +#define ICW2_MASTER 0x20 +#define ICW2_SLAVE 0x28 +#define ICW3_MASTER 0x04 +#define ICW3_SLAVE 0x02 +#define ICW4 0x01 + +/* End-of-interrupt byte. This gets OR'd with + * the interrupt number and sent out to the PIC + * to declare the interrupt finished */ +#define EOI 0x60 + +/* Externally-visible functions */ + +/* Initialize both PICs */ +void i8259_init(void); +/* Enable (unmask) the specified IRQ */ +void enable_irq(uint32_t irq_num); +/* Disable (mask) the specified IRQ */ +void disable_irq(uint32_t irq_num); +/* Send end-of-interrupt signal for the specified IRQ */ +void send_eoi(uint32_t irq_num); + +#endif /* _I8259_H */ diff --git a/i8259.o b/i8259.o new file mode 100644 index 0000000..680178a Binary files /dev/null and b/i8259.o differ diff --git a/idt_handler.c b/idt_handler.c new file mode 100644 index 0000000..a7d99b4 --- /dev/null +++ b/idt_handler.c @@ -0,0 +1,375 @@ +#include "lib.h" +#include "idt_handler.h" +#include "i8259.h" +#include "terminal.h" +#include "rtc.h" +#define nFrequence 404 +static int counter =0; +static int flages =0; +static void deep(void); +/* divide_error + * Description: display divide_error message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying divide_error message + */ +void +divide_error() +{ +sti(); +printf("Divide error \n"); +while(1); +} +/* debug + * Description: display debug message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying debug message + */ +void +debug() +{ +sti(); +printf("debug \n"); +while(1); +} +/* nmi + * Description: display nmi message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying nmi message + */ +void +nmi() +{ +sti(); +printf("nmi \n"); +while(1); +} +/* int3 + * Description: display Break point message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying Break point message + */ +void +int3() +{sti(); +printf("Break point \n"); +while(1); +} +/* overflow + * Description: display Overflow message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying Overflow message + */ +void +overflow() +{ +sti(); +printf("Overflow \n"); +while(1); +} +/* bounds + * Description: display Bounds check message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying Bounds check message + */ +void +bounds() +{ +sti(); +printf("Bounds check \n"); +while(1); +} +/* invalid_op + * Description: display Invalid opcode message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying Invalid opcode message + */ +void +invalid_op() +{ +sti(); +printf("Invalid opcode \n"); +while(1); +} +/* device_not_available + * Description: display Device_not_available message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying Device_not_available message + */ +void +device_not_available() +{ +sti(); +printf("Device_not_available \n"); +while(1); +} +/* doublefault_fn + * Description: display Double fault message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying Double fault message + */ +void +doublefault_fn() +{ +sti(); +printf("Double fault \n"); +while(1); +} +/* coprocessor_segment_overrun + * Description: display coprocessor_segment_overrunt message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying + * coprocessor_segment_overrun message + */ +void +coprocessor_segment_overrun() +{ +sti(); +printf("Coprocessor segment overrun \n"); +while(1); +} +/* invalid_TSS + * Description: display invalid TSS message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying invalid TSS message + */ +void +invalid_TSS() +{ +sti(); +printf("invalid TSS \n"); +while(1); +} +/* segment_not_present + * Description: display invalid Segment not present message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying Segment not present message + */ +void +segment_not_present() +{ +sti(); +printf("Segment not present \n"); +while(1); +} +/* stack_segment + * Description: display invalid stack_segment message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying stack_segment message + */ +void +stack_segment() +{ +sti(); +printf("Stack segment fault \n"); +while(1); +} +/* general_protection + * Description: display invalid general_protection message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying general_protection message + */ +void +general_protection() +{ +sti(); +printf("General protection \n"); +//zhuxihao added it on 3-24 +//open_terminal(); +//end +while(1); +} +/* page_fault + * Description: display invalid page_fault message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying page_fault message + */ +void +page_fault() +{ +sti(); +printf("page fault \n"); +while(1); +} + +/* coprocessor_error + * Description: display invalid Floating-point error message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying Floating-point error message + */ +void +coprocessor_error() +{ +sti(); +printf("Floating-point error \n"); +while(1); +} +/* alignment_check + * Description: display invalid alignment_check message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying alignment_check message + */ +void +alignment_check() +{ +sti(); +printf("Alignment check \n"); +while(1); +} +/* machine_check + * Description: display invalid Machine check message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep displaying Machine check message + */ +void +machine_check() +{ +sti(); +printf("Machine check \n"); +while(1); +} +/* simd_coprocessor_error + * Description: display SIMD floating point check message + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable interrups and keep SIMD floating point check message + */ +void +simd_coprocessor_error() +{ +sti(); +printf("SIMD floating point \n"); +while(1); +} + + +//void +//system_call() +//{ +//printf("system_call \n"); +//} +/* do_irq1 + * Description: set up irq1 which is the keyboard + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable irq1 + */ +void +do_irq1() +{ + //int rec; + unsigned char scancode = inb(0x60); + //if(scancode==0x0E || scancode==0x8E) printf("\b"); + //unsigned char key=scancode; + //if(key<0x60 && key>=0x00) + //printf("we want %x ", scancode); + void *p; + uint32_t fd01; + read_terminal(fd01, p, scancode); + + //outb(0x20, 0x20); + //send the ending interrupt signal + send_eoi(1); + +} +/* do_irq8 + * Description: set up irq1 which is the keyboard + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable irq8 + */ +void +do_irq8() +{ + //write to the rtc register + //printf("rtc "); + outb(0x0C,0x70); + inb(0x71); + happen(); + //send the ending interrupt signal + send_eoi(8); +} +/* do_irq0 + * Description: set up irq1 which is the keyboard + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable irq10 + */ +void +do_irq0() +{ + + deep(); + counter++; + if(counter >= 60) + { + flages = 1; + uint8_t tmp = (inb(0x61) & 0xFC); + outb( tmp, 0x61); + } + + //printf("do_irq0"); + switch_task(); + send_eoi(0); +} + + + +void deep(void) +{ + uint32_t Div; + uint8_t tmp; + if(flages == 0) + { + //Set the PIT to the desired frequency + Div = 1193180 / nFrequence; + outb(0xb6, 0x43); + outb( (uint8_t)(Div), 0x42 ); + outb( (uint8_t) (Div >> 8), 0x42); + + // And play the sound using the PC speaker + tmp = inb(0x61); + if (tmp != (tmp | 3)) { + outb( tmp | 3, 0x61);} + } +} + diff --git a/idt_handler.h b/idt_handler.h new file mode 100644 index 0000000..eefb21a --- /dev/null +++ b/idt_handler.h @@ -0,0 +1,31 @@ +#ifndef _IDT_HANDLER_H +#define _IDT_HANDLER_H +#include "types.h" +#include "task.h" +//system internal interrupts and expections +extern void divide_error(void); +extern void debug(void); +extern void nmi(void); +extern void int3(void); +extern void overflow(void); +extern void bounds(void); +extern void invalid_op(void); +extern void device_not_available(void); +extern void doublefault_fn(void); +extern void coprocessor_segment_overrun(void); +extern void invalid_TSS(void); +extern void segment_not_present(void); +extern void stack_segment(void); +extern void general_protection(void); +extern void page_fault(void); +extern void coprocessor_error(void); +extern void alignment_check(void); +extern void machine_check(void); +extern void simd_coprocessor_error(void); +//interrupt of outer devices +extern void do_irq1(void); +extern void do_irq8(void); +extern void do_irq0(); +#endif + + diff --git a/idt_handler.o b/idt_handler.o new file mode 100644 index 0000000..494cd68 Binary files /dev/null and b/idt_handler.o differ diff --git a/irq0.c b/irq0.c new file mode 100644 index 0000000..511b80a --- /dev/null +++ b/irq0.c @@ -0,0 +1,58 @@ +#include "irq0.h" +#include "lib.h" +#include "i8259.h" + +//NoBcd,leastfirst then msn, cntr counter0 +#define timer_ctrl_port 0x43 +#define timer_port 0x40 +#define INTR_ON_TERMNAL_COUNT 0x30 +#define HARD_RE_TRIG_ONE_SHOT 0x32 +#define RATE_GENERATOR 0x34 +#define SQUARE_WAVE_MODE 0x36 +#define SOFTWARE_STROBE 0x38 +#define HZ 20 +#define DIVISOR 1193180/HZ +/* open_IRQ0 + * Description: start up the IRQ0 + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable irq0 + */ +void +open_IRQ0(void) +{ + +outb(RATE_GENERATOR, timer_ctrl_port); +/* Write the divisor to the time chip port*/ +outb(DIVISOR&0xFF, timer_port); +outb(DIVISOR>>8, timer_port); +enable_irq(0); +//printf("IRQ0 ENABLED"); +} +/* open_IRQ12 + * Description: start up the IRQ12 + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: enable irq12 + */ +void +open_IRQ12(void) +{ + +printf("enter mouse"); +/* + frequency approximate 18hz +*/ +//set up the registers. +outb(0xFF, 0x60); +outb(0xF6, 0x60); +outb(0xE6, 0x60); +// enable the mouse. +enable_irq(12); +printf("mouse ENABLED"); +} + + + diff --git a/irq0.h b/irq0.h new file mode 100644 index 0000000..ddf6df6 --- /dev/null +++ b/irq0.h @@ -0,0 +1,13 @@ +/* lib.h - Defines for useful library functions + * vim:ts=4 noexpandtab + */ + +#ifndef _IRQ0_H +#define _IRQ0_H +#include "lib.h" + +extern void open_IRQ0(void); + +#endif + + diff --git a/irq0.o b/irq0.o new file mode 100644 index 0000000..71abba4 Binary files /dev/null and b/irq0.o differ diff --git a/kernel.c b/kernel.c new file mode 100644 index 0000000..68ef8e4 --- /dev/null +++ b/kernel.c @@ -0,0 +1,229 @@ +/* kernel.c - the C part of the kernel + * vim:ts=4 noexpandtab + */ + +#include "multiboot.h" +#include "x86_desc.h" +#include "lib.h" +#include "i8259.h" +#include "debug.h" +#include "idt_handler.h" +#include "sys_call.h" +#include "stub_handler.h" +#include "page.h" +#include "rtc.h" +#include "terminal.h" +#include "file_system.h" +#include "test.h" + +#define debug_by_showing_dentries 0 + +/* Macros. */ +/* Check if the bit BIT in FLAGS is set. */ +#define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit))) + +/* Check if MAGIC is valid and print the Multiboot information structure + pointed by ADDR. */ +void +entry (unsigned long magic, unsigned long addr) +{ + multiboot_info_t *mbi; + + /* Clear the screen. */ + clear(); + + uint32_t filestart; + /* Am I booted by a Multiboot-compliant boot loader? */ + if (magic != MULTIBOOT_BOOTLOADER_MAGIC) + { + printf ("Invalid magic number: 0x%#x\n", (unsigned) magic); + return; + } + + /* Set MBI to the address of the Multiboot information structure. */ + mbi = (multiboot_info_t *) addr; + + /* Print out the flags. */ + printf ("flags = 0x%#x\n", (unsigned) mbi->flags); + + /* Are mem_* valid? */ + if (CHECK_FLAG (mbi->flags, 0)) + printf ("mem_lower = %uKB, mem_upper = %uKB\n", + (unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper); + + /* Is boot_device valid? */ + if (CHECK_FLAG (mbi->flags, 1)) + printf ("boot_device = 0x%#x\n", (unsigned) mbi->boot_device); + + /* Is the command line passed? */ + if (CHECK_FLAG (mbi->flags, 2)) + printf ("cmdline = %s\n", (char *) mbi->cmdline); + + if (CHECK_FLAG (mbi->flags, 3)) { + int mod_count = 0; + int i; + module_t* mod = (module_t*)mbi->mods_addr; + while(mod_count < mbi->mods_count) { + printf("Module %d loaded at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_start); + filestart = mod->mod_start; + printf("Module %d ends at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_end); + printf("First few bytes of module:\n"); + for(i = 0; i<16; i++) { + printf("0x%x ", *((char*)(mod->mod_start+i))); + } + printf("\n"); + mod_count++; + } + } + /* Bits 4 and 5 are mutually exclusive! */ + if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5)) + { + printf ("Both bits 4 and 5 are set.\n"); + return; + } + + /* Is the section header table of ELF valid? */ + if (CHECK_FLAG (mbi->flags, 5)) + { + elf_section_header_table_t *elf_sec = &(mbi->elf_sec); + + printf ("elf_sec: num = %u, size = 0x%#x," + " addr = 0x%#x, shndx = 0x%#x\n", + (unsigned) elf_sec->num, (unsigned) elf_sec->size, + (unsigned) elf_sec->addr, (unsigned) elf_sec->shndx); + } + + /* Are mmap_* valid? */ + if (CHECK_FLAG (mbi->flags, 6)) + { + memory_map_t *mmap; + + printf ("mmap_addr = 0x%#x, mmap_length = 0x%x\n", + (unsigned) mbi->mmap_addr, (unsigned) mbi->mmap_length); + for (mmap = (memory_map_t *) mbi->mmap_addr; + (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length; + mmap = (memory_map_t *) ((unsigned long) mmap + + mmap->size + sizeof (mmap->size))) + printf (" size = 0x%x, base_addr = 0x%#x%#x\n" + " type = 0x%x, length = 0x%#x%#x\n", + (unsigned) mmap->size, + (unsigned) mmap->base_addr_high, + (unsigned) mmap->base_addr_low, + (unsigned) mmap->type, + (unsigned) mmap->length_high, + (unsigned) mmap->length_low); + } + + /* Construct an LDT entry in the GDT */ + { + seg_desc_t the_ldt_desc; + the_ldt_desc.granularity = 0; + the_ldt_desc.opsize = 1; + the_ldt_desc.reserved = 0; + the_ldt_desc.avail = 0; + the_ldt_desc.present = 1; + the_ldt_desc.dpl = 0x0; + the_ldt_desc.sys = 0; + the_ldt_desc.type = 0x2; + + SET_LDT_PARAMS(the_ldt_desc, &ldt, ldt_size); + ldt_desc_ptr = the_ldt_desc; + lldt(KERNEL_LDT); + } + + /* Construct a TSS entry in the GDT */ + { + seg_desc_t the_tss_desc; + the_tss_desc.granularity = 0; + the_tss_desc.opsize = 0; + the_tss_desc.reserved = 0; + the_tss_desc.avail = 0; + the_tss_desc.seg_lim_19_16 = TSS_SIZE & 0x000F0000; + the_tss_desc.present = 1; + the_tss_desc.dpl = 0x0; + the_tss_desc.sys = 0; + the_tss_desc.type = 0x9; + the_tss_desc.seg_lim_15_00 = TSS_SIZE & 0x0000FFFF; + + SET_TSS_PARAMS(the_tss_desc, &tss, tss_size); + + tss_desc_ptr = the_tss_desc; + + tss.ldt_segment_selector = KERNEL_LDT; + tss.ss0 = KERNEL_DS; + tss.esp0 = 0x800000; + ltr(KERNEL_TSS); + } + //Initialization of IDE + { + printf("Initilization of Idt table..."); + set_trap_gate(0,divide_error); + set_trap_gate(1,debug); + set_intr_gate(2,nmi); + set_system_intr_gate(3,int3); + set_system_gate(4,overflow); + set_system_gate(5,bounds); + set_trap_gate(6,invalid_op); + set_trap_gate(7,device_not_available); + set_task_gate(8,31); + set_trap_gate(9,coprocessor_segment_overrun); + set_trap_gate(10,invalid_TSS); + set_trap_gate(11,segment_not_present); + set_trap_gate(12,stack_segment); + set_trap_gate(13,general_protection); + set_trap_gate(14,page_fault);//intr + set_trap_gate(16,coprocessor_error); + set_trap_gate(17,alignment_check); + set_trap_gate(18,machine_check); + set_trap_gate(19,simd_coprocessor_error); + set_system_gate(128,system_call); + set_intr_gate(32,irq0); //intr + set_intr_gate(33,irq1); //intr + set_intr_gate(34,0); //intr + set_intr_gate(40,irq8); //intr + //set_intr_gate(44,irq12); //intr + lidt(idt_desc_ptr); + printf("ok!\n"); + } + + // Init the PIC + i8259_init(); + + //Enable interrupts + + + enable_irq(1); + enable_irq(2); + open_rtc(); + enable_irq(8); + enable_irq(12); + + uint8_t file =0x00; + + //Enable paging + printf("Enabling paging...\n"); + paging(); + printf("ok!\n"); + + //Restore interrupts + sti(); + + //Mounting file system + printf("Mounting filesystem...\n"); + open_terminal(&file); + setstart(filestart); + printf("ok!\n"); + + //clear(); + //Executing first program shell + uint8_t cmd[10]={"shell "}; +#if debug_by_showing_dentries +test_dentries(); +while(1); +#endif + + test_system_call((int32_t)cmd, NULL, 0, 2); + + asm volatile(".1: hlt; jmp .1;"); +} + diff --git a/kernel.o b/kernel.o new file mode 100644 index 0000000..b992ed7 Binary files /dev/null and b/kernel.o differ diff --git a/lib.c b/lib.c new file mode 100644 index 0000000..027b2de --- /dev/null +++ b/lib.c @@ -0,0 +1,832 @@ +/* lib.c - Some basic library functions (printf, strlen, etc.) + * vim:ts=4 noexpandtab + */ + +#include "lib.h" +#define VIDEO 0xB8000 +#define NUM_COLS 80 +#define NUM_ROWS 25 +#define ATTRIB 0x7 +#define screen_width 79 +#include "task.h" + + +extern volatile uint32_t cur_terminal; +extern volatile uint32_t alt_terminal; +extern volatile uint32_t system_init_flag; +int screen_x[NUM_TERMINAL]; +int screen_y[NUM_TERMINAL]; +static char* video_mem = (char *)VIDEO; + + /*dir + * Description: update the position by direction + * Input: --dd: scanned value for direction + * Output: N/A + * Return value: N/A + * Side effect: update the screen coordinates + */ +void dir(unsigned char dd) +{ + switch(dd) + { + // up + case 0x48: if(screen_y[cur_terminal]!=0) screen_y[cur_terminal]--; break; + // left + case 0x4B: if(screen_x[cur_terminal]!=0) screen_x[cur_terminal]--; update_cursor(screen_y[alt_terminal], screen_x[alt_terminal]);break; + // down + case 0x50: screen_y[cur_terminal]++; break; + // right + case 0x4D: if(screen_x[cur_terminal]=79) + { + // set it to 0 + screen_x[cur_terminal]=0; + // update the y coordinate + screen_y[cur_terminal]++; + } + +} + + + /*scroll + * Description: scroll the screen + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: update the video mem + */ + +void scroll(void) +{ + int32_t i; + + video_mem=(char *)VIDEO; + for(i=NUM_COLS; i< (NUM_ROWS*NUM_COLS-NUM_COLS); i++) { + // if it does not reach the bottom line, shift the video mem + *(uint8_t *)(video_mem + (i << 1)) = *(uint8_t *)(video_mem + ((i+NUM_COLS)<< 1)); + // also the content of color + *(uint8_t *)(video_mem + (i << 1) + 1) = *(uint8_t *)(video_mem + ((i+NUM_COLS)<< 1)+1);; + } + //if it reaches the bottom line + for(i=(NUM_ROWS*NUM_COLS-NUM_COLS); i< (NUM_ROWS*NUM_COLS); i++) { + // replace with space + *(uint8_t *)(video_mem + (i << 1)) = ' '; + // as well as the color + *(uint8_t *)(video_mem + (i << 1) + 1) = ATTRIB;; + } + + + screen_x[cur_terminal] = 0; + screen_y[cur_terminal]= NUM_ROWS - 1; + +} + /*clear + * Description: clear the screen + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: update the video mem + */ +void +clear(void) +{ + int32_t i; + + video_mem=(char *)VIDEO; + // fill every pixel in the terminal with space + for(i=NUM_COLS; i= 24) + { + for(i=NUM_COLS; i< (NUM_ROWS*NUM_COLS-NUM_COLS); i++) { + + *(uint8_t *)(VIDEO + (i << 1)) = *(uint8_t *)(VIDEO+ ((i+NUM_COLS)<< 1)); + *(uint8_t *)(VIDEO+ (i << 1) + 1) = *(uint8_t *)(VIDEO+ ((i+NUM_COLS)<< 1)+1);; + } + for(i=(NUM_ROWS*NUM_COLS-NUM_COLS); i< (NUM_ROWS*NUM_COLS); i++) { + *(uint8_t *)(VIDEO+ (i << 1)) = ' '; + *(uint8_t *)(VIDEO + (i << 1) + 1) = ATTRIB; + } + screen_x[cur_terminal] =0; + screen_y[cur_terminal] =23; + } + } + else + { + if(screen_x[cur_terminal]>=79) + { + screen_x[cur_terminal]=0; + screen_y[cur_terminal]++; + } + *(uint8_t *)(video_mem + ((NUM_COLS*screen_y[cur_terminal] + screen_x[cur_terminal]) << 1)) = c; + *(uint8_t *)(video_mem + ((NUM_COLS*screen_y[cur_terminal] + screen_x[cur_terminal]) << 1) + 1) = ATTRIB; + screen_x[cur_terminal]++; + screen_x[cur_terminal] %= NUM_COLS; + if(screen_y[cur_terminal] >= 24) + { + for(i=NUM_COLS; i< (NUM_ROWS*NUM_COLS-NUM_COLS); i++) { + + *(uint8_t *)(VIDEO + (i << 1)) = *(uint8_t *)(VIDEO+ ((i+NUM_COLS)<< 1)); + *(uint8_t *)(VIDEO+ (i << 1) + 1) = *(uint8_t *)(VIDEO+ ((i+NUM_COLS)<< 1)+1);; + } + for(i=(NUM_ROWS*NUM_COLS-NUM_COLS); i< (NUM_ROWS*NUM_COLS); i++) { + *(uint8_t *)(VIDEO+ (i << 1)) = ' '; + *(uint8_t *)(VIDEO + (i << 1) + 1) = ATTRIB; + } + screen_x[cur_terminal] =0; + screen_y[cur_terminal] =23; + } + } + +if(system_init_flag) + if(cur_terminal == alt_terminal) + { + // *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + ((NUM_COLS*screen_y[cur_terminal] + screen_x[cur_terminal]) << 1)) = c; + // *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + ((NUM_COLS*screen_y[cur_terminal] + screen_x[cur_terminal]) << 1) + 1) = ATTRIB; + memcpy((char *)VIDEO+(alt_terminal+1)*size_of_vmem ,(char *)VIDEO, size_of_vmem); + update_cursor(screen_y[alt_terminal], screen_x[alt_terminal]); + } + + +} + +/* Convert a number to its ASCII representation, with base "radix" */ +int8_t* +itoa(uint32_t value, int8_t* buf, int32_t radix) +{ + static int8_t lookup[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + int8_t *newbuf = buf; + int32_t i; + uint32_t newval = value; + + /* Special case for zero */ + if(value == 0) { + buf[0]='0'; + buf[1]='\0'; + return buf; + } + + /* Go through the number one place value at a time, and add the + * correct digit to "newbuf". We actually add characters to the + * ASCII string from lowest place value to highest, which is the + * opposite of how the number should be printed. We'll reverse the + * characters later. */ + while(newval > 0) { + i = newval % radix; + *newbuf = lookup[i]; + newbuf++; + newval /= radix; + } + + /* Add a terminating NULL */ + *newbuf = '\0'; + + /* Reverse the string and return */ + return strrev(buf); +} + +/* In-place string reversal */ +int8_t* +strrev(int8_t* s) +{ + register int8_t tmp; + register int32_t beg=0; + register int32_t end=strlen(s) - 1; + + while(beg < end) { + tmp = s[end]; + s[end] = s[beg]; + s[beg] = tmp; + beg++; + end--; + } + + return s; +} + +/* String length */ +uint32_t +strlen(const int8_t* s) +{ + register uint32_t len = 0; + while(s[len] != '\0') + len++; + + return len; +} + +/* Optimized memset */ +void* +memset(void* s, int32_t c, uint32_t n) +{ + c &= 0xFF; + asm volatile(" \n\ + .memset_top: \n\ + testl %%ecx, %%ecx \n\ + jz .memset_done \n\ + testl $0x3, %%edi \n\ + jz .memset_aligned \n\ + movb %%al, (%%edi) \n\ + addl $1, %%edi \n\ + subl $1, %%ecx \n\ + jmp .memset_top \n\ + .memset_aligned: \n\ + movw %%ds, %%dx \n\ + movw %%dx, %%es \n\ + movl %%ecx, %%edx \n\ + shrl $2, %%ecx \n\ + andl $0x3, %%edx \n\ + cld \n\ + rep stosl \n\ + .memset_bottom: \n\ + testl %%edx, %%edx \n\ + jz .memset_done \n\ + movb %%al, (%%edi) \n\ + addl $1, %%edi \n\ + subl $1, %%edx \n\ + jmp .memset_bottom \n\ + .memset_done: \n\ + " + : + : "a"(c << 24 | c << 16 | c << 8 | c), "D"(s), "c"(n) + : "edx", "memory", "cc" + ); + + return s; +} + +/* Optimized memset_word */ +void* +memset_word(void* s, int32_t c, uint32_t n) +{ + asm volatile(" \n\ + movw %%ds, %%dx \n\ + movw %%dx, %%es \n\ + cld \n\ + rep stosw \n\ + " + : + : "a"(c), "D"(s), "c"(n) + : "edx", "memory", "cc" + ); + + return s; +} + +/* Optimized memset_dword */ +void* +memset_dword(void* s, int32_t c, uint32_t n) +{ + asm volatile(" \n\ + movw %%ds, %%dx \n\ + movw %%dx, %%es \n\ + cld \n\ + rep stosl \n\ + " + : + : "a"(c), "D"(s), "c"(n) + : "edx", "memory", "cc" + ); + + return s; +} + +/* Optimized memcpy */ +void* +memcpy(void* dest, const void* src, uint32_t n) +{ + asm volatile(" \n\ + .memcpy_top: \n\ + testl %%ecx, %%ecx \n\ + jz .memcpy_done \n\ + testl $0x3, %%edi \n\ + jz .memcpy_aligned \n\ + movb (%%esi), %%al \n\ + movb %%al, (%%edi) \n\ + addl $1, %%edi \n\ + addl $1, %%esi \n\ + subl $1, %%ecx \n\ + jmp .memcpy_top \n\ + .memcpy_aligned: \n\ + movw %%ds, %%dx \n\ + movw %%dx, %%es \n\ + movl %%ecx, %%edx \n\ + shrl $2, %%ecx \n\ + andl $0x3, %%edx \n\ + cld \n\ + rep movsl \n\ + .memcpy_bottom: \n\ + testl %%edx, %%edx \n\ + jz .memcpy_done \n\ + movb (%%esi), %%al \n\ + movb %%al, (%%edi) \n\ + addl $1, %%edi \n\ + addl $1, %%esi \n\ + subl $1, %%edx \n\ + jmp .memcpy_bottom \n\ + .memcpy_done: \n\ + " + : + : "S"(src), "D"(dest), "c"(n) + : "eax", "edx", "memory", "cc" + ); + + return dest; +} + +/* Optimized memmove (used for overlapping memory areas) */ +void* +memmove(void* dest, const void* src, uint32_t n) +{ + asm volatile(" \n\ + movw %%ds, %%dx \n\ + movw %%dx, %%es \n\ + cld \n\ + cmp %%edi, %%esi \n\ + jae .memmove_go \n\ + leal -1(%%esi, %%ecx), %%esi \n\ + leal -1(%%edi, %%ecx), %%edi \n\ + std \n\ + .memmove_go: \n\ + rep movsb \n\ + " + : + : "D"(dest), "S"(src), "c"(n) + : "edx", "memory", "cc" + ); + + return dest; +} + +/* Standard strncmp */ +int32_t +strncmp(const int8_t* s1, const int8_t* s2, uint32_t n) +{ + int32_t i; + for(i=0; i>8)&0xFF), 0x3D5); + } + /*statusbar + * Description: display status + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: modify the video mem + */ + void statusbar(void) +{ + int i,j; + uint8_t text[] = "terminal IOTA OS "; + text[9] = (uint8_t) 49; + //mapping the video mem from text + video_mem=(char *)VIDEO; + for(i=0; i< 80 ; i++) { + + *(uint8_t *)(video_mem + (i << 1)) = text[i]; + *(uint8_t *)(video_mem + (i << 1) + 1) = 0x3 | 0x80; + } + + + for(j =0; j< NUM_TERMINAL; j++) + { + // text[9] indicating the terminal number + text[9] = (uint8_t) j + 49; + video_mem=(char *)VIDEO+(j+1)*size_of_vmem; + for(i=0; i< 80 ; i++) { + // the video mem will never interact with alt_terminal. + *(uint8_t *)(video_mem + (i << 1)) = text[i]; + *(uint8_t *)(video_mem + (i << 1) + 1) = 0x3 | (0x80 + 0x10*j); + } + screen_x[j]=0; + screen_y[j]=1; + } + + +} + /*putcur + * Description: print current terminal to the screen + * Input: --c: command + * Output: N/A + * Return value: N/A + * Side effect: N/A + */ +void putcur(char c) +{ + + int32_t i; + if(c == '\n' || c == '\r') {//change line + screen_y[alt_terminal]++; + screen_x[alt_terminal]=0; + if(screen_y[alt_terminal] >= 24)//scolling + { + for(i=NUM_COLS; i< (NUM_ROWS*NUM_COLS-NUM_COLS); i++) { + + *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + (i << 1)) = *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + ((i+NUM_COLS)<< 1)); + *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + (i << 1) + 1) = *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + ((i+NUM_COLS)<< 1)+1);; + } + for(i=(NUM_ROWS*NUM_COLS-NUM_COLS); i< (NUM_ROWS*NUM_COLS); i++) { + *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + (i << 1)) = ' '; + *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + (i << 1) + 1) = ATTRIB; + } + screen_x[alt_terminal] =0; + screen_y[alt_terminal] =23; + } + + } + else + { + if(screen_x[alt_terminal]>=79) + { + screen_x[alt_terminal]=0; + screen_y[alt_terminal]++; + } + //put to alt video memeory + *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + ((NUM_COLS*screen_y[alt_terminal] + screen_x[alt_terminal]) << 1)) = c; + *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + ((NUM_COLS*screen_y[alt_terminal] + screen_x[alt_terminal]) << 1) + 1) = ATTRIB; + screen_x[alt_terminal] ++; + screen_x[alt_terminal] %= NUM_COLS; + if(screen_y[alt_terminal] >= 24)//scolling + { + for(i=NUM_COLS; i< (NUM_ROWS*NUM_COLS-NUM_COLS); i++) { + + *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + (i << 1)) = *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + ((i+NUM_COLS)<< 1)); + *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + (i << 1) + 1) = *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + ((i+NUM_COLS)<< 1)+1);; + } + for(i=(NUM_ROWS*NUM_COLS-NUM_COLS); i< (NUM_ROWS*NUM_COLS); i++) { + *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + (i << 1)) = ' '; + *(uint8_t *)(VIDEO+(alt_terminal+1)*size_of_vmem + (i << 1) + 1) = ATTRIB; + } + screen_x[alt_terminal] =0; + screen_y[alt_terminal] =23; + } + } + update_cursor(screen_y[alt_terminal], screen_x[alt_terminal]); + +} + + + /*putcur + * Description: put a string to the alt_terminal + * Input: --buff: buffer stored the string + * Output: increment index + * Return value: N/A + * Side effect: N/A + */ +void +printscur( char * buff) +{ + register int32_t index = 0; + while(buff[index] != '\0') { + //if not reach the end, print the char. + putcur(buff[index]); + // increment the index + index++; + } +} + diff --git a/lib.h b/lib.h new file mode 100644 index 0000000..fb118c9 --- /dev/null +++ b/lib.h @@ -0,0 +1,161 @@ +/* lib.h - Defines for useful library functions + * vim:ts=4 noexpandtab + */ + +#ifndef _LIB_H +#define _LIB_H + +#include "types.h" +#include "task.h" +int32_t printf(int8_t *format, ...); +void putc(uint8_t c); +int32_t puts(int8_t *s); +int8_t *itoa(uint32_t value, int8_t* buf, int32_t radix); +int8_t *strrev(int8_t* s); +uint32_t strlen(const int8_t* s); +void clear(void); +extern void test_interrupts(void); + +extern void printscur( char * buff); + +extern void putcur(char c); +extern void statusbar(void); +extern void bksp(void); +extern void bksp_t(void); +extern void up_screen(void); +extern void dir(unsigned char dd); +extern void screen_ptr(int x, int y); +extern int gety(void); +extern int getx(void); +extern void scroll(void); +extern void update_cursor(int row, int col); +extern int screen_x[NUM_TERMINAL]; +extern int screen_y[NUM_TERMINAL]; +void* memset(void* s, int32_t c, uint32_t n); +void* memset_word(void* s, int32_t c, uint32_t n); +void* memset_dword(void* s, int32_t c, uint32_t n); +void* memcpy(void* dest, const void* src, uint32_t n); +void* memmove(void* dest, const void* src, uint32_t n); +int32_t strncmp(const int8_t* s1, const int8_t* s2, uint32_t n); +int8_t* strcpy(int8_t* dest, const int8_t*src); +int8_t* strncpy(int8_t* dest, const int8_t*src, uint32_t n); + +/* Userspace address-check functions */ +int32_t bad_userspace_addr(const void* addr, int32_t len); +int32_t safe_strncpy(int8_t* dest, const int8_t* src, int32_t n); + +/* Port read functions */ +/* Inb reads a byte and returns its value as a zero-extended 32-bit + * unsigned int */ +static inline uint32_t inb(port) +{ + uint32_t val; + asm volatile("xorl %0, %0\n \ + inb (%w1), %b0" + : "=a"(val) + : "d"(port) + : "memory" ); + return val; +} + +/* Reads two bytes from two consecutive ports, starting at "port", + * concatenates them little-endian style, and returns them zero-extended + * */ +static inline uint32_t inw(port) +{ + uint32_t val; + asm volatile("xorl %0, %0\n \ + inw (%w1), %w0" + : "=a"(val) + : "d"(port) + : "memory" ); + return val; +} + +/* Reads four bytes from four consecutive ports, starting at "port", + * concatenates them little-endian style, and returns them */ +static inline uint32_t inl(port) +{ + uint32_t val; + asm volatile("inl (%w1), %0" + : "=a"(val) + : "d"(port) + : "memory" ); + return val; +} + +/* Writes a byte to a port */ +#define outb(data, port) \ +do { \ + asm volatile("outb %b1, (%w0)" \ + : \ + : "d" (port), "a" (data) \ + : "memory", "cc" ); \ +} while(0) + +/* Writes two bytes to two consecutive ports */ +#define outw(data, port) \ +do { \ + asm volatile("outw %w1, (%w0)" \ + : \ + : "d" (port), "a" (data) \ + : "memory", "cc" ); \ +} while(0) + +/* Writes four bytes to four consecutive ports */ +#define outl(data, port) \ +do { \ + asm volatile("outl %l1, (%w0)" \ + : \ + : "d" (port), "a" (data) \ + : "memory", "cc" ); \ +} while(0) + +/* Clear interrupt flag - disables interrupts on this processor */ +#define cli() \ +do { \ + asm volatile("cli" \ + : \ + : \ + : "memory", "cc" \ + ); \ +} while(0) + +/* Save flags and then clear interrupt flag + * Saves the EFLAGS register into the variable "flags", and then + * disables interrupts on this processor */ +#define cli_and_save(flags) \ +do { \ + asm volatile("pushfl \n \ + popl %0 \n \ + cli" \ + : "=r"(flags) \ + : \ + : "memory", "cc" \ + ); \ +} while(0) + +/* Set interrupt flag - enable interrupts on this processor */ +#define sti() \ +do { \ + asm volatile("sti" \ + : \ + : \ + : "memory", "cc" \ + ); \ +} while(0) + +/* Restore flags + * Puts the value in "flags" into the EFLAGS register. Most often used + * after a cli_and_save_flags(flags) */ +#define restore_flags(flags) \ +do { \ + asm volatile("pushl %0 \n \ + popfl" \ + : \ + : "r"(flags) \ + : "memory", "cc" \ + ); \ +} while(0) + +#endif /* _LIB_H */ diff --git a/lib.o b/lib.o new file mode 100644 index 0000000..43b285b Binary files /dev/null and b/lib.o differ diff --git a/mp3.img b/mp3.img new file mode 100644 index 0000000..f920f26 Binary files /dev/null and b/mp3.img differ diff --git a/multiboot.h b/multiboot.h new file mode 100644 index 0000000..b07b87c --- /dev/null +++ b/multiboot.h @@ -0,0 +1,76 @@ +/* multiboot.h - Defines used in working with Multiboot-compliant + * bootloaders (such as GRUB) + * vim:ts=4 noexpandtab + */ + +#ifndef _MULTIBOOT_H +#define _MULTIBOOT_H + +#define MULTIBOOT_HEADER_FLAGS 0x00000003 +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +#ifndef ASM + +/* Types */ +#include "types.h" + +/* The Multiboot header. */ +typedef struct multiboot_header +{ + uint32_t magic; + uint32_t flags; + uint32_t checksum; + uint32_t header_addr; + uint32_t load_addr; + uint32_t load_end_addr; + uint32_t bss_end_addr; + uint32_t entry_addr; +} multiboot_header_t; + +/* The section header table for ELF. */ +typedef struct elf_section_header_table +{ + uint32_t num; + uint32_t size; + uint32_t addr; + uint32_t shndx; +} elf_section_header_table_t; + +/* The Multiboot information. */ +typedef struct multiboot_info +{ + uint32_t flags; + uint32_t mem_lower; + uint32_t mem_upper; + uint32_t boot_device; + uint32_t cmdline; + uint32_t mods_count; + uint32_t mods_addr; + elf_section_header_table_t elf_sec; + uint32_t mmap_length; + uint32_t mmap_addr; +} multiboot_info_t; + +typedef struct module { + uint32_t mod_start; + uint32_t mod_end; + uint32_t string; + uint32_t reserved; +} module_t; + +/* The memory map. Be careful that the offset 0 is base_addr_low + but no size. */ +typedef struct memory_map +{ + uint32_t size; + uint32_t base_addr_low; + uint32_t base_addr_high; + uint32_t length_low; + uint32_t length_high; + uint32_t type; +} memory_map_t; + +#endif /* ASM */ + +#endif /* _MULTIBOOT_H */ diff --git a/page.S b/page.S new file mode 100644 index 0000000..02736ff --- /dev/null +++ b/page.S @@ -0,0 +1,196 @@ +.text +.global paging +.global user_space_alloc +.global flush_tlb +.global user_page_mapper_4K +.global user_page_mapper_4M +#|-----------------------------------Glabal Parameters-----------------------------------------| +Kernel: +.long 0x00400000 #virtual addr of kernel +Program_img: +.long 0x08000000 #virtual addr of program img +Program_phys: #physical addr of program img +.long 0x00800000 +Video_mem: +.long 0x000B8000 #virtual addr of video mem +#|--------------------------------Allocate local static physical memory -----------------------| + +.align 4096 +_PageDir: +PageDir: +.rept 1024 +.long 0 +.endr + +.align 4096 +_PageTbl: +PageTbl: +.rept 1024 +.long 0 +.endr + +#|--------------------------------End of allocation of memory --- -----------------------------| +# void paging:(void); +# Description: allocate page for the system +# Interface : Register-based arguments (not C-style) +# Inputs : Program_img +# Program_phys +# Video_mem +# PageDir +# PageTbl +# Outputs : dynamically allocated page in virtual memory +# Registers: gs,fs,es,ds,eax,esp,ebp,edi,esi,edx,ecx,ebx +paging: +pushl %ebp #construct a stack +movl %esp, %ebp +pushl %edi +pushl %ebx +pushl %eax + +init_ker: +movl Kernel,%ebx #fetch data +movl %ebx,%eax #prepare the entry +shrl $22,%ebx #get index of page dir(higher bits) +andl $0xFFC00000,%eax #get to-be-written physaddr bits 31-22,16-13 +orl $0x085, %eax #set U/S(bit 2),R/W(bit 1),P(bit 0) and PSE(bit 7) +leal PageDir,%edi #load page dir +movl %eax,(%edi,%ebx,4) #build the entry + + + +#|-------------------------------Initialize video mem------------------------------------------| +init_vmem: +movl Video_mem,%ebx #fetch data +movl %ebx,%eax #prepare the entry +shrl $22,%ebx #get index of page dir(higher bits) +xorl %eax, %eax #entry for dir +orl $0x07, %eax #set U/S(bit 2),R/W(bit 1),P(bit 0) +leal PageTbl,%edi #get the page table +orl %edi,%eax #load the table +leal PageDir,%edi #load page dir +movl %eax,(%edi,%ebx,4) #build the entry + +movl Video_mem,%ebx #fetch data +movl %ebx,%eax #prepare the entry +shrl $12,%ebx #get index of page dir(higher bits) +andl $0x000003FF,%ebx #get the lower bits as indes of page table +andl $0x003FF000,%eax #the page physical addr's higher bits +orl $0x07,%eax #set U/S(bit 2),R/W(bit 1),P(bit 0) +leal PageTbl,%edi #load page dir +movl %eax,(%edi,%ebx,4) #build the entry + +# -------------------------------------Load Regs------------------------------------------------ +init_cr3: +leal PageDir ,%eax +andl $0xfffff000,%eax +movl %cr3, %ebx +andl $0x00000fff,%ebx +orl %eax, %ebx +movl %ebx,%cr3 + +init_cr4: +movl %cr4, %eax +orl $0x00000010,%eax +movl %eax, %cr4 + +init_cr0: +movl %cr0, %eax +orl $0x80000001,%eax +movl %eax, %cr0 + +# -------------------------------------Load Regs------------------------------------------------ +popl %eax #tear down stacks +popl %ebx +popl %edi +leave +ret + +# -------------------------------------User spac------------------------------------------------ +# void user_space_alloc:(void); +# Description: allocate page for the system +# Interface : Register-based arguments (not C-style) +# Inputs : none +# Outputs : allocate spaces for user space +# Registers: gs,fs,es,ds,eax,esp,ebp,edi,esi,edx,ecx,ebx +user_space_alloc: +pushl %ebp #construct a stack +movl %esp, %ebp +pushl %edi +pushl %ebx +pushl %eax +movl Program_img,%ebx #fetch vitual +movl Program_phys,%eax #prepare the entry physical +movl 8(%ebp),%edi #get parameter +addl %edi,%eax #8MB+4MB*user_space_alloc +shrl $22,%ebx #get index of page dir(higher bits) +andl $0xFFC00000,%eax #get higher physaddr bits after masked +orl $0x087, %eax #set U/S(bit 2),R/W(bit 1),P(bit 0) and PSE(bit 7) +leal PageDir,%edi #load page dir +movl %eax,(%edi,%ebx,4) #build the entry +call flush_tlb +popl %eax #tear down stacks +popl %ebx +popl %edi +leave +ret + +#---------------------------------------flush tlb----------------------------------------------- +flush_tlb: +pushl %ebp #construct a stack +movl %esp, %ebp +pushl %eax +movl %cr3,%eax +movl %eax,%cr3 +popl %eax +leave +ret + +#---------------------------------------4kb page_mapper----------------------------------------- +user_page_mapper_4K: +pushl %ebp #construct a stack +movl %esp, %ebp +pushl %edi +pushl %ebx +pushl %eax +movl 8(%ebp),%ebx #fetch vitual +shrl $22,%ebx #get index of page dir(higher bits) +xorl %eax, %eax #entry for dir +orl $0x07, %eax #set U/S(bit 2),R/W(bit 1),P(bit 0) +leal PageTbl,%edi #get the page table +orl %edi,%eax #load the table +leal PageDir,%edi #load page dir +movl %eax,(%edi,%ebx,4) #build the entry +movl 8(%ebp),%ebx #fetch vitual +movl 12(%ebp),%eax #prepare the entry +shrl $12,%ebx #get index of page dir(higher bits) +andl $0x000003FF,%ebx #get the lower bits as indes of page table +andl $0x003FF000,%eax #the page physical addr's higher bits +orl $0x07,%eax #set U/S(bit 2),R/W(bit 1),P(bit 0) +leal PageTbl,%edi #load page dir +movl %eax,(%edi,%ebx,4) #build the entry +call flush_tlb #flush_tlb +popl %eax #tear down stacks +popl %ebx +popl %edi +leave +ret +#---------------------------------------4Mb page_mapper----------------------------------------- +user_page_mapper_4M: +pushl %ebp #construct a stack +movl %esp, %ebp +pushl %edi +pushl %ebx +pushl %eax +movl 8(%ebp),%ebx #fetch vitual +movl 12(%ebp),%eax #prepare the entry physical +shrl $22,%ebx #get index of page dir(higher bits) +andl $0xFFC00000,%eax #get higher physaddr bits after masked +orl $0x087, %eax #set U/S(bit 2),R/W(bit 1),P(bit 0) and PSE(bit 7) +leal PageDir,%edi #load page dir +movl %eax,(%edi,%ebx,4) #build the entry +call flush_tlb +popl %eax #tear down stacks +popl %ebx +popl %edi +leave +ret diff --git a/page.h b/page.h new file mode 100644 index 0000000..0d493b6 --- /dev/null +++ b/page.h @@ -0,0 +1,45 @@ +#ifndef _PAGE_H +#define _PAGE_H +#include "types.h" +#define fourmb 0x0400000 + +#define CreateNewPageTable(name) \ +ALIGN 4096;\ +name: \ +.rept 1024\ +.long 0\ +.endr\ + + +extern void paging(void); +extern __attribute__((regparm(0))) void user_space_alloc(uint32_t pid_4mb); +extern void flush_tlb(void); +//////////////////////////////////////////////////////////////MUST READ THE COMMENT!!!!!!////////////////////////////////////////////////// + +//Cannot map many 1 virtual page to many physical page at the same time, but can map many 1 physical page to virtual page at the same time +//UNSAFE function: +//would raise fatal fault when mapping to vir_addr(This can hardly be fixed): +//0x00400000~0x007FFFFF; +//0x08000000~0x083FFFFF; +// +//Essentially: +//IT ONLY WORKS FOR virtual address(This can be fixed by entroducing new Page Table): +//0x00000000~0x003FFFFF +extern __attribute__((regparm(0))) void user_page_mapper_4K(uint32_t vir_addr,uint32_t phys_addr); +//UNSAFE function: +//would raise fatal fault when mapping to vir_addr(This can hardly be fixed): +//0x00000000~0x003FFFFF; +// +//Essentially: +//IT ONLY WORKS FOR virtual address +//0x00400000~0x007FFFFF;0x08000000~0x083FFFFF +//which is already allocated (therefore useless)(This can be fixed by entroducing new Page Table) +//Therefore this function is completely useless and should never be used. +extern __attribute__((regparm(0))) void user_page_mapper_4M(uint32_t vir_addr,uint32_t phys_addr); + +#endif + + + + + diff --git a/page.o b/page.o new file mode 100644 index 0000000..fd2aabf Binary files /dev/null and b/page.o differ diff --git a/rtc.c b/rtc.c new file mode 100644 index 0000000..e822969 --- /dev/null +++ b/rtc.c @@ -0,0 +1,156 @@ +#include "rtc.h" +#include "lib.h" +#define debug_read_rtc 0 +#include "task.h" +static int getrate(int f); +static volatile int itr_flag[NUM_TERMINAL]={0}; +extern volatile uint32_t cur_terminal; +extern volatile uint32_t alt_terminal; + +/* + * open_rtc + * Description: turn on the IRQ8 + * INPUTS: none + * OUTPUTS: reset register A + * RETURN VALUE: none + * SIDE EFFECTS: none + */ +void +open_rtc(void) +{ + +//setting up the +outb(0x0B, 0x70); +/* Read the current value of register*/ +char x = inb(0x71); +x |= 0x40; +/* Set the index again*/ +outb(0x0B, 0x70); +/* Write the previous value*/ +outb(x, 0x71); +/* Set the default frequency*/ +write_rtc(2); +} + +/* + * read_rtc + * Description: check if the rtc is currently working + * INPUTS: none + * OUTPUTS: reset the itr_flag to 0 + * RETURN VALUE: 0 for success and -1 for failure + * SIDE EFFECTS: none + */ +int read_rtc(void) +{ +#if debug_read_rtc +printf("rtc in\n"); +#endif + +while(itr_flag[cur_terminal]==0); +itr_flag[cur_terminal]=0; +#if debug_read_rtc +printf("rtc out\n"); +#endif +return 0; +} +/* + * happen + * Description: set the interrupt + * INPUTS: none + * OUTPUTS: none + * RETURN VALUE: none + * SIDE EFFECTS: none + */ +void +happen(void) +{ +itr_flag[cur_terminal]=1; +} +/* + * write_rtc + * Description: write the frequency into the register A + * INPUTS: freq -- the frequency + * OUTPUTS: none + * RETURN VALUE: 0 for success and -1 for failure + * SIDE EFFECTS: none + */ + +int write_rtc(int freq) +{ +int rate; +rate=getrate(freq*4); +if(rate==-1) return -1; +rate &= 0x0F; /* Ensure that rate must be above 2 and not over 15*/ +outb(0x0A, 0x70); /* Set index to register A*/ +char prev=inb(0x71); /* Get initial value of register A*/ +outb(0x0A, 0x70); /* Reset index to A*/ +/* Write only our rate to A. Note, rate is the lower 4 bits.*/ +outb((prev&0xF0)|rate, 0x71); +return 0; + +} +/* + * getrate + * Description: change the rate to the desired format + * INPUTS: f -- the frequency + * OUTPUTS: none + * RETURN VALUE: the modified frequency + * SIDE EFFECTS: none + */ + +int getrate(int f) +{ +int rate; +switch(f) +{ +case 2: + rate=0x000F; + break; +case 4: + rate=0x000E; + break; +case 8: + rate=0x000D; + break; + + case 16: + rate=0x000C; + break; +case 32: + rate=0x000B; + break; +case 64: + rate=0x000A; + break; + + case 128: + rate=0x0009; + break; +case 256: + rate=0x0008; + break; +case 512: + rate=0x0007; + break; + +case 1024: + rate=0x0006; + break; +case 2048: + rate=0x0005; + break; +case 4096: + rate=0x0004; + break; +case 8192: + rate=0x0003; + break; + +default: + rate=-1; + +} +return rate; +} + + diff --git a/rtc.h b/rtc.h new file mode 100644 index 0000000..05402bf --- /dev/null +++ b/rtc.h @@ -0,0 +1,17 @@ +/* lib.h - Defines for useful library functions + * vim:ts=4 noexpandtab + */ + +#ifndef _RTC_H +#define _RTC_H +#include "lib.h" + +extern void open_rtc(void); +extern void set_rtc(void); +extern int write_rtc(int fre); +extern int read_rtc(void); +extern void happen(void); + +#endif + + diff --git a/rtc.o b/rtc.o new file mode 100644 index 0000000..c889afa Binary files /dev/null and b/rtc.o differ diff --git a/stub_handler.S b/stub_handler.S new file mode 100644 index 0000000..36666df --- /dev/null +++ b/stub_handler.S @@ -0,0 +1,285 @@ +.text +.global irq0 +.global irq1 +.global irq8 +.global system_call +#-------------------------------------------------------------------------- +#=====stack=====# +# ebx # +# ecx # +# edx # +# esi # +# edi # +# ebp # +# esp # +# eax # +# ds # +# es # +# fs # +# gs # +# int number # +# err code # +# ret addr (p)# +# cs (p)# +# eflags (p)# +# p_esp (p)# +# ss (p)# +#===============# + + + + +# -----------------------------------------------------irq------------------------------------------------------------- +# void irq0:(void); +# Description: do irq0 function call +# Interface : Register-based arguments (not C-style) +# Inputs : push 0, push 0x20 +# Outputs : do irq0 function call +# Registers: +.align 4 +irq0: +pushl $0 #dummy error code +pushl $0x20 #irq_num +jmp common_handler +# void irq1:(void); +# Description: do irq1 function call +# Interface : Register-based arguments (not C-style) +# Inputs : push 0, push 0x21 +# Outputs : do irq1 function call +# Registers: +.align 4 +irq1: +pushl $0 #dummy error code +pushl $0x21 #irq_num +jmp common_handler +# void irq8:(void); +# Description: do irq8 function call +# Interface : Register-based arguments (not C-style) +# Inputs : push 0, push 0x28 +# Outputs : do irq8 function call +# Registers: +.align 4 +irq8: +pushl $0 #dummy error code +pushl $0x28 #irq_num +jmp common_handler + +# -----Context Save (stack bottom is the processor saved context) + +.align 4 +common_handler: +pushl %gs +pushl %fs +pushl %es +pushl %ds +pushl %eax +pushl %esp +pushl %ebp +pushl %edi +pushl %esi +pushl %edx +pushl %ecx +pushl %ebx + +# -----Spare the context info +pushfl +pushl %edx #spare the regs to be used by the system call +pushl %ecx +pushl %ebx +pushl %eax +leal 20(%esp),%eax +pushl %eax #push argument, which is a ptr to the context regs +call save_context_for_terminal_switch #save context +addl $4,%esp #pop argument +popl %eax +popl %ebx +popl %ecx +popl %edx +popfl + +# -----Data segment switch to kernel mode +pushl %eax #cs set by idt entry,ss and esp set by tss +movw $0x18,%ax +movw %ax,%ds +movw %ax,%es +movw %ax,%gs +movw %ax,%fs +popl %eax + +# -----Do irq call functions +movl 48(%esp),%eax +call *irq_except_table(,%eax,4) #look up jump table to find desired function + + +# -----Context Restore +popl %ebx #pop regs +popl %ecx +popl %edx +popl %esi +popl %edi +popl %ebp +addl $4,%esp +addl $4,%esp +popl %ds +popl %es +popl %fs +popl %gs +addl $8,%esp #pop arguments +iret + + + +.align 4 +irq_except_table: +#---exceptions--- +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.rept 16 +.long 0 +.endr +#---irqs--- +.long do_irq0 +.long do_irq1 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long do_irq8 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 + + + + +# -----------------------------------------------------system call------------------------------------------------------------- +# void system_call:(void); +# Description: perform system call otherwise returns +# Interface : Register-based arguments (not C-style) +# Inputs : 0x80, init sys call. +# Outputs : jump to the desired function call according +# to jump table, perform kernel/user stack switch +# Registers: gs,fs,es,ds,eax,esp,ebp,edi,esi,edx,ecx,ebx +.align 4 +system_call: +# -----Context Save (stack bottom is the processor saved context) + +cli +cmpl $10,%eax #system service number validity check +jae badsys +pushl $0 #dummy error code +pushl $0x80 +pushl %gs +pushl %fs +pushl %es +pushl %ds +pushl %eax +pushl %esp +pushl %ebp +pushl %edi +pushl %esi +pushl %edx +pushl %ecx +pushl %ebx + + +# -----Spare the context info +pushfl +pushl %edx #spare the regs to be used by the system call +pushl %ecx +pushl %ebx +pushl %eax +leal 20(%esp),%eax +pushl %eax #push argument, which is a ptr to the context regs +call save_context #save context +addl $4,%esp #pop argument +popl %eax +popl %ebx +popl %ecx +popl %edx +popfl + +# -----Data segment switch to kernel mode +pushl %eax #cs set by idt entry,ss and esp set by tss +movw $0x18,%ax #store 0x18 onto the user stack +movw %ax,%ds +movw %ax,%es +movw %ax,%gs +movw %ax,%fs +popl %eax + +# -----Do system call functions +pushl %edx #push arguments +pushl %ecx +pushl %ebx +call *sys_call_table(,%eax,4) #look up jump table to find desired function +popl %ebx +popl %ecx +popl %edx + + +# -----Context Restore +popl %ebx #pop regs +popl %ecx +popl %edx +popl %esi +popl %edi +popl %ebp +addl $4,%esp +addl $4,%esp #update esp +popl %ds +popl %es +popl %fs +popl %gs +addl $8,%esp #pop arguments +iret + +.align 4 +badsys: #bad system call +movl $-1,%eax +iret + +.align 4 +sys_call_table: #jump table +.long do_test +.long do_halt +.long do_execute +.long do_read +.long do_write +.long do_open +.long do_close +.long do_getargs +.long do_vidmap +.long do_set_handler +.long do_sigreturn + + + + + + + + + + + diff --git a/stub_handler.h b/stub_handler.h new file mode 100644 index 0000000..a7a0c68 --- /dev/null +++ b/stub_handler.h @@ -0,0 +1,13 @@ +#ifndef _STUB_HANDLER_H +#define _STUB_HANDLER_H + +#define ENTRY(name) \ +.globl name; \ +ALIGN;\ +name: +extern void irq0(); +extern void irq1(); +extern void irq8(); +extern void system_call(); + +#endif diff --git a/stub_handler.o b/stub_handler.o new file mode 100644 index 0000000..fade950 Binary files /dev/null and b/stub_handler.o differ diff --git a/sys_call.c b/sys_call.c new file mode 100644 index 0000000..bbeb4d0 --- /dev/null +++ b/sys_call.c @@ -0,0 +1,433 @@ +#include "sys_call.h" +#include "file_op_table.h" +#include "rtc.h" +#include "task.h" +#include "file_system.h" +#include "page.h" +#define debug_exec 0 +#define debug_open 0 +#define debug_read 0 +#define debug_write 0 +#define failure_msg_on 0 + +////////////////////////////////////////////////sys_call 0///////////////////////////////////////////////// +/* do_test + * Description: N/A + * Input: N/A + * Output: N/A + * Return value: return 0 + * Side effect: N/A + */ +int32_t +do_test() +{ + return 0; +} + + +////////////////////////////////////////////////sys_call 1///////////////////////////////////////////////// +/* do_halt + * Description: halt the process. + * Input: --status + * Output: N/A + * Return value: remove_pcb function call + * Side effect: N/A + */ +int32_t +do_halt (uint8_t status){ + int32_t i; + + //close all files in current process + for(i=2;i<=7;i++) + do_close(i); + //remove pcb + + return remove_pcb(status); +} + + +////////////////////////////////////////////////sys_call 2///////////////////////////////////////////////// +/* do_execute + * Description: execute other function call by dealing with the file name and rest of the command + * Input: --command: pointer of keyboard input from terminal + * Output: N/A + * Return value: return 0 but should not happen. + * Side effect: get new pcb, set the correct of regs for kenel stack and perform pcb switch func call + * and write the program to the memory. + */ +int32_t +do_execute (const uint8_t* command){ + //notice:interrupt mask?? + uint32_t fd, cmd_index,excutable; + int32_t inode; + uint8_t command_word[COMM_WORD_LENGTH]={0}; + pcb_t* pcb; + + //-------------------------------Before create a process, check if the process is valid---------------- + //Get the length of the command + for( cmd_index = 0; + command[cmd_index] != ' ' && command[cmd_index] != (uint8_t)"\0" && command[cmd_index] != 0; + cmd_index++); + /* If the cmd length is 0, return -1 */ + if(cmd_index == 0) + return -1; + /* Copy the string of command into command_word*/ + strncpy((int8_t*)command_word, (const int8_t*)command, cmd_index); + /* Obtain the inode from the function call*/ + inode = get_inode_by_name(command_word); +#if debug_exec + printf("inode :%x:",inode); +#endif + /* Check if the inode is valid */ + if(inode ==-1) { +#if failure_msg_on + printf("FAIL exec002:do_execute inode returned -1\n",cmd_index); +#endif + return -1;} + /* If the read file system func does not operate properly, return -1*/ + if(read_data(inode,0,(uint8_t *) &excutable, 0x04) == -1 || excutable != 0x464c457f ) + { +#if failure_msg_on + printf("FAIL exec003:program loaded is not executable or read_data failed\n"); +#endif + return -1; + } + //------------------------------Spare info for halt----------------------------------------------------- + + spare_info_for_halt_for_this_pcb(); + + //------------------------------Attempt to get process(If this fail no process will be created---------- + pcb=get_new_pcb(); + /* Check if pcb is valid*/ + if (pcb==NULL) { +#if failure_msg_on + printf("FAIL exec001:do_execute pcb is NULL\n",cmd_index); +#endif + return -1;} + +#if debug_exec + printf("cmd_index %d\n",cmd_index); +#endif + + //Copy the command to the name buffer,probably bug + strncpy((int8_t*)pcb->command_word, (const int8_t*)command_word, cmd_index); + + //Build pcb by storing pcb->arg,probably bug + if(strlen((int8_t*)command) > (cmd_index + 1)) + strncpy((int8_t *)pcb->args, (const int8_t*)command + cmd_index + 1, strlen((int8_t*)command)-cmd_index-1); + +#if debug_exec + printf("enter do_execute done with read by name\n %d cmd: pcb->command_word \%s\ cmb %s\n", inode,pcb->command_word,command); +#endif + + //Check if file is excutable + for( fd = 0; fd<8; fd++) + { + pcb->file_array[fd].flags = 0; + } + + //Stdin,0 for terminal, set the appropriate parameter + pcb->file_array[0].file_operations_pointer = &terminal_type_op; + pcb->file_array[0].inode_pointer = 0; + pcb->file_array[0].file_position =0; + pcb->file_array[0].flags = 1; + + //Stdout, 1 for keyboard, set the appropriate parameter + pcb->file_array[1].file_operations_pointer = &terminal_type_op; + pcb->file_array[1].inode_pointer = 0; + pcb->file_array[1].file_position =0; + pcb->file_array[1].flags = 1; + + //Done kernel stuff. Allocate page for user_used space + __user_space_alloc(pcb); + +#if debug_exec + printf("enter do_execute done copy program to memory\n"); +#endif + + //Write the program to the memory + read_data(inode,0,(uint8_t *)0x08048000, sizeofinode(inode)); +#if debug_exec + printf("enter do_execute done copy program to memory\n"); +#endif + +#if debug_exec + printf("command_word : %s\n" , pcb->command_word); +#endif + +#if debug_exec + printf("first instruction of this program: %x\n" , *(uint32_t *)(pcb->regs.return_addr)); +#endif + + //Get the new eip which is 24-27 bytes as the program entry point + pcb->regs.return_addr=(uint32_t)*(uint32_t *)0x08048018; + + //initialization process + get_inode_init(inode); + + //Switch process, enter the program + switch_pcb(pcb); + + //This return should never happen +return 0; +} + + + + +////////////////////////////////////////////////sys_call 3///////////////////////////////////////////////// +/* do_read + * Description: read the file to the end of the file, or return the line has been terminated + * Input: --fd: index of file array + * --buf: pointer to where to read + * --nbutes: length need to read. + * Output: N/A + * Return value: return the number of bytes read or -1 if failed + * Side effect: N/A + */ +int32_t +do_read (int32_t fd, void* buf, int32_t nbytes){ +#if debug_read + //printf("entering read: %d",fd); +#endif + /* Obtain the current pcb. */ + pcb_t* pcb = get_cur_pcb(); + /* Check the condition of the file.*/ + if(fd >= 8 || buf == NULL || pcb->file_array[fd].flags == 0 || pcb->file_array[fd].file_operations_pointer == NULL||fd==1) +#if failure_msg_on + printf("FAIL read001:failed\n" ); +#endif + return -1; +#if debug_read + int32_t K; + K=((file_type_op_action_t *) (pcb->file_array[fd].file_operations_pointer))-> read((filedescriptor_t*)&pcb->file_array[fd],buf,(uint32_t)nbytes); + printf("read_buf %s\n",buf); +#endif + /* return the number of bytes read. */ + return ((file_type_op_action_t *) (pcb->file_array[fd].file_operations_pointer))-> read((filedescriptor_t*)&pcb->file_array[fd],buf,(uint32_t)nbytes); +} + + + + + +////////////////////////////////////////////////sys_call 4///////////////////////////////////////////////// +/* do_write + * Description: write the data to the terminal or to a device + * Input: --fd: index of file array + * --buf: pointer to where to write + * --nbutes: length need to write. + * Output: N/A + * Return value: return the number of bytes write or -1 if failed + * Side effect: N/A + */ +int32_t +do_write (int32_t fd, const void* buf, int32_t nbytes){ +#if debug_write + printf("entering write %d ",fd); +#endif + /* Obtain the current pcb. */ + pcb_t* pcb = get_cur_pcb(); + /* Check the condition of the file.*/ + if(fd >= 8 || buf == NULL || pcb->file_array[fd].flags == 0 || pcb->file_array[fd].file_operations_pointer == NULL||fd==0) +#if failure_msg_on + printf("FAIL writ001:failed\n" ); +#endif + return -1; + /* return the number of bytes write. */ + return ((file_type_op_action_t *) (pcb->file_array[fd].file_operations_pointer))-> write((filedescriptor_t*)&pcb->file_array[fd],buf,(uint32_t)nbytes); +} + + + + + +////////////////////////////////////////////////sys_call 5///////////////////////////////////////////////// +/* do_open + * Description: provides the access of the file. + * Input: --filename: the file that needs access to + * Output: N/A + * Return value: return the file descriptor index or -1 if failed + * Side effect: N/A + */ +int32_t +do_open (const uint8_t* filename){ + int32_t fd; + dentry_t dentry; + +#if debug_open + printf("filename : %s\n" , filename); +#endif + /* Obtain the dentry by the following func call*/ + read_dentry_by_name(filename,&dentry); +#if debug_open + printf("file read success : %s\n" , filename); +#endif + uint32_t inode = get_inode_by_name((uint8_t*)filename); + /* Obtain the current pcb*/ + pcb_t* pcb = get_cur_pcb(); + + /* Search for the file which is accessible */ + for( fd = 2; fd<8; fd++) + { + if(pcb->file_array[fd].flags == 0) + break; + } + + if(fd == 8) + + { +#if failure_msg_on + printf("FAIL open001:too many opened" ); +#endif + return -1; + + } + /* Set up the file according to dentry type. */ + if(dentry.type == 0) + { + pcb->file_array[fd].file_operations_pointer = &RTC_type_op;//file_type_op table address + pcb->file_array[fd].inode_pointer = 0; + pcb->file_array[fd].file_position = 0; + pcb->file_array[fd].flags = 1; + } + if(dentry.type == 1) + { + pcb->file_array[fd].file_operations_pointer = &directry_type_op;//file_type_op table address + pcb->file_array[fd].inode_pointer = 0; + pcb->file_array[fd].file_position = 0; + pcb->file_array[fd].flags = 1; + } + if(dentry.type == 2) + { + pcb->file_array[fd].file_operations_pointer = &file_type_op;//file_type_op table address + /* For a "file" type, set up the inode obtained from above. */ + pcb->file_array[fd].inode_pointer = inode; + pcb->file_array[fd].file_position = 0; + pcb->file_array[fd].flags = 1; + } +#if debug_open + printf("fd : %d\n" , fd); +#endif + /* Return fd which its file has been set to accesible*/ + return fd; + +} + + + + +////////////////////////////////////////////////sys_call 6///////////////////////////////////////////////// +/* do_close + * Description: set the specific file descriptor's flag and be ready to reopen + * Input: --fd: the specific file descriptor + * Output: N/A + * Return value: return 0 if succeed or -1 if failed + * Side effect: N/A + */ +int32_t +do_close (int32_t fd) +{ + /* Obtain the current pcb */ + pcb_t* pcb = get_cur_pcb(); + if(fd >= 8 || fd <2) { +#if failure_msg_on + printf("do_close invalid fd\n" ); +#endif + return -1;} + /*Set the position to 0 as well as the flag*/ + pcb->file_array[fd].file_position = 0; + pcb->file_array[fd].flags = 0; + return 0; +} + + + +////////////////////////////////////////////////sys_call 7///////////////////////////////////////////////// +/* do_getargs + * Description: get the args from the command line except the first word and store them into the buffer + * Input: --buf: the buffer which store the data from command line + * --nbytes: the length of the bytes that needs to store + * Output: N/A + * Return value: return 0 if succeed or -1 if failed + * Side effect: N/A + */ +int32_t +do_getargs (uint8_t* buf, int32_t nbytes) +{ + /* Obtain the current pcb */ + pcb_t* pcb = get_cur_pcb(); + if (strlen((const int8_t*)(pcb->args)) > nbytes || nbytes < 1) { +#if failure_msg_on + printf("FAIL getag001:try to get too more arg or too few bytes\n"); +#endif + return -1;} + /* Copy the arguments into the buffer. */ + strncpy((int8_t*)buf, (const int8_t*)(pcb->args), nbytes); + return 0; +} + + + + +////////////////////////////////////////////////sys_call 8///////////////////////////////////////////////// +/* do_vidmap + * Description: maps the text-mode video memory into user space + * Input: --screen_start: starting addr of the screen + * Output: the starting memory has been maps to the correct video memory + * Return value: return 0 if succeed or -1 if failed + * Side effect: N/A + */ +int32_t +do_vidmap (uint8_t** screen_start) +{ + /* Check if the addr is within the program image*/ + if(screen_start < (uint8_t**) 0x08000000 || screen_start > (uint8_t**) 0x08400000) +#if failure_msg_on + printf("FAIL dovid001:fail\n"); +#endif + return -1; + /* Maps the video memory*/ + *screen_start = (uint8_t*) get_vid_start(); + return 0; +} + + + +////////////////////////////////////////////////sys_call 9///////////////////////////////////////////////// +/* do_set_handler + * Description: N/A + * Input: --signum: N/A + * --handler_address: N/A + * Output: N/A + * Return value: N/A + * Side effect: N/A + */ +int32_t +do_set_handler (int32_t signum, void* handler_address) +{ +return -1; +} + + + +////////////////////////////////////////////////sys_call 10///////////////////////////////////////////////// +/* do_sigreturn + * Description: N/A + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: N/A + */ +int32_t +do_sigreturn (void) +{ +return -1; +} + + + + + + + diff --git a/sys_call.h b/sys_call.h new file mode 100644 index 0000000..9418bc1 --- /dev/null +++ b/sys_call.h @@ -0,0 +1,29 @@ +#ifndef _SYS_CALL_H +#define _SYS_CALL_H +#include "types.h" + +extern int32_t do_test (void); +extern int32_t do_halt (uint8_t status); +extern int32_t do_execute (const uint8_t* command); +extern int32_t do_read (int32_t fd, void* buf, int32_t nbytes); +extern int32_t do_write (int32_t fd, const void* buf, int32_t nbytes); +extern int32_t do_open (const uint8_t* filename); +extern int32_t do_close (int32_t fd); +extern int32_t do_getargs (uint8_t* buf, int32_t nbytes); +extern int32_t do_vidmap (uint8_t** screen_start); +extern int32_t do_set_handler (int32_t signum, void* handler_address); +extern int32_t do_sigreturn (void); + +#endif + + + + + + + + + + + + diff --git a/sys_call.o b/sys_call.o new file mode 100644 index 0000000..d009cd6 Binary files /dev/null and b/sys_call.o differ diff --git a/table.c b/table.c new file mode 100644 index 0000000..d1683bf --- /dev/null +++ b/table.c @@ -0,0 +1,149 @@ +#include "task.h" +#include "lib.h" +#include "table.h" + +#define maxhist 20 +/********************************************************* + * this table is a data structure we referenced from internet + * Description : It provides functions: push, pop and get elements + * in table. Table functioned as a container like + * queue. + */ +static char buffer[NUM_TERMINAL * maxhist ][1024]; +static int buffer_cur[NUM_TERMINAL]; +static int buffer_total[NUM_TERMINAL]; +/* init_table + * Description: initial the table + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: clear the buffer. + */ +void init_table(void) +{ + int i,j,k; + for(i = 0; i < NUM_TERMINAL;i++) + { + for(j = 0; j < maxhist;j++) + for(k = 0; k < 1024;k++) + { + buffer[i*maxhist + j ][k] = 0; + } + buffer_cur[i] = 0; + } +} +/* uptable + * Description: increase the table + * Input: -- buf: store the data from the terminal + * -- terminal: current terminal + * Output: N/A + * Return value: the length stored + * Side effect: N/A + */ + +int uptable(char * buf, uint32_t terminal) +{ + int k; + // if(buffer_cur[terminal] < buffer_total[terminal]) + // { + if((buffer_cur[terminal]) == 0) + { + return strlen(buf); + } + else + { + buffer_cur[terminal]--; + for(k = 0; k < 1024;k++) + { + buf[k]=buffer[terminal*maxhist + buffer_cur[terminal]][k]; + } + return strlen(buffer[terminal*maxhist + buffer_cur[terminal]]); + } + + // } + // else + // { + // for(k = 0; k < strlen(buf);k++) + // { + // if((buf[k] != '\n') && (buf[k] != '\0' )) + // buffer[terminal*maxhist + buffer_total[terminal]][k] = buf[k]; + // } + // buffer_total[terminal]++; + // buffer_cur[terminal] = buffer_total[terminal]; + // } +} + + +/* downtable + * Description: decrease the table + * Input: -- buf: store the data from the terminal + * -- terminal: current terminal + * Output: N/A + * Return value: the length stored + * Side effect: N/A + */ + +int downtable(char * buf, uint32_t terminal) +{ + int k; + if((buffer_cur[terminal] ) == buffer_total[terminal]) + { + return strlen(buf); + } + else + { + buffer_cur[terminal]++; + for(k = 0; k < 1024;k++) + { + buf[k] = buffer[terminal*maxhist + buffer_cur[terminal]][k] ; + } + return strlen(buf); + } + +} + +/* pushtable + * Description: push the table + * Input: -- buf: pop the data stored + * -- terminal: current terminal + * Output: N/A + * Return value: the length stored + * Side effect: if the content reaches maximum, clear the oldest one. + */ +void pushtable(char * buf, uint32_t terminal) +{ + int j,k; + if((buffer_total[terminal]) == maxhist) + { + for(j = 0; j <(maxhist - 1);j++) + for(k = 0; k < 1024;k++) + { + buffer[terminal*maxhist + j ][k] = buffer[terminal*maxhist + j + 1][k]; + } + for(k = 0; k < 1024;k++) + { + if((buf[k] != '\n') && (buf[k] != '\0' )) + buffer[terminal*maxhist + j][k] = buf[k]; + else + buffer[terminal*maxhist + j][k] = 0; + } + buffer_cur[terminal] = buffer_total[terminal]; + } + else + { + if((buf[0] == '\n') || (buf[0] == '\0' )) + return; + for(k = 0; k < 1024;k++) + { + if((buf[k] != '\n') && (buf[k] != '\0' )) + buffer[terminal*maxhist + buffer_total[terminal]][k] = buf[k]; + } + buffer_total[terminal]++; + buffer_cur[terminal] = buffer_total[terminal]; + + } + + +} + + diff --git a/table.h b/table.h new file mode 100644 index 0000000..b09f22d --- /dev/null +++ b/table.h @@ -0,0 +1,20 @@ +#ifndef _TABLE_H +#define _TABLE_H + +extern int uptable(char * buf, uint32_t terminal); +extern int downtable(char * buf, uint32_t terminal); +extern void pushtable(char * buf, uint32_t terminal); +extern void init_table(void); +#endif + + + + + + + + + + + + diff --git a/table.o b/table.o new file mode 100644 index 0000000..fe61117 Binary files /dev/null and b/table.o differ diff --git a/task.c b/task.c new file mode 100644 index 0000000..09a8651 --- /dev/null +++ b/task.c @@ -0,0 +1,486 @@ +//memory wasteful algorithm + +#include "task.h" +#include "page.h" +#include "x86_desc.h" +#include "file_system.h" +#include "lib.h" +#include "i8259.h" +#include "irq0.h" + +#define debug_get_new_pcb 0 +#define debug_switch_pcb 0 +#define debug_remove_pcb 0 +#define debug_change_task 0 +#define debug_task_num_on 1 + + +extern int screen_x[NUM_TERMINAL]; +extern int screen_y[NUM_TERMINAL]; + +regs_t program_state_b4_task_switch; //save run-time state b4 irq0 happened in a particular terminal +regs_t context_regs[NUM_TERMINAL]; //save run-time state b4 syscall +regs_t parent_of_current_task[NUM_TERMINAL]; //when a execute happens, this is a backup of run-time state b4 execute runs + + + +static pcb_t* pcb_list_head[NUM_TERMINAL] ; //currently executing program in each terminal +static uint32_t task_bitmap[NUM_OF_TASK_TOTAL]={0}; //bitmap of the task in each terminal +static int32_t inode_init; //only for initialization of the pcbs for each terminal + +volatile uint32_t cur_terminal = 0; //currently running program in scheduleing time slice +volatile uint32_t alt_terminal = 0; //the terminal we are looking at +volatile uint32_t system_init_flag = 0; //system initialization flag.1 means +//volatile uint32_t irq0_flag =0; + + +//internal function +static void system_terminal_init(); +static const char haltimg0 []= "\\(^_^\\)~~~~~~~~~~~~~~~~~~~~~~~~~~~\\(>o<)/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(/^_^)/\n"; +static const char haltimg1 []= "\\(^_^\\)---------------The operating systam is halted-------------------(/^_^)/\n"; +static const char haltimg2 []= "\\(^_^\\) (/^_^)/\n"; +/* Swtich_task + * Description: It maps the data into video mmemory and increment the current task + * Input: -- cur_terminal: The identity of the current terminal, i.e: Terminal 1, Terminal 2, etc. + * Output: Increment the current terminal number + * Return value: N/A + * Side effect: allocate page for the user lvl, and switch the task. + */ +void +switch_task() +{ + + uint32_t stack_ptr_temp; + + /* Store the regs info before switching into pcb.*/ + pcb_list_head[cur_terminal]->regs=program_state_b4_task_switch; + + /* Temp variable for storing the esp*/ + stack_ptr_temp=pcb_list_head[cur_terminal]->regs.esp; + /* Map the video mem from vitrual to physical */ + user_page_mapper_4K((uint32_t)0xB8000,(uint32_t)0xB8000); + /* Map the video mem for the displaying terminal which going to switch. */ + user_page_mapper_4K((uint32_t)0xB8000+(alt_terminal+1)*size_of_vmem,(uint32_t)0xB8000+(alt_terminal+1)*size_of_vmem); + /* Map the video mem for the running terminal which going to switch. */ + user_page_mapper_4K((uint32_t)(uint32_t)0xB8000+(cur_terminal+1)*size_of_vmem,(uint32_t)0xB8000+(cur_terminal+1)*size_of_vmem); + if(alt_terminal==cur_terminal) + /* Memory copy from 0xB800 to the video mem of running terminal*/ + memcpy((void*)0xB8000+(cur_terminal+1)*size_of_vmem, (void*)0xB8000, size_of_vmem); + /* Else, increment the running terminal. */ + cur_terminal++; + /* If it reaches the max, then switch back to terminal 0*/ + if(cur_terminal==NUM_TERMINAL) + cur_terminal=0; + + if(alt_terminal==cur_terminal) + /* Memory copy from 0xB800 to the video mem of displaying terminal*/ + memcpy((void*)0xB8000+(alt_terminal+1)*size_of_vmem, (void*)0xB8000, size_of_vmem); + + + user_page_mapper_4K((uint32_t)0xB8000,(uint32_t)0xB8000+(cur_terminal+1)*size_of_vmem); + user_page_mapper_4K((uint32_t)0xB8000+(alt_terminal+1)*size_of_vmem,(uint32_t)0xB8000); + + //update_cursor(screen_y[alt_terminal],screen_x[alt_terminal]); + + __user_space_alloc((pcb_t*)pcb_list_head[cur_terminal]); + + +#if debug_change_task + printf("\n Going to p_esp:%x,return_addr:%x,cs:%x,ds:%x,es:%x,ss:%x\n",pcb_list_head[cur_terminal]->regs.p_esp,pcb_list_head[cur_terminal]->regs.return_addr,pcb_list_head[cur_terminal]->regs.cs,pcb_list_head[cur_terminal]->regs.ds,pcb_list_head[cur_terminal]->regs.es,pcb_list_head[cur_terminal]->regs.ss); +#endif + /* Obtain the esp info back to the pcb, for protection purpose. */ + pcb_list_head[cur_terminal]->regs.esp=stack_ptr_temp; + /* Call switch function to switch pcb. */ + switch_pcb ((pcb_t*)pcb_list_head[cur_terminal]); +} + +/* get_inode_init + * Description: obtain the inode + * Input: -- inode: index node from file + * Output: obtain the inode + * Return value: N/A + * Side effect: N/A + */ +void +get_inode_init(int32_t inode) +{ + inode_init=inode; +} + +/* system_terminal_init + * Description: initialize each terminals + * Input: -- inode: index node from file + * Output: allocate pages for each terminal video mem + * Return value: N/A + * Side effect: start the system timer and shwo the statusbar for each terminal + */ +static void +system_terminal_init() +{ + uint32_t i; + uint32_t k=0; + for (i=0;ikernel_esp = (uint32_t)((pcb_t*)0x007ffffc-i); //allocate kernel stack for each terminal task + pcb_list_head[i]->pid=i; + pcb_list_head[i]->parent=pcb_list_head[i]; + pcb_list_head[i]->child=pcb_list_head[i]; + k=(i-i%SCALE)/SCALE; + task_bitmap[k]|=(1<<(i%SCALE)); //map to each task_bitmap + user_space_alloc((uint32_t)(fourmb * i)); //write program image to each terminal + read_data(inode_init,0,(uint8_t *)0x08048000, sizeofinode(inode_init)); //user physical page + user_page_mapper_4K((uint32_t)0xB9000+i*size_of_vmem,(uint32_t)0xB9000+i*size_of_vmem); //allocate pages for each terminal video mem + } + + user_page_mapper_4K((uint32_t)0xB8000,(uint32_t)0xB8000+(cur_terminal+1)*size_of_vmem); //intialize to first terminal + user_page_mapper_4K((uint32_t)0xB8000+(alt_terminal+1)*size_of_vmem,(uint32_t)0xB8000); + __user_space_alloc(pcb_list_head[cur_terminal]); + /* Call the statusbar func to display message of current terminal. */ + statusbar(); + open_IRQ0(); + cli(); +#if debug_task_num_on + int task_count; + for(k=0;k>i) & 1)),++i); +#endif + + system_init_flag=1; +} + +/* changetask + * Description: initialize each terminals + * Input: -- inode: index node from file + * Output: allocate pages for each terminal video mem + * Return value: N/A + * Side effect: start the system timer and shwo the statusbar for each terminal + */ + +void +changetask() +{ + + user_page_mapper_4K((uint32_t)0xB8000,(uint32_t)0xB8000); + user_page_mapper_4K((uint32_t)0xB8000+(alt_terminal+1)*size_of_vmem,(uint32_t)0xB8000+(alt_terminal+1)*size_of_vmem); + memcpy((void *)0xB8000,(const void *)(0xB8000 + (alt_terminal+1)*size_of_vmem),(uint32_t)size_of_vmem); + /* Switch the displaying terminal */ + alt_terminal++; + /* If it reaches the end, go back to 0*/ + if(alt_terminal==NUM_TERMINAL) + alt_terminal=0; + /* Map the video mem from vitrual to physical */ + memcpy((void *)0xB8000,(const void *)(0xB8000 + (alt_terminal+1)*size_of_vmem),(uint32_t)size_of_vmem); + /* Map the video mem for the displaying terminal which going to switch. */ + user_page_mapper_4K((uint32_t)0xB8000,(uint32_t)0xB8000+(cur_terminal+1)*size_of_vmem); + /* Memory copy from 0xB800 to the video mem of running terminal*/ + user_page_mapper_4K((uint32_t)0xB8000+(alt_terminal+1)*size_of_vmem,(uint32_t)0xB8000); + /* Update the cursor when switch to a new terminal */ + __user_space_alloc(pcb_list_head[cur_terminal]); + update_cursor(screen_y[alt_terminal],screen_x[alt_terminal]); +} + + +/* __user_space_alloc + * Description: allocat the user space + * Input: -- context_reg_stack: context of the current terminal + * Output: N/A + * Return value: N/A + * Side effect: store the info + */ + +void +__user_space_alloc(pcb_t* pcb) +{ + user_space_alloc((uint32_t)(fourmb * pcb->pid)); +} + +/* save_context_for_terminal_switch + * Description: save the context before switching + * Input: -- context_reg_stack: context of the current terminal + * Output: N/A + * Return value: N/A + * Side effect: store the info + */ +void +save_context_for_terminal_switch(regs_t* context_reg_stack) +{ + + //spare the context info + if (context_reg_stack->irq_num==0x20) + { + /* Store the context reg info b4 task switch*/ + memcpy((void*)&program_state_b4_task_switch, (void*)context_reg_stack, sizeof(regs_t)); + program_state_b4_task_switch.esp = (uint32_t)context_reg_stack; + } + +} + +/* save_context + * Description: save the context + * Input: -- context_reg_stack: context of the current terminal + * Output: N/A + * Return value: N/A + * Side effect: store the info + */ + + +void +save_context(regs_t* context_reg_stack) +{ + uint32_t i; + if(!system_init_flag) { + for (i=0;iuser_esp=(uint32_t)context_reg_stack->p_esp; + //spare the context info + memcpy((void*)&context_regs[cur_terminal], (void*)context_reg_stack, sizeof(regs_t)); + //set current esp point to the stack head + context_regs[cur_terminal].esp = (uint32_t)context_reg_stack; +} + + +void +spare_info_for_halt_for_this_pcb(void) +{ + memcpy((void*)&parent_of_current_task[cur_terminal],(void*)&context_regs[cur_terminal],sizeof(regs_t)); +} + +/* Obtaining the current pcb*/ +pcb_t* +get_cur_pcb(void) +{ + return (pcb_t*)pcb_list_head[cur_terminal]; +} + +/* get_new_pcb + * Description: create the new pcb if it is available. + * Input: -- cur_terminal: current terminal numbers + * Output: N/A + * Return value: N/A + * Side effect: construct a new pcb + */ + +pcb_t* +get_new_pcb(void) +{ + pcb_t* new_pcb; + uint32_t i, alloc_pid; + uint32_t k=0; + +#if debug_task_num_on + int task_count; + for(k=0;k>i) & 1)),++i); +#endif + + + for(k=0;(kpid=alloc_pid; + new_pcb->parent=(pcb_t*)pcb_list_head[cur_terminal]; + new_pcb->parent->child=(pcb_t*)new_pcb; + //new_pcb->child=NULL; + new_pcb->kernel_esp=(uint32_t)((pcb_t*)0x7ffffc - alloc_pid); + new_pcb->user_esp=(uint32_t)0x83ffffc; + memcpy((void*)&(new_pcb->regs),(void*)&context_regs[cur_terminal], sizeof(regs_t)); + new_pcb->regs.cs = USER_CS; + new_pcb->regs.ss = USER_DS; + new_pcb->regs.ds = USER_DS; + new_pcb->regs.es = USER_DS; + new_pcb->regs.fs = USER_DS; + new_pcb->regs.gs = USER_DS; + new_pcb->regs.ebp=(uint32_t)new_pcb->user_esp; + new_pcb->regs.p_esp=(uint32_t)new_pcb->user_esp; + new_pcb->regs.eflags=0x200|new_pcb->regs.eflags; + pcb_list_head[cur_terminal] = new_pcb; + +#if debug_task_num_on + for(k=0;k>i) & 1)),++i); +#endif + + return new_pcb; +} + + + +/* switch_pcb + * Description: create the new pcb if it is available. + * Input: -- cur_terminal: current terminal numbers + * Output: N/A + * Return value: N/A + * Side effect: set the ss as kernel and copy the regs onto kernel stack + */ +void +switch_pcb (pcb_t* pcb) +{ + +#if debug_task_num_on + int task_count,i,k; + for(k=0;k>i) & 1)),++i); +#endif + + //if it's the system initializing execute + if(!system_init_flag) + system_terminal_init(); + /* Set the tss according to the appendix */ + tss.ss0 = KERNEL_DS; + tss.esp0 = (uint32_t)(pcb->kernel_esp); + +#if debug_switch_pcb + printf("\npid:%d,parent:%x,child:%x,command_word:%s,arg:%s,ebp:%x,ss:%x,cs:%x,p_esp:%x,return_addr:%x,eflags:%x,list_head:%x,kernel_esp=%x,user_esp:%x,eax:%x\n" + ,pcb->pid,(uint32_t)pcb->parent,(uint32_t)pcb->child,pcb->command_word,pcb->args,pcb->regs.ebp,pcb->regs.ss,pcb->regs.cs,pcb->regs.p_esp,pcb->regs.return_addr + ,pcb->regs.eflags,(uint32_t) pcb_list_head[cur_terminal],pcb->kernel_esp,pcb->user_esp,pcb->regs.eax); +#endif + + /* Copy the regs info onto kernel stack. */ + memcpy((void*)(pcb->regs.esp),(void*)&pcb->regs, sizeof(regs_t)); + +} + +/* remove_pcb + * Description: remove the pcb + * Input: -- cur_terminal: current terminal numbers + * -- status: the current status + * Output: N/A + * Return value: -- parent->regs.eax : the return addr of the parent. + * Side effect: remove from the taks bit map and pcb head points to the parent + */ + +int32_t +remove_pcb(uint8_t status) +{ + int32_t i; + int32_t task_count=0; + uint32_t k; + pcb_t* parent; + + //Get the number of task now + + for(k=0;k>i) & 1)),++i); + + + if (task_count==1) { + clear(); + printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + haltimg0,haltimg2,haltimg2,haltimg2,haltimg2,haltimg2,haltimg2,haltimg2,haltimg2,haltimg2, + haltimg1,haltimg2,haltimg2,haltimg2,haltimg2,haltimg2,haltimg2,haltimg2,haltimg2,haltimg0); + cli(); + while(1); + } + +#if debug_remove_pcb + //printf("task_count before exit:%d,bit_map:%d\n",task_count,task_bitmap[k]); +#endif + else if (task_count==0) { + printf("FAIL rpcb001:No task at all. You must execute a shell in kernel.c!!\n"); + return -1;} + + else { + //Remove current process from the bit-map + for(k=0; (kpid)%SCALE))); + +#if debug_remove_pcb + printf("task_count after exit:%d,bit_map:%d\n",task_count,task_bitmap[cur_terminal]); +#endif + //Killing no task will raise error + if (pcb_list_head[cur_terminal]==NULL) { + printf("FAIL rpcb002:Attemp to remove a non existed task!\n"); + return -1; + } + + //set the pcb list head to parent; + parent = (pcb_t*)pcb_list_head[cur_terminal]->parent; + // and copy the related info. + memcpy((void*)&parent->regs,(void*)&parent_of_current_task[cur_terminal],sizeof(regs_t)); + + //remap page for the parent + __user_space_alloc(parent); + +#if debug_remove_pcb + printf("Trying to remove task from list.."); + printf("\n:::current task info:::\n list_head:%x,tss.esp0:%x\n",(uint32_t)pcb_list_head[cur_terminal],(uint32_t)tss.esp0); + printf(":::parent pcb general info:::\n pid:%d,command_word:%s,arg:%s,kernel_esp=%x,user_esp:%x,parent:%x,child:%x\n" + ,parent->pid,parent->command_word,parent->args,parent->kernel_esp,parent->user_esp,(uint32_t)parent->parent,(uint32_t)parent->child); + printf(":::parent pcb reg info::: \nebx:%x,ecx:%x,edx:%x,esi:%x,edi:%x,ebp:%x,esp:%x,eax:%x,ds:%x,es:%x,fs:%x,gs:%x,irq_num:%x,error_code:%x,return_addr:%x,cs:%x,elags:%x,p_esp:%x,ss:%x\n", + parent->regs.ebx,parent->regs.ecx,parent->regs.edx,parent->regs.esi,parent->regs.edi,parent->regs.ebp,parent->regs.esp, + parent->regs.eax,parent->regs.ds,parent->regs.es,parent->regs.fs,parent->regs.gs,parent->regs.irq_num,parent->regs.error_code, + parent->regs.return_addr,parent->regs.cs,parent->regs.eflags,parent->regs.p_esp,parent->regs.ss); +#endif + + //A fake halter, since there is an unknown bug when the system going back to kernel + tss.ss0 = KERNEL_DS; + tss.esp0 = (uint32_t)(parent->kernel_esp); +#if debug_remove_pcb + printf(":::Tried to return to stack:::\nebx:%x,ecx:%x,edx:%x,esi:%x,edi:%x,ebp:%x,esp:%x,eax:%x,ds:%x,es:%x,fs:%x,gs:%x,irq_num:%x,error_code:%x,return_addr:%x,cs:%x,elags:%x,p_esp:%x,ss:%x\n", + parent->regs.ebx,parent->regs.ecx,parent->regs.edx,parent->regs.esi,parent->regs.edi,parent->regs.ebp,parent->regs.esp, + parent->regs.eax,parent->regs.ds,parent->regs.es,parent->regs.fs,parent->regs.gs,parent->regs.irq_num,parent->regs.error_code, + parent->regs.return_addr,parent->regs.cs,parent->regs.eflags,parent->regs.p_esp,parent->regs.ss); +#endif + + + //Kill children;Update linklist + parent->child = NULL; + parent->regs.eax = (uint32_t)status&0x0ff; + pcb_list_head[cur_terminal] = parent; + + pcb_list_head[cur_terminal]->regs.esp=context_regs[cur_terminal].esp; + switch_pcb ((pcb_t*)pcb_list_head[cur_terminal]); + return parent->regs.eax; + } +} +/* get_vid_start + * Description: Obtain the staring video mem. + * Input: N/A + * Output: N/A + * Return value: video mem + * Side effect: N/A + */ +uint8_t* get_vid_start() +{ +if(cur_terminal==alt_terminal) +/* If the displaying terminal is the running terminal,then update the video mem*/ +return (uint8_t*)0xB8000+ (alt_terminal + 1)*size_of_vmem; +else +return (uint8_t*)0xB8000; +} + + + + + + + diff --git a/task.h b/task.h new file mode 100644 index 0000000..eb1f305 --- /dev/null +++ b/task.h @@ -0,0 +1,80 @@ +#ifndef _TASK_H +#define _TASK_H + +#include "types.h" +#include "file_desc.h" +#define COMM_WORD_LENGTH 64 +#define ARG_LENGTH 64 +#define size_of_vmem 4096 + +#define NUM_TERMINAL 3 +#define NUM_OF_TASK 68 +#define SCALE 32 +#define NUM_OF_TASK_TOTAL (int)(NUM_OF_TASK/SCALE + NUM_TERMINAL/SCALE+1) + +//Register stack +typedef struct{ + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t esi; + uint32_t edi; + uint32_t ebp; + uint32_t esp; + uint32_t eax; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; + uint32_t irq_num; + uint32_t error_code; + uint32_t return_addr; + uint32_t cs; + uint32_t eflags; + uint32_t p_esp; + uint32_t ss; +}regs_t; + +//Process Control Block Structure +union pcb__t{ +struct{ + uint32_t pid; + filedescriptor_t file_array[8]; + uint8_t command_word[COMM_WORD_LENGTH]; + uint8_t args[64]; + uint32_t kernel_esp; + uint32_t user_esp; + union pcb__t* parent; + union pcb__t* child; + union pcb__t* nxt_task; + union pcb__t* prv_task; + regs_t regs; //run-time state of the program +}; +uint32_t ker_stack[2048]; +}; +typedef union pcb__t pcb_t; + +extern void changetask(); +extern pcb_t* get_new_pcb(void); +extern pcb_t* get_cur_pcb(void); +extern void switch_pcb (pcb_t* pcb); +extern int32_t remove_pcb(uint8_t status); +extern void save_context(regs_t* context_reg_stack); +extern void spare_info_for_halt_for_this_pcb(void); +extern void __user_space_alloc(pcb_t* pcb); +extern void get_inode_init(int32_t inode); +extern volatile uint32_t cur_terminal; +extern volatile uint32_t alt_terminal; +extern void save_context_for_terminal_switch(regs_t* context_reg_stack); +extern void switch_task(); +extern uint8_t* get_vid_start(); +extern volatile uint32_t sys_init_flag; +#endif + + + + + + + + diff --git a/task.o b/task.o new file mode 100644 index 0000000..f0d7e3f Binary files /dev/null and b/task.o differ diff --git a/terminal.c b/terminal.c new file mode 100644 index 0000000..0bb4d3c --- /dev/null +++ b/terminal.c @@ -0,0 +1,394 @@ +#include "terminal.h" +#include "lib.h" +#include "task.h" +#include "table.h" + +static int ctrl=0; +static int alt=0; +static int capital=0; + +static int counter[NUM_TERMINAL]; +static volatile int lock[NUM_TERMINAL]; +static char buffer[NUM_TERMINAL][1024]; + +static void command(unsigned char cmd); +static void common(unsigned char key); +static void transform(unsigned key); +static void clear_buf(void); +static void up_buf(void); +static void down_buf(void); + +/* bufdel + * Description: delete the buffer + * Input: N/A + * Output: decrement the counter + * Return value: -1 if failed and 1 if succeed + * Side effect: N/A + */ +static int bufdel(void) +{ +if(counter[alt_terminal] == 0) + return -1; + // decrement the counter + counter[alt_terminal]--; + // set the buffer to 0 + buffer[alt_terminal][counter[alt_terminal]]=0; + return 1; +} +/* clear_buf + * Description: clear the buffer + * Input: N/A + * Output: clear the buffer + * Return value: N/A + * Side effect: N/A + */ + +void clear_buf(void) +{ + int j; + for(j=0;j< counter[alt_terminal];j++) + /*Clear every elements in this buffer */ + {buffer[alt_terminal][j]=0;} + /* Counter goes to 0*/ + counter[alt_terminal]=0; +} +/* command + * Description: check the command + * Input: --cmd: command input + * Output: clear N/A + * Return value: N/A + * Side effect: open the terminal + */ + + +void command(unsigned char cmd) +{ + uint8_t file; + if(cmd==0x26) open_terminal(&file); +} +/* altcommand + * Description: check the command + * Input: --cmd: command input + * Output: clear N/A + * Return value: N/A + * Side effect: change the task + */ +void altcommand(unsigned char cmd) +{ + + if(cmd==0x3c) + { + changetask(); + } +} + +/* common + * Description: deal with the common key input without capitals. + * Input: --key: key scanned from keyboard + * Output: clear N/A + * Return value: N/A + * Side effect: output the char or turn on capital. + */ +void common(unsigned char key) +{ +//printf("key : %x ::",key); +switch(key) +{ +case 0x1C: putcur('\n'); + // set the lock + lock[alt_terminal] = 1; + buffer[alt_terminal][counter[alt_terminal]]= '\n'; + // increment the counter + counter[alt_terminal]++; + //screen_ptr(getx(), gety()); + //printf("X: %d,Y: %d",getx(), gety()); + break; // ENTER!!!!!!!!!! +// "tab" +case 0x0F: printf("%c", 9); break; + + +// back space +case 0x0E: + + if(bufdel() == 1 ) + { + bksp_t(); + break; + } + else + break; + +//direction +case 0x50: down_buf();break;//down +case 0x48: up_buf();break;//up +case 0x4D: dir(key);break; +case 0x4B: dir(key);break; + +} +} +/* up_buf + * Description: increse the buffer + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect: modify the counter + */ +void up_buf(void) +{ + int i; + for (i = 0; i < strlen(buffer[alt_terminal]); i++) + { + bksp_t(); + } + counter[alt_terminal] = uptable((char * )buffer[alt_terminal],alt_terminal);//down + for (i = 0; i < strlen(buffer[alt_terminal]); i++) + { + putcur(buffer[alt_terminal][i]); + } +} +/* down_buf + * Description: decrease the buffer + * Input: N/A + * Output: clear N/A + * Return value: N/A + * Side effect: modify the counter + */ +void down_buf(void) +{ + int i; + for (i = 0; i < strlen(buffer[alt_terminal]); i++) + { + bksp_t(); + } + + counter[alt_terminal] = downtable((char * )buffer[alt_terminal],alt_terminal);//up + + for (i = 0; i < strlen(buffer[alt_terminal]); i++) + { + putcur(buffer[alt_terminal][i]); + } + +} +/* open_terminal + * Description: Turn on the terminal + * Input: --filename: file need to access + * Output: clear N/A + * Return value: N/A + * Side effect: clear + */ +void +open_terminal(const uint8_t* filename) +{ +//int8_t s[9]="[user@ ]$"; +clear(); + +clear_buf(); + +} + +/* read_terminal + * Description: read the keyboard input + * Input: --fd: file descriptor + * --buf: + * --key : scan code for keyboard + * Output: N/A + * Return value: N/A + * Side effect: transform the keys to Capital if needed + */ + +void read_terminal(int32_t fd, const void* buf, int32_t key) +{ + common(key); //common parts, don't need any Capital letter consideration:D + + //to judge the CAPITAL or NOT + if(key==0x2A ||key==0x36) + capital++; //shift + else if(key==0xAA || key==0xB6) + capital--; + + if(key==0x3A) + capital=(capital==0)?1:0; //Capslock[cur_terminal] + + + //to judge the ctrl + if(key==0x1D) + ctrl++; + else + if(key==0x9D) ctrl--; + //to judge the alt + if(key==0x38) + alt++; + else + if(key==0xB8) alt--; + + if(alt!=0) + altcommand(key); + else if(ctrl!=0) + command(key); + else if(key<0x60 && key>=0x00) + { + // change to capital letters + transform(key); + } + +} +/* write_terminal + * Description: write the keyboard input + * Input: --fd: file descriptor + * --buf: buf need to print + * --nbytes : number of bytes need to write + * Output: N/A + * Return value: N/A + * Side effect: print to the current buffer + */ + +void write_terminal(int32_t fd, void* buf, int32_t nbytes) +{ + printscur((char *) buf); +} + +/* r_terminal + * Description: read the terminal when switch terminals + * Input: --fd: file descriptor + * --buf: buf need to print + * --key : scan code for keyboard + * Output: N/A + * Return value: k: counter + * Side effect: print to the current buffer + */ + +int r_terminal(int32_t fd, uint8_t* buf, int32_t key) +{ + + int i,k; + //set the lock to 0 + lock[alt_terminal]=0; + while(1){ + // only return the keyboard input after press "Enter" + if((lock[alt_terminal] == 1 ) && (alt_terminal == cur_terminal)) + break;} + //set the lock to 0 + lock[alt_terminal]=0; + for(i =0; i < key; i++) + // store them into the buffer + buf[i] = (uint8_t) buffer[alt_terminal][i]; + k = counter[alt_terminal]; + cli(); + pushtable((char *) buf, alt_terminal); + sti(); + // clear the buffer + clear_buf(); + return k; +} + + +/* transform + * Description: transform the letter to capital + * Input: --key : scan code for keyboard + * Output: temp storing the char + * Return value: k: counter + * Side effect: print the temp + */ + + +void transform(unsigned key) +{ + char temp; + int cao=0; + //small case + if(capital==0){ +switch(key) +{ +//1-0 +case 0x02: temp='1'; putcur(temp);break; +case 0x03: temp='2'; putcur(temp);break; +case 0x04: temp='3'; putcur(temp);break; +case 0x05: temp='4'; putcur(temp);break; +case 0x06: temp='5'; putcur(temp);break; +case 0x07: temp='6'; putcur(temp);break; +case 0x08: temp='7'; putcur(temp);break; +case 0x09: temp='8'; putcur(temp);break; +case 0x0A: temp='9'; putcur(temp);break; +case 0x0B: temp='0'; putcur(temp); break; +case 0x0C: temp='-'; putcur(temp);break; +case 0x0D: temp='='; putcur(temp);break; +//q-? only chars +case 0x10: temp='q'; putcur(temp);break; case 0x11: temp='w'; putcur(temp);break; case 0x12: temp='e'; putcur(temp); break; +case 0x13: temp='r'; putcur(temp);break; case 0x14: temp='t'; putcur(temp); break; case 0x15: temp='y'; putcur(temp);break; +case 0x16: temp='u'; putcur(temp);break; case 0x17: temp='i'; putcur(temp); break; case 0x18: temp='o'; putcur(temp); break; +case 0x19: temp='p'; putcur(temp);break; case 0x1A: temp='['; putcur(temp); break; case 0x1B: temp=']'; putcur(temp); break; +case 0x2B: temp=92; putcur(temp);break; + +case 0x1E: temp='a'; putcur(temp);break; case 0x1F: temp='s'; putcur(temp); break; case 0x20: temp='d'; putcur(temp); break; +case 0x21: temp='f'; putcur(temp);break; case 0x22: temp='g'; putcur(temp);break; case 0x23: temp='h'; putcur(temp);break; +case 0x24: temp='j'; putcur(temp);break; case 0x25: temp='k'; putcur(temp);break; case 0x26: temp='l'; putcur(temp);break; +case 0x27: temp=';'; putcur(temp);break; case 0x28: temp=39; putcur(temp);break; + +case 0x2C: temp='z'; putcur(temp); break; case 0x2D: temp='x'; putcur(temp); break; case 0x2E: temp='c'; putcur(temp); break; +case 0x2F: temp='v'; putcur(temp); break; case 0x30: temp='b'; putcur(temp); break; case 0x31: temp='n'; putcur(temp); break; +case 0x32: temp='m'; putcur(temp); break; case 0x33: temp=','; putcur(temp);break; case 0x34: temp='.'; putcur(temp); break; +case 0x35: temp='/'; putcur(temp); break; +case 0x39: temp=' '; putcur(temp); break; + default: cao=1;break; + +} + +} + +//CAPITAL case +else +{ +switch(key){ + +case 0x02: temp='!'; putcur(temp);break; +case 0x03: temp='@'; putcur(temp);break; +case 0x04: temp='#'; putcur(temp);break; +case 0x05: temp='$'; putcur(temp);break; +case 0x06: temp='%'; putcur(temp);break; +case 0x07: temp='^'; putcur(temp);break; +case 0x08: temp='&'; putcur(temp);break; +case 0x09: temp='*'; putcur(temp);break; +case 0x0A: temp='('; putcur(temp);break; +case 0x0B: temp=')'; putcur(temp);break; +case 0x0C: temp='_'; putcur(temp);break; +case 0x0D: temp='+'; putcur(temp);break; +case 0x10: temp='Q'; putcur(temp);break; case 0x11: temp='W'; putcur(temp);break; case 0x12: temp='E'; putcur(temp);break; +case 0x13: temp='R'; putcur(temp);break; case 0x14: temp='T'; putcur(temp);break; case 0x15: temp='Y'; putcur(temp); break; +case 0x16: temp='U'; putcur(temp);break; case 0x17: temp='I'; putcur(temp);break; case 0x18: temp='O'; putcur(temp); break; +case 0x19: temp='P'; putcur(temp);break; case 0x1A: temp='{'; putcur(temp);break; case 0x1B: temp='}'; putcur(temp); break; +case 0x2B: temp='|'; putcur(temp);break; + +case 0x1E: temp='A'; putcur(temp);break; case 0x1F: temp='S'; putcur(temp); break; case 0x20: temp='D'; putcur(temp);break; +case 0x21: temp='F'; putcur(temp);break; case 0x22: temp='G'; putcur(temp); break; case 0x23: temp='H'; putcur(temp);break; +case 0x24: temp='J'; putcur(temp);break; case 0x25: temp='K'; putcur(temp); break; case 0x26: temp='L'; putcur(temp); break; +case 0x27: temp=':'; putcur(temp);break; case 0x28: temp=34; putcur(temp); break; + +case 0x2C: temp='Z'; putcur(temp);break; case 0x2D: temp='X'; putcur(temp); break; case 0x2E: temp='C'; putcur(temp);break; +case 0x2F: temp='V'; putcur(temp);break; case 0x30: temp='B'; putcur(temp);break; case 0x31: temp='N'; putcur(temp); break; +case 0x32: temp='M'; putcur(temp);break; case 0x33: temp='<'; putcur(temp); break; case 0x34: temp='>'; putcur(temp);break; +case 0x35: temp='?'; putcur(temp);break; +case 0x39: temp=' '; putcur(temp);break; +default: cao=1;break; +putcur(temp); +} +} + + if(cao!=1) + { + //check if it is out of range + if(counter[alt_terminal]<1024) + { + //restore the value from temp + buffer[alt_terminal][counter[alt_terminal]]=temp; + counter[alt_terminal]++; + } + else + printf("out of range"); + + } +} + + + + + diff --git a/terminal.h b/terminal.h new file mode 100644 index 0000000..80487d1 --- /dev/null +++ b/terminal.h @@ -0,0 +1,9 @@ +#ifndef _TERMINAL_H +#define _TERMINAL_H +#include "types.h" +extern void read_terminal(int32_t fd, const void * buf, int32_t key); +extern void open_terminal(const uint8_t* filename); +extern void write_terminal(int32_t fd, void * buf, int32_t key); +extern int r_terminal(int32_t fd, uint8_t* buf, int32_t key); + +#endif diff --git a/terminal.o b/terminal.o new file mode 100644 index 0000000..2fa7e9d Binary files /dev/null and b/terminal.o differ diff --git a/test.c b/test.c new file mode 100644 index 0000000..e5ebc56 --- /dev/null +++ b/test.c @@ -0,0 +1,68 @@ +#include "test.h" +#include "lib.h" + +#include "multiboot.h" +#include "x86_desc.h" +#include "lib.h" +#include "i8259.h" +#include "debug.h" +#include "idt_handler.h" +#include "page.h" +#include "rtc.h" +#include "terminal.h" +#include "file_system.h" + +int32_t +test_system_call(int32_t arg1, int32_t *arg2, int32_t arg3, int32_t call_num) +{ + int res; + __asm__ volatile( + "int $0x80" /* make the request to the OS */ + : "=a" (res) , /* return result in eax ("a") */ + "+b" (arg1), /* pass arg1 in ebx ("b") */ + "+c" (arg2), /* pass arg2 in ecx ("c") */ + "+d" (arg3) /* pass arg3 in edx ("d") */ + : "a" (call_num) /* pass system call number in eax ("a") */ + : "memory", "cc"); /* announce to the compiler that the memory and condition codes have been modified */ + + /* The operating system will return a negative value on error; + * wrappers return -1 on error and set the errno global variable */ + + return res; +} + +/* test_dentries + * Description: testing + * Input: N/A + * Output: N/A + * Return value: N/A + * Side effect:testing + */ +void +test_dentries() +{ + + uint8_t buf[2000]; + int i; + dentry_t dentry; + uint8_t name[32] = "frame1.txt"; + read_dentry_by_name(name, &dentry); + printf("name is %s \n", dentry.name); + printf("type is %x \n", dentry.type); + printf("index is %x \n", dentry.inode); + read_data( dentry.inode, 0x00, buf, 2000); + for(i = 0; i when building this OS + * vim:ts=4 noexpandtab + */ + +#ifndef _TYPES_H +#define _TYPES_H + +#define NULL 0 + +#ifndef ASM + +/* Types defined here just like in */ +typedef int int32_t; +typedef unsigned int uint32_t; + +typedef short int16_t; +typedef unsigned short uint16_t; + +typedef char int8_t; +typedef unsigned char uint8_t; + + + + + + +#endif /* ASM */ + +#endif /* _TYPES_H */ diff --git a/x86_desc.S b/x86_desc.S new file mode 100644 index 0000000..c3e9a75 --- /dev/null +++ b/x86_desc.S @@ -0,0 +1,111 @@ +# x86_desc.S - Set up x86 segment descriptors, descriptor tables +# vim:ts=4 noexpandtab + +#define ASM 1 +#include "x86_desc.h" + +.text + +.globl ldt_size, tss_size +.globl gdt_desc, ldt_desc, tss_desc +.globl tss, tss_desc_ptr, ldt, ldt_desc_ptr +.globl gdt_ptr +.globl idt_desc_ptr, idt + +.align 4 + + +tss_size: + .long tss_bottom - tss - 1 + +ldt_size: + .long ldt_bottom - ldt - 1 + + .word 0 # Padding + +gdt_desc: + .word gdt_bottom - gdt - 1 + .long gdt + .align 16 + +ldt_desc: + .word KERNEL_LDT + .long ldt + + .align 4 +tss: +_tss: + .rept 104 + .byte 0 + .endr +tss_bottom: + + .align 16 +gdt: +_gdt: + + # First GDT entry cannot be used + .quad 0 + + # NULL entry + .quad 0 + + # Segmentation will not be used + # CS and DS both are 0-4GB r/w segments + # + # The layout is (from Intel IA-32 reference manual): + # 31 24 23 22 21 20 19 16 15 14 13 12 11 8 7 0 + # |----------------------------------------------------------------------| + # | | | D | | A | Seg | | D | | | | + # | Base 31:24 | G | / | 0 | V | Limit | P | P | S | Type | Base 23:16 | + # | | | B | | L | 19:16 | | L | | | | + # |----------------------------------------------------------------------| + # + # |----------------------------------------------------------------------| + # | | | + # | Base 15:0 | Segment Limit 15:0 | + # | | | + # |----------------------------------------------------------------------| + +gdt_ptr: + # Set up an entry for kernel CS + .quad 0x00CF9A000000FFFF + + # Set up an entry for kernel DS + .quad 0x00CF92000000FFFF + + # Set up an entry for user CS + .quad 0x00CFFA000000FFFF + + # Set up an entry for user DS + .quad 0x00CFF2000000FFFF + + # Set up an entry for TSS +tss_desc_ptr: + .quad 0 + + # Set up one LDT +ldt_desc_ptr: + .quad 0 + +gdt_bottom: + + .align 16 +ldt: + .rept 4 + .quad 0 + .endr +ldt_bottom: + +.align 4 + .word 0 # Padding +idt_desc_ptr: + .word idt_bottom - idt - 1 + .long idt + .align 16 +idt: +_idt: + .rept NUM_VEC + .quad 0 + .endr +idt_bottom: diff --git a/x86_desc.h b/x86_desc.h new file mode 100644 index 0000000..962f805 --- /dev/null +++ b/x86_desc.h @@ -0,0 +1,298 @@ +/* x86_desc.h - Defines for various x86 descriptors, descriptor tables, + * and selectors + * vim:ts=4 noexpandtab + */ + +#ifndef _X86_DESC_H +#define _X86_DESC_H + +#include "types.h" + +/* Segment selector values */ +#define KERNEL_CS 0x0010 +#define KERNEL_DS 0x0018 +#define USER_CS 0x0023 +#define USER_DS 0x002B +#define KERNEL_TSS 0x0030 +#define KERNEL_LDT 0x0038 + +/* Size of the task state segment (TSS) */ +#define TSS_SIZE 104 + +/* Number of vectors in the interrupt descriptor table (IDT) */ +#define NUM_VEC 256 + +#ifndef ASM + +/* This structure is used to load descriptor base registers + * like the GDTR and IDTR */ +typedef struct x86_desc { + uint16_t padding; + uint16_t size; + uint32_t addr; +} x86_desc_t; + +/* This is a segment descriptor. It goes in the GDT. */ +typedef struct seg_desc { + union { + uint32_t val; + struct { + uint16_t seg_lim_15_00; + uint16_t base_15_00; + uint8_t base_23_16; + uint32_t type : 4; + uint32_t sys : 1; + uint32_t dpl : 2; + uint32_t present : 1; + uint32_t seg_lim_19_16 : 4; + uint32_t avail : 1; + uint32_t reserved : 1; + uint32_t opsize : 1; + uint32_t granularity : 1; + uint8_t base_31_24; + } __attribute__((packed)); + }; +} seg_desc_t; + +/* TSS structure */ +typedef struct __attribute__((packed)) tss_t { + uint16_t prev_task_link; + uint16_t prev_task_link_pad; + + uint32_t esp0; + uint16_t ss0; + uint16_t ss0_pad; + + uint32_t esp1; + uint16_t ss1; + uint16_t ss1_pad; + + uint32_t esp2; + uint16_t ss2; + uint16_t ss2_pad; + + uint32_t cr3; + + uint32_t eip; + uint32_t eflags; + + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + + uint16_t es; + uint16_t es_pad; + + uint16_t cs; + uint16_t cs_pad; + + uint16_t ss; + uint16_t ss_pad; + + uint16_t ds; + uint16_t ds_pad; + + uint16_t fs; + uint16_t fs_pad; + + uint16_t gs; + uint16_t gs_pad; + + uint16_t ldt_segment_selector; + uint16_t ldt_pad; + + uint16_t debug_trap : 1; + uint16_t io_pad : 15; + uint16_t io_base_addr; +} tss_t; + +/* Some external descriptors declared in .S files */ +extern x86_desc_t gdt_desc; + +extern uint16_t ldt_desc; +extern uint32_t ldt_size; +extern seg_desc_t ldt_desc_ptr; +extern seg_desc_t gdt_ptr; +extern uint32_t ldt; + +extern uint32_t tss_size; +extern seg_desc_t tss_desc_ptr; +extern tss_t tss; + +/* Sets runtime-settable parameters in the GDT entry for the LDT */ +#define SET_LDT_PARAMS(str, addr, lim) \ +do { \ + str.base_31_24 = ((uint32_t)(addr) & 0xFF000000) >> 24; \ + str.base_23_16 = ((uint32_t)(addr) & 0x00FF0000) >> 16; \ + str.base_15_00 = (uint32_t)(addr) & 0x0000FFFF; \ + str.seg_lim_19_16 = ((lim) & 0x000F0000) >> 16; \ + str.seg_lim_15_00 = (lim) & 0x0000FFFF; \ +} while(0) + +/* Sets runtime parameters for the TSS */ +#define SET_TSS_PARAMS(str, addr, lim) \ +do { \ + str.base_31_24 = ((uint32_t)(addr) & 0xFF000000) >> 24; \ + str.base_23_16 = ((uint32_t)(addr) & 0x00FF0000) >> 16; \ + str.base_15_00 = (uint32_t)(addr) & 0x0000FFFF; \ + str.seg_lim_19_16 = ((lim) & 0x000F0000) >> 16; \ + str.seg_lim_15_00 = (lim) & 0x0000FFFF; \ +} while(0) + +/* An interrupt descriptor entry (goes into the IDT) */ +typedef union idt_desc_t { + uint32_t val; + struct { + uint16_t offset_15_00; + uint16_t seg_selector; + uint8_t reserved4; + uint32_t reserved3 : 1; + uint32_t reserved2 : 1; + uint32_t reserved1 : 1; + uint32_t size : 1; + uint32_t reserved0 : 1; + uint32_t dpl : 2; + uint32_t present : 1; + uint16_t offset_31_16; + } __attribute__((packed)); +} idt_desc_t; + +/* The IDT itself (declared in x86_desc.S */ +extern idt_desc_t idt[NUM_VEC]; +/* The descriptor used to load the IDTR */ +extern x86_desc_t idt_desc_ptr; +/* Sets runtime parameters for an IDT entry */ +#define SET_IDT_ENTRY(str, handler) \ +do { \ + str.offset_31_16 = ((uint32_t)(handler) & 0xFFFF0000) >> 16; \ + str.offset_15_00 = ((uint32_t)(handler) & 0xFFFF); \ +} while(0) + +static inline void set_trap_gate (unsigned int n, void *handler) +{ + idt[n].seg_selector = KERNEL_CS; + idt[n].reserved4 = 0; + idt[n].reserved3 = 1; + idt[n].reserved2 = 1; + idt[n].reserved1 = 1; + idt[n].size = 1; + idt[n].reserved0 = 0; + idt[n].dpl = 0; //0 + idt[n].present = 1; + SET_IDT_ENTRY(idt[n], handler); +} + +static inline void set_system_gate (unsigned int n, void *handler) +{ + + idt[n].seg_selector = KERNEL_CS; + idt[n].reserved4 = 0; + idt[n].reserved3 = 1; + idt[n].reserved2 = 1; + idt[n].reserved1 = 1; + idt[n].size = 1; + idt[n].reserved0 = 0; + idt[n].dpl = 3; + idt[n].present = 1; + SET_IDT_ENTRY(idt[n], handler); + +} + +static inline void set_intr_gate (unsigned int n, void *handler) +{ + + idt[n].seg_selector = KERNEL_CS; + idt[n].reserved4 = 0; + idt[n].reserved3 = 0; + idt[n].reserved2 = 1; + idt[n].reserved1 = 1; + idt[n].size = 1; + idt[n].reserved0 = 0; + idt[n].dpl = 0;// 0 + idt[n].present = 1; + SET_IDT_ENTRY(idt[n], handler); + +} + + +static inline void set_system_intr_gate (unsigned int n, void *handler) +{ + + idt[n].seg_selector = KERNEL_CS; + idt[n].reserved4 = 0; + idt[n].reserved3 = 0; + idt[n].reserved2 = 1; + idt[n].reserved1 = 1; + idt[n].size = 1; + idt[n].reserved0 = 0; + idt[n].dpl = 3; + idt[n].present = 1; + SET_IDT_ENTRY(idt[n], handler); + +} + +static inline void set_task_gate (unsigned int n, unsigned int gdt) +{ + + + idt[n].seg_selector = gdt<<3; + idt[n].reserved4 = 0; + idt[n].reserved3 = 1; + idt[n].reserved2 = 0; + idt[n].reserved1 = 1; + idt[n].size = 0; + idt[n].reserved0 = 0; + idt[n].dpl = 3; + idt[n].present = 1; + + +} + + + + +/* Load task register. This macro takes a 16-bit index into the GDT, + * which points to the TSS entry. x86 then reads the GDT's TSS + * descriptor and loads the base address specified in that descriptor + * into the task register */ +#define ltr(desc) \ +do { \ + asm volatile("ltr %w0" \ + : \ + : "r" (desc) \ + : "memory", "cc" ); \ +} while(0) + +/* Load the interrupt descriptor table (IDT). This macro takes a 32-bit + * address which points to a 6-byte structure. The 6-byte structure + * (defined as "struct x86_desc" above) contains a 2-byte size field + * specifying the size of the IDT, and a 4-byte address field specifying + * the base address of the IDT. */ +#define lidt(desc) \ +do { \ + asm volatile("lidt (%0)" \ + : \ + : "g" (desc) \ + : "memory"); \ +} while(0) + +/* Load the local descriptor table (LDT) register. This macro takes a + * 16-bit index into the GDT, which points to the LDT entry. x86 then + * reads the GDT's LDT descriptor and loads the base address specified + * in that descriptor into the LDT register */ +#define lldt(desc) \ +do { \ + asm volatile("lldt %%ax" \ + : \ + : "a" (desc) \ + : "memory" ); \ +} while(0) + +#endif /* ASM */ + +#endif /* _x86_DESC_H */ diff --git a/x86_desc.o b/x86_desc.o new file mode 100644 index 0000000..9c5924a Binary files /dev/null and b/x86_desc.o differ