採用微核心。
IPC 分為兩種:
IPC 分為兩種:
- 非同步 IPC:送完訊息就不管了
- 同步 IPC:發送者一直等到接收者收到訊息才放手,接收者接不到訊息就一直等著。優勢如下:
- 作業系統無須另外維護緩衝區來存放正在傳遞的訊息
- 作業系統無須保留一份訊息副本
- 作業系統無須維護接收佇列(發送佇列還是需要的)
- 發送者和接收者都可在任何時刻清晰且容易第知道訊息是否送達。
假設有處理序 A 想要向 B 發送訊息 M,其過程如下:
- A 首先準備好 M
- A 透過系統使用 sendrec,最終使用 msg_send
- 簡單判斷是否發生鎖死
- 判斷目標處理序 B 是否正在等待來自 A 的訊息
- 如果是:訊息被複製給 B,B被解除阻塞,繼續執行
- 如果否:A 被阻塞,並被加入到 B 的發送佇列中
假設有處理序 B 想要接收訊息(來自特定處理序、中斷或者任意處理序),其過程如下:
- B 準備一個空的訊息結構體 M,用於接收訊息
- B 通過系統使用 sendrec,最終使用 msg_receive
- 判斷 B 是否有個來自硬體的訊息(通過 has_int_msg),如果是,且 B 準備接收來自中斷的訊息或準備接收任意訊息,則馬上準備一個訊息給 B,並返回。
- 如果 B 想接收來自任意處理序的訊息,則從自己的發送佇列中選取締一個(如果佇列非空的話),將其訊息複製給 M
- 如果 B 想接收來自特定處理序 A 的訊息,則先判斷 A 是否正在等待向 B 發送訊息,若是的話,將其訊息複製給 M
- 如果此時沒有任何處理序發訊息給 B,B 會被阻塞
程式碼
include/string.h (新增)
/** * `phys_copy' and `phys_set' are used only in the kernel, where segments * are all flat (based on 0). In the meanwhile, currently linear address * space is mapped to the identical physical address space. Therefore, * a `physical copy' will be as same as a common copy, so does `phys_set'. */ #define phys_copy memcpy #define phys_set memset
include/console.h
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ console.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #ifndef _ORANGES_CONSOLE_H_ #define _ORANGES_CONSOLE_H_ /* CONSOLE */ typedef struct s_console { unsigned int current_start_addr; /* 當前顯示到了什麼位置 */ unsigned int original_addr; /* 當前控制台對應顯存位置 */ unsigned int v_mem_limit; /* 當前控制台占的顯存大小 */ unsigned int cursor; /* 當前光標位置 */ }CONSOLE; #define SCR_UP 1 /* scroll forward */ #define SCR_DN -1 /* scroll backward */ #define SCREEN_SIZE (80 * 25) #define SCREEN_WIDTH 80 #define DEFAULT_CHAR_COLOR 0x07 /* 0000 0111 黑底白字 */ #endif /* _ORANGES_CONSOLE_H_ */
include/const.h
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ const.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #ifndef _ORANGES_CONST_H_ #define _ORANGES_CONST_H_ #define ASSERT #ifdef ASSERT void assertion_failure(char *exp, char *file, char *base_file, int line); #define assert(exp if (exp); \ else assertion_failure(#exp, __FILE__, __BASE_FILE__, __LINE__) #else #define assert(exp) #endif /* EXTERN */ #define EXTERN extern /* EXTERN is defined as extern except in global.c */ /* 函數類型 */ #define PUBLIC /* PUBLIC is the opposite of PRIVATE */ #define PRIVATE static /* PRIVATE x limits the scope of x */ /* Color */ /* * e.g. MAKE_COLOR(BLUE, RED) * MAKE_COLOR(BLACK, RED) | BRIGHT * MAKE_COLOR(BLACK, RED) | BRIGHT | FLASH */ #define BLACK 0x0 /* 0000 */ #define WHITE 0x7 /* 0111 */ #define RED 0x4 /* 0100 */ #define GREEN 0x2 /* 0010 */ #define BLUE 0x1 /* 0001 */ #define FLASH 0x80 /* 1000 0000 */ #define BRIGHT 0x08 /* 0000 1000 */ #define MAKE_COLOR(x,y) (x | y) /* MAKE_COLOR(Background,Foreground) */ /* GDT 和 IDT 中描述符的個數 */ #define GDT_SIZE 128 #define IDT_SIZE 256 /* 權限 */ #define PRIVILEGE_KRNL 0 #define PRIVILEGE_TASK 1 #define PRIVILEGE_USER 3 /* RPL */ #define RPL_KRNL SA_RPL0 #define RPL_TASK SA_RPL1 #define RPL_USER SA_RPL3 /* TTY */ #define NR_CONSOLES 3 /* consoles */ /* 8259A interrupt controller ports. */ #define INT_M_CTL 0x20 /* I/O port for interrupt controller <Master> */ #define INT_M_CTLMASK 0x21 /* setting bits in this port disables ints <Master> */ #define INT_S_CTL 0xA0 /* I/O port for second interrupt controller <Slave> */ #define INT_S_CTLMASK 0xA1 /* setting bits in this port disables ints <Slave> */ /* 8253/8254 PIT (Programmable Interval Timer) */ #define TIMER0 0x40 /* I/O port for timer channel 0 */ #define TIMER_MODE 0x43 /* I/O port for timer mode control */ #define RATE_GENERATOR 0x34 /* 00-11-010-0 : * Counter0 - LSB then MSB - rate generator - binary */ #define TIMER_FREQ 1193182L/* clock frequency for timer in PC and AT */ #define HZ 100 /* clock freq (software settable on IBM-PC) */ /* AT keyboard */ /* 8042 ports */ #define KB_DATA 0x60 /* I/O port for keyboard data Read : Read Output Buffer Write: Write Input Buffer(8042 Data&8048 Command) */ #define KB_CMD 0x64 /* I/O port for keyboard command Read : Read Status Register Write: Write Input Buffer(8042 Command) */ #define LED_CODE 0xED #define KB_ACK 0xFA /* VGA */ #define CRTC_ADDR_REG 0x3D4 /* CRT Controller Registers - Addr Register */ #define CRTC_DATA_REG 0x3D5 /* CRT Controller Registers - Data Register */ #define START_ADDR_H 0xC /* reg index of video mem start addr (MSB) */ #define START_ADDR_L 0xD /* reg index of video mem start addr (LSB) */ #define CURSOR_H 0xE /* reg index of cursor position (MSB) */ #define CURSOR_L 0xF /* reg index of cursor position (LSB) */ #define V_MEM_BASE 0xB8000 /* base of color video memory */ #define V_MEM_SIZE 0x8000 /* 32K: B8000H -> BFFFFH */ /* Hardware interrupts */ #define NR_IRQ 16 /* Number of IRQs */ #define CLOCK_IRQ 0 #define KEYBOARD_IRQ 1 #define CASCADE_IRQ 2 /* cascade enable for 2nd AT controller */ #define ETHER_IRQ 3 /* default ethernet interrupt vector */ #define SECONDARY_IRQ 3 /* RS232 interrupt vector for port 2 */ #define RS232_IRQ 4 /* RS232 interrupt vector for port 1 */ #define XT_WINI_IRQ 5 /* xt winchester */ #define FLOPPY_IRQ 6 /* floppy disk */ #define PRINTER_IRQ 7 #define AT_WINI_IRQ 14 /* at winchester */ /* system call */ #define NR_SYS_CALL 2 #endif /* _ORANGES_CONST_H_ */
include/global.h
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ global.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* EXTERN is defined as extern except in global.c */ #ifdef GLOBAL_VARIABLES_HERE #undef EXTERN #define EXTERN #endif EXTERN int ticks; EXTERN int disp_pos; EXTERN u8 gdt_ptr[6]; // 0~15:Limit 16~47:Base EXTERN DESCRIPTOR gdt[GDT_SIZE]; EXTERN u8 idt_ptr[6]; // 0~15:Limit 16~47:Base EXTERN GATE idt[IDT_SIZE]; EXTERN u32 k_reenter; EXTERN TSS tss; EXTERN PROCESS* p_proc_ready; EXTERN int nr_current_console; extern PROCESS proc_table[]; extern char task_stack[]; extern TASK task_table[]; extern TASK user_proc_table[]; extern irq_handler irq_table[]; extern TTY tty_table[]; extern CONSOLE console_table[];
include/proc.h
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ proc.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ typedef struct s_stackframe { /* proc_ptr points here ↑ Low */ u32 gs; /* ┓ │ */ u32 fs; /* ┃ │ */ u32 es; /* ┃ │ */ u32 ds; /* ┃ │ */ u32 edi; /* ┃ │ */ u32 esi; /* ┣ pushed by save() │ */ u32 ebp; /* ┃ │ */ u32 kernel_esp; /* <- 'popad' will ignore it │ */ u32 ebx; /* ┃ ↑棧從高地址往低地址增長*/ u32 edx; /* ┃ │ */ u32 ecx; /* ┃ │ */ u32 eax; /* ┛ │ */ u32 retaddr; /* return address for assembly code save() │ */ u32 eip; /* ┓ │ */ u32 cs; /* ┃ │ */ u32 eflags; /* ┣ these are pushed by CPU during interrupt │ */ u32 esp; /* ┃ │ */ u32 ss; /* ┛ ┷High */ }STACK_FRAME; typedef struct s_proc { STACK_FRAME regs; /* process registers saved in stack frame */ u16 ldt_sel; /* gdt selector giving ldt base and limit */ DESCRIPTOR ldts[LDT_SIZE]; /* local descriptors for code and data */ int ticks; /* remained ticks */ int priority; u32 pid; /* process id passed in from MM */ char p_name[16]; /* name of the process */ int nr_tty; }PROCESS; typedef struct s_task { task_f initial_eip; int stacksize; char name[32]; }TASK; /* Number of tasks & procs */ #define NR_TASKS 1 #define NR_PROCS 3 /* stacks of tasks */ #define STACK_SIZE_TTY 0x8000 #define STACK_SIZE_TESTA 0x8000 #define STACK_SIZE_TESTB 0x8000 #define STACK_SIZE_TESTC 0x8000 #define STACK_SIZE_TOTAL (STACK_SIZE_TTY + \ STACK_SIZE_TESTA + \ STACK_SIZE_TESTB + \ STACK_SIZE_TESTC)
include/protect.h
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ protect.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #ifndef _ORANGES_PROTECT_H_ #define _ORANGES_PROTECT_H_ /* 存儲段描述符/系統段描述符 */ typedef struct s_descriptor /* 共 8 個字節 */ { u16 limit_low; /* Limit */ u16 base_low; /* Base */ u8 base_mid; /* Base */ u8 attr1; /* P(1) DPL(2) DT(1) TYPE(4) */ u8 limit_high_attr2; /* G(1) D(1) 0(1) AVL(1) LimitHigh(4) */ u8 base_high; /* Base */ }DESCRIPTOR; /* 門描述符 */ typedef struct s_gate { u16 offset_low; /* Offset Low */ u16 selector; /* Selector */ u8 dcount; /* 該字段只在調用門描述符中有效。 如果在利用調用門調用子程序時引起特權級的轉換和堆棧的改變,需要將外層堆棧中的參數複製到內層堆棧。 該雙字計數字段就是用於說明這種情況發生時,要複製的雙字參數的數量。 */ u8 attr; /* P(1) DPL(2) DT(1) TYPE(4) */ u16 offset_high; /* Offset High */ }GATE; typedef struct s_tss { u32 backlink; u32 esp0; /* stack pointer to use during interrupt */ u32 ss0; /* " segment " " " " */ u32 esp1; u32 ss1; u32 esp2; u32 ss2; u32 cr3; u32 eip; u32 flags; u32 eax; u32 ecx; u32 edx; u32 ebx; u32 esp; u32 ebp; u32 esi; u32 edi; u32 es; u32 cs; u32 ss; u32 ds; u32 fs; u32 gs; u32 ldt; u16 trap; u16 iobase; /* I/O位圖基址大於或等於TSS段界限,就表示沒有I/O許可位圖 */ /*u8 iomap[2];*/ }TSS; /* GDT */ /* 描述符索引 */ #define INDEX_DUMMY 0 // ┓ #define INDEX_FLAT_C 1 // ┣ LOADER 裡面已經確定了的. #define INDEX_FLAT_RW 2 // ┃ #define INDEX_VIDEO 3 // ┛ #define INDEX_TSS 4 #define INDEX_LDT_FIRST 5 /* 選擇子 */ #define SELECTOR_DUMMY 0 // ┓ #define SELECTOR_FLAT_C 0x08 // ┣ LOADER 裡面已經確定了的. #define SELECTOR_FLAT_RW 0x10 // ┃ #define SELECTOR_VIDEO (0x18+3) // ┛<-- RPL=3 #define SELECTOR_TSS 0x20 // TSS. 從外層跳到內存時 SS 和 ESP 的值從裡面獲得. #define SELECTOR_LDT_FIRST 0x28 #define SELECTOR_KERNEL_CS SELECTOR_FLAT_C #define SELECTOR_KERNEL_DS SELECTOR_FLAT_RW #define SELECTOR_KERNEL_GS SELECTOR_VIDEO /* 每個任務有一個單獨的 LDT, 每個 LDT 中的描述符個數: */ #define LDT_SIZE 2 /* 描述符類型值說明 */ #define DA_32 0x4000 /* 32 位段 */ #define DA_LIMIT_4K 0x8000 /* 段界限粒度為 4K 字節 */ #define DA_DPL0 0x00 /* DPL = 0 */ #define DA_DPL1 0x20 /* DPL = 1 */ #define DA_DPL2 0x40 /* DPL = 2 */ #define DA_DPL3 0x60 /* DPL = 3 */ /* 存儲段描述符類型值說明 */ #define DA_DR 0x90 /* 存在的只讀數據段類型值 */ #define DA_DRW 0x92 /* 存在的可讀寫數據段屬性值 */ #define DA_DRWA 0x93 /* 存在的已訪問可讀寫數據段類型值 */ #define DA_C 0x98 /* 存在的只執行代碼段屬性值 */ #define DA_CR 0x9A /* 存在的可執行可讀代碼段屬性值 */ #define DA_CCO 0x9C /* 存在的只執行一致代碼段屬性值 */ #define DA_CCOR 0x9E /* 存在的可執行可讀一致代碼段屬性值 */ /* 系統段描述符類型值說明 */ #define DA_LDT 0x82 /* 局部描述符表段類型值 */ #define DA_TaskGate 0x85 /* 任務門類型值 */ #define DA_386TSS 0x89 /* 可用 386 任務狀態段類型值 */ #define DA_386CGate 0x8C /* 386 調用門類型值 */ #define DA_386IGate 0x8E /* 386 中斷門類型值 */ #define DA_386TGate 0x8F /* 386 陷阱門類型值 */ /* 選擇子類型值說明 */ /* 其中, SA_ : Selector Attribute */ #define SA_RPL_MASK 0xFFFC #define SA_RPL0 0 #define SA_RPL1 1 #define SA_RPL2 2 #define SA_RPL3 3 #define SA_TI_MASK 0xFFFB #define SA_TIG 0 #define SA_TIL 4 /* 中斷向量 */ #define INT_VECTOR_DIVIDE 0x0 #define INT_VECTOR_DEBUG 0x1 #define INT_VECTOR_NMI 0x2 #define INT_VECTOR_BREAKPOINT 0x3 #define INT_VECTOR_OVERFLOW 0x4 #define INT_VECTOR_BOUNDS 0x5 #define INT_VECTOR_INVAL_OP 0x6 #define INT_VECTOR_COPROC_NOT 0x7 #define INT_VECTOR_DOUBLE_FAULT 0x8 #define INT_VECTOR_COPROC_SEG 0x9 #define INT_VECTOR_INVAL_TSS 0xA #define INT_VECTOR_SEG_NOT 0xB #define INT_VECTOR_STACK_FAULT 0xC #define INT_VECTOR_PROTECTION 0xD #define INT_VECTOR_PAGE_FAULT 0xE #define INT_VECTOR_COPROC_ERR 0x10 /* 中斷向量 */ #define INT_VECTOR_IRQ0 0x20 #define INT_VECTOR_IRQ8 0x28 /* 系統調用 */ #define INT_VECTOR_SYS_CALL 0x90 /* 宏 */ /* 線性地址 → 物理地址 */ #define vir2phys(seg_base, vir) (u32)(((u32)seg_base) + (u32)(vir)) #endif /* _ORANGES_PROTECT_H_ */
include/proto.h
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ proto.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* klib.asm */ PUBLIC void out_byte(u16 port, u8 value); PUBLIC u8 in_byte(u16 port); PUBLIC void disp_str(char * info); PUBLIC void disp_color_str(char * info, int color); /* protect.c */ PUBLIC void init_prot(); PUBLIC u32 seg2phys(u16 seg); /* klib.c */ PUBLIC void delay(int time); /* kernel.asm */ void restart(); /* main.c */ void TestA(); void TestB(); void TestC(); /* i8259.c */ PUBLIC void put_irq_handler(int irq, irq_handler handler); PUBLIC void spurious_irq(int irq); /* clock.c */ PUBLIC void clock_handler(int irq); PUBLIC void init_clock(); /* keyboard.c */ PUBLIC void init_keyboard(); /* tty.c */ PUBLIC void task_tty(); PUBLIC void in_process(TTY* p_tty, u32 key); /* console.c */ PUBLIC void out_char(CONSOLE* p_con, char ch); PUBLIC void scroll_screen(CONSOLE* p_con, int direction); /* printf.c */ PUBLIC int printf(const char *fmt, ...); /* vsprintf.c */ PUBLIC int vsprintf(char *buf, const char *fmt, va_list args); /* 以下是系統調用相關 */ /* 系統調用 - 系統級 */ /* proc.c */ PUBLIC int sys_get_ticks(); PUBLIC int sys_write(char* buf, int len, PROCESS* p_proc); /* syscall.asm */ PUBLIC void sys_call(); /* int_handler */ /* 系統調用 - 用戶級 */ PUBLIC int get_ticks(); PUBLIC void write(char* buf, int len);
include/type.h
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ type.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #ifndef _ORANGES_TYPE_H_ #define _ORANGES_TYPE_H_ typedef unsigned int u32; typedef unsigned short u16; typedef unsigned char u8; typedef char * va_list; typedef void (*int_handler) (); typedef void (*task_f) (); typedef void (*irq_handler) (int irq); typedef void* system_call; #endif /* _ORANGES_TYPE_H_ */
kernel/console.c
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ console.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* 迴車鍵: 把光標移到第一列 換行鍵: 把光標前進到下一行 */ #include "type.h" #include "const.h" #include "protect.h" #include "string.h" #include "proc.h" #include "tty.h" #include "console.h" #include "global.h" #include "keyboard.h" #include "proto.h" PRIVATE void set_cursor(unsigned int position); PRIVATE void set_video_start_addr(u32 addr); PRIVATE void flush(CONSOLE* p_con); /*======================================================================* init_screen *======================================================================*/ PUBLIC void init_screen(TTY* p_tty) { int nr_tty = p_tty - tty_table; p_tty->p_console = console_table + nr_tty; int v_mem_size = V_MEM_SIZE >> 1; /* 顯存總大小 (in WORD) */ int con_v_mem_size = v_mem_size / NR_CONSOLES; p_tty->p_console->original_addr = nr_tty * con_v_mem_size; p_tty->p_console->v_mem_limit = con_v_mem_size; p_tty->p_console->current_start_addr = p_tty->p_console->original_addr; /* 默認光標位置在最開始處 */ p_tty->p_console->cursor = p_tty->p_console->original_addr; if (nr_tty == 0) { /* 第一個控制台沿用原來的光標位置 */ p_tty->p_console->cursor = disp_pos / 2; disp_pos = 0; } else { out_char(p_tty->p_console, nr_tty + '0'); out_char(p_tty->p_console, '#'); } set_cursor(p_tty->p_console->cursor); } /*======================================================================* is_current_console *======================================================================*/ PUBLIC int is_current_console(CONSOLE* p_con) { return (p_con == &console_table[nr_current_console]); } /*======================================================================* out_char *======================================================================*/ PUBLIC void out_char(CONSOLE* p_con, char ch) { u8* p_vmem = (u8*)(V_MEM_BASE + p_con->cursor * 2); switch(ch) { case '\n': if (p_con->cursor < p_con->original_addr + p_con->v_mem_limit - SCREEN_WIDTH) { p_con->cursor = p_con->original_addr + SCREEN_WIDTH * ((p_con->cursor - p_con->original_addr) / SCREEN_WIDTH + 1); } break; case '\b': if (p_con->cursor > p_con->original_addr) { p_con->cursor--; *(p_vmem-2) = ' '; *(p_vmem-1) = DEFAULT_CHAR_COLOR; } break; default: if (p_con->cursor < p_con->original_addr + p_con->v_mem_limit - 1) { *p_vmem++ = ch; *p_vmem++ = DEFAULT_CHAR_COLOR; p_con->cursor++; } break; } while (p_con->cursor >= p_con->current_start_addr + SCREEN_SIZE) { scroll_screen(p_con, SCR_DN); } flush(p_con); } /*======================================================================* flush *======================================================================*/ PRIVATE void flush(CONSOLE* p_con) { if (is_current_console(p_con)) { set_cursor(p_con->cursor); set_video_start_addr(p_con->current_start_addr); } } /*======================================================================* set_cursor *======================================================================*/ PRIVATE void set_cursor(unsigned int position) { disable_int(); out_byte(CRTC_ADDR_REG, CURSOR_H); out_byte(CRTC_DATA_REG, (position >> 8) & 0xFF); out_byte(CRTC_ADDR_REG, CURSOR_L); out_byte(CRTC_DATA_REG, position & 0xFF); enable_int(); } /*======================================================================* set_video_start_addr *======================================================================*/ PRIVATE void set_video_start_addr(u32 addr) { disable_int(); out_byte(CRTC_ADDR_REG, START_ADDR_H); out_byte(CRTC_DATA_REG, (addr >> 8) & 0xFF); out_byte(CRTC_ADDR_REG, START_ADDR_L); out_byte(CRTC_DATA_REG, addr & 0xFF); enable_int(); } /*======================================================================* select_console *======================================================================*/ PUBLIC void select_console(int nr_console) /* 0 ~ (NR_CONSOLES - 1) */ { if ((nr_console < 0) || (nr_console >= NR_CONSOLES)) { return; } nr_current_console = nr_console; flush(&console_table[nr_console]); } /*======================================================================* scroll_screen *----------------------------------------------------------------------* 滾屏. *----------------------------------------------------------------------* direction: SCR_UP : 向上滾屏 SCR_DN : 向下滾屏 其它 : 不做處理 *======================================================================*/ PUBLIC void scroll_screen(CONSOLE* p_con, int direction) { if (direction == SCR_UP) { if (p_con->current_start_addr > p_con->original_addr) { p_con->current_start_addr -= SCREEN_WIDTH; } } else if (direction == SCR_DN) { if (p_con->current_start_addr + SCREEN_SIZE < p_con->original_addr + p_con->v_mem_limit) { p_con->current_start_addr += SCREEN_WIDTH; } } else{ } flush(p_con); }
kernel/global.c
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ global.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #define GLOBAL_VARIABLES_HERE #include "type.h" #include "const.h" #include "protect.h" #include "tty.h" #include "console.h" #include "proc.h" #include "global.h" #include "proto.h" PUBLIC PROCESS proc_table[NR_TASKS + NR_PROCS]; PUBLIC TASK task_table[NR_TASKS] = { {task_tty, STACK_SIZE_TTY, "tty"}}; PUBLIC TASK user_proc_table[NR_PROCS] = { {TestA, STACK_SIZE_TESTA, "TestA"}, {TestB, STACK_SIZE_TESTB, "TestB"}, {TestC, STACK_SIZE_TESTC, "TestC"}}; PUBLIC char task_stack[STACK_SIZE_TOTAL]; PUBLIC TTY tty_table[NR_CONSOLES]; PUBLIC CONSOLE console_table[NR_CONSOLES]; PUBLIC irq_handler irq_table[NR_IRQ]; PUBLIC system_call sys_call_table[NR_SYS_CALL] = {sys_get_ticks, sys_write};
kernel/kernel.asm
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; kernel.asm ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Forrest Yu, 2005 ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %include "sconst.inc" ; 導入函數 extern cstart extern kernel_main extern exception_handler extern spurious_irq extern clock_handler extern disp_str extern delay extern irq_table ; 導入全局變量 extern gdt_ptr extern idt_ptr extern p_proc_ready extern tss extern disp_pos extern k_reenter extern sys_call_table bits 32 [SECTION .data] clock_int_msg db "^", 0 [SECTION .bss] StackSpace resb 2 * 1024 StackTop: ; 堆疊頂 [section .text] ; 程式碼在此 global _start ; 導出 _start global restart global sys_call global divide_error global single_step_exception global nmi global breakpoint_exception global overflow global bounds_check global inval_opcode global copr_not_available global double_fault global copr_seg_overrun global inval_tss global segment_not_present global stack_exception global general_protection global page_fault global copr_error global hwint00 global hwint01 global hwint02 global hwint03 global hwint04 global hwint05 global hwint06 global hwint07 global hwint08 global hwint09 global hwint10 global hwint11 global hwint12 global hwint13 global hwint14 global hwint15 _start: ; 此時記憶體看上去是這樣的(更詳細的記憶體情況在 LOADER.ASM 中有說明): ; ┃ ┃ ; ┃ ... ┃ ; ┣━━━━━━━━━━━━━━━━━━┫ ; ┃■■■■■■Page Tables■■■■■■┃ ; ┃■■■■■(大小由LOADER決定)■■■■┃ PageTblBase ; 00101000h ┣━━━━━━━━━━━━━━━━━━┫ ; ┃■■■■Page Directory Table■■■■┃ PageDirBase = 1M ; 00100000h ┣━━━━━━━━━━━━━━━━━━┫ ; ┃□□□□ Hardware Reserved □□□□┃ B8000h ← gs ; 9FC00h ┣━━━━━━━━━━━━━━━━━━┫ ; ┃■■■■■■■LOADER.BIN■■■■■■┃ somewhere in LOADER ← esp ; 90000h ┣━━━━━━━━━━━━━━━━━━┫ ; ┃■■■■■■■KERNEL.BIN■■■■■■┃ ; 80000h ┣━━━━━━━━━━━━━━━━━━┫ ; ┃■■■■■■■■KERNEL■■■■■■■┃ 30400h ← KERNEL 入口 (KernelEntryPointPhyAddr) ; 30000h ┣━━━━━━━━━━━━━━━━━━┫ ; ┋ ... ┋ ; ┋ ┋ ; 0h ┗━━━━━━━━━━━━━━━━━━┛ ← cs, ds, es, fs, ss ; ; ; GDT 以及相應的描述符是這樣的: ; ; Descriptors Selectors ; ┏━━━━━━━━━━━━━━━━━━┓ ; ┃ Dummy Descriptor ┃ ; ┣━━━━━━━━━━━━━━━━━━┫ ; ┃ DESC_FLAT_C (0~4G) ┃ 8h = cs ; ┣━━━━━━━━━━━━━━━━━━┫ ; ┃ DESC_FLAT_RW (0~4G) ┃ 10h = ds, es, fs, ss ; ┣━━━━━━━━━━━━━━━━━━┫ ; ┃ DESC_VIDEO ┃ 1Bh = gs ; ┗━━━━━━━━━━━━━━━━━━┛ ; ; 注意! 在使用 C 程式碼的時候一定要保證 ds, es, ss 這幾個段暫存器的值是一樣的 ; 因為編譯器有可能編譯出使用它們的程式碼, 而編譯器默認它們是一樣的. 比如串拷貝操作會用到 ds 和 es. ; ; ; 把 esp 從 LOADER 挪到 KERNEL mov esp, StackTop ; 堆疊在 bss 段中 mov dword [disp_pos], 0 sgdt [gdt_ptr] ; cstart() 中將會用到 gdt_ptr call cstart ; 在此函數中改變了gdt_ptr,讓它指向新的GDT lgdt [gdt_ptr] ; 使用新的GDT lidt [idt_ptr] jmp SELECTOR_KERNEL_CS:csinit csinit: ; “這個跳轉指令強制使用剛剛初始化的結構”——<<OS:D&I 2nd>> P90. ;jmp 0x40:0 ;ud2 xor eax, eax mov ax, SELECTOR_TSS ltr ax ;sti jmp kernel_main ;hlt ; 中斷和異常 -- 硬件中斷 ; --------------------------------- %macro hwint_master 1 call save in al, INT_M_CTLMASK ; `. or al, (1 << %1) ; | 屏蔽當前中斷 out INT_M_CTLMASK, al ; / mov al, EOI ; `. 置EOI位 out INT_M_CTL, al ; / sti ; CPU在響應中斷的過程中會自動關中斷,這句之後就允許響應新的中斷 push %1 ; `. call [irq_table + 4 * %1] ; | 中斷處理程序 pop ecx ; / cli in al, INT_M_CTLMASK ; `. and al, ~(1 << %1) ; | 恢復接受當前中斷 out INT_M_CTLMASK, al ; / ret %endmacro ALIGN 16 hwint00: ; Interrupt routine for irq 0 (the clock). hwint_master 0 ALIGN 16 hwint01: ; Interrupt routine for irq 1 (keyboard) hwint_master 1 ALIGN 16 hwint02: ; Interrupt routine for irq 2 (cascade!) hwint_master 2 ALIGN 16 hwint03: ; Interrupt routine for irq 3 (second serial) hwint_master 3 ALIGN 16 hwint04: ; Interrupt routine for irq 4 (first serial) hwint_master 4 ALIGN 16 hwint05: ; Interrupt routine for irq 5 (XT winchester) hwint_master 5 ALIGN 16 hwint06: ; Interrupt routine for irq 6 (floppy) hwint_master 6 ALIGN 16 hwint07: ; Interrupt routine for irq 7 (printer) hwint_master 7 ; --------------------------------- %macro hwint_slave 1 push %1 call spurious_irq add esp, 4 hlt %endmacro ; --------------------------------- ALIGN 16 hwint08: ; Interrupt routine for irq 8 (realtime clock). hwint_slave 8 ALIGN 16 hwint09: ; Interrupt routine for irq 9 (irq 2 redirected) hwint_slave 9 ALIGN 16 hwint10: ; Interrupt routine for irq 10 hwint_slave 10 ALIGN 16 hwint11: ; Interrupt routine for irq 11 hwint_slave 11 ALIGN 16 hwint12: ; Interrupt routine for irq 12 hwint_slave 12 ALIGN 16 hwint13: ; Interrupt routine for irq 13 (FPU exception) hwint_slave 13 ALIGN 16 hwint14: ; Interrupt routine for irq 14 (AT winchester) hwint_slave 14 ALIGN 16 hwint15: ; Interrupt routine for irq 15 hwint_slave 15 ; 中斷和異常 -- 異常 divide_error: push 0xFFFFFFFF ; no err code push 0 ; vector_no = 0 jmp exception single_step_exception: push 0xFFFFFFFF ; no err code push 1 ; vector_no = 1 jmp exception nmi: push 0xFFFFFFFF ; no err code push 2 ; vector_no = 2 jmp exception breakpoint_exception: push 0xFFFFFFFF ; no err code push 3 ; vector_no = 3 jmp exception overflow: push 0xFFFFFFFF ; no err code push 4 ; vector_no = 4 jmp exception bounds_check: push 0xFFFFFFFF ; no err code push 5 ; vector_no = 5 jmp exception inval_opcode: push 0xFFFFFFFF ; no err code push 6 ; vector_no = 6 jmp exception copr_not_available: push 0xFFFFFFFF ; no err code push 7 ; vector_no = 7 jmp exception double_fault: push 8 ; vector_no = 8 jmp exception copr_seg_overrun: push 0xFFFFFFFF ; no err code push 9 ; vector_no = 9 jmp exception inval_tss: push 10 ; vector_no = A jmp exception segment_not_present: push 11 ; vector_no = B jmp exception stack_exception: push 12 ; vector_no = C jmp exception general_protection: push 13 ; vector_no = D jmp exception page_fault: push 14 ; vector_no = E jmp exception copr_error: push 0xFFFFFFFF ; no err code push 16 ; vector_no = 10h jmp exception exception: call exception_handler add esp, 4*2 ; 讓堆疊頂指向 EIP,堆疊中從頂向下依次是:EIP、CS、EFLAGS hlt ; ==================================================================================== ; save ; ==================================================================================== save: pushad ; `. push ds ; | push es ; | 保存原暫存器值 push fs ; | push gs ; / ;; 注意,從這裡開始,一直到 `mov esp, StackTop',中間堅決不能用 push/pop 指令, ;; 因為當前 esp 指向 proc_table 裡的某個位置,push 會破壞掉處理序表,導致災難性後果! mov esi, edx ; 保存 edx,因為 edx 裡保存了系統使用的參數 ; (沒用堆疊,而是用了另一個暫存器 esi) mov dx, ss mov ds, dx mov es, dx mov fs, dx mov edx, esi ; 恢復 esi mov esi, esp ;esi = 進程表起始位址 inc dword [k_reenter] ;k_reenter++; cmp dword [k_reenter], 0 ;if(k_reenter ==0) jne .1 ;{ mov esp, StackTop ; mov esp, StackTop <--切換到內核堆疊 push restart ; push restart jmp [esi + RETADR - P_STACKBASE]; return; .1: ;} else { 已經在內核堆疊,不需要再切換 push restart_reenter ; push restart_reenter jmp [esi + RETADR - P_STACKBASE]; return; ;} ; ==================================================================================== ; sys_call ; ==================================================================================== sys_call: call save sti push sti push dword [p_proc_ready] push edx push ecx push ebx call [sys_call_table + eax * 4] add esp, 4 * 4 pop esi mov [esi + EAXREG - P_STACKBASE], eax cli ret ; ==================================================================================== ; restart ; ==================================================================================== restart: mov esp, [p_proc_ready] lldt [esp + P_LDT_SEL] lea eax, [esp + P_STACKTOP] mov dword [tss + TSS3_S_SP0], eax restart_reenter: dec dword [k_reenter] pop gs pop fs pop es pop ds popad add esp, 4 iretd
kernel/keyboard.c
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ keyboard.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #include "type.h" #include "const.h" #include "protect.h" #include "string.h" #include "proc.h" #include "tty.h" #include "console.h" #include "global.h" #include "proto.h" #include "keyboard.h" #include "keymap.h" PRIVATE KB_INPUT kb_in; PRIVATE int code_with_E0; PRIVATE int shift_l; /* l shift state */ PRIVATE int shift_r; /* r shift state */ PRIVATE int alt_l; /* l alt state */ PRIVATE int alt_r; /* r left state */ PRIVATE int ctrl_l; /* l ctrl state */ PRIVATE int ctrl_r; /* l ctrl state */ PRIVATE int caps_lock; /* Caps Lock */ PRIVATE int num_lock; /* Num Lock */ PRIVATE int scroll_lock; /* Scroll Lock */ PRIVATE int column; PRIVATE int caps_lock; /* Caps Lock */ PRIVATE int num_lock; /* Num Lock */ PRIVATE int scroll_lock; /* Scroll Lock */ PRIVATE u8 get_byte_from_kbuf(); PRIVATE void set_leds(); PRIVATE void kb_wait(); PRIVATE void kb_ack(); /*======================================================================* keyboard_handler *======================================================================*/ PUBLIC void keyboard_handler(int irq) { u8 scan_code = in_byte(KB_DATA); if (kb_in.count < KB_IN_BYTES) { *(kb_in.p_head) = scan_code; kb_in.p_head++; if (kb_in.p_head == kb_in.buf + KB_IN_BYTES) { kb_in.p_head = kb_in.buf; } kb_in.count++; } } /*======================================================================* init_keyboard *======================================================================*/ PUBLIC void init_keyboard() { kb_in.count = 0; kb_in.p_head = kb_in.p_tail = kb_in.buf; shift_l = shift_r = 0; alt_l = alt_r = 0; ctrl_l = ctrl_r = 0; caps_lock = 0; num_lock = 1; scroll_lock = 0; set_leds(); put_irq_handler(KEYBOARD_IRQ, keyboard_handler);/*設定鍵盤中斷處理程序*/ enable_irq(KEYBOARD_IRQ); /*開鍵盤中斷*/ } /*======================================================================* keyboard_read *======================================================================*/ PUBLIC void keyboard_read(TTY* p_tty) { u8 scan_code; char output[2]; int make; /* 1: make; 0: break. */ u32 key = 0;/* 用一個整型來表示一個鍵。比如,如果 Home 被按下, * 則 key 值將為定義在 keyboard.h 中的 'HOME'。 */ u32* keyrow; /* 指向 keymap[] 的某一行 */ if(kb_in.count > 0){ code_with_E0 = 0; scan_code = get_byte_from_kbuf(); /* 下面開始解析掃描碼 */ if (scan_code == 0xE1) { int i; u8 pausebrk_scode[] = {0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5}; int is_pausebreak = 1; for(i=1;i<6;i++){ if (get_byte_from_kbuf() != pausebrk_scode[i]) { is_pausebreak = 0; break; } } if (is_pausebreak) { key = PAUSEBREAK; } } else if (scan_code == 0xE0) { scan_code = get_byte_from_kbuf(); /* PrintScreen 被按下 */ if (scan_code == 0x2A) { if (get_byte_from_kbuf() == 0xE0) { if (get_byte_from_kbuf() == 0x37) { key = PRINTSCREEN; make = 1; } } } /* PrintScreen 被釋放 */ if (scan_code == 0xB7) { if (get_byte_from_kbuf() == 0xE0) { if (get_byte_from_kbuf() == 0xAA) { key = PRINTSCREEN; make = 0; } } } /* 不是PrintScreen, 此時scan_code為0xE0緊跟的那個值. */ if (key == 0) { code_with_E0 = 1; } } if ((key != PAUSEBREAK) && (key != PRINTSCREEN)) { /* 首先判斷Make Code 還是 Break Code */ make = (scan_code & FLAG_BREAK ? 0 : 1); /* 先定位到 keymap 中的行 */ keyrow = &keymap[(scan_code & 0x7F) * MAP_COLS]; column = 0; int caps = shift_l || shift_r; if (caps_lock) { if ((keyrow[0] >= 'a') && (keyrow[0] <= 'z')){ caps = !caps; } } if (caps) { column = 1; } if (code_with_E0) { column = 2; } key = keyrow[column]; switch(key) { case SHIFT_L: shift_l = make; break; case SHIFT_R: shift_r = make; break; case CTRL_L: ctrl_l = make; break; case CTRL_R: ctrl_r = make; break; case ALT_L: alt_l = make; break; case ALT_R: alt_l = make; break; case CAPS_LOCK: if (make) { caps_lock = !caps_lock; set_leds(); } break; case NUM_LOCK: if (make) { num_lock = !num_lock; set_leds(); } break; case SCROLL_LOCK: if (make) { scroll_lock = !scroll_lock; set_leds(); } break; default: break; } if (make) { /* 忽略 Break Code */ int pad = 0; /* 首先處理小鍵盤 */ if ((key >= PAD_SLASH) && (key <= PAD_9)) { pad = 1; switch(key) { case PAD_SLASH: key = '/'; break; case PAD_STAR: key = '*'; break; case PAD_MINUS: key = '-'; break; case PAD_PLUS: key = '+'; break; case PAD_ENTER: key = ENTER; break; default: if (num_lock && (key >= PAD_0) && (key <= PAD_9)) { key = key - PAD_0 + '0'; } else if (num_lock && (key == PAD_DOT)) { key = '.'; } else{ switch(key) { case PAD_HOME: key = HOME; break; case PAD_END: key = END; break; case PAD_PAGEUP: key = PAGEUP; break; case PAD_PAGEDOWN: key = PAGEDOWN; break; case PAD_INS: key = INSERT; break; case PAD_UP: key = UP; break; case PAD_DOWN: key = DOWN; break; case PAD_LEFT: key = LEFT; break; case PAD_RIGHT: key = RIGHT; break; case PAD_DOT: key = DELETE; break; default: break; } } break; } } key |= shift_l ? FLAG_SHIFT_L : 0; key |= shift_r ? FLAG_SHIFT_R : 0; key |= ctrl_l ? FLAG_CTRL_L : 0; key |= ctrl_r ? FLAG_CTRL_R : 0; key |= alt_l ? FLAG_ALT_L : 0; key |= alt_r ? FLAG_ALT_R : 0; key |= pad ? FLAG_PAD : 0; in_process(p_tty, key); } } } } /*======================================================================* get_byte_from_kbuf *======================================================================*/ PRIVATE u8 get_byte_from_kbuf() /* 從鍵盤緩衝區中讀取下一個字節 */ { u8 scan_code; while (kb_in.count <= 0) {} /* 等待下一個字節到來 */ disable_int(); scan_code = *(kb_in.p_tail); kb_in.p_tail++; if (kb_in.p_tail == kb_in.buf + KB_IN_BYTES) { kb_in.p_tail = kb_in.buf; } kb_in.count--; enable_int(); return scan_code; } /*======================================================================* kb_wait *======================================================================*/ PRIVATE void kb_wait() /* 等待 8042 的輸入緩衝區空 */ { u8 kb_stat; do { kb_stat = in_byte(KB_CMD); } while (kb_stat & 0x02); } /*======================================================================* kb_ack *======================================================================*/ PRIVATE void kb_ack() { u8 kb_read; do { kb_read = in_byte(KB_DATA); } while (kb_read =! KB_ACK); } /*======================================================================* set_leds *======================================================================*/ PRIVATE void set_leds() { u8 leds = (caps_lock << 2) | (num_lock << 1) | scroll_lock; kb_wait(); out_byte(KB_DATA, LED_CODE); kb_ack(); kb_wait(); out_byte(KB_DATA, leds); kb_ack(); }
kernel/main.c
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #include "type.h" #include "const.h" #include "protect.h" #include "string.h" #include "proc.h" #include "tty.h" #include "console.h" #include "global.h" #include "proto.h" /*======================================================================* kernel_main *======================================================================*/ PUBLIC int kernel_main() { disp_str("-----\"kernel_main\" begins-----\n"); TASK* p_task = task_table; PROCESS* p_proc = proc_table; char* p_task_stack = task_stack + STACK_SIZE_TOTAL; u16 selector_ldt = SELECTOR_LDT_FIRST; int i; u8 privilege; u8 rpl; int eflags; for (i = 0; i < NR_TASKS+NR_PROCS; i++) { if (i < NR_TASKS) { /* 任務 */ p_task = task_table + i; privilege = PRIVILEGE_TASK; rpl = RPL_TASK; eflags = 0x1202; /* IF=1, IOPL=1, bit 2 is always 1 */ } else { /* 用戶進程 */ p_task = user_proc_table + (i - NR_TASKS); privilege = PRIVILEGE_USER; rpl = RPL_USER; eflags = 0x202; /* IF=1, bit 2 is always 1 */ } strcpy(p_proc->p_name, p_task->name); // name of the process p_proc->pid = i; // pid p_proc->ldt_sel = selector_ldt; memcpy(&p_proc->ldts[0], &gdt[SELECTOR_KERNEL_CS >> 3], sizeof(DESCRIPTOR)); p_proc->ldts[0].attr1 = DA_C | privilege << 5; memcpy(&p_proc->ldts[1], &gdt[SELECTOR_KERNEL_DS >> 3], sizeof(DESCRIPTOR)); p_proc->ldts[1].attr1 = DA_DRW | privilege << 5; p_proc->regs.cs = (0 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl; p_proc->regs.ds = (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl; p_proc->regs.es = (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl; p_proc->regs.fs = (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl; p_proc->regs.ss = (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl; p_proc->regs.gs = (SELECTOR_KERNEL_GS & SA_RPL_MASK) | rpl; p_proc->regs.eip = (u32)p_task->initial_eip; p_proc->regs.esp = (u32)p_task_stack; p_proc->regs.eflags = eflags; p_proc->nr_tty = 0; p_task_stack -= p_task->stacksize; p_proc++; p_task++; selector_ldt += 1 << 3; } proc_table[0].ticks = proc_table[0].priority = 15; proc_table[1].ticks = proc_table[1].priority = 5; proc_table[2].ticks = proc_table[2].priority = 5; proc_table[3].ticks = proc_table[3].priority = 5; proc_table[1].nr_tty = 0; proc_table[2].nr_tty = 1; proc_table[3].nr_tty = 1; k_reenter = 0; ticks = 0; p_proc_ready = proc_table; init_clock(); init_keyboard(); restart(); while(1){} } /*======================================================================* TestA *======================================================================*/ void TestA() { int i = 0; while (1) { printf("<Ticks:%x>", get_ticks()); milli_delay(200); } } /*======================================================================* TestB *======================================================================*/ void TestB() { int i = 0x1000; while(1){ printf("B"); milli_delay(200); } } /*======================================================================* TestB *======================================================================*/ void TestC() { int i = 0x2000; while(1){ printf("C"); milli_delay(200); } }
kernel/printf.c
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ printf.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #include "type.h" #include "const.h" /****************************************************************************************** 可變參數函數調用原理(其中涉及的數字皆為舉例) =========================================================================================== i = 0x23; j = 0x78; char fmt[] = "%x%d"; printf(fmt, i, j); push j push i push fmt call printf add esp, 3 * 4 ┃ HIGH ┃ ┃ HIGH ┃ ┃ ... ┃ ┃ ... ┃ ┣━━━━━━━━━━┫ ┣━━━━━━━━━━┫ ┃ ┃ 0x32010┃ '\0' ┃ ┣━━━━━━━━━━┫ ┣━━━━━━━━━━┫ 0x3046C┃ 0x78 ┃ 0x3200c┃ d ┃ ┣━━━━━━━━━━┫ ┣━━━━━━━━━━┫ arg = 0x30468┃ 0x23 ┃ 0x32008┃ % ┃ ┣━━━━━━━━━━┫ ┣━━━━━━━━━━┫ 0x30464┃ 0x32000 ───╂────┐ 0x32004┃ x ┃ ┣━━━━━━━━━━┫ │ ┣━━━━━━━━━━┫ ┃ ┃ └──→ 0x32000┃ % ┃ ┣━━━━━━━━━━┫ ┣━━━━━━━━━━┫ ┃ ... ┃ ┃ ... ┃ ┃ LOW ┃ ┃ LOW ┃ 實際上,調用 vsprintf 的情形是這樣的: vsprintf(buf, 0x32000, 0x30468); ******************************************************************************************/ /*======================================================================* printf *======================================================================*/ int printf(const char *fmt, ...) { int i; char buf[256]; va_list arg = (va_list)((char*)(&fmt) + 4); /*4是參數fmt所占堆棧中的大小*/ i = vsprintf(buf, fmt, arg); write(buf, i); return i; }
kernel/proc.c
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ proc.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #include "type.h" #include "const.h" #include "protect.h" #include "tty.h" #include "console.h" #include "string.h" #include "proc.h" #include "global.h" #include "proto.h" /*======================================================================* schedule *======================================================================*/ PUBLIC void schedule() { PROCESS* p; int greatest_ticks = 0; while (!greatest_ticks) { for (p = proc_table; p < proc_table+NR_TASKS+NR_PROCS; p++) { if (p->ticks > greatest_ticks) { greatest_ticks = p->ticks; p_proc_ready = p; } } if (!greatest_ticks) { for(p=proc_table;p<proc_table+NR_TASKS+NR_PROCS;p++) { p->ticks = p->priority; } } } } /*======================================================================* sys_get_ticks *======================================================================*/ PUBLIC int sys_get_ticks() { return ticks; } /*********************************************************************** * sys_sendrec ***********************************************************************/ /** * <Ring 0> The core routine of system call `sendrec()'. * * @parm function SEND or RECEIVE * @parm src_dest To/From whom the message is transferred. * @parm m Ptr to the MESSAGE body * @parm p The caller proc. * * @return Zero if success. ***********************************************************************/ PUBLIC int sys_sendrec(int function, int src_dest, MESSAGE* m, struct proc*p) { assert(k_reenter == 0); /* make sure we are not in ring0 */ assert((src_dest >= 0 && src_dest < NR_TASKS + NR_PROCS) || src_dest == ANY || src_dest == INTERRUPT); int ret = 0; int caller = proc2pid(p); MESSAGE* mla = (MESSAGE*)va2la(caller, m); mla->source = caller; assert(mla->source != src_dest); /** * Actually we have the third message type: BOTH. However, it is not allowed to be passed to the kernel directly. * Kernel doesn't know it at all. It is transformed into a SEND followed by a RECEIVE by `send_recv()'. */ if (function == SEND) { ret = msg_send(p, src_dest, m); if (ret != 0) return ret; } else if (function == RECEIVE) { ret = msg_receive(p, src_dest, m); if (ret != 0) return ret; } else { panic("{sys_sendrec} invalid function: " "%d (SEND:%d, RECEIVE:%d).", function, SEND, RECEIVE); } return 0; }
kernel/protect.c
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ protect.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #include "type.h" #include "const.h" #include "protect.h" #include "tty.h" #include "console.h" #include "proc.h" #include "global.h" #include "proto.h" /* 本文件內函數聲明 */ PRIVATE void init_idt_desc(unsigned char vector, u8 desc_type, int_handler handler, unsigned char privilege); PRIVATE void init_descriptor(DESCRIPTOR * p_desc, u32 base, u32 limit, u16 attribute); /* 中斷處理函數 */ void divide_error(); void single_step_exception(); void nmi(); void breakpoint_exception(); void overflow(); void bounds_check(); void inval_opcode(); void copr_not_available(); void double_fault(); void copr_seg_overrun(); void inval_tss(); void segment_not_present(); void stack_exception(); void general_protection(); void page_fault(); void copr_error(); void hwint00(); void hwint01(); void hwint02(); void hwint03(); void hwint04(); void hwint05(); void hwint06(); void hwint07(); void hwint08(); void hwint09(); void hwint10(); void hwint11(); void hwint12(); void hwint13(); void hwint14(); void hwint15(); /*======================================================================* init_prot *----------------------------------------------------------------------* 初始化 IDT *======================================================================*/ PUBLIC void init_prot() { init_8259A(); // 全部初始化成中斷門(沒有陷阱門) init_idt_desc(INT_VECTOR_DIVIDE, DA_386IGate, divide_error, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_DEBUG, DA_386IGate, single_step_exception, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_NMI, DA_386IGate, nmi, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_BREAKPOINT, DA_386IGate, breakpoint_exception, PRIVILEGE_USER); init_idt_desc(INT_VECTOR_OVERFLOW, DA_386IGate, overflow, PRIVILEGE_USER); init_idt_desc(INT_VECTOR_BOUNDS, DA_386IGate, bounds_check, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_INVAL_OP, DA_386IGate, inval_opcode, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_COPROC_NOT, DA_386IGate, copr_not_available, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_DOUBLE_FAULT, DA_386IGate, double_fault, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_COPROC_SEG, DA_386IGate, copr_seg_overrun, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_INVAL_TSS, DA_386IGate, inval_tss, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_SEG_NOT, DA_386IGate, segment_not_present, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_STACK_FAULT, DA_386IGate, stack_exception, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_PROTECTION, DA_386IGate, general_protection, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_PAGE_FAULT, DA_386IGate, page_fault, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_COPROC_ERR, DA_386IGate, copr_error, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 0, DA_386IGate, hwint00, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 1, DA_386IGate, hwint01, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 2, DA_386IGate, hwint02, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 3, DA_386IGate, hwint03, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 4, DA_386IGate, hwint04, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 5, DA_386IGate, hwint05, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 6, DA_386IGate, hwint06, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 7, DA_386IGate, hwint07, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 0, DA_386IGate, hwint08, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 1, DA_386IGate, hwint09, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 2, DA_386IGate, hwint10, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 3, DA_386IGate, hwint11, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 4, DA_386IGate, hwint12, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 5, DA_386IGate, hwint13, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 6, DA_386IGate, hwint14, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 7, DA_386IGate, hwint15, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_SYS_CALL, DA_386IGate, sys_call, PRIVILEGE_USER); /* 填充 GDT 中 TSS 這個描述符 */ memset(&tss, 0, sizeof(tss)); tss.ss0 = SELECTOR_KERNEL_DS; init_descriptor(&gdt[INDEX_TSS], vir2phys(seg2phys(SELECTOR_KERNEL_DS), &tss), sizeof(tss) - 1, DA_386TSS); tss.iobase = sizeof(tss); /* 沒有I/O許可位圖 */ // 填充 GDT 中進程的 LDT 的描述符 int i; PROCESS* p_proc = proc_table; u16 selector_ldt = INDEX_LDT_FIRST << 3; for (i = 0; i < NR_TASKS+NR_PROCS; i++){ init_descriptor(&gdt[selector_ldt>>3], vir2phys(seg2phys(SELECTOR_KERNEL_DS), proc_table[i].ldts), LDT_SIZE * sizeof(DESCRIPTOR) - 1, DA_LDT); p_proc++; selector_ldt += 1 << 3; } } /*======================================================================* init_idt_desc *----------------------------------------------------------------------* 初始化 386 中斷門 *======================================================================*/ PUBLIC void init_idt_desc(unsigned char vector, u8 desc_type, int_handler handler, unsigned char privilege) { GATE * p_gate = &idt[vector]; u32 base = (u32)handler; p_gate->offset_low = base & 0xFFFF; p_gate->selector = SELECTOR_KERNEL_CS; p_gate->dcount = 0; p_gate->attr = desc_type | (privilege << 5); p_gate->offset_high = (base >> 16) & 0xFFFF; } /*======================================================================* seg2phys *----------------------------------------------------------------------* 由段名求絕對地址 *======================================================================*/ PUBLIC u32 seg2phys(u16 seg) { DESCRIPTOR* p_dest = &gdt[seg >> 3]; return (p_dest->base_high << 24) | (p_dest->base_mid << 16) | (p_dest->base_low); } /*======================================================================* init_descriptor *----------------------------------------------------------------------* 初始化段描述符 *======================================================================*/ PRIVATE void init_descriptor(DESCRIPTOR * p_desc, u32 base, u32 limit, u16 attribute) { p_desc->limit_low = limit & 0x0FFFF; // 段界限 1 (2 字節) p_desc->base_low = base & 0x0FFFF; // 段基址 1 (2 字節) p_desc->base_mid = (base >> 16) & 0x0FF; // 段基址 2 (1 字節) p_desc->attr1 = attribute & 0xFF; // 屬性 1 p_desc->limit_high_attr2 = ((limit >> 16) & 0x0F) | (attribute >> 8) & 0xF0;// 段界限 2 + 屬性 2 p_desc->base_high = (base >> 24) & 0x0FF; // 段基址 3 (1 字節) } /*======================================================================* exception_handler *----------------------------------------------------------------------* 異常處理 *======================================================================*/ PUBLIC void exception_handler(int vec_no, int err_code, int eip, int cs, int eflags) { int i; int text_color = 0x74; /* 灰底紅字 */ char err_description[][64] = { "#DE Divide Error", "#DB RESERVED", "— NMI Interrupt", "#BP Breakpoint", "#OF Overflow", "#BR BOUND Range Exceeded", "#UD Invalid Opcode (Undefined Opcode)", "#NM Device Not Available (No Math Coprocessor)", "#DF Double Fault", " Coprocessor Segment Overrun (reserved)", "#TS Invalid TSS", "#NP Segment Not Present", "#SS Stack-Segment Fault", "#GP General Protection", "#PF Page Fault", "— (Intel reserved. Do not use.)", "#MF x87 FPU Floating-Point Error (Math Fault)", "#AC Alignment Check", "#MC Machine Check", "#XF SIMD Floating-Point Exception" }; /* 通過打印空格的方式清空屏幕的前五行,並把 disp_pos 清零 */ disp_pos = 0; for(i=0;i<80*5;i++){ disp_str(" "); } disp_pos = 0; disp_color_str("Exception! --> ", text_color); disp_color_str(err_description[vec_no], text_color); disp_color_str("\n\n", text_color); disp_color_str("EFLAGS:", text_color); disp_int(eflags); disp_color_str("CS:", text_color); disp_int(cs); disp_color_str("EIP:", text_color); disp_int(eip); if(err_code != 0xFFFFFFFF){ disp_color_str("Error code:", text_color); disp_int(err_code); } }
kernel/start.c
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ start.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #include "type.h" #include "const.h" #include "protect.h" #include "string.h" #include "proc.h" #include "tty.h" #include "console.h" #include "global.h" #include "proto.h" /*======================================================================* cstart *======================================================================*/ PUBLIC void cstart() { disp_str("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n-----\"cstart\" begins-----\n"); // 將 LOADER 中的 GDT 複製到新的 GDT 中 memcpy( &gdt, // New GDT (void*)(*((u32*)(&gdt_ptr[2]))), // Base of Old GDT *((u16*)(&gdt_ptr[0])) + 1 // Limit of Old GDT ); // gdt_ptr[6] 共 6 個字節:0~15:Limit 16~47:Base。用作 sgdt 以及 lgdt 的參數。 u16* p_gdt_limit = (u16*)(&gdt_ptr[0]); u32* p_gdt_base = (u32*)(&gdt_ptr[2]); *p_gdt_limit = GDT_SIZE * sizeof(DESCRIPTOR) - 1; *p_gdt_base = (u32)&gdt; // idt_ptr[6] 共 6 個字節:0~15:Limit 16~47:Base。用作 sidt 以及 lidt 的參數。 u16* p_idt_limit = (u16*)(&idt_ptr[0]); u32* p_idt_base = (u32*)(&idt_ptr[2]); *p_idt_limit = IDT_SIZE * sizeof(GATE) - 1; *p_idt_base = (u32)&idt; init_prot(); disp_str("-----\"cstart\" finished-----\n"); }
kernel/syscall.asm
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; syscall.asm ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Forrest Yu, 2005 ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %include "sconst.inc" INT_VECTOR_SYS_CALL equ 0x90 _NR_get_ticks equ 0 _NR_write equ 1 ; 導出符號 global get_ticks global write global sednrec bits 32 [section .text] ; ==================================================================== ; get_ticks ; ==================================================================== get_ticks: mov eax, _NR_get_ticks int INT_VECTOR_SYS_CALL ret ; ==================================================================== ; sendrec(int function, int src_dest, MESSAGE* msg) ; ==================================================================== ; Never call sendrec() directly, call send_recv() instead. sendrec: mov eax, _NR_sendrec mov ebx, [esp + 4] ; function mov ecx, [esp + 8] ; src_dest mov edx, [esp + 12] ; p_msg int INT_VECTOR_SYS_CALL ret ; ==================================================================================== ; void write(char* buf, int len); ; ==================================================================================== write: mov eax, _NR_write mov ebx, [esp + 4] mov ecx, [esp + 8] int INT_VECTOR_SYS_CALL ret
kernel/systask.c
/*************************************************************************//** ***************************************************************************** * @file systask.c * @brief * @author Forrest Y. Yu * @date 2007 ***************************************************************************** *****************************************************************************/ #include "type.h" #include "const.h" #include "protect.h" #include "string.h" #include "proc.h" #include "tty.h" #include "console.h" #include "global.h" #include "keyboard.h" #include "proto.h" /***************************************************************************** * task_sys *****************************************************************************/ /** * <Ring 1> The main loop of TASK SYS. * *****************************************************************************/ PUBLIC void task_sys() { MESSAGE msg; while (1) { send_recv(RECEIVE, ANY, &msg); int src = msg.source; switch (msg.type) { case GET_TICKS: msg.RETVAL = ticks; send_recv(SEND, src, &msg); break; default: panic("unknown msg type"); break; } } }
kernel/tty.c
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tty.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #include "type.h" #include "const.h" #include "protect.h" #include "string.h" #include "proc.h" #include "tty.h" #include "console.h" #include "global.h" #include "keyboard.h" #include "proto.h" #define TTY_FIRST (tty_table) #define TTY_END (tty_table + NR_CONSOLES) PRIVATE void init_tty(TTY* p_tty); PRIVATE void tty_do_read(TTY* p_tty); PRIVATE void tty_do_write(TTY* p_tty); PRIVATE void put_key(TTY* p_tty, u32 key); /*======================================================================* task_tty *======================================================================*/ PUBLIC void task_tty() { TTY* p_tty; init_keyboard(); for (p_tty=TTY_FIRST;p_tty<TTY_END;p_tty++) { init_tty(p_tty); } select_console(0); while (1) { for (p_tty=TTY_FIRST;p_tty<TTY_END;p_tty++) { tty_do_read(p_tty); tty_do_write(p_tty); } } } /*======================================================================* init_tty *======================================================================*/ PRIVATE void init_tty(TTY* p_tty) { p_tty->inbuf_count = 0; p_tty->p_inbuf_head = p_tty->p_inbuf_tail = p_tty->in_buf; init_screen(p_tty); } /*======================================================================* in_process *======================================================================*/ PUBLIC void in_process(TTY* p_tty, u32 key) { char output[2] = {'\0', '\0'}; if (!(key & FLAG_EXT)) { put_key(p_tty, key); } else { int raw_code = key & MASK_RAW; switch(raw_code) { case ENTER: put_key(p_tty, '\n'); break; case BACKSPACE: put_key(p_tty, '\b'); break; case UP: if ((key & FLAG_SHIFT_L) || (key & FLAG_SHIFT_R)) { scroll_screen(p_tty->p_console, SCR_DN); } break; case DOWN: if ((key & FLAG_SHIFT_L) || (key & FLAG_SHIFT_R)) { scroll_screen(p_tty->p_console, SCR_UP); } break; case F1: case F2: case F3: case F4: case F5: case F6: case F7: case F8: case F9: case F10: case F11: case F12: /* Alt + F1~F12 */ if ((key & FLAG_ALT_L) || (key & FLAG_ALT_R)) { select_console(raw_code - F1); } break; default: break; } } } /*======================================================================* put_key *======================================================================*/ PRIVATE void put_key(TTY* p_tty, u32 key) { if (p_tty->inbuf_count < TTY_IN_BYTES) { *(p_tty->p_inbuf_head) = key; p_tty->p_inbuf_head++; if (p_tty->p_inbuf_head == p_tty->in_buf + TTY_IN_BYTES) { p_tty->p_inbuf_head = p_tty->in_buf; } p_tty->inbuf_count++; } } /*======================================================================* tty_do_read *======================================================================*/ PRIVATE void tty_do_read(TTY* p_tty) { if (is_current_console(p_tty->p_console)) { keyboard_read(p_tty); } } /*======================================================================* tty_do_write *======================================================================*/ PRIVATE void tty_do_write(TTY* p_tty) { if (p_tty->inbuf_count) { char ch = *(p_tty->p_inbuf_tail); p_tty->p_inbuf_tail++; if (p_tty->p_inbuf_tail == p_tty->in_buf + TTY_IN_BYTES) { p_tty->p_inbuf_tail = p_tty->in_buf; } p_tty->inbuf_count--; out_char(p_tty->p_console, ch); } } /*======================================================================* tty_write *======================================================================*/ PUBLIC void tty_write(TTY* p_tty, char* buf, int len) { char* p = buf; int i = len; while (i) { out_char(p_tty->p_console, *p++); i--; } } /*======================================================================* sys_write *======================================================================*/ PUBLIC int sys_write(char* buf, int len, PROCESS* p_proc) { tty_write(&tty_table[p_proc->nr_tty], buf, len); return 0; }
kernel/vsprintf.c
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vsprintf.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forrest Yu, 2005 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #include "type.h" #include "const.h" #include "string.h" /* * 為更好地理解此函數的原理,可參考 printf 的注釋部分。 */ /*======================================================================* vsprintf *======================================================================*/ int vsprintf(char *buf, const char *fmt, va_list args) { char* p; char tmp[256]; va_list p_next_arg = args; for (p=buf;*fmt;fmt++) { if (*fmt != '%') { *p++ = *fmt; continue; } fmt++; switch (*fmt) { case 'x': itoa(tmp, *((int*)p_next_arg)); strcpy(p, tmp); p_next_arg += 4; p += strlen(tmp); break; case 's': break; default: break; } } return (p - buf); }
lib/misc.c
PUBLIC void assertion_failure(char *exp, char *file, char *base_file, int line) { printl("%c assert(%s) failed: file: %s, base_file: %s, ln%d", MAG_CH_ASSERT, exp, file, base_file, line); spin("assertion_failure()"); __asm__ __volatile__("ud2"); }
Makefile
######################### # Makefile for Orange'S # ######################### # Entry point of Orange'S # It must have the same value with 'KernelEntryPointPhyAddr' in load.inc! ENTRYPOINT = 0x30400 # Offset of entry point in kernel file # It depends on ENTRYPOINT ENTRYOFFSET = 0x400 # Programs, flags, etc. ASM = nasm DASM = objdump CC = gcc LD = ld ASMBFLAGS = -I boot/include/ ASMKFLAGS = -I include/ -f elf CFLAGS = -I include/ -m32 -c -fno-builtin -Wall #CFLAGS = -I include/ -m32 -c -fno-builtin -fno-stack-protector LDFLAGS = -s -melf_i386 -Ttext $(ENTRYPOINT) DASMFLAGS = -D # This Program ORANGESBOOT = boot/boot.bin boot/loader.bin ORANGESKERNEL = kernel.bin OBJS = kernel/kernel.o kernel/syscall.o kernel/start.o kernel/main.o\ kernel/clock.o kernel/keyboard.o kernel/tty.o kernel/console.o\ kernel/i8259.o kernel/global.o kernel/protect.o kernel/proc.o\ kernel/systask.o\ kernel/printf.o kernel/vsprintf.o\ lib/kliba.o lib/klib.o lib/string.o lib/misc.o DASMOUTPUT = kernel.bin.asm # All Phony Targets .PHONY : everything final image clean realclean disasm all buildimg # Default starting position nop : @echo "why not \`make image' huh? :)" everything : $(ORANGESBOOT) $(ORANGESKERNEL) all : realclean everything image : realclean everything clean buildimg clean : rm -f $(OBJS) realclean : rm -f $(OBJS) $(ORANGESBOOT) $(ORANGESKERNEL) disasm : $(DASM) $(DASMFLAGS) $(ORANGESKERNEL) > $(DASMOUTPUT) # We assume that "a.img" exists in current folder buildimg : mkdir tmp sleep 1 sudo mount -o loop a.img tmp sleep 1 sudo cp -fv boot/loader.bin tmp sudo cp -fv kernel.bin tmp sleep 1 sudo umount tmp sleep 1 rmdir tmp boot/boot.bin : boot/boot.asm boot/include/load.inc boot/include/fat12hdr.inc $(ASM) $(ASMBFLAGS) -o $@ $< boot/loader.bin : boot/loader.asm boot/include/load.inc boot/include/fat12hdr.inc boot/include/pm.inc $(ASM) $(ASMBFLAGS) -o $@ $< $(ORANGESKERNEL) : $(OBJS) $(LD) $(LDFLAGS) -o $(ORANGESKERNEL) $(OBJS) kernel/kernel.o : kernel/kernel.asm include/sconst.inc $(ASM) $(ASMKFLAGS) -o $@ $< kernel/syscall.o : kernel/syscall.asm include/sconst.inc $(ASM) $(ASMKFLAGS) -o $@ $< kernel/start.o: kernel/start.c include/type.h include/const.h include/protect.h include/string.h include/proc.h include/proto.h \ include/global.h $(CC) $(CFLAGS) -o $@ $< kernel/main.o: kernel/main.c include/type.h include/const.h include/protect.h include/string.h include/proc.h include/proto.h \ include/global.h $(CC) $(CFLAGS) -o $@ $< kernel/clock.o: kernel/clock.c $(CC) $(CFLAGS) -o $@ $< kernel/keyboard.o: kernel/keyboard.c $(CC) $(CFLAGS) -o $@ $< kernel/tty.o: kernel/tty.c $(CC) $(CFLAGS) -o $@ $< kernel/console.o: kernel/console.c $(CC) $(CFLAGS) -o $@ $< kernel/i8259.o: kernel/i8259.c include/type.h include/const.h include/protect.h include/proto.h $(CC) $(CFLAGS) -o $@ $< kernel/global.o: kernel/global.c include/type.h include/const.h include/protect.h include/proc.h \ include/global.h include/proto.h $(CC) $(CFLAGS) -o $@ $< kernel/protect.o: kernel/protect.c include/type.h include/const.h include/protect.h include/proc.h include/proto.h \ include/global.h $(CC) $(CFLAGS) -o $@ $< kernel/proc.o: kernel/proc.c $(CC) $(CFLAGS) -o $@ $< kernel/printf.o: kernel/printf.c $(CC) $(CFLAGS) -o $@ $< kernel/vsprintf.o: kernel/vsprintf.c $(CC) $(CFLAGS) -o $@ $< kernel/systask.o: kernel/systask.c $(CC) $(CFLAGS) -o $@ $< lib/klib.o: lib/klib.c include/type.h include/const.h include/protect.h include/string.h include/proc.h include/proto.h \ include/global.h $(CC) $(CFLAGS) -o $@ $< lib/misc.o: lib/misc.c $(CC) $(CFLAGS) -o $@ $< lib/kliba.o : lib/kliba.asm $(ASM) $(ASMKFLAGS) -o $@ $< lib/string.o : lib/string.asm $(ASM) $(ASMKFLAGS) -o $@ $<
![]() |
執行畫面 |
目錄結構
. ├── a.img ├── boot │ ├── boot.asm │ ├── include │ │ ├── fat12hdr.inc │ │ ├── load.inc │ │ └── pm.inc │ └── loader.asm ├── include │ ├── console.h │ ├── const.h │ ├── global.h │ ├── keyboard.h │ ├── keymap.h │ ├── proc.h │ ├── protect.h │ ├── proto.h │ ├── sconst.inc │ ├── string.h │ ├── tty.h │ └── type.h ├── kernel │ ├── clock.c │ ├── console.c │ ├── global.c │ ├── i8259.c │ ├── kernel.asm │ ├── keyboard.c │ ├── main.c │ ├── printf.c │ ├── proc.c │ ├── protect.c │ ├── start.c │ ├── syscall.asm │ ├── systask.c │ ├── tty.c │ └── vsprintf.c ├── lib │ ├── kliba.asm │ ├── klib.c │ ├── misc.c │ └── string.asm └── Makefile
留言
張貼留言