我们把所有的东西都放到了main.c中,一开始代码量很小其实无所谓,但随着代码量的增加我们有必要分门别类整理一下了
首先将下面代码放到io.h中
//读port端口 #define inb(port) ({ \ unsigned char _v; \ __asm__ volatile ("inb %%dx,%%al":"=a" (_v):"d" (port)); \ _v; \ }) //带延时的向port端口写value,用两条跳转语句做延时 #define outb_p(value,port) \ __asm__ ("outb %%al,%%dx\n" \ "\tjmp 1f\n" \ "1:\tjmp 1f\n" \ "1:"::"a" (value),"d" (port)) //带延时的读port端口 #define inb_p(port) ({ \ unsigned char _v; \ __asm__ volatile ("inb %%dx,%%al\n" \ "\tjmp 1f\n" \ "1:\tjmp 1f\n" \ "1:":"=a" (_v):"d" (port)); \ _v; \ })
#define set_registers() \ __asm__ ("movl $0x17,%%eax\n\t" \ "movw %%ax,%%ds\n\t" \ "movw %%ax,%%es\n\t" \ "movw %%ax,%%fs\n\t" \ "movw $0x18,%%ax\n\t" \ "movw %%ax,%%gs" \ :::"ax") #define set_stack_registers() \ __asm__ ("movl $0x10,%%eax\n\t" \ "movw %%ax,%%ds\n\t" \ "movw %%ax,%%es\n\t" \ "movw %%ax,%%ss\n\t" \ "lss stack_start,%%esp"\ :::"ax") #define move_to_user_mode2() \ __asm__ ("movl %%esp,%%eax\n\t" \ "pushl $0x17\n\t" \ "pushl %%eax\n\t" \ "pushfl\n\t"\ "pushl $0xf\n\t" \ "pushl $testA\n\t" \ "iret\n" \ :::"ax") #define move_to_user_mode() \ __asm__ ("movl %%esp,%%eax\n\t" \ "pushl $0x17\n\t" \ "pushl %%eax\n\t" \ "pushfl\n\t" \ "pushl $0x0f\n\t" \ "pushl $1f\n\t" \ "iret\n" \ "1:\tmovl $0x17,%%eax\n\t" \ "movw %%ax,%%ds\n\t" \ "movw %%ax,%%es\n\t" \ "movw %%ax,%%fs\n\t" \ "movw $0x18,%%ax\n\t" \ "movw %%ax,%%gs" \ :::"ax")下面代码放到head.h中
typedef unsigned int u32; typedef unsigned short u16; typedef unsigned char u8; typedef struct Descriptor { 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; #define DA_C 0x98 #define DA_32 0x4000 #define DA_DPL3 0x60 #define DA_DPL0 0x00 #define DA_DRWA 0x93 #define DA_DRW 0x92 #define SA_RPL3 3 #define DA_CR 0x9A #define DA_LIMIT_4K 0x8000 #define DA_386TSS 0x89 #define DA_LDT 0x82
#ifndef _SCHED_H #define _SCHED_H typedef struct tss_struct { 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许可位图 */ }TSS; #define FIRST_TSS_ENTRY 4 #define FIRST_LDT_ENTRY 5 #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3)) #define switch_to(n) {\ struct {long a,b;} __tmp; \ __asm__("movw %%dx,%1\n\t" \ "ljmp %0\n\t" \ ::"m" (*&__tmp.a),"m" (*&__tmp.b), \ "d" (_TSS(n))); \ } #define PAGE_SIZE 4096 #define NR_TASKS 64 struct task_struct { long state; long pid,father; struct desc_struct ldt[3]; /* tss for this task */ struct tss_struct tss; }; union task_union { struct task_struct task; char stack[PAGE_SIZE]; }; struct stack_struct{ char stack[256]; int top; }; #define INIT_TASK \ { 0,0,0,\ { \ {0,0}, \ /* ldt */ {0x9f,0xc0fa00}, \ {0x9f,0xc0f200}, \ }, \ /*tss*/ {\ }, \ } #define lldt() \ __asm__ ("movw $0x28,%%ax\n\t" \ "lldt %%ax\n\t" \ :::"ax") #define ltr() \ __asm__ ("movw $0x20,%%ax\n\t" \ "ltr %%ax\n\t" \ :::"ax") extern void registe_task(union task_union * task,struct stack_struct *stack,void *test); extern long volatile jiffies; typedef struct { long * a; short b; } STACK_START; extern STACK_START stack_start; #endif
在kernel中新建chr_drv文件夹,并将keyboard.S移到这里,然后新建console.c、key_board.c、Makefile
chr_drv中的console.c
#include <linux/head.h> #include <asm/system.h> #include <asm/io.h> extern void keyboard_interrupt(void); void con_init(void) { register unsigned char a; set_trap_gate(0x21,&keyboard_interrupt); outb_p(inb_p(0x21)&0xfd,0x21); a=inb_p(0x61); outb_p(a|0x80,0x61); outb(a,0x61); }
#include <asm/io.h> void none(void) { disp_str("none"); } void do_self(void) { disp_str("do_self"); } void ctrl(void) { disp_str("ctrl"); } void lshift(void) { disp_str("lshift"); } void rshift(void) { disp_str("rshift"); } void minus(void) { disp_str("minus"); } void alt(void) { disp_str("alt"); } void caps(void) { disp_str("caps"); } void func(void) { disp_str("func"); } void num(void) { disp_str("num"); } void scroll(void) { disp_str("scroll"); } void cursor(void) { disp_str("cursor"); } void unctrl(void) { disp_str("unctrl"); } void unlshift(void) { disp_str("unlshift"); } void unrshift(void) { disp_str("unrshift"); } void unalt(void) { disp_str("unalt"); } void uncaps(void) { disp_str("uncaps"); } typedef void (*function)(void); #define Function(address) (*(function)address)() static function key_table[] = { none,do_self,do_self,do_self /* 00-03 s0 esc 1 2 */ ,do_self,do_self,do_self,do_self /* 04-07 3 4 5 6 */ ,do_self,do_self,do_self,do_self /* 08-0B 7 8 9 0 */ ,do_self,do_self,do_self,do_self /* 0C-0F + ' bs tab */ ,do_self,do_self,do_self,do_self /* 10-13 q w e r */ ,do_self,do_self,do_self,do_self /* 14-17 t y u i */ ,do_self,do_self,do_self,do_self /* 18-1B o p } ^ */ ,do_self,ctrl,do_self,do_self /* 1C-1F enter ctrl a s */ ,do_self,do_self,do_self,do_self /* 20-23 d f g h */ ,do_self,do_self,do_self,do_self /* 24-27 j k l | */ ,do_self,do_self,lshift,do_self /* 28-2B { para lshift , */ ,do_self,do_self,do_self,do_self /* 2C-2F z x c v */ ,do_self,do_self,do_self,do_self /* 30-33 b n m , */ ,do_self,minus,rshift,do_self /* 34-37 . - rshift * */ ,alt,do_self,caps,func /* 38-3B alt sp caps f1 */ ,func,func,func,func /* 3C-3F f2 f3 f4 f5 */ ,func,func,func,func /* 40-43 f6 f7 f8 f9 */ ,func,num,scroll,cursor /* 44-47 f10 num scr home */ ,cursor,cursor,do_self,cursor /* 48-4B up pgup - left */ ,cursor,cursor,do_self,cursor /* 4C-4F n5 right + end */ ,cursor,cursor,cursor,cursor /* 50-53 dn pgdn ins del */ ,none,none,do_self,func /* 54-57 sysreq ? < f11 */ ,func,none,none,none /* 58-5B f12 ? ? ? */ ,none,none,none,none /* 5C-5F ? ? ? ? */ ,none,none,none,none /* 60-63 ? ? ? ? */ ,none,none,none,none /* 64-67 ? ? ? ? */ ,none,none,none,none /* 68-6B ? ? ? ? */ ,none,none,none,none /* 6C-6F ? ? ? ? */ ,none,none,none,none /* 70-73 ? ? ? ? */ ,none,none,none,none /* 74-77 ? ? ? ? */ ,none,none,none,none /* 78-7B ? ? ? ? */ ,none,none,none,none /* 7C-7F ? ? ? ? */ ,none,none,none,none /* 80-83 ? br br br */ ,none,none,none,none /* 84-87 br br br br */ ,none,none,none,none /* 88-8B br br br br */ ,none,none,none,none /* 8C-8F br br br br */ ,none,none,none,none /* 90-93 br br br br */ ,none,none,none,none /* 94-97 br br br br */ ,none,none,none,none /* 98-9B br br br br */ ,none,unctrl,none,none /* 9C-9F br unctrl br br */ ,none,none,none,none /* A0-A3 br br br br */ ,none,none,none,none /* A4-A7 br br br br */ ,none,none,unlshift,none /* A8-AB br br unlshift br */ ,none,none,none,none /* AC-AF br br br br */ ,none,none,none,none /* B0-B3 br br br br */ ,none,none,unrshift,none /* B4-B7 br br unrshift br */ ,unalt,none,uncaps,none /* B8-BB unalt br uncaps br */ ,none,none,none,none /* BC-BF br br br br */ ,none,none,none,none /* C0-C3 br br br br */ ,none,none,none,none /* C4-C7 br br br br */ ,none,none,none,none /* C8-CB br br br br */ ,none,none,none,none /* CC-CF br br br br */ ,none,none,none,none /* D0-D3 br br br br */ ,none,none,none,none /* D4-D7 br br br br */ ,none,none,none,none /* D8-DB br ? ? ? */ ,none,none,none,none /* DC-DF ? ? ? ? */ ,none,none,none,none /* E0-E3 e0 e1 ? ? */ ,none,none,none,none /* E4-E7 ? ? ? ? */ ,none,none,none,none /* E8-EB ? ? ? ? */ ,none,none,none,none /* EC-EF ? ? ? ? */ ,none,none,none,none /* F0-F3 ? ? ? ? */ ,none,none,none,none /* F4-F7 ? ? ? ? */ ,none,none,none,none /* F8-FB ? ? ? ? */ ,none,none,none,none /* FC-FF ? ? ? ? */ }; void do_keyboard(void) { register unsigned char scan_code; scan_code=inb_p(0x60); if(scan_code==0xe0) { disp_str("0xe0"); } else if(scan_code==0xe1) { disp_str("0xe1"); } else { key_table[scan_code](); } }
# Makefile for the simple example kernel. AS =as LD =ld LDFLAGS = --oformat binary -N -e start -Ttext 0x0 CC =gcc CFLAGS = -I../../include .c.s: $(CC) $(CFLAGS) \ -S -o $*.s $< .s.o: $(AS) -c -o $*.o $< .c.o: $(CC) $(CFLAGS) \ -c -o $*.o $< OBJS = keyboard.o key_board.o console.o chr_drv.o:$(OBJS) $(LD) -r -o chr_drv.o $(OBJS) sync clean: rm -f *.o *.s
#include <linux/head.h> #include <linux/sched.h> int current_task=0; unsigned int TOTAL_TASK=0; long volatile jiffies=0; long user_stack [ PAGE_SIZE>>2 ] ; STACK_START stack_start = { & user_stack [PAGE_SIZE>>2] , 0x20 }; void do_timer(void) { int next_task = current_task+1; if(next_task>TOTAL_TASK-1) next_task = 0; if(next_task!=current_task){ current_task=next_task; switch_to(next_task); } } void registe_task(union task_union * task,struct stack_struct *stack,void *process) { //填充task1的TSS task->task.tss.backlink = 0; task->task.tss.esp0=PAGE_SIZE+(long)task; task->task.tss.ss0=0x10; task->task.tss.eip=process; task->task.tss.esp = &stack->top; task->task.tss.flags=0x200; task->task.tss.es=0x17; task->task.tss.cs=0xf; task->task.tss.ss=0x17; task->task.tss.ds=0x17; task->task.tss.fs=0x17; task->task.tss.gs=0x18; task->task.tss.ldt=(FIRST_LDT_ENTRY+TOTAL_TASK*2)*8; task->task.tss.trap=0x8000; task->task.tss.iobase=0x0; //init_task的LDT 0x28 _set_gdt_desc(&gdt[FIRST_LDT_ENTRY+TOTAL_TASK*2],&(task->task.ldt[0]),0x40,DA_LDT); //task1的TSS 0x30 _set_gdt_desc(&gdt[FIRST_TSS_ENTRY+TOTAL_TASK*2],&(task->task.tss),0x68,DA_386TSS+DA_DPL3); TOTAL_TASK++; }
# Makefile for the simple example kernel. AS =as LD =ld LDFLAGS = --oformat binary -N -e start -Ttext 0x0 CC =gcc CFLAGS = -I../include .c.s: $(CC) $(CFLAGS) \ -S -o $*.s $< .s.o: $(AS) -c -o $*.o $< .c.o: $(CC) $(CFLAGS) \ -c -o $*.o $< OBJS = asm.o kliba.o System_call.o chr_drv/chr_drv.o Traps.o sched.o kernel.o:$(OBJS) $(LD) -r -o kernel.o $(OBJS) sync chr_drv/chr_drv.o: (cd chr_drv; make) clean: rm -f *.o *.s (cd chr_drv;make clean)
# Makefile for the simple example kernel. AS =as LD =ld LDFLAGS = --oformat binary -N -e start -Ttext 0x0 all:Image Image:boot/bootsect boot/setup system cat boot/bootsect boot/setup system >Image boot/bootsect:boot/bootsect.s $(AS) -o boot/bootsect.o -a boot/bootsect.s $(LD) $(LDFLAGS) -o boot/bootsect boot/bootsect.o boot/setup:boot/setup.s $(AS) -o boot/setup.o -a boot/setup.s $(LD) $(LDFLAGS) -o boot/setup boot/setup.o boot/head.o:boot/head.s $(AS) -o boot/head.o -a boot/head.s init/main.o: init/main.c gcc -Iinclude -c -o init/main.o init/main.c kernel/kernel.o: (cd kernel; make) system: boot/head.o init/main.o kernel/kernel.o $(LD) $(LDFLAGS) -o system boot/head.o kernel/kernel.o init/main.o clean: rm -f Image system *.o *.s rm -f boot/head.o boot/setup boot/bootsect rm -f init/*.o (cd kernel; make clean)
#include <linux/head.h> #include <asm/system.h> #include <asm/io.h> #include <linux/sched.h> void disp_str(char *info); extern void timer_interrupt(void); static union task_union init_task = {INIT_TASK,}; struct stack_struct stack0; struct stack_struct stack1; static union task_union task1 = {INIT_TASK,}; void delay(int time) { int i, j, k; for (k = 0; k < time; k++) { for (i = 0; i < 10; i++) { for (j = 0; j < 10000; j++) {} } } } void testC(void) { while(1){ disp_str("C"); delay(2); } } void _set_gdt_desc(struct desc_struct *descriptor_addr,u32 base,u32 limit,u16 attr) { DESCRIPTOR *descriptor = (DESCRIPTOR *)descriptor_addr; descriptor->limit_low = limit & 0x0FFFF; descriptor->base_low = base & 0x0FFFF; descriptor->base_mid = (base >> 16) & 0x0FF; descriptor->attr1 = attr & 0xFF; descriptor->limit_high_attr2= ((limit>>16) & 0x0F) | (attr>>8) & 0xF0; descriptor->base_high = (base >> 24) & 0x0FF; } void rebuid_gdt(void) { _set_gdt_desc(&gdt[1],0x0000,0x7ff,DA_CR+DA_32+DA_LIMIT_4K); //堆栈段 0x10 _set_gdt_desc(&gdt[2],0x0000,0x7ff,DA_DRW+DA_32+DA_LIMIT_4K); //视频段 0x18 _set_gdt_desc(&gdt[3],0xb8000,0x2,DA_DRW+DA_32+DA_DPL3+DA_LIMIT_4K); } void timer_init(void) { set_intr_gate(32,&timer_interrupt); } void main(void) { disp_str("How old are you?\n"); con_init(); timer_init(); rebuid_gdt(); stack_start.b=0x10; set_stack_registers(); registe_task(&init_task,&stack0,0); registe_task(&task1,&stack1,&testC); ltr();//加载tss lldt();//加载ldt sti();//开中断 move_to_user_mode(); while(1){ disp_str("M"); delay(2); } }