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