├── .gitignore ├── Makefile ├── README ├── RUN_i386.bat ├── bochsrc ├── boot ├── boot.asm └── e820.c ├── deeppink.img ├── doc ├── arch.pptx └── help.md ├── drivers ├── block.c ├── block.h ├── floppy.c ├── hd.c ├── keyboard.c ├── task.c └── timer.c ├── fs └── ext4.c ├── include ├── README.md ├── boot.h ├── buddy.h ├── console.h ├── ctype.h ├── ctypes.h ├── debug.h ├── descriptor.h ├── error.h ├── ext4.h ├── font.h ├── i386 │ ├── fork.c │ ├── fork.h │ ├── linkage.h │ ├── sys.c │ ├── sys.h │ └── system.h ├── init.h ├── interrupt.h ├── keyboard.h ├── keymap.h ├── list.h ├── memory.h ├── page.h ├── peripheral.h ├── pmm.h ├── protect.h ├── schedule.h ├── slab.h ├── string.h ├── task.h ├── task_struct.h ├── timer.h ├── tty.h ├── unistd.h ├── vargs.h └── vmm.h ├── init ├── console.c ├── interrupt.c ├── kernel.asm ├── memory.c ├── palette.c ├── pmm.c ├── start.c └── vmm.c ├── kernel ├── buddy.c ├── panic.c ├── prink.c ├── sched.c ├── sched.s ├── slab.c └── tty.c ├── qemu_run_os.sh └── scripts └── kernel.ld /.gitignore: -------------------------------------------------------------------------------- 1 | prj/ 2 | .autogit/ 3 | .sicode/ 4 | boot/e820.s 5 | *.o 6 | *.txt 7 | *.elf 8 | *.bin 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # 目前kernel.bin的加载地址是0x8000,其大小不能越过BIOS的地址0x9fc00 3 | # 当前kernel.bin的大小不能超过621568byte 4 | # 5 | # 6 | # author : wangrongwei 7 | # time : 2018/08/12 8 | # usage : make 9 | # make qemu 10 | # make bochs 11 | # make dis 12 | ##################################################################### 13 | 14 | 15 | BOOT:=boot/boot.asm 16 | BOOT_O:=boot/boot.o 17 | E820_C:=boot/e820.c 18 | E820_S:=boot/e820.s 19 | E820_O:=boot/e820.o 20 | KERNEL:=init/kernel.asm 21 | BOOT_BIN:=$(subst .asm,.bin,$(BOOT)) 22 | 23 | KERNEL_ELF:=$(subst .asm,.elf,$(KERNEL)) 24 | KERNEL_BIN:=$(subst .asm,.bin,$(KERNEL)) 25 | 26 | # 寻找当前目录下.c文件 27 | C_SOURCES = $(shell find . -path "./.sicode*" -prune -o -path "./boot/*" -prune -o -name "*.c" -print) 28 | C_OBJECTS = $(patsubst %.c,%.o,$(C_SOURCES)) 29 | 30 | # 寻找init下的汇编文件(待优化) 31 | S_SOURCES = $(shell find ./init -name "*.asm") 32 | S_OBJECTS = $(patsubst %.asm,%.o,$(S_SOURCES)) 33 | 34 | 35 | CC = gcc 36 | AS = as 37 | ASM = nasm 38 | LD = ld 39 | OBJCOPY = objcopy 40 | 41 | C_FLAGS = -c -Wall -m32 -ggdb -gstabs+ -nostdinc -fno-builtin -std=c99\ 42 | -fno-stack-protector -I include -I drivers 43 | 44 | LD_FLAGS = -T scripts/kernel.ld -m elf_i386 45 | ASM_FLAGS = -f elf32 -g -F stabs 46 | 47 | IMG:=deeppink.img 48 | 49 | # 直接将内核代码写进deeppink 50 | deeppink.img : $(BOOT_BIN) $(KERNEL_BIN) 51 | dd if=/dev/zero of=$(IMG) bs=512 count=2880 52 | dd if=$(BOOT_BIN) of=$(IMG) conv=notrunc 53 | dd if=$(KERNEL_BIN) of=$(IMG) seek=1 conv=notrunc 54 | 55 | $(BOOT_BIN) : $(BOOT_O) $(E820_O) 56 | $(LD) -Ttext 0x7c00 -m elf_i386 $^ -o $@ 57 | 58 | $(BOOT_O) : $(BOOT) 59 | $(ASM) -f elf $< -o $@ 60 | $(E820_O) : $(E820_S) 61 | $(AS) --32 -march=i386 $< -o $@ 62 | $(E820_S) : $(E820_C) 63 | $(CC) -m16 -masm=intel -I include $< -S -o $@ 64 | 65 | $(KERNEL_BIN) : $(S_OBJECTS) $(C_OBJECTS) 66 | @echo 链接生成kernel.bin文件 67 | $(LD) $(LD_FLAGS) $(S_OBJECTS) $(C_OBJECTS) -o $(KERNEL_ELF) 68 | $(OBJCOPY) -O binary -R .note -R .comment -S $(KERNEL_ELF) $(KERNEL_BIN) 69 | 70 | 71 | # 将所有.c源文件生成.o目标文件 72 | .c.o: 73 | @echo $(C_SOURCES) 74 | $(CC) $(C_FLAGS) $< -o $@ 75 | 76 | # 如果在init下不止一个.asm文件,此处要更改(需要测试) 77 | $(S_OBJECTS):$(S_SOURCES) 78 | @echo 将.c文件编译为.o文件 79 | @echo $(S_SOURCES) 80 | $(ASM) $(ASM_FLAGS) $< -o $@ 81 | 82 | 83 | .PHONY: oldqemu qemu clean bochs debug dis 84 | oldqemu: 85 | @echo '启动虚拟机...' 86 | qemu-system-i386 -boot order=a -drive file=deeppink.img,format=raw 87 | 88 | qemu: 89 | @echo '启动虚拟机...' 90 | qemu-system-i386 \ 91 | -accel tcg,thread=single \ 92 | -cpu core2duo \ 93 | -m 64 \ 94 | -boot order=a -fda deeppink.img \ 95 | -serial stdio \ 96 | -smp 1 \ 97 | -usb \ 98 | -vga std 99 | 100 | clean : 101 | rm -f $(BOOT_BIN) $(KERNEL_BIN) $(S_OBJECTS) $(C_OBJECTS) 102 | rm ./boot/boot.txt ./init/kernel.txt 103 | 104 | debug: 105 | qemu-system-i386 -s -S deeppink.img 106 | 107 | #qemu-system-i386 -s -S -boot order=a -fda deeppink.img 108 | 109 | bochs: 110 | bochs -f ./bochsrc 111 | 112 | dis: 113 | ndisasm ./boot/boot.bin > ./boot/boot.txt 114 | objdump -d ./init/kernel.elf > ./init/kernel.txt 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | UNIX386 2 | ======== 3 | 4 | 一个i386架构的简单内核 5 | 6 | 借鉴了《30天自制操作系统》、《一个orange操作系统的实现》和《linux内核设计的艺 7 | 术》相关代码,对其中思路重新调整,多处初始化流程细节不在按照经典的启动流程来, 8 | 采用简单和便于理解的方式对内核完善。 9 | 10 | 当前两个分支 11 | ------------ 12 | master:master分支可直接clone运行; 13 | new分:支属于正在开发中的分支,存在较多的bug,不能运行; 14 | 15 | 编译环境 16 | ======== 17 | 18 | 1. 编译环境:linux 19 | 2. 编译器:gcc 20 | 3. 汇编器:nasm 21 | 4. 链接器:ld 22 | 5. 仿真器:bochs 23 | 6. 其他工具:objcopy 24 | 25 | 1. 如果只用汇编语言编写 16 位程序,请使用 .code16 指令,并保证 26 | 只使用 16 位的指令和寄存器;如果要和 C 语言一起工作,请使用 27 | .code16gcc 指令,并且在函数框架中使用 pushl,calll,retl,leavel 28 | jmpl,使用 0x8(%ebp) 开始访问函数的参数;很显然,使用 C 语言和 29 | 汇编语言混编的程序可以在实模式下运行,但是不能在 286 之前的真实 30 | CPU 上运行,因为 286 之前的 CPU 还没有 pushl、calll、retl、leavel 31 | jmpl 等指令。 32 | 33 | 2. 使用 as 时,请指定 --32 选项,使用 gcc 时,请指定 -m32 选项,使 34 | 用 ld 时,请指定 -m elf_i386 选项。如果是反汇编 16 位代码,在使 35 | 用 objdump 时,请使用 -m i8086 选项。 36 | 37 | 说明 38 | ===== 39 | 40 | 最开始,打算按照《30天自制操作系统》一书再次慢慢研究操作系统的设计知识,最后由 41 | 于将开发环境换成ubuntu,使用gcc和nasm编译整个内核,开始此计划时,内核相关知识有 42 | 但是还缺少实验,再加上对gcc和nasm编译一个x86文件感觉不太可能,参考了其他简单内 43 | 核,最终确定可以修改原来的Makefile文件,使用gcc和nasm。 44 | 45 | 推荐:使用bochs慢慢单步调试,这些问题都能发现。 46 | 47 | DeeppinkOS文件结构(按照创建先后列出) 48 | ------------------------------------- 49 | 50 | . 51 | ├── boot 52 | │   ├── boot.asm 53 | │   └── e820.c 54 | ├── deeppink.img 55 | ├── doc 56 | │   ├── arch.pptx 57 | │   └── help.md 58 | ├── drivers 59 | │   ├── block.c 60 | │   ├── block.h 61 | │   ├── floppy.c 62 | │   ├── hd.c 63 | │   ├── keyboard.c 64 | │   ├── task.c 65 | │   └── timer.c 66 | ├── fs 67 | │   └── ext4.c 68 | ├── include 69 | │   ├── boot.h 70 | │   ├── buddy.h 71 | │   ├── console.h 72 | │   ├── ctype.h 73 | │   ├── ctypes.h 74 | │   ├── debug.h 75 | │   ├── descriptor.h 76 | │   ├── error.h 77 | │   ├── ext4.h 78 | │   ├── font.h 79 | │   ├── i386 80 | │   │   ├── fork.c 81 | │   │   ├── fork.h 82 | │   │   ├── linkage.h 83 | │   │   ├── sys.c 84 | │   │   ├── sys.h 85 | │   │   └── system.h 86 | │   ├── init.h 87 | │   ├── interrupt.h 88 | │   ├── keyboard.h 89 | │   ├── keymap.h 90 | │   ├── list.h 91 | │   ├── memory.h 92 | │   ├── page.h 93 | │   ├── peripheral.h 94 | │   ├── pmm.h 95 | │   ├── protect.h 96 | │   ├── README.md 97 | │   ├── schedule.h 98 | │   ├── slab.h 99 | │   ├── string.h 100 | │   ├── task.h 101 | │   ├── task_struct.h 102 | │   ├── timer.h 103 | │   ├── tty.h 104 | │   ├── unistd.h 105 | │   ├── vargs.h 106 | │   └── vmm.h 107 | ├── init 108 | │   ├── console.c 109 | │   ├── interrupt.c 110 | │   ├── kernel.asm 111 | │   ├── memory.c 112 | │   ├── palette.c 113 | │   ├── pmm.c 114 | │   ├── start.c 115 | │   └── vmm.c 116 | ├── kernel 117 | │   ├── buddy.c 118 | │   ├── panic.c 119 | │   ├── prink.c 120 | │   ├── sched.c 121 | │   ├── sched.s 122 | │   ├── slab.c 123 | │   └── tty.c 124 | ├── Makefile 125 | ├── qemu_run_os.sh 126 | ├── README 127 | ├── RUN_i386.bat 128 | └── scripts 129 | └── kernel.ld 130 | 131 | 运行说明 132 | --------- 133 | 134 | 该工程在ubuntu16.04和CentOS7上已测试通过,需要安装最新的bochs运行,可支持三种方 135 | 式: 136 | 137 | 1. make bochs 138 | 2. make qemu 139 | 3. make debug 140 | 141 | make debug表示以调试模式运行,详情可查看Makefile文档。 142 | 143 | TODO 144 | ===== 145 | 146 | 1. asm切换为.S 147 | 2. 调度器 148 | 3. buddy系统 149 | 4. slab分配器 150 | 5. 82258(DMA控制器) 151 | 6. 8259A(中断控制器) 152 | 7. 8272(磁盘控制器) 153 | 8. 82385(Cache控制器) 154 | 9. 82062(硬盘控制器) 155 | 10. 8254(可编程定时/计数器) 156 | 157 | 正在完善中... 158 | 159 | 160 | -------------------------------------------------------------------------------- /RUN_i386.bat: -------------------------------------------------------------------------------- 1 | D:/"Program Files"/qemu/qemu-system-i386.exe ^ 2 | -accel tcg,thread=single ^ 3 | -cpu core2duo ^ 4 | -m 64 ^ 5 | -boot order=a -fda deeppink.img ^ 6 | -serial stdio ^ 7 | -smp 1 ^ 8 | -usb ^ 9 | -vga std 10 | -------------------------------------------------------------------------------- /bochsrc: -------------------------------------------------------------------------------- 1 | ############################################################### 2 | #Configuration file for Bochs(Linux) 3 | ############################################################### 4 | 5 | 6 | 7 | #======================================================================= 8 | #filename of ROM images 9 | #======================================================================= 10 | 11 | romimage:file=$BXSHARE/BIOS-bochs-latest 12 | 13 | 14 | 15 | #======================================================================= 16 | #VGAROMIMAGE 17 | #You now need to load a VGA ROM BIOS into C0000. 18 | #======================================================================= 19 | 20 | vgaromimage:file=/usr/share/bochs/VGABIOS-lgpl-latest 21 | 22 | 23 | 24 | #======================================================================= 25 | #what disk images will be used 26 | #======================================================================= 27 | 28 | floppya:1_44=/root/repo/UNIX386/deeppink.img, status=inserted 29 | 30 | 31 | 32 | #======================================================================= 33 | #choose the boot disk. 34 | #======================================================================= 35 | 36 | boot:floppy 37 | 38 | 39 | 40 | #======================================================================= 41 | #where do we send log messages? 42 | #======================================================================= 43 | 44 | log:bochsout.txt 45 | 46 | 47 | 48 | #======================================================================= 49 | #disable the mouse 50 | #======================================================================= 51 | 52 | mouse: enabled=0 53 | 54 | 55 | 56 | #======================================================================= 57 | #enable key mapping, using US layout as default. 58 | #======================================================================= 59 | 60 | keyboard:keymap=/usr/share/bochs/keymaps/x11-pc-us.map 61 | 62 | 63 | #======================================================================= 64 | 65 | #how much memory the emulated machine will have 66 | 67 | #======================================================================= 68 | 69 | megs:32 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /boot/boot.asm: -------------------------------------------------------------------------------- 1 | ; Deeppinkos 2 | ; TAB=4 SP=0x7c00 0x8000=拷贝到启动区 3 | ;------------------------------------------------------------------------------- 4 | ;|中断向量表 | | ;代码存储的位置 |...... |512| 5 | ;| | | |...... | | 6 | ;------------------------------------------------------------------------------- 7 | ; 0x8200=后边的程序 8 | ;在某种意义上理解,只需要将程序放在磁盘开始的512字节, 9 | ;然后硬件会自动去读取磁盘上的开始的512字节,然后执行这段程序 10 | 11 | ;目前在boot.asm里边读取了180k程序,超过这个数字,需要更改boot.asm程序 12 | 13 | ;1-> 读取磁盘后边扇区的数据 14 | ;2-> 在bootsecond.nas中添加LCD支持 15 | ;3-> 初始化PIC 16 | ;4-> 打开A20,进入保护模型 17 | ;5-> 跳转到start 18 | ;6-> 设置堆栈,跳转到kernel_start函数 19 | ;7-> 20 | 21 | [bits 16] 22 | extern detect_memory; 23 | 24 | CYLS EQU 10 ;读取10个柱面 25 | BOOT_ADDR EQU 0x7C00 26 | KERNEL_ADDR EQU 0xC0000000 27 | INITSEG EQU 0x9000 28 | 29 | LCDMODE EQU 0x0ff2 ; 30 | SCREENX EQU 0x0ff4 ; x 31 | SCREENY EQU 0x0ff6 ; y 32 | LCDRAM EQU 0x0ff8 ; 图像缓冲区的开始地址 33 | 34 | 35 | ;初始化段SS=0 DS=0 ES=0 SP指向程序加载的地址 36 | ;因为程序加载的地址是0x7c00,所以我们的段地址必须是0, 37 | ;不然地址就不是0x7c00 38 | MOV AX,CS 39 | MOV SS,AX 40 | MOV SP,BOOT_ADDR 41 | MOV DS,AX 42 | MOV ES,AX 43 | ; 44 | ;The second stage 45 | ; Now ,load kernel from img 46 | ; 47 | MOV SI,msg 48 | putloop: 49 | MOV AL,[SI] 50 | ADD SI,1 51 | CMP AL,0 52 | JE Read_Sector 53 | MOV AH,0x0e 54 | MOV BX,0x0f 55 | INT 0x10 ;ִ执行BIOS中断0x10 56 | JMP putloop 57 | 58 | Read_Sector: 59 | MOV SI,msg_1 ;打开成功显示字符 60 | Read: 61 | MOV AL,[SI] 62 | ADD SI,1 63 | CMP AL,0 64 | JE Read_Ok 65 | MOV AH,0x0e 66 | MOV BX,0x0f 67 | INT 0x10 ;ִ执行BIOS中断0x10 68 | JMP Read 69 | ;------------------------------------------------------------ 70 | ;下面开始读磁盘程序数据 71 | ;代码借鉴《30天...》川和秀实 72 | ;ES:BX 代表缓冲器地址 73 | ;------------------------------------------------------------ 74 | Read_Ok: 75 | MOV AX,0x0800 ;读取剩下的内核到0x8000 76 | MOV ES,AX 77 | MOV BX,0x00 78 | MOV CH,0 ;柱面0 79 | MOV DH,0 ;磁头0 80 | MOV CL,2 ;扇区2 81 | readloop: 82 | MOV SI,0 83 | retry: 84 | MOV AH,0x02 ;AH=0x02:读取扇区 85 | MOV AL,1 ;读取扇区数 86 | MOV BX,0 87 | MOV DL,0x00 ;代表读的软盘 88 | INT 0x13 89 | JNC next ;如果读取扇区成功,跳转到next 90 | ADD SI,1 ;SI+1(执行这代表读取失败) 91 | CMP SI,5 ;SI与5比较(再尝试读取5次) 92 | JAE error ;SI >= 5,则跳转到error 93 | MOV AH,0x00 94 | MOV DL,0x00 95 | INT 0x13 ;开始读取软盘程序 96 | JMP retry 97 | next: 98 | MOV AX,ES ;缓冲地址往后0x200 99 | ADD AX,0x0020 100 | MOV ES,AX 101 | ADD CL,1 102 | CMP CL,18 ;CL与18相比 103 | JBE readloop ;BE == below and eq:若CL <= 18,则跳转 104 | MOV CL,1 ;|||| 105 | ADD DH,1 ;|||| 磁头指向下一个,又开始读下一个第一个扇区 106 | CMP DH,2 ;|||| 107 | JB readloop ;DH < 2 跳转 108 | MOV DH,0 109 | ADD CH,1 ;---------最终改变读到柱面 110 | CMP CH,CYLS ;读取10个柱面 111 | JB readloop ;若CH < CYLS,则跳转 112 | ;10*2*18*512= 180k 113 | MOV [0x0ff0],CH 114 | 115 | ;---------------------------------------------------------------------------------- 116 | ; 开始复制boot.bin到0x90000 117 | ;---------------------------------------------------------------------------------- 118 | copy_start: 119 | CLD 120 | MOV AX,0x07c0 ;源地址 121 | MOV DS,AX 122 | MOV AX,0x9000 ;目的地址 123 | MOV ES,AX 124 | 125 | MOV CX,256 ;表示复制的字节x/2 126 | SUB SI,SI ;DS:SI--->ES:DI 127 | SUB DI,DI 128 | REP MOVSW ;在linux-0.1.1中使用rep movw的intel的格式 129 | ;这里是相对跳转,保证程序跳转后从相同位置继续往下执行 130 | JMP INITSEG:(copy_end-0x7c00) 131 | copy_end: 132 | ;跳转到一个新的内存区域后,重新设置DS,ES,SS和SP指针 133 | MOV AX,CS 134 | MOV DS,AX 135 | MOV ES,AX 136 | MOV SS,AX 137 | MOV SP,0xFC00 138 | 139 | ; 140 | ;打印成功读取状态 141 | ;换显示坐标 142 | MOV AH,0x02 143 | MOV BX,0x0f 144 | MOV DX,0x0e16 145 | INT 0x10 146 | 147 | MOV SI,(msg_2-0x7c00);打开成功要显示字符 148 | print_loop: 149 | MOV AL,[SI] 150 | ADD SI,1 151 | CMP AL,0 152 | JE goto_PM 153 | MOV AH,0x0e 154 | MOV BX,0x0f 155 | INT 0x10 156 | 157 | JMP print_loop; 158 | 159 | ; 160 | ; read e820: memory layout 161 | ; 162 | call detect_memory 163 | ; 164 | ;The third stage 165 | ; goto PM mode 166 | ; 167 | goto_PM: 168 | MOV AL,0X03 169 | MOV AH,0X00 170 | ;MOV AL,0x13 ;设置显示模式 171 | ;MOV AH,0x00 ;设置成00H无法显示字符 172 | ;MOV BX,0x07 173 | INT 0x10 174 | 175 | ;MOV BYTE [LCDMODE],8 176 | ;MOV WORD [SCREENX],320 177 | ;MOV WORD [SCREENY],200 178 | ;MOV DWORD [LCDRAM],0x000a0000 179 | 180 | MOV AL,0xFF 181 | OUT 0x21,AL 182 | NOP 183 | OUT 0xa1,AL 184 | 185 | CLI 186 | 187 | ;开始移动第二部分内核(0x7c00+512后面的代码)到0x0地址,因此原中断服务程序被覆盖 188 | move_start: 189 | CLI 190 | MOV AX,0x0800 ;源地址 191 | MOV DS,AX 192 | MOV AX,0x0500 ;目的地址 193 | MOV ES,AX 194 | 195 | MOV CX,0x7000 ;表示复制的字节x/2 196 | SUB SI,SI ;DS:SI--->ES:DI 197 | SUB DI,DI 198 | REP MOVSW ;在linux-0.1.1中使用rep movw的intel的格式 199 | move_end: 200 | MOV AX,CS ;还原改变的两个段 201 | MOV ES,AX 202 | MOV DS,AX 203 | ; 204 | ; OPEN A20 205 | ; 206 | CALL waitkbd_8042 207 | MOV AL,0xd1 ;写命令 208 | OUT 0x64,AL 209 | CALL waitkbd_8042 210 | MOV AL,0xdf 211 | OUT 0x60,AL 212 | CALL waitkbd_8042 ;打开A20 213 | 214 | 215 | ;MOV AH,0x0e 216 | ;MOV AL,'O' 217 | ;INT 0x10 218 | 219 | ;MOV AH,0x0e 220 | ;MOV AL,'S' 221 | ;INT 0x10 222 | 223 | ;jmp $ 224 | CLI 225 | ;由于最开始编译这个程序是按0x7c00为偏移地址的, 226 | ;所以移动到0x0地址以后,需要重新计算GDTR0存储的地址 227 | LGDT [GDTR0-0x7c00] 228 | 229 | IN AL,92h 230 | OR AL,0x02 231 | OUT 92h,AL 232 | 233 | MOV EAX,CR0 234 | AND EAX,0x7fffffff 235 | OR AL,1 236 | MOV CR0,EAX ;打开段保护机制,不开分页机制 237 | ;程序执行到这里结束,跳转到init/kernel.asm(即移动到0x0处的代码)执行 238 | JMP dword 0x08:0x5000 239 | 240 | ; 241 | ; 这一部分移动到kernel.asm里边 242 | ; 243 | ;[bits 32] 244 | ;PM_MODE: 245 | ; MOV EAX,0x00000010 246 | ; MOV DS,AX 247 | ; MOV ES,AX 248 | ; MOV FS,AX 249 | ; MOV GS,AX 250 | ; MOV SS,AX 251 | 252 | ; MOV EAX,0x0000018 253 | ; MOV GS,EAX 254 | 255 | ; MOV EAX,0x0 256 | ; JMP 0x10:0 ;dword 0x08:0x8200 257 | ; 258 | ; 显示需要的相关字符串 259 | ; 260 | 261 | waitkbd_8042: 262 | IN AL,0x64 263 | AND AL,0x02 ;输入缓冲区是否满了 264 | JNZ waitkbd_8042 265 | RET 266 | 267 | ; 268 | ;进入保护模型,不再按照CS*16+IP取指令执行,需要按照向全局描述符 269 | ; 270 | GDT0: 271 | DW 0x0000,0x0000,0x0000,0x0000 272 | ;---代码段基地址 0x0047取00,0x9a28取28,0x0000取全部===0x00280000 273 | DW 0xffff,0x0000,0x9a00,0x00cf 274 | ;---数据段基地址 0x00cf取00,0x9200取00,0x0000取全部===0x00000000 275 | DW 0xffff,0x0000,0x9200,0x00cf 276 | DW 0xffff,0x8000,0xf20b,0x000f 277 | ;为tss准备的 278 | DW 0x0000,0x0000,0x0000,0x0000 279 | ;为ldt准备的 280 | DW 0x0000,0x0000,0x0000,0x0000 281 | ;DW 0xffff,0x8000,0xf20b,0x000f 282 | GDT0_LEN EQU $-GDT0 283 | GDTR0: 284 | DW GDT0_LEN-1 285 | DW GDT0-0x7c00,0x9 286 | 287 | error: 288 | MOV SI,msg_error ;打开失败要显示的字符 289 | error_loop: 290 | MOV AL,[SI] 291 | ADD SI,1 292 | CMP AL,0 293 | JE fin_error 294 | MOV AH,0x0e 295 | MOV BX,0x0f 296 | INT 0x10 297 | JMP error_loop 298 | 299 | ;表示最后读取扇区失败,将会执行这里 300 | fin_error: 301 | HLT 302 | JMP fin_error 303 | 304 | msg: 305 | DB 0x0a, 0x0a ;换行 306 | DB "Welcome to DeeppinkOS:" 307 | DB 0x0a ;换行 308 | DB 0 309 | msg_1: 310 | DB 0x0a, 0x0a 311 | DB "Read Sectors..." 312 | DB 0x0a 313 | DB 0 314 | msg_2: 315 | DB "Read Completely!!" 316 | DB 0x0a 317 | DB 0 318 | 319 | msg_error: 320 | DB "Load error" 321 | DB 0x0a 322 | DB 0 323 | 324 | stack: 325 | times 510-($-$$) db 0 326 | DW 0xaa55 327 | 328 | 329 | -------------------------------------------------------------------------------- /boot/e820.c: -------------------------------------------------------------------------------- 1 | // running in real mode may require: 2 | __asm__(".code16gcc\n"); 3 | 4 | // SMAP entry structure 5 | #include 6 | #include 7 | #include 8 | 9 | struct boot_params boot_params __attribute__((aligned(16))); 10 | 11 | /* 12 | * struct boot_params 13 | */ 14 | // load memory map to buffer - note: regparm(3) avoids stack issues with gcc in real mode 15 | int __attribute__((noinline)) __attribute__((regparm(3))) 16 | detect_memory_e820(SMAP_entry_t *buffer, int maxentries) 17 | { 18 | uint32_t contID = 0; 19 | int entries = 0, signature, bytes; 20 | 21 | do { 22 | __asm__ __volatile__ ("int 0x15" 23 | : "=a"(signature), "=c"(bytes), "=b"(contID) 24 | : "a"(0xE820), "b"(contID), "c"(24), "d"(0x534D4150), "D"(buffer)); 25 | if (signature != 0x534D4150) 26 | return -1; // error 27 | if (bytes > 20 && (buffer->ACPI & 0x0001) == 0) { 28 | // ignore this entry 29 | } else { 30 | buffer++; 31 | entries++; 32 | } 33 | } while (contID != 0 && entries < maxentries); 34 | 35 | return entries; 36 | } 37 | 38 | /* 39 | * This function will be invoked by boot.asm, then detecting memory layout. 40 | */ 41 | void detect_memory(void) 42 | { 43 | SMAP_entry_t *desc = NULL; 44 | 45 | desc = boot_params.e820_map; 46 | boot_params.e820_entries = detect_memory_e820(desc, 128); 47 | return; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /deeppink.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangrongwei/UNIX386/c4148895e36d493ca146180bffb5fdbaa6ef6a72/deeppink.img -------------------------------------------------------------------------------- /doc/arch.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangrongwei/UNIX386/c4148895e36d493ca146180bffb5fdbaa6ef6a72/doc/arch.pptx -------------------------------------------------------------------------------- /doc/help.md: -------------------------------------------------------------------------------- 1 | ## 修改过程 ## 2 | 3 | ---------- 4 | 5 | 使用gcc和nasm断断续续修改Makefile,最终完全解决和达到最初在windows下的效果,大概花了十多天时间,中间遇到许多问题,也不单单是gcc和nasm命令的问题,尤其是是否在第一个汇编文件boot.asm里就进入保护模式。。。。。还是放在kernel.asm里边。。。。这花了我七八天时间,本来是将进入保护模式的程序放在kernel.asm里边但是发现不成功,然后我怀疑是不是gcc和nasm的问题,还是代码对齐的问题-----最后没有这么干,但是发现了问题,是生成的kernel.bin文件前有elf头(大概0x1000),其本质就是在boot.asm里边跳转地址不对(这都是采用第二种方法后debug出来的),还一个说明,就是在保护模式下的跳转(jmp)不能跟原来一样了,, 6 | 7 | - 例如: 8 | jmp 0x08:_start;(_start在第二个文件开头,使用这个指令不知道jmp到什么地方去了) 9 | 10 | - 可以采用的跳转: 11 | MOV EAX,0x9000 12 | JMP EAX 13 | 感觉如果使用汇编不精通,写的代码啥都有可能发生,解决办法就一个:慢慢使用bochs慢慢单步调试,这些问题都能发现 14 | 15 | 16 | ---------- 17 | 18 | 19 | **-------->2017.05.13**
20 | ======= 21 | ---------- 22 | 23 | ## 内核调试笔记 24 | 25 | ---------- 26 | 27 | 28 | ### -------->2017.05.13 29 | 30 | C:\kernel developer\tolset\helloos0>make 31 | 32 | C:\kernel developer\tolset\helloos0>..\z_tools\make.exe 33 | ../z_tools/make.exe -r img 34 | make.exe[1]: Entering directory `C:/kernel developer/tolset/helloos0' 35 | ../z_tools/make.exe -r wrwos.img 36 | make.exe[2]: Entering directory `C:/kernel developer/tolset/helloos0' 37 | ../z_tools/nask.exe bootfirst.nas bootfirst.bin bootfirst.lst 38 | NASK : LSTBUF is not enough 39 | make.exe[2]: *** [bootfirst.bin] Error 19 40 | make.exe[2]: Leaving directory `C:/kernel developer/tolset/helloos0' 41 | make.exe[1]: *** [img] Error 2 42 | make.exe[1]: Leaving directory `C:/kernel developer/tolset/helloos0' 43 | ..\z_tools\make.exe: *** [default] Error 2 44 | 这个错误是没有将bootfirst后边填充数据的代码去掉,由于添加了其他代码,空间已经不过用了 45 | 46 | ### -------->2017.05.14 47 | 48 | **-------->2017.05.14**
49 | ======= 50 | C:\kernel developer\tolset\helloos0>make 51 | 52 | C:\kernel developer\tolset\helloos0>..\z_tools\make.exe 53 | ../z_tools/make.exe -r img 54 | make.exe[1]: Entering directory `C:/kernel developer/tolset/helloos0' 55 | ../z_tools/make.exe -r wrwos.img 56 | make.exe[2]: Entering directory `C:/kernel developer/tolset/helloos0' 57 | ../z_tools/nask.exe bootfirst.nas bootfirst.bin bootfirst.lst 58 | ../z_tools/edimg.exe imgin:../z_tools/fdimg0at.tek \ 59 | wbinimg src:bootfirst.bin len:512 from:0 to:0 \ 60 | copy from:bootsecond.sys to:@: \ 61 | imgout:wrwos.img 62 | imgout BPB data error. 63 | make.exe[2]: *** [wrwos.img] Error 37 64 | make.exe[2]: Leaving directory `C:/kernel developer/tolset/helloos0' 65 | make.exe[1]: *** [img] Error 2 66 | make.exe[1]: Leaving directory `C:/kernel developer/tolset/helloos0' 67 | ..\z_tools\make.exe: *** [default] Error 2 68 | FAT12文件的很重要,不能随意更改其中的文件名字(只是更改名字会出错) 69 | 70 | ### -------->2017.05.24 71 | 72 | **-------->2017.05.24**
73 |        向64h端口写入的字节,被认为是对8042芯片发布的命令(Command): 写入的字节将会被存放Input Register中; 同时会引起Status Register的Bit-3自动被设置为1,表示现在放在 74 | ======= 75 | 向64h端口写入的字节,被认为是对8042芯片发布的命令(Command): 写入的字节将会被存 76 | 放Input Register中; 同时会引起Status Register的Bit-3自动被设置为1,表示现在放在 77 | Input Register中的数据是一个Command,而不是一个Data;在向64h端口写某些命令之前必 78 | 须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放Output Register中,而键 79 | 盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖; 80 | 在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1 81 | 是否为0)。60h端口(读操作),对60h端口进行读操作,将会读取Output Register的内容。 82 | Output Register的内容可能是:来自8048的数据。这些数据包括Scan Code,对8048发送的 83 | 命令的确认字节(ACK)及回复数据。 通过64h端口对8042发布的命令的返回结果。在向60h端口 84 | 读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。 85 | 60h端口(写操作)向60h端口写入的字节,有两种可能:
86 |    [1].如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被 87 | 认为是数据;
88 |    [2].否则,此字节被认为是发送给8048的命令。 在向60h端口写数据之前,必须确保 89 | Input Register是空的(通过判断Status Register的Bit-1是否为0)。 90 | 91 | **-------->2017.06.21**
92 |        向一个空软盘保存文件的时候, 93 | ======= 94 | ### -------->2017.06.21 95 | 向一个空软盘保存文件的时候, 96 | 1.文件名会写在0x2600以后的地方(这里我没有去验证); 97 | 2.文件的内容会写入到0x4200以后的地方. 98 | 决定后边的0xc200 99 | 100 | **-------->2017.06.23**
101 |        使用一般的编译器编译操作系统,不再依赖原来作者自己的编译器 102 | >>使用linux系统,在ubuntu下选择和组合一套工具编译运行这个操作系统 103 | 104 | **-------->2017/08/22**
105 |        当前对系统只将堆栈指针指向0x7c00,此处在C代码里边定义一个全局变量,似乎没有存储 106 | ======= 107 | ### -------->2017.06.23 108 | 109 | 使用一般的编译器编译操作系统,不再依赖原来作者自己的编译器使用linux系统,在ubuntu下选择和组合一套工具编译运行这个操作系统 110 | 111 | ### -------->2017/08/22 112 | 当前对系统只将堆栈指针指向0x7c00,此处在C代码里边定义一个全局变量,似乎没有存储 113 | 这个全局变量的空间,如果设置成局部变量,达到了预想的效果,猜测可能是没有在链接脚本 114 | 指定全局变量空间 115 |        debug:此处的问题不是链接脚本的问题,是生成的kernel.bin文件是一个elf文件,文件最 116 | 开始是elf的头,所以是跳转的地址不对 117 | 118 | **-------->2017/08/23**
119 |        完善Deeppink的显示字符串函数(console_puts),添加对字符串里换行等的支持,添加 120 | 光标移动函数(console_movecursor) 121 | 122 | **-------->2017/08/24**
123 |        添加kernel/printk.c文件 124 | 125 | **-------->2017/08/25**
126 |        添加descriptor.h文件,使用c语言重新初始化gdt和idt表 127 |        问题:在使用bochs调试时,sreg命令显示的valid=1 or 31是什么意思 128 | 129 | **-------->2017/08/26**
130 |        问题:console_puts函数有一个bug,使用printk函数时总是不能按下原来的光标坐标 131 | 往下显示。 132 | 133 | **-------->2017/08/27**
134 |        console_puts函数的bug是在do{}while里边使用break,以为这个break可以跳出外边的 135 | while循环,看来只是跳出了do-while循环 136 |        另外添加console_readcursor函数(读取光标坐标),在console_puts函数开始,先读取 137 | 坐标,然后往下显示 138 | 139 | **-------->2017/08/28**
140 |        添加时钟中断,出现bug如下:
141 |        链接生成kernel.bin文件
142 | ======= 143 | ### -------->2017/08/23 144 | 145 | 完善Deeppink的显示字符串函数(console_puts),添加对字符串里换行等的支持,添加 146 | 光标移动函数(console_movecursor) 147 | 148 | ### -------->2017/08/24 149 | 添加kernel/printk.c文件 150 | ### -------->2017/08/25 151 | 添加descriptor.h文件,使用c语言重新初始化gdt和idt表。 152 | 问题:在使用bochs调试时,sreg命令显示的valid=1 or 31是什意思?? 153 | ### -------->2017/08/26 154 | 问题:console_puts函数有一个bug,使用printk函数时总是不能按下原来的光标坐标往下显示。 155 | ### -------->2017/08/27 156 | console_puts函数的bug是在do{}while里边使用break,以为这个break可以跳出外边的while循环,看来只是跳出了do-while循环另外添加console_readcursor函数(读取光标坐标),在console_puts函数开始,先读取 157 | 坐标,然后往下显示 158 | ### -------->2017/08/28 159 | 160 | - 添加时钟中断,出现bug如下: 161 | 链接生成kernel.bin文件 162 | ld -T scripts/kernel.ld -m elf_i386 ./init/kernel.o ./init/console.o ./init/start.o ./kernel/prink.o ./drivers/timer.o -o init/kernel.bin 163 | ./drivers/timer.o:在函数‘isr_handler’中: 164 | /home/lollipop/DeeppinkOS/include/interrupt.h:85: `isr_handler'被多次定义 165 | ./init/start.o:/home/lollipop/DeeppinkOS/include/interrupt.h:85:第一次在此定义 166 | ./drivers/timer.o:在函数‘irq_handler’中: 167 | /home/lollipop/DeeppinkOS/include/interrupt.h:135: `irq_handler'被多次定义 168 | ./init/start.o:/home/lollipop/DeeppinkOS/include/interrupt.h:135:第一次在此定义 169 | ./drivers/timer.o:在函数‘register_interrupt_handler’中: 170 | /home/lollipop/DeeppinkOS/include/interrupt.h:151: `register_interrupt_handler'被多次定义 171 | ./init/start.o:/home/lollipop/DeeppinkOS/include/interrupt.h:151:第一次在此定义 172 | Makefile:50: recipe for target 'link' failed 173 | make: *** [link] Error 1
174 | 解决办法:
175 |        源文件的头文件太多,相互关系包括可能有重复,因此将interrupt.h分成两部分 176 | ----->interrupt.h和interrupt.c,这样只在头文件里边定义原型,在interrupt.c里边 177 | 定义函数内容 178 | 179 | **-------->2017年 08月 30日 星期四 00:17:18 CST**
180 |        添加键盘处理功能,包括文件keyboard.c和keyboard.h,本来打算按照hurlex-doc将 181 | 内存管理部分的分页功能打开,但是发现有点复杂,以后在完善内存管理功能
182 |        按键部分目前不完善,只是做了简单的中断处理,和显示数字、小写字母等,对于一 183 | 些包括ctrl、shift等按键不支持,按键部分先这样,以后有需求再更改 184 | 185 | **-------->2017年 08月 31日 星期四 21:17:50 CST**
186 |        目前,发现整个DeeppinkOS的内存映射特别混乱,包括gdt表地址、ldt表地址和堆栈, 187 | 有太多地方需要规范了,先不再往后打开分页机制和进程管理 188 | 189 | **-------->2017年 09月 01日 星期五 20:41:05 CST**
190 |        今天,编译这个内核大于1.44M,因此,在想是否使用dd产生的软盘是否可以大于 191 | 1.44M。 192 |        修改pmm.c文件,将物理内存从0--4G重新分配到一个数组里边,因此导致整个内核 193 | 需要4M的连续空间,原来的内核加载地址0x8000已经不能满足需要,因此必须将内核加载 194 | 到0x100000(1M)以后才行(1M以后是连续可以的空间)。 195 | ======= 196 | make: *** [link] Error 1 197 | 198 | - 解决办法: 199 | 源文件的头文件太多,相互关系包括可能有重复,因此将interrupt.h分成两部分:interrupt.h和interrupt.c,这样只在头文件里边定义原型,在interrupt.c里边定义函数内容。 200 | 201 | ### -------->2017年 08月 30日 星期四 00:17:18 CST 202 | 添加键盘处理功能,包括文件keyboard.c和keyboard.h,本来打算按照hurlex-doc将内存管理部分的分页功能打开,但是发现有点复杂,以后再完善内存管理功能。 203 | 按键部分目前不完善,只是做了简单的中断处理,和显示数字、小写字母等,对于一些包括ctrl、shift等按键不支持,按键部分先这样,以后有需求再更改。 204 | 205 | ### -------->2017年 08月 31日 星期四 21:17:50 CST 206 | 目前,发现整个DeeppinkOS的内存映射特别混乱,包括gdt表地址、ldt表地址和堆栈,有太多地方需要规范了,先不再往后打开分页机制和进程管理。 207 | 208 | ### -------->2017年 09月 01日 星期五 20:41:05 CST 209 | 今天,编译这个内核大于1.44M,因此,在想是否使用dd产生的软盘是否可以大于1.44M。 210 | 修改pmm.c文件,将物理内存从0--4G重新分配到一个数组里边,因此导致整个内核需要4M的连续空间,原来的内核加载地址0x8000已经不能满足需要,因此必须将内核加载到0x100000(1M)以后才行(1M以后是连续可以的空间)。 211 | 212 | ### -------->2017年 11月 17日 星期五 12:24:20 CST 213 | 在Makefile添加objcopy功能,删掉kernel.elf相关头信息,节约了一点内存。 214 | 215 | -------------------------------------------------------------------------------- /drivers/block.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | static struct dlist device_list; 6 | 7 | /* 8 | * 初始化块设备 9 | */ 10 | void init_block_device() 11 | { 12 | device_list.dev = NULL; 13 | floppy_init(); 14 | hd_init(); 15 | } 16 | 17 | void register_device(struct device *dev) 18 | { 19 | int i; 20 | struct device *devtmp; 21 | struct dlist *dev_cur = NULL, *dev_next = NULL; 22 | 23 | dev_cur = &device_list; 24 | do { 25 | if (dev_next != NULL) { 26 | dev_cur = dev_next; 27 | } 28 | devtmp = dev_cur->dev; 29 | dev_next = dev_cur->next; 30 | }while(devtmp != NULL); 31 | 32 | dev_cur->dev = dev; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /drivers/block.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | struct file_operation { 6 | int (*write)(); 7 | int (*read)(); 8 | int (*ioctl)(); 9 | }; 10 | 11 | struct device { 12 | char *name; 13 | struct file_operation *ops; 14 | struct list_head lnode; 15 | }; 16 | 17 | struct dlist { 18 | struct device *dev; 19 | struct dlist* prev; 20 | struct dlist* next; 21 | }; 22 | 23 | void register_device(struct device *dev); 24 | void init_block_device(); 25 | void floppy_init(); 26 | void hd_init(); 27 | 28 | -------------------------------------------------------------------------------- /drivers/floppy.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * floopy driver 4 | * 5 | * http://www.brokenthorn.com/Resources/OSDev20.html 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | volatile bool ReceivedIRQ = false; 13 | extern void outb(unsigned short port,unsigned short value); 14 | extern unsigned char inb(unsigned short port); 15 | extern unsigned short inw(unsigned short port); 16 | 17 | static void fdc_handler(pt_regs *r) 18 | { 19 | ReceivedIRQ = true; 20 | } 21 | 22 | 23 | void reset_floppy(int device) 24 | { 25 | int i; 26 | char devs[] = {0x1C, 0x2D, 0x4E, 0x8F}; 27 | 28 | register_interrupt_handler(IRQ6, fdc_handler); 29 | 30 | outb(0x3f7, 0x00); 31 | outb(0x3f2, 0x0c); 32 | 33 | ReceivedIRQ = false; // This will prevent the FDC from being faster than us! 34 | 35 | // Enter, then exit reset mode. 36 | outb(FLPYDSK_CTRL, 0x00); 37 | outb(FLPYDSK_DOR, 0x0C); 38 | 39 | while(!ReceivedIRQ); // Wait for the IRQ handler to run 40 | 41 | #if 0 42 | // sense interrupt -- 4 of them typically required after a reset 43 | for (i = 4 ; i > 0 ; --i); 44 | { 45 | flpydsk_send_command(SENSE_INTERRUPT); 46 | flpydsk_read_data(); 47 | flpydsk_read_data(); 48 | } 49 | 50 | outb(FLPYDSK_CTRL, 0x00); // 500Kbps -- for 1.44M floppy 51 | 52 | // configure the drive 53 | flpydsk_send_command(SPECIFY); 54 | outb(DATA_FIFO, steprate_headunload); 55 | outb(DATA_FIFO, headload_ndma); 56 | #endif 57 | } 58 | 59 | /* 60 | * floppy init 61 | */ 62 | void floppy_init() 63 | { 64 | int device; 65 | 66 | reset_floppy(device); 67 | // fdc_flag 68 | while(ReceivedIRQ); 69 | return; 70 | } 71 | 72 | uint8_t flpydsk_read_status() 73 | { 74 | //! just return main status register 75 | return inb (FLPYDSK_MSR); 76 | } 77 | 78 | void flpydsk_send_command(uint8_t cmd) 79 | { 80 | //! wait until data register is ready. We send commands to the data register 81 | for (int i = 0; i < 500; i++ ) 82 | if ( flpydsk_read_status () & FLPYDSK_MSR_MASK_DATAREG ) 83 | return outb (DATA_FIFO, cmd); 84 | } 85 | 86 | uint8_t flpydsk_read_data() 87 | { 88 | //! same as above function but returns data register for reading 89 | for (int i = 0; i < 500; i++ ) 90 | if ( flpydsk_read_status () & FLPYDSK_MSR_MASK_DATAREG ) 91 | return inb (DATA_FIFO); 92 | } 93 | 94 | //! initialize DMA to use phys addr 1k-64k 95 | void flpydsk_initialize_dma() 96 | { 97 | outb(0x0a,0x06); //mask dma channel 2 98 | outb(0xd8,0xff); //reset master flip-flop 99 | outb(0x04, 0); //address=0x1000 100 | outb(0x04, 0x10); 101 | outb(0xd8, 0xff); //reset master flip-flop 102 | outb(0x05, 0xff); //count to 0x23ff (number of bytes in a 3.5" floppy disk track) 103 | outb(0x05, 0x23); 104 | outb(0x80, 0); //external page register = 0 105 | outb(0x0a, 0x02); //unmask dma channel 2 106 | } 107 | 108 | //! prepare the DMA for read transfer 109 | void flpydsk_dma_read() 110 | { 111 | 112 | outb(0x0a, 0x06); //mask dma channel 2 113 | outb(0x0b, 0x56); //single transfer, address increment, autoinit, read, channel 2 114 | outb(0x0a, 0x02); //unmask dma channel 2 115 | } 116 | 117 | //! prepare the DMA for write transfer 118 | void flpydsk_dma_write() 119 | { 120 | outb(0x0a, 0x06); //mask dma channel 2 121 | outb(0x0b, 0x5a); //single transfer, address increment, autoinit, write, channel 2 122 | outb(0x0a, 0x02); //unmask dma channel 2 123 | } 124 | 125 | -------------------------------------------------------------------------------- /drivers/hd.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | /* 6 | * 磁盘初始化 7 | */ 8 | void hd_init() 9 | { 10 | return; 11 | } 12 | 13 | int hd_write() 14 | { 15 | return 0; 16 | } 17 | 18 | int hd_read() 19 | { 20 | return 0; 21 | } 22 | 23 | int hd_ioctl() 24 | { 25 | return 0; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /drivers/keyboard.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 初始化键盘相关函数 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | /* 10 | * 说明:注册键盘中断处理函数 11 | */ 12 | static KB_INPUT kb_in; 13 | 14 | void init_keyboard() 15 | { 16 | printk("keyboard initial,and set keyboard_handler!\n"); 17 | kb_in.count = 0; 18 | kb_in.p_head = kb_in.p_tail = kb_in.buf; 19 | register_interrupt_handler(IRQ1, keyboard_handler); 20 | 21 | } 22 | 23 | /* 24 | * 说明:键盘中断处理函数 25 | */ 26 | void keyboard_handler(pt_regs *regs) 27 | { 28 | unsigned char scancode; 29 | scancode = inb(0x60); 30 | if(kb_in.count < KB_IN_BYTES){ 31 | *(kb_in.p_head) = scancode; 32 | kb_in.p_head++; 33 | /* 判断键盘缓冲区是否满,若满,则指向开始 */ 34 | if(kb_in.p_head == kb_in.buf+KB_IN_BYTES){ 35 | kb_in.p_head = kb_in.buf; 36 | } 37 | 38 | } 39 | kb_in.count++; 40 | //printk("0x%02X,",scancode); 41 | 42 | } 43 | 44 | /* 45 | * 读取键盘缓存区kb_in,并打印显示 46 | */ 47 | void keyboard_read() 48 | { 49 | unsigned char scancode; 50 | __asm__ volatile("cli"); 51 | if(kb_in.count > 0){ 52 | scancode = *(kb_in.p_tail); 53 | kb_in.p_tail++; 54 | kb_in.p_tail++; 55 | /* 判断是否读到最后 */ 56 | if(kb_in.p_tail == kb_in.buf + KB_IN_BYTES){ 57 | kb_in.p_tail = kb_in.buf; 58 | } 59 | kb_in.count = kb_in.count - 2; 60 | //keycode[0] = scancode; 61 | printk("%c",keymap[scancode*3]); 62 | } 63 | __asm__ volatile("sti"); 64 | } 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /drivers/task.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 初始化task_tables,支持多任务间切换 4 | */ 5 | 6 | #include "task_struct.h" 7 | #include "task.h" 8 | 9 | //struct task_struct task_tables[NR_TASKS] = {&(init_task.task),}; 10 | 11 | /* 12 | * 创建内核线程接口 13 | */ 14 | void kernel_thread_create(int (*fn)(void *),void *args) 15 | { 16 | /* TODO 构建进程 */ 17 | return; 18 | } 19 | 20 | 21 | /* 与tty相关的进程 */ 22 | void task_tty() 23 | { 24 | /* 初始化tty */ 25 | 26 | /* 读写tty */ 27 | while(1); 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /drivers/timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 说明:定义时钟驱动相关函数 3 | * 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | long jiffies; 12 | 13 | /* 14 | * 时钟测试函数 15 | */ 16 | void timer_callback(pt_regs *regs) 17 | { 18 | static unsigned int tick = 0; 19 | tick++; 20 | schedule(); 21 | } 22 | 23 | /* 24 | * 正式的时钟中断 25 | * 供进程实现 26 | */ 27 | void timer_interrupt(pt_regs *regs) 28 | { 29 | static long tick = 0; 30 | cli(); 31 | tick++; 32 | jiffies++; 33 | save_context(regs); 34 | if(tick <= 200){ 35 | //current = &(task_tables[0]->task); 36 | //schedule(); 37 | } 38 | else if(tick <= 500){ 39 | //current = &(task_tables[1]->task); 40 | //schedule(); 41 | } 42 | else{ 43 | tick = 0; 44 | } 45 | } 46 | 47 | 48 | /* 49 | * 时钟初始化驱动 50 | * frequency:时钟频率,越大,中断产生越频繁 51 | */ 52 | void init_timer(unsigned int frequency) 53 | { 54 | printk("initial timer,set timer interrupt......\n"); 55 | unsigned char low=0,high=0; 56 | unsigned int div=0; 57 | register_interrupt_handler(IRQ0,timer_interrupt); 58 | 59 | // 设置时钟模式:模式3 60 | outb(0x43,0x36); 61 | 62 | // 将frequency拆分成两部分写到0x40端口 63 | div = 1193180 / frequency; 64 | low = (unsigned char)div & 0xff; 65 | high = (unsigned char)(div >> 8) & 0xff; 66 | outb(0x40,low); 67 | outb(0x40,high); 68 | 69 | // 开启时钟中断 70 | outb(0x21,inb(0x21)&~0x01); 71 | 72 | } 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /fs/ext4.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /include/README.md: -------------------------------------------------------------------------------- 1 | # 说明 2 |        本文档在每一个源文件夹下都存在,用来说明当前路径的文件夹下各子文件功能,包括Makefile、源文件和其他类型文件,其初衷是有序化整个工程,帮助后续代码优化,防止代码冗余,此外也帮助其他开发者快速的了解整个系统架构。 3 | 4 | # 源文件 5 | 6 | - **i386**文件夹---------定义与i386体系结构相关的代码; 7 | - **vargs.h**--------------实现printk多变量的基本,与编译器相关; 8 | - **page.h**---------------页保护机制相关定义 9 | -------------------------------------------------------------------------------- /include/boot.h: -------------------------------------------------------------------------------- 1 | // running in real mode may require: 2 | __asm__(".code16gcc\n"); 3 | 4 | #ifndef __BOOT_H__ 5 | #define __BOOT_H__ 6 | 7 | #include 8 | 9 | #define E820_MAX_ENTRIES_ZEROPAGE 128 10 | 11 | typedef struct SMAP_entry { 12 | uint32_t BaseL; // base address uint64_t 13 | uint32_t BaseH; 14 | uint32_t LengthL; // length uint64_t 15 | uint32_t LengthH; 16 | uint32_t Type; // entry Type 17 | uint32_t ACPI; // extended 18 | 19 | }__attribute__((packed)) SMAP_entry_t; 20 | 21 | struct boot_e820_entry { 22 | u64 addr; /* start of memory segment */ 23 | u64 size; /* size of memory segment */ 24 | u32 type; /* type of memory segment */ 25 | } __attribute__((packed)); 26 | 27 | 28 | /* The so-called "zeropage" */ 29 | struct boot_params { 30 | #if 0 31 | struct screen_info screen_info; /* 0x000 */ 32 | struct apm_bios_info apm_bios_info; /* 0x040 */ 33 | #endif 34 | u8 _pad2[4]; /* 0x054 */ 35 | u64 tboot_addr; /* 0x058 */ 36 | #if 0 37 | struct ist_info ist_info; /* 0x060 */ 38 | #endif 39 | u8 _pad3[16]; /* 0x070 */ 40 | u8 hd0_info[16]; /* obsolete! */ /* 0x080 */ 41 | u8 hd1_info[16]; /* obsolete! */ /* 0x090 */ 42 | #if 0 43 | struct sys_desc_table sys_desc_table; /* obsolete! */ /* 0x0a0 */ 44 | struct olpc_ofw_header olpc_ofw_header; /* 0x0b0 */ 45 | #endif 46 | u32 ext_ramdisk_image; /* 0x0c0 */ 47 | u32 ext_ramdisk_size; /* 0x0c4 */ 48 | u32 ext_cmd_line_ptr; /* 0x0c8 */ 49 | u8 _pad4[116]; /* 0x0cc */ 50 | #if 0 51 | struct edid_info edid_info; /* 0x140 */ 52 | struct efi_info efi_info; /* 0x1c0 */ 53 | #endif 54 | u32 alt_mem_k; /* 0x1e0 */ 55 | u32 scratch; /* Scratch field! */ /* 0x1e4 */ 56 | u8 e820_entries; /* 0x1e8 */ 57 | u8 eddbuf_entries; /* 0x1e9 */ 58 | u8 edd_mbr_sig_buf_entries; /* 0x1ea */ 59 | u8 kbd_status; /* 0x1eb */ 60 | u8 secure_boot; /* 0x1ec */ 61 | u8 _pad5[2]; /* 0x1ed */ 62 | /* 63 | * The sentinel is set to a nonzero value (0xff) in header.S. 64 | * 65 | * A bootloader is supposed to only take setup_header and put 66 | * it into a clean boot_params buffer. If it turns out that 67 | * it is clumsy or too generous with the buffer, it most 68 | * probably will pick up the sentinel variable too. The fact 69 | * that this variable then is still 0xff will let kernel 70 | * know that some variables in boot_params are invalid and 71 | * kernel should zero out certain portions of boot_params. 72 | */ 73 | u8 sentinel; /* 0x1ef */ 74 | u8 _pad6[1]; /* 0x1f0 */ 75 | #if 0 76 | struct setup_header hdr; /* setup header */ /* 0x1f1 */ 77 | __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; 78 | __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ 79 | #endif 80 | #if 0 81 | struct boot_e820_entry e820_map[E820_MAX_ENTRIES_ZEROPAGE]; /* 0x2d0 */ 82 | #else 83 | SMAP_entry_t e820_map[E820_MAX_ENTRIES_ZEROPAGE]; /* 0x2d0 */ 84 | #endif 85 | u8 _pad8[48]; /* 0xcd0 */ 86 | #if 0 87 | struct edd_info eddbuf[EDDMAXNR]; /* 0xd00 */ 88 | #endif 89 | u8 _pad9[276]; /* 0xeec */ 90 | } __attribute__((packed)); 91 | 92 | /* 93 | * This variable is used to store some parameters during boot time. 94 | */ 95 | extern struct boot_params boot_params; 96 | 97 | #endif 98 | 99 | -------------------------------------------------------------------------------- /include/buddy.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __BUDDY_H__ 3 | #define __BUDDY_H__ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | struct buddy_element{ 10 | uint32_t index; /* 空闲数量 */ 11 | uint32_t *data; 12 | struct list_head order_list_head; 13 | }; 14 | 15 | extern struct buddy_element *buddy_order[]; 16 | 17 | uint32_t buddy_alloc_pages(int count, int flags); 18 | int buddy_alloc_scheme(int count); 19 | 20 | #endif 21 | 22 | 23 | -------------------------------------------------------------------------------- /include/console.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONSOLE_H__ 2 | #define __CONSOLE_H__ 3 | 4 | enum color { 5 | black = 0, 6 | blue = 1, 7 | green = 2, 8 | blue_green = 3, 9 | red = 4, 10 | magenta = 5, 11 | brown = 6, 12 | white = 7 13 | }; 14 | 15 | /* 16 | * 定义两个与屏幕有关的函数-清屏和显示一个字符串 17 | */ 18 | void console_clear(); 19 | void console_puts(unsigned char *string, unsigned char color_b, unsigned char color_z); 20 | void console_movecursor(int x, int y); 21 | unsigned short console_readcursor(); 22 | 23 | 24 | #endif 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /include/ctype.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __CTYPE_H__ 3 | #define __CTYPE_H__ 4 | 5 | /* 字符类型头文件 */ 6 | 7 | 8 | 9 | 10 | 11 | 12 | #endif 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /include/ctypes.h: -------------------------------------------------------------------------------- 1 | #ifndef __CTYPES_H__ 2 | #define __CTYPES_H__ 3 | 4 | /* 5 | * arch Size: char short int long ptr long-long u8 u16 u32 u64 6 | * i386 1 2 4 4 4 8 1 2 4 8 7 | */ 8 | typedef unsigned char u8; 9 | typedef unsigned short u16; 10 | typedef unsigned int u32; 11 | typedef unsigned long long u64; 12 | 13 | #endif 14 | 15 | -------------------------------------------------------------------------------- /include/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEBUG_H__ 2 | #define __DEBUG_H__ 3 | 4 | 5 | #include "console.h" 6 | #include "vargs.h" 7 | 8 | /* 开启调试功能 */ 9 | #define _DEBUG 0 10 | 11 | void printk(const char *format,...); 12 | volatile void panic(const char * s); 13 | 14 | 15 | #endif 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /include/descriptor.h: -------------------------------------------------------------------------------- 1 | #ifndef __DESCRIPTOR_H__ 2 | #define __DESCRIPTOR_H__ 3 | 4 | /* 5 | * 文件描述:全局描述符和中断描述符相关结构体定义 6 | */ 7 | #include "debug.h" 8 | #include "console.h" 9 | #include "vargs.h" 10 | #include "interrupt.h" 11 | #include "string.h" 12 | 13 | 14 | #define GDT_LEN 256 15 | #define IDT_LEN 256 16 | 17 | #define P_UNSET 0x00 18 | #define P_SET 0x80 19 | #define S_SS (0x00) /* 系统段 */ 20 | #define S_NSS (0x01 << 4) /* 非系统段 */ 21 | 22 | #define TI_UNSET (0x00 << 2) 23 | #define TI_SET (0x01 << 2) 24 | 25 | #define GDT_TI TI_UNSET 26 | #define LDT_TI TI_SET 27 | 28 | /* 全局描述符 */ 29 | 30 | #define DPL0 0x00 31 | #define DPL1 0x01 32 | #define DPL2 0x02 33 | #define DPL3 0x03 34 | 35 | /* RPL只在选择子(selector)中 */ 36 | #define RPL0 0x00 37 | #define RPL1 0x01 38 | #define RPL2 0x02 39 | #define RPL3 0x03 40 | 41 | #define TYPE_NOTBUSY 0x09 42 | #define TYPE_BUSY 0x0b 43 | 44 | #define AVL 0 45 | 46 | /* 中断描述符 */ 47 | 48 | 49 | 50 | /* 51 | * P----DPL----S----TYPE 52 | * S=0:系统段 53 | * S=1:非系统段 54 | * 在系统段中,TYPE字段意义不同 55 | * 在非系统段中,TYPE字段分为代码段和数据段,四位分别为X-R-C-A 56 | */ 57 | 58 | /* 以下为TYPE的字段功能 */ 59 | /* S=0 */ 60 | #define TYPE_TSS_BUSY 0x0B 61 | #define TYPE_TSS_NOTBUSY 0x09 62 | #define TYPE_LDT 0x02 63 | 64 | /* 三种门 */ 65 | #define TYPE_TASK_GATE 0x05 66 | #define TYPE_CALL_GATE 0x0C 67 | #define TYPE_INT_GATE 0x0E 68 | #define TYPE_TRAP_GATE 0x0F 69 | 70 | /* S=1 */ 71 | #define TYPE_KERNEL_CS 0x0A 72 | #define TYPE_KERNEL_DS 0x02 73 | 74 | #define TYPE_USER_CS 0x0F 75 | #define TYPE_USER_DS 0x07 76 | 77 | 78 | /* 使用选择子的概念 */ 79 | #define _KERNEL_CS_SELECTOR ((0x01 << 3) | GDT_TI | RPL0) 80 | #define _KERNEL_DS_SELECTOR ((0x02 << 3) | GDT_TI | RPL0) 81 | #define _USER_CS_SELECTOR ((0x04 << 3) | GDT_TI | RPL3) 82 | #define _USER_DS_SELECTOR ((0x05 << 3) | GDT_TI | RPL3) 83 | 84 | extern load_gdtr(unsigned int *); 85 | extern load_idtr(unsigned int *); 86 | 87 | static void init_gdt(); 88 | static void init_idt(); 89 | 90 | // 填充gdt表 91 | static void set_gdt(int num,unsigned int base,unsigned int limit,\ 92 | unsigned char access,unsigned char G_DB_L_AVL); 93 | 94 | /* 设置tss与ldt */ 95 | static void set_tssldt2_gdt(int num,unsigned int base,unsigned int limit,char type); 96 | // 填充idt表 97 | static void set_idt(int num,unsigned int base,unsigned short sel,\ 98 | unsigned short flags); 99 | 100 | /* 全局段描述符 */ 101 | typedef struct gdt_struct_t{ 102 | unsigned short limit0; //长度限制15--0 占两个字节 103 | unsigned short base0; //基地址15--0 104 | unsigned char base1; //基地址23--16 105 | unsigned char access; //P_DPL(2bits)_S_Type(4bits),共8位 106 | unsigned char limit1:4; //长度限制19--16 107 | unsigned char G_DB_L_AVL:4; // 108 | unsigned char base2; //基地址31--24 109 | }__attribute__((packed)) gdt_struct_t; 110 | 111 | struct gdtr_t{ 112 | unsigned short length; //这个大小代表了gdt表的大小 113 | unsigned int base; //gdt表的基地址 114 | }__attribute__((packed)) gdtr_t; 115 | 116 | /* 局部段描述符 */ 117 | typedef struct ldt_struct_t{ 118 | unsigned short limit0; //长度限制15--0 占两个字节 119 | unsigned short base0; //基地址15--0 120 | unsigned char base1; //基地址23--16 121 | unsigned char access; //P_DPL(2位)_S_Type 122 | unsigned char limit1:4; //长度限制19--16 123 | unsigned char G_DB_L_AVL:4; // 124 | unsigned char base2; //基地址31--24 125 | }__attribute__((packed)) ldt_struct_t; 126 | 127 | /* 中断门 / 调用门 / 陷阱门 */ 128 | typedef struct idt_struct_t{ 129 | unsigned short base0; //中断函数基地址15--0 130 | unsigned short sel; //选择段描述符 131 | unsigned char zero; //全是0 132 | unsigned char flags; //相关标志 P_DPL_TYPE 133 | unsigned short base1; //中断函数基地址31--16 134 | }__attribute__((packed)) idt_struct_t; 135 | 136 | struct idtr_t{ 137 | unsigned short length; //这个大小代表了idt表的大小 138 | unsigned int base; //gdt表的基地址 139 | }__attribute__((packed)) idtr_t; 140 | 141 | gdt_struct_t gdt_list[GDT_LEN]; 142 | struct gdtr_t GDTR; 143 | 144 | idt_struct_t idt_list[IDT_LEN]; 145 | struct idtr_t IDTR; 146 | 147 | 148 | /* 149 | * 填充gdt列表 150 | * num: 在gdt的位置 151 | * base: 填充的段的基地址 152 | * limit: 该段的段限长 153 | * access: 包括段的特权级别、段类型(代码段、数据段或者堆栈段) 154 | * 对于进程而言,ldt: access=0x82,tss: access=0x89 155 | * G_DB_L_AVL: 权限 156 | */ 157 | static void set_gdt(int num,unsigned int base,unsigned int limit,\ 158 | unsigned char access,unsigned char G_DB_L_AVL) 159 | { 160 | gdt_list[num].limit0 = (limit & 0xffff); 161 | gdt_list[num].base0 = (base & 0xffff); 162 | gdt_list[num].base1 = (base >> 16) & 0xff; 163 | gdt_list[num].access = access; 164 | gdt_list[num].limit1 = (limit >> 16); 165 | gdt_list[num].G_DB_L_AVL = G_DB_L_AVL; 166 | gdt_list[num].base2 = (base >> 24); 167 | 168 | } 169 | 170 | /* 171 | * 填充gdt列表 172 | * num: 在gdt的位置 173 | * base: 填充的段的基地址 174 | * type: 0x89为tss,0x82为ldt 175 | */ 176 | static void set_tssldt2_gdt(int num,unsigned int base,unsigned int limit,char type) 177 | { 178 | gdt_list[num].limit0 = (104 & 0xffff); 179 | gdt_list[num].base0 = (base & 0xffff); 180 | gdt_list[num].base1 = (base >> 16) & 0xff; 181 | gdt_list[num].access = type; 182 | gdt_list[num].limit1 = 0; 183 | gdt_list[num].G_DB_L_AVL = 0x0c; 184 | gdt_list[num].base2 = (base >> 24); 185 | 186 | } 187 | 188 | /* 189 | * 填充idt表 190 | * num: 填充的中断项在idt中的位置 191 | * base: 192 | * sel: 193 | * flags: 194 | */ 195 | static void set_idt(int num,unsigned int base,unsigned short sel,unsigned short flags) 196 | { 197 | idt_list[num].base0 = base & 0xffff; 198 | idt_list[num].base1 = (base >> 16) & 0xffff; 199 | idt_list[num].sel = sel; 200 | idt_list[num].zero = 0x0; 201 | idt_list[num].flags = flags; 202 | 203 | } 204 | 205 | 206 | // 中断(权限为0) 207 | #define set_int_gate(num,base) set_idt(num,base, TYPE_KERNEL_CS, (P_SET & (~(DPL3 << 5))) | TYPE_INT_GATE) 208 | // 陷阱(权限为0) 209 | #define set_trap_gate(num,base) set_idt(num,base, TYPE_KERNEL_CS, (P_SET & (~(DPL3 << 5))) | TYPE_TRAP_GATE) 210 | // 特殊的陷阱(权限为3)--系统调用 211 | #define set_system_gate(num,base) set_idt(num,base, TYPE_KERNEL_CS, (P_SET | (DPL3 << 5)) | TYPE_TRAP_GATE) 212 | 213 | /* 214 | * 设置5个全局描述符(包括全0) 215 | * 使用load_gdtr函数加载到gdtr寄存器 216 | */ 217 | static void init_gdt() 218 | { 219 | int i=0; 220 | printk("update gdt!\n"); 221 | printk("CS: 0x%x\n", (P_SET & (~(DPL3 << 5))) | S_NSS | TYPE_KERNEL_CS); 222 | printk("DS: 0x%x\n", (P_SET & (~(DPL3 << 5))) | S_NSS | TYPE_KERNEL_DS); 223 | // sizeof是编译器内部的宏,不需要定义 224 | GDTR.length = sizeof(gdt_struct_t)*GDT_LEN - 1; 225 | GDTR.base = (unsigned int)&gdt_list; 226 | 227 | // 开始设置gdt表中的内容 228 | set_gdt(0,0,0,0,0); 229 | //set_gdt(1,0,0xfffff,0x9a,0x0c); //内核代码段 230 | //set_gdt(2,0,0xfffff,0x92,0x0c); //内核数据段 231 | set_gdt(1, 0, 0xfffff, (P_SET & (~(DPL3 << 5))) | S_NSS | TYPE_KERNEL_CS, 0x0c); //内核代码段 232 | set_gdt(2, 0, 0xfffff, (P_SET & (~(DPL3 << 5))) | S_NSS | TYPE_KERNEL_DS, 0x0c); //内核数据段 233 | 234 | set_gdt(3,0,0,0,0);//null 235 | //set_gdt(4,0,0xfffff,0xfa,0x0c); //用户代码段-------| 进程0的TSS0(任务状态段) 236 | //set_gdt(5,0,0xfffff,0xf2,0x0c); //用户数据段-------| 进程0的LDT0 237 | set_gdt(4, 0, 0xfffff, (P_SET | (DPL3 << 5)) | S_NSS | TYPE_USER_CS, 0x0c); //用户代码段-------| 进程0的TSS0(任务状态段) 238 | set_gdt(5, 0, 0xfffff, (P_SET | (DPL3 << 5)) | S_NSS | TYPE_USER_DS, 0x0c); //用户数据段-------| 进程0的LDT0 239 | /* 后续的段描符初始化为0(与进程相关的代码) */ 240 | for(i=6;i<256;i++){ 241 | set_gdt(i,0,0,0,0); 242 | } 243 | 244 | // 加载gdt地址到gdtr寄存器 245 | load_gdtr((unsigned int)&GDTR); 246 | } 247 | 248 | 249 | /* 250 | * 初始化8259A,设置中断向量表 251 | */ 252 | static void init_idt() 253 | { 254 | printk("load idt!\n"); 255 | // 重新映射 IRQ 表 256 | // 两片级联的 Intel 8259A 芯片 257 | // 主片端口 0x20 0x21 258 | // 从片端口 0xA0 0xA1 259 | 260 | // 初始化主片、从片 261 | // 0001 0001 262 | outb(0x20, 0x11); 263 | outb(0xA0, 0x11); 264 | 265 | // 设置主片 IRQ 从 0x20(32) 号中断开始 266 | outb(0x21, 0x20); 267 | 268 | // 设置从片 IRQ 从 0x28(40) 号中断开始 269 | outb(0xA1, 0x28); 270 | 271 | // 设置主片 IR2 引脚连接从片 272 | outb(0x21, 0x04); 273 | 274 | // 告诉从片输出引脚和主片 IR2 号相连 275 | outb(0xA1, 0x02); 276 | 277 | // 设置主片和从片按照 8086 的方式工作 278 | outb(0x21, 0x01); 279 | outb(0xA1, 0x01); 280 | 281 | // 设置主从片允许中断 282 | outb(0x21, 0x0); 283 | outb(0xA1, 0x0); 284 | 285 | 286 | IDTR.length = sizeof(idt_struct_t)*256 - 1; 287 | IDTR.base = (unsigned int)&idt_list; 288 | 289 | bzero((unsigned char *)interrupt_handlers,sizeof(interrupt_handler_t)*256); 290 | bzero((unsigned char *)idt_list,sizeof(idt_struct_t)*256); 291 | 292 | //此处后续需要优化,将set_idt分成set_int_gate/set_system_gate/set_trap_gate实现 293 | set_trap_gate(0,(unsigned int)isr0); 294 | set_trap_gate(1,(unsigned int)isr1); 295 | set_trap_gate(2,(unsigned int)isr2); 296 | set_trap_gate(3,(unsigned int)isr3); 297 | set_trap_gate(4,(unsigned int)isr4); 298 | set_trap_gate(5,(unsigned int)isr5); 299 | 300 | set_trap_gate(6,(unsigned int)isr6); 301 | set_trap_gate(7,(unsigned int)isr7); 302 | set_trap_gate(8,(unsigned int)isr8); 303 | set_trap_gate(9,(unsigned int)isr9); 304 | set_trap_gate(10,(unsigned int)isr10); 305 | set_trap_gate(11,(unsigned int)isr11); 306 | set_trap_gate(12,(unsigned int)isr12); 307 | set_trap_gate(13,(unsigned int)isr13); 308 | set_trap_gate(14,(unsigned int)isr14); 309 | set_trap_gate(15,(unsigned int)isr15); 310 | set_trap_gate(16,(unsigned int)isr16); 311 | set_trap_gate(17,(unsigned int)isr17); 312 | set_trap_gate(18,(unsigned int)isr18); 313 | set_trap_gate(19,(unsigned int)isr19); 314 | /* Intel保留 */ 315 | set_trap_gate(20,(unsigned int)isr20); 316 | set_trap_gate(21,(unsigned int)isr21); 317 | set_trap_gate(22,(unsigned int)isr22); 318 | set_trap_gate(23,(unsigned int)isr23); 319 | set_trap_gate(24,(unsigned int)isr24); 320 | set_trap_gate(25,(unsigned int)isr25); 321 | set_trap_gate(26,(unsigned int)isr26); 322 | set_trap_gate(27,(unsigned int)isr27); 323 | set_trap_gate(28,(unsigned int)isr28); 324 | set_trap_gate(29,(unsigned int)isr29); 325 | set_trap_gate(30,(unsigned int)isr30); 326 | set_trap_gate(31,(unsigned int)isr31); 327 | /* 用户定义 */ 328 | set_trap_gate(32,(unsigned int)irq0); 329 | set_trap_gate(33,(unsigned int)irq1); 330 | set_trap_gate(34,(unsigned int)irq2); 331 | set_trap_gate(35,(unsigned int)irq3); 332 | set_trap_gate(36,(unsigned int)irq4); 333 | set_trap_gate(37,(unsigned int)irq5); 334 | set_trap_gate(38,(unsigned int)irq6); 335 | set_trap_gate(39,(unsigned int)irq7); 336 | set_trap_gate(40,(unsigned int)irq8); 337 | set_trap_gate(41,(unsigned int)irq9); 338 | set_trap_gate(42,(unsigned int)irq10); 339 | set_trap_gate(43,(unsigned int)irq11); 340 | set_trap_gate(44,(unsigned int)irq12); 341 | set_trap_gate(45,(unsigned int)irq13); 342 | set_trap_gate(46,(unsigned int)irq14); 343 | set_trap_gate(47,(unsigned int)irq15); 344 | 345 | /* 用于实现系统调用 */ 346 | set_system_gate(255,(unsigned int)isr255); 347 | /* 加载idt表地址 */ 348 | load_idtr((unsigned int)&IDTR); 349 | 350 | } 351 | 352 | 353 | 354 | 355 | #endif 356 | 357 | 358 | 359 | 360 | 361 | -------------------------------------------------------------------------------- /include/error.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __ERROR_H__ 3 | #define __ERROR_H__ 4 | 5 | /* 关于错误头文件 */ 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | #endif 15 | 16 | 17 | -------------------------------------------------------------------------------- /include/ext4.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __EXT4_H__ 3 | #define __EXT4_H__ 4 | 5 | /* 6 | * support VFS 7 | */ 8 | 9 | enum filetype { 10 | TXT = 0, 11 | }; 12 | 13 | struct node { 14 | char *name; 15 | char *path; 16 | struct node *parent; 17 | struct node *child; 18 | }; 19 | 20 | struct file { 21 | struct node *self; 22 | 23 | }; 24 | 25 | void mkdir(); 26 | void mkfile(); 27 | 28 | void mknode(); 29 | 30 | #endif 31 | 32 | -------------------------------------------------------------------------------- /include/font.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 实现font相关函数 4 | */ 5 | 6 | #ifndef __FONT_H__ 7 | #define __FONT_H__ 8 | /* 9 | * 头文件描述: 10 | * 在tty模式下的字库数组,包括大小写字母和数字 11 | */ 12 | 13 | #if 1 14 | char font_A[16]={ 15 | 0x00,0x18,0x18,0x18,0x18,0x24,0x24,0x24, 16 | 0x24,0x7e,0x42,0x42,0x42,0xe7,0x00,0x00 17 | }; 18 | #endif 19 | 20 | #endif 21 | 22 | -------------------------------------------------------------------------------- /include/i386/fork.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 实现fork 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | 12 | /* 实现fork */ 13 | inline _create_systemcall(int,fork) 14 | /* 实现pause */ 15 | static inline _create_systemcall(int,pause) 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /include/i386/fork.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 定义fork相关函数 4 | */ 5 | 6 | #ifndef __FORK_H__ 7 | #define __FORK_H__ 8 | 9 | 10 | 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /include/i386/linkage.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __ASM_LINKAGE_H 3 | #define __ASM_LINKAGE_H 4 | 5 | /* 本文件参考linux-2.6.22.6 */ 6 | 7 | #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) 8 | #define FASTCALL(x) x __attribute__((regparm(3))) 9 | /* 使用三个寄存器传递参数(EAX,EDX,ECX) */ 10 | #define fastcall __attribute__((regparm(3))) 11 | 12 | #define prevent_tail_call(ret) __asm__ ("" : "=r" (ret) : "0" (ret)) 13 | 14 | #ifdef CONFIG_X86_ALIGNMENT_16 15 | #define __ALIGN .align 16,0x90 16 | #define __ALIGN_STR ".align 16,0x90" 17 | #endif 18 | 19 | #endif 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /include/i386/sys.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 实现sys.h下相关系统调用,采用宏实现部分相关系统调用 4 | * 5 | */ 6 | 7 | 8 | #include "sys.h" 9 | #include "tty.h" 10 | #include "task_struct.h" 11 | 12 | #define filename #sys.h 13 | 14 | 15 | /* 16 | * 先使用这7个系统调用,system_call_table会被kernel.asm中调用 17 | */ 18 | syscall_ptr system_call_table[]={sys_setup,sys_exit,sys_fork, 19 | sys_read,sys_write,sys_open,sys_close}; 20 | 21 | 22 | 23 | 24 | int sys_setup() 25 | { 26 | return 0; 27 | } 28 | 29 | int sys_exit() 30 | { 31 | return 0; 32 | } 33 | 34 | /* 汇编实现,执行fork时被调用 */ 35 | int sys_fork() 36 | { 37 | printk("fork...\n"); 38 | return 0; 39 | } 40 | 41 | int sys_read() 42 | { 43 | printk("read...\n"); 44 | return 0; 45 | } 46 | 47 | int sys_write(char * buf, int len, struct task_struct *task) 48 | { 49 | printk("write...\n"); 50 | tty_write(&tty_table[task->nr_tty], buf, len); 51 | return 0; 52 | } 53 | 54 | int sys_open() 55 | { 56 | return 0; 57 | } 58 | 59 | int sys_close() 60 | { 61 | return 0; 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /include/i386/sys.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 系统调用表头文件 4 | * 简单实现sys_setup() sys_exit() sys_open() sys_read()等 5 | * 完整的内核支持的系统调用较多,本内核简单设置 6 | */ 7 | 8 | #define HZ 100 9 | 10 | #define __NR_setup 0 11 | #define __NR_exit 1 12 | #define __NR_fork 2 13 | #define __NR_read 3 14 | #define __NR_write 4 15 | #define __NR_open 5 16 | #define __NR_close 6 17 | 18 | #define __NR_pause 29 19 | 20 | 21 | /* __NR_##name ---> __NR_fork */ 22 | /* 定义无形参的系统调用 */ 23 | #define _create_systemcall(type,name)\ 24 | type name(void)\ 25 | {\ 26 | long __res;\ 27 | __asm__ __volatile__("int $0x80"\ 28 | : "=a"(__res)\ 29 | : "0"(__NR_##name));\ 30 | if(__res >= 0){\ 31 | return (type)__res;\ 32 | }\ 33 | else{\ 34 | return -1;\ 35 | }\ 36 | } 37 | 38 | /* 支持单个形参的系统调用 */ 39 | 40 | 41 | /* 支持两个形参的系统调用 */ 42 | 43 | 44 | 45 | 46 | 47 | /* 定义函数指针,代表各系统调用函数 */ 48 | typedef int (*syscall_ptr)(); 49 | 50 | extern int sys_setup(); 51 | extern int sys_exit(); 52 | extern int sys_fork(); /* 汇编实现,执行fork时被调用 */ 53 | extern int sys_read(); 54 | extern int sys_write(); 55 | extern int sys_open(); 56 | extern int sys_close(); 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /include/i386/system.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 在编写内核过程中,需要在C语言中嵌套汇编语言,该头文件定义相关函数 4 | * 其中必须使用汇编语言实现的与系统相关的函数 5 | */ 6 | 7 | 8 | /* 9 | * 添加进程的tss和ldt到gdt表后的基本函数 10 | * 采用intel嵌套汇编形式 11 | */ 12 | 13 | #define _set_tssldt_gdt2(n,addr,type)\ 14 | __asm__ __volatile__("movb $104,%0\n\t"\ 15 | "movl %6,%%ecx\n\t"\ 16 | "movw %%cx,%1\n\t" \ 17 | "rorl $16,%%eax\n\t" \ 18 | "movb %%al,%2\n\t" \ 19 | "movb %7,%3\n\t" \ 20 | "movb $0,%4\n\t" \ 21 | "movb %%ah,%5\n\t" \ 22 | "rorl $16,%%eax\n\t"\ 23 | :"=m"(*(n)),"=m"(*(n+2)),"=m"(*(n+4)),"=m"(*(n+5)),"=m"(*(n+6)),"=m"(*(n+7))\ 24 | :"g"(addr),"g"(type)\ 25 | :"memory"\ 26 | ) 27 | 28 | /* 29 | * 在全局表中设置任务状态段/局部表描述符。 30 | * 参数:n - 在全局表中描述符项n 所对应的地址;addr - 状态段/局部表所在内存的基地址。 31 | * type - 描述符中的标志类型字节。 32 | * %0 - eax(地址addr);%1 - (描述符项n 的地址);%2 - (描述符项n 的地址偏移2 处); 33 | * %3 - (描述符项n 的地址偏移4 处);%4 - (描述符项n 的地址偏移5 处); 34 | * %5 - (描述符项n 的地址偏移6 处);%6 - (描述符项n 的地址偏移7 处); 35 | */ 36 | #define _set_tssldt_gdt(n,addr,type) \ 37 | __asm__ __volatile__( "movw $104,%1\n\t" \ 38 | "movl %0,%%eax\n\t"\ 39 | "movw %%ax,%2\n\t" \ 40 | "rorl $16,%%eax\n\t" \ 41 | "movb %%al,%3\n\t" \ 42 | "movb $"type",%4\n\t" \ 43 | "movb $0x00,%5\n\t" \ 44 | "movb %%ah,%6\n\t" \ 45 | "rorl $16,%%eax" \ 46 | ::"g" (addr), "m" (*(n)), "m" (*(n + 2)), "m" (*(n + 4)),\ 47 | "m" (*(n + 5)), "m" (*(n + 6)), "m" (*(n + 7))) 48 | 49 | 50 | // 将进程的tss和ldt添加到系统全局gdt和ldt上 51 | // 其中0x89代表tss,0x82代表ldt 52 | #define set_tss_gdt(n,addr) _set_tssldt_gdt(((char *) (n)),addr,"0x89") 53 | #define set_ldt_gdt(n,addr) _set_tssldt_gdt(((char *) (n)),addr,"0x82") 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /include/init.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __INIT_H__ 3 | #define __INIT_H__ 4 | 5 | /* 6 | * 系统初始化函数放在此处 7 | */ 8 | 9 | #include 10 | 11 | extern uint32_t page_dir2[]; 12 | extern uint32_t page_table2[][1024]; 13 | 14 | void init_paging(); 15 | 16 | 17 | #endif 18 | 19 | 20 | -------------------------------------------------------------------------------- /include/interrupt.h: -------------------------------------------------------------------------------- 1 | #ifndef __INTERRUPT_H__ 2 | #define __INTERRUPT_H__ 3 | 4 | /* 5 | * 说明:在初始化gdt表以后,需要开始初始化idt,该头文件定义相关中断处理函数 6 | * 这些中断处理函数只是填充idt表中的offset项 7 | */ 8 | 9 | /* 10 | ---| 11 | ---| 12 | ---| 13 | 14 | */ 15 | 16 | void sti(); 17 | void cli(); 18 | 19 | /* 寄存器类型 */ 20 | typedef struct pt_regs_t { 21 | long ds; // 用于保存用户的数据段描述符 22 | long edi; // 从 edi 到 eax 由 pusha 指令压入 23 | long esi; 24 | long ebp; 25 | long esp; 26 | long ebx; 27 | long edx; 28 | long ecx; 29 | long eax; 30 | long int_no; // 中断号 31 | long err_code; // 错误代码(有中断错误代码的中断会由CPU压入) 32 | long eip; // 以下由处理器自动压入 33 | long cs; 34 | long eflags; 35 | long useresp; 36 | long ss; 37 | } pt_regs; 38 | 39 | // 定义中断处理函数指针 40 | typedef void (*interrupt_handler_t)(pt_regs *); 41 | 42 | // 注册一个中断处理函数 43 | // n:中断号 44 | // h:中断处理函数 45 | void register_interrupt_handler(unsigned char n, interrupt_handler_t h); 46 | 47 | 48 | /* 49 | * 在CPU中存在中断、异常和陷阱(与软中断实现相关)三种方式 50 | * 需要在此处分开设计 51 | * 52 | */ 53 | 54 | 55 | // 调用异常处理函数 56 | void isr_handler(pt_regs *regs); 57 | 58 | interrupt_handler_t interrupt_handlers[256]; 59 | 60 | 61 | // 32~255 用户自定义异常 62 | void isr255(); 63 | 64 | 65 | /* 66 | * 系统调用(需要嵌套AT&T汇编),gcc只支持在c语言中嵌套AT&T汇编 67 | * 在即isr128 68 | * 69 | * 此函数后续直接使用汇编完成,此处不再需要 70 | */ 71 | extern int system_call(void); 72 | 73 | 74 | // 声明中断处理函数 0-19 属于 CPU 的异常 75 | // ISR:中断服务程序(interrupt service routine) 76 | void isr0(); // 0 #DE 除 0 异常 77 | void isr1(); // 1 #DB 调试异常 78 | void isr2(); // 2 NMI 79 | void isr3(); // 3 BP 断点异常 80 | void isr4(); // 4 #OF 溢出 81 | void isr5(); // 5 #BR 对数组的引用超出边界 82 | void isr6(); // 6 #UD 无效或未定义的操作码 83 | void isr7(); // 7 #NM 设备不可用(无数学协处理器) 84 | void isr8(); // 8 #DF 双重故障(有错误代码) 85 | void isr9(); // 9 协处理器跨段操作 86 | void isr10(); // 10 #TS 无效TSS(有错误代码) 87 | void isr11(); // 11 #NP 段不存在(有错误代码) 88 | void isr12(); // 12 #SS 栈错误(有错误代码) 89 | void isr13(); // 13 #GP 常规保护(有错误代码) 90 | void isr14(); // 14 #PF 页故障(有错误代码) 91 | void isr15(); // 15 CPU 保留 92 | void isr16(); // 16 #MF 浮点处理单元错误 93 | void isr17(); // 17 #AC 对齐检查 94 | void isr18(); // 18 #MC 机器检查 95 | void isr19(); // 19 #XM SIMD(单指令多数据)浮点异常 96 | 97 | // 20-31 Intel 保留 98 | void isr20(); 99 | void isr21(); 100 | void isr22(); 101 | void isr23(); 102 | void isr24(); 103 | void isr25(); 104 | void isr26(); 105 | void isr27(); 106 | void isr28(); 107 | void isr29(); 108 | void isr30(); 109 | void isr31(); 110 | 111 | 112 | // IRQ 处理函数 113 | void irq_handler(pt_regs *regs); 114 | 115 | /* 116 | * 外部中断从0x20开始 117 | * 8259相关 118 | */ 119 | #define IRQ0 32 // 电脑系统计时器 120 | #define IRQ1 33 // 键盘 121 | #define IRQ2 34 // 与 IRQ9 相接,MPU-401 MD 使用 122 | #define IRQ3 35 // 串口设备 123 | #define IRQ4 36 // 串口设备 124 | #define IRQ5 37 // 建议声卡使用 125 | #define IRQ6 38 // 软驱传输控制使用 126 | #define IRQ7 39 // 打印机传输控制使用 127 | #define IRQ8 40 // 即时时钟 128 | #define IRQ9 41 // 与 IRQ2 相接,可设定给其他硬件 129 | #define IRQ10 42 // 建议网卡使用 130 | #define IRQ11 43 // 建议 AGP 显卡使用 131 | #define IRQ12 44 // 接 PS/2 鼠标,也可设定给其他硬件 132 | #define IRQ13 45 // 协处理器使用 133 | #define IRQ14 46 // IDE0 传输控制使用 134 | #define IRQ15 47 // IDE1 传输控制使用 135 | 136 | // 声明 IRQ 函数 137 | // IRQ:中断请求(Interrupt Request) 138 | void irq0(); // 电脑系统计时器 139 | void irq1(); // 键盘 140 | void irq2(); // 与 IRQ9 相接(连接到slave chips) 141 | void irq3(); // 串口设备 142 | void irq4(); // 串口设备 143 | void irq5(); // 建议声卡使用 144 | void irq6(); // 软驱传输控制使用 145 | void irq7(); // 打印机传输控制使用 146 | 147 | void irq8(); // RTC 148 | void irq9(); // 与 IRQ2 相接,可设定给其他硬件 149 | void irq10(); // 建议网卡使用 150 | void irq11(); // 建议 AGP 显卡使用 151 | void irq12(); // 接 PS/2 鼠标,也可设定给其他硬件 152 | void irq13(); // 协处理器使用 153 | void irq14(); // IDE0 传输控制使用 154 | void irq15(); // IDE1 传输控制使用 155 | 156 | 157 | #endif 158 | 159 | -------------------------------------------------------------------------------- /include/keyboard.h: -------------------------------------------------------------------------------- 1 | #ifndef __KEYBOARD_H__ 2 | #define __KEYBOARD_H__ 3 | 4 | #include "interrupt.h" 5 | 6 | void keyboard_handler(pt_regs *regs); 7 | void init_keyboard(); 8 | void keyboard_read(); 9 | 10 | 11 | 12 | 13 | 14 | 15 | /************************************************************************/ 16 | /* Macros Declaration */ 17 | /************************************************************************/ 18 | #define KB_IN_BYTES 32 /* size of keyboard input buffer */ 19 | #define MAP_COLS 3 /* Number of columns in keymap */ 20 | #define NR_SCAN_CODES 0x80 /* Number of scan codes (rows in keymap) */ 21 | 22 | #define FLAG_BREAK 0x0080 /* Break Code */ 23 | #define FLAG_EXT 0x0100 /* Normal function keys */ 24 | #define FLAG_SHIFT_L 0x0200 /* Shift key */ 25 | #define FLAG_SHIFT_R 0x0400 /* Shift key */ 26 | #define FLAG_CTRL_L 0x0800 /* Control key */ 27 | #define FLAG_CTRL_R 0x1000 /* Control key */ 28 | #define FLAG_ALT_L 0x2000 /* Alternate key */ 29 | #define FLAG_ALT_R 0x4000 /* Alternate key */ 30 | #define FLAG_PAD 0x8000 /* keys in num pad */ 31 | 32 | /* 33 | * raw key value = code passed to tty & MASK_RAW 34 | * the value can be found either in the keymap column 0 35 | * or in the list below 36 | */ 37 | #define MASK_RAW 0x01FF 38 | 39 | 40 | 41 | /* Special keys */ 42 | #define ESC (0x01 + FLAG_EXT) /* Esc */ 43 | #define TAB (0x02 + FLAG_EXT) /* Tab */ 44 | #define ENTER (0x03 + FLAG_EXT) /* Enter */ 45 | #define BACKSPACE (0x04 + FLAG_EXT) /* BackSpace */ 46 | 47 | #define GUI_L (0x05 + FLAG_EXT) /* L GUI */ 48 | #define GUI_R (0x06 + FLAG_EXT) /* R GUI */ 49 | #define APPS (0x07 + FLAG_EXT) /* APPS */ 50 | 51 | /* Shift, Ctrl, Alt */ 52 | #define SHIFT_L (0x08 + FLAG_EXT) /* L Shift */ 53 | #define SHIFT_R (0x09 + FLAG_EXT) /* R Shift */ 54 | #define CTRL_L (0x0A + FLAG_EXT) /* L Ctrl */ 55 | #define CTRL_R (0x0B + FLAG_EXT) /* R Ctrl */ 56 | #define ALT_L (0x0C + FLAG_EXT) /* L Alt */ 57 | #define ALT_R (0x0D + FLAG_EXT) /* R Alt */ 58 | 59 | /* Lock keys */ 60 | #define CAPS_LOCK (0x0E + FLAG_EXT) /* Caps Lock */ 61 | #define NUM_LOCK (0x0F + FLAG_EXT) /* Number Lock */ 62 | #define SCROLL_LOCK (0x10 + FLAG_EXT) /* Scroll Lock */ 63 | 64 | /* Function keys */ 65 | #define F1 (0x11 + FLAG_EXT) /* F1 */ 66 | #define F2 (0x12 + FLAG_EXT) /* F2 */ 67 | #define F3 (0x13 + FLAG_EXT) /* F3 */ 68 | #define F4 (0x14 + FLAG_EXT) /* F4 */ 69 | #define F5 (0x15 + FLAG_EXT) /* F5 */ 70 | #define F6 (0x16 + FLAG_EXT) /* F6 */ 71 | #define F7 (0x17 + FLAG_EXT) /* F7 */ 72 | #define F8 (0x18 + FLAG_EXT) /* F8 */ 73 | #define F9 (0x19 + FLAG_EXT) /* F9 */ 74 | #define F10 (0x1A + FLAG_EXT) /* F10 */ 75 | #define F11 (0x1B + FLAG_EXT) /* F11 */ 76 | #define F12 (0x1C + FLAG_EXT) /* F12 */ 77 | 78 | /* Control Pad */ 79 | #define PRINTSCREEN (0x1D + FLAG_EXT) /* Print Screen */ 80 | #define PAUSEBREAK (0x1E + FLAG_EXT) /* Pause/Break */ 81 | #define INSERT (0x1F + FLAG_EXT) /* Insert */ 82 | #define DELETE (0x20 + FLAG_EXT) /* Delete */ 83 | #define HOME (0x21 + FLAG_EXT) /* Home */ 84 | #define END (0x22 + FLAG_EXT) /* End */ 85 | #define PAGEUP (0x23 + FLAG_EXT) /* Page Up */ 86 | #define PAGEDOWN (0x24 + FLAG_EXT) /* Page Down */ 87 | #define UP (0x25 + FLAG_EXT) /* Up */ 88 | #define DOWN (0x26 + FLAG_EXT) /* Down */ 89 | #define LEFT (0x27 + FLAG_EXT) /* Left */ 90 | #define RIGHT (0x28 + FLAG_EXT) /* Right */ 91 | 92 | /* ACPI keys */ 93 | #define POWER (0x29 + FLAG_EXT) /* Power */ 94 | #define SLEEP (0x2A + FLAG_EXT) /* Sleep */ 95 | #define WAKE (0x2B + FLAG_EXT) /* Wake Up */ 96 | 97 | /* Num Pad */ 98 | #define PAD_SLASH (0x2C + FLAG_EXT) /* / */ 99 | #define PAD_STAR (0x2D + FLAG_EXT) /* * */ 100 | #define PAD_MINUS (0x2E + FLAG_EXT) /* - */ 101 | #define PAD_PLUS (0x2F + FLAG_EXT) /* + */ 102 | #define PAD_ENTER (0x30 + FLAG_EXT) /* Enter */ 103 | #define PAD_DOT (0x31 + FLAG_EXT) /* . */ 104 | #define PAD_0 (0x32 + FLAG_EXT) /* 0 */ 105 | #define PAD_1 (0x33 + FLAG_EXT) /* 1 */ 106 | #define PAD_2 (0x34 + FLAG_EXT) /* 2 */ 107 | #define PAD_3 (0x35 + FLAG_EXT) /* 3 */ 108 | #define PAD_4 (0x36 + FLAG_EXT) /* 4 */ 109 | #define PAD_5 (0x37 + FLAG_EXT) /* 5 */ 110 | #define PAD_6 (0x38 + FLAG_EXT) /* 6 */ 111 | #define PAD_7 (0x39 + FLAG_EXT) /* 7 */ 112 | #define PAD_8 (0x3A + FLAG_EXT) /* 8 */ 113 | #define PAD_9 (0x3B + FLAG_EXT) /* 9 */ 114 | #define PAD_UP PAD_8 /* Up */ 115 | #define PAD_DOWN PAD_2 /* Down */ 116 | #define PAD_LEFT PAD_4 /* Left */ 117 | #define PAD_RIGHT PAD_6 /* Right */ 118 | #define PAD_HOME PAD_7 /* Home */ 119 | #define PAD_END PAD_1 /* End */ 120 | #define PAD_PAGEUP PAD_9 /* Page Up */ 121 | #define PAD_PAGEDOWN PAD_3 /* Page Down */ 122 | #define PAD_INS PAD_0 /* Ins */ 123 | #define PAD_MID PAD_5 /* Middle key */ 124 | #define PAD_DEL PAD_DOT /* Del */ 125 | 126 | 127 | /************************************************************************/ 128 | /* Stucture Definition */ 129 | /************************************************************************/ 130 | /* Keyboard structure, 1 per console. */ 131 | typedef struct s_kb { 132 | char* p_head; /* 指向缓冲区中下一个空闲位置 */ 133 | char* p_tail; /* 指向键盘任务应处理的字节 */ 134 | int count; /* 缓冲区中共有多少字节 */ 135 | char buf[KB_IN_BYTES]; /* 缓冲区 */ 136 | }KB_INPUT; 137 | 138 | 139 | 140 | 141 | 142 | #endif 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /include/keymap.h: -------------------------------------------------------------------------------- 1 | #ifndef __KEYMAP_H__ 2 | #define __KEYMAP_H__ 3 | 4 | #include "keyboard.h" 5 | /* Keymap for US MF-2 keyboard. */ 6 | 7 | unsigned int keymap[0x80 * 3] = { 8 | 9 | /* scan-code !Shift Shift E0 XX */ 10 | /* ==================================================================== */ 11 | /* 0x00 - none */ 0, 0, 0, 12 | /* 0x01 - ESC */ ESC, ESC, 0, 13 | /* 0x02 - '1' */ '1', '!', 0, 14 | /* 0x03 - '2' */ '2', '@', 0, 15 | /* 0x04 - '3' */ '3', '#', 0, 16 | /* 0x05 - '4' */ '4', '$', 0, 17 | /* 0x06 - '5' */ '5', '%', 0, 18 | /* 0x07 - '6' */ '6', '^', 0, 19 | /* 0x08 - '7' */ '7', '&', 0, 20 | /* 0x09 - '8' */ '8', '*', 0, 21 | /* 0x0A - '9' */ '9', '(', 0, 22 | /* 0x0B - '0' */ '0', ')', 0, 23 | /* 0x0C - '-' */ '-', '_', 0, 24 | /* 0x0D - '=' */ '=', '+', 0, 25 | /* 0x0E - BS */ BACKSPACE, BACKSPACE, 0, 26 | /* 0x0F - TAB */ TAB, TAB, 0, 27 | /* 0x10 - 'q' */ 'q', 'Q', 0, 28 | /* 0x11 - 'w' */ 'w', 'W', 0, 29 | /* 0x12 - 'e' */ 'e', 'E', 0, 30 | /* 0x13 - 'r' */ 'r', 'R', 0, 31 | /* 0x14 - 't' */ 't', 'T', 0, 32 | /* 0x15 - 'y' */ 'y', 'Y', 0, 33 | /* 0x16 - 'u' */ 'u', 'U', 0, 34 | /* 0x17 - 'i' */ 'i', 'I', 0, 35 | /* 0x18 - 'o' */ 'o', 'O', 0, 36 | /* 0x19 - 'p' */ 'p', 'P', 0, 37 | /* 0x1A - '[' */ '[', '{', 0, 38 | /* 0x1B - ']' */ ']', '}', 0, 39 | /* 0x1C - CR/LF */ ENTER, ENTER, PAD_ENTER, 40 | /* 0x1D - l. Ctrl */ CTRL_L, CTRL_L, CTRL_R, 41 | /* 0x1E - 'a' */ 'a', 'A', 0, 42 | /* 0x1F - 's' */ 's', 'S', 0, 43 | /* 0x20 - 'd' */ 'd', 'D', 0, 44 | /* 0x21 - 'f' */ 'f', 'F', 0, 45 | /* 0x22 - 'g' */ 'g', 'G', 0, 46 | /* 0x23 - 'h' */ 'h', 'H', 0, 47 | /* 0x24 - 'j' */ 'j', 'J', 0, 48 | /* 0x25 - 'k' */ 'k', 'K', 0, 49 | /* 0x26 - 'l' */ 'l', 'L', 0, 50 | /* 0x27 - ';' */ ';', ':', 0, 51 | /* 0x28 - '\'' */ '\'', '"', 0, 52 | /* 0x29 - '`' */ '`', '~', 0, 53 | /* 0x2A - l. SHIFT */ SHIFT_L, SHIFT_L, 0, 54 | /* 0x2B - '\' */ '\\', '|', 0, 55 | /* 0x2C - 'z' */ 'z', 'Z', 0, 56 | /* 0x2D - 'x' */ 'x', 'X', 0, 57 | /* 0x2E - 'c' */ 'c', 'C', 0, 58 | /* 0x2F - 'v' */ 'v', 'V', 0, 59 | /* 0x30 - 'b' */ 'b', 'B', 0, 60 | /* 0x31 - 'n' */ 'n', 'N', 0, 61 | /* 0x32 - 'm' */ 'm', 'M', 0, 62 | /* 0x33 - ',' */ ',', '<', 0, 63 | /* 0x34 - '.' */ '.', '>', 0, 64 | /* 0x35 - '/' */ '/', '?', PAD_SLASH, 65 | /* 0x36 - r. SHIFT */ SHIFT_R, SHIFT_R, 0, 66 | /* 0x37 - '*' */ '*', '*', 0, 67 | /* 0x38 - ALT */ ALT_L, ALT_L, ALT_R, 68 | /* 0x39 - ' ' */ ' ', ' ', 0, 69 | /* 0x3A - CapsLock */ CAPS_LOCK, CAPS_LOCK, 0, 70 | /* 0x3B - F1 */ F1, F1, 0, 71 | /* 0x3C - F2 */ F2, F2, 0, 72 | /* 0x3D - F3 */ F3, F3, 0, 73 | /* 0x3E - F4 */ F4, F4, 0, 74 | /* 0x3F - F5 */ F5, F5, 0, 75 | /* 0x40 - F6 */ F6, F6, 0, 76 | /* 0x41 - F7 */ F7, F7, 0, 77 | /* 0x42 - F8 */ F8, F8, 0, 78 | /* 0x43 - F9 */ F9, F9, 0, 79 | /* 0x44 - F10 */ F10, F10, 0, 80 | /* 0x45 - NumLock */ NUM_LOCK, NUM_LOCK, 0, 81 | /* 0x46 - ScrLock */ SCROLL_LOCK, SCROLL_LOCK, 0, 82 | /* 0x47 - Home */ PAD_HOME, '7', HOME, 83 | /* 0x48 - CurUp */ PAD_UP, '8', UP, 84 | /* 0x49 - PgUp */ PAD_PAGEUP, '9', PAGEUP, 85 | /* 0x4A - '-' */ PAD_MINUS, '-', 0, 86 | /* 0x4B - Left */ PAD_LEFT, '4', LEFT, 87 | /* 0x4C - MID */ PAD_MID, '5', 0, 88 | /* 0x4D - Right */ PAD_RIGHT, '6', RIGHT, 89 | /* 0x4E - '+' */ PAD_PLUS, '+', 0, 90 | /* 0x4F - End */ PAD_END, '1', END, 91 | /* 0x50 - Down */ PAD_DOWN, '2', DOWN, 92 | /* 0x51 - PgDown */ PAD_PAGEDOWN, '3', PAGEDOWN, 93 | /* 0x52 - Insert */ PAD_INS, '0', INSERT, 94 | /* 0x53 - Delete */ PAD_DOT, '.', DELETE, 95 | /* 0x54 - Enter */ 0, 0, 0, 96 | /* 0x55 - ??? */ 0, 0, 0, 97 | /* 0x56 - ??? */ 0, 0, 0, 98 | /* 0x57 - F11 */ F11, F11, 0, 99 | /* 0x58 - F12 */ F12, F12, 0, 100 | /* 0x59 - ??? */ 0, 0, 0, 101 | /* 0x5A - ??? */ 0, 0, 0, 102 | /* 0x5B - ??? */ 0, 0, GUI_L, 103 | /* 0x5C - ??? */ 0, 0, GUI_R, 104 | /* 0x5D - ??? */ 0, 0, APPS, 105 | /* 0x5E - ??? */ 0, 0, 0, 106 | /* 0x5F - ??? */ 0, 0, 0, 107 | /* 0x60 - ??? */ 0, 0, 0, 108 | /* 0x61 - ??? */ 0, 0, 0, 109 | /* 0x62 - ??? */ 0, 0, 0, 110 | /* 0x63 - ??? */ 0, 0, 0, 111 | /* 0x64 - ??? */ 0, 0, 0, 112 | /* 0x65 - ??? */ 0, 0, 0, 113 | /* 0x66 - ??? */ 0, 0, 0, 114 | /* 0x67 - ??? */ 0, 0, 0, 115 | /* 0x68 - ??? */ 0, 0, 0, 116 | /* 0x69 - ??? */ 0, 0, 0, 117 | /* 0x6A - ??? */ 0, 0, 0, 118 | /* 0x6B - ??? */ 0, 0, 0, 119 | /* 0x6C - ??? */ 0, 0, 0, 120 | /* 0x6D - ??? */ 0, 0, 0, 121 | /* 0x6E - ??? */ 0, 0, 0, 122 | /* 0x6F - ??? */ 0, 0, 0, 123 | /* 0x70 - ??? */ 0, 0, 0, 124 | /* 0x71 - ??? */ 0, 0, 0, 125 | /* 0x72 - ??? */ 0, 0, 0, 126 | /* 0x73 - ??? */ 0, 0, 0, 127 | /* 0x74 - ??? */ 0, 0, 0, 128 | /* 0x75 - ??? */ 0, 0, 0, 129 | /* 0x76 - ??? */ 0, 0, 0, 130 | /* 0x77 - ??? */ 0, 0, 0, 131 | /* 0x78 - ??? */ 0, 0, 0, 132 | /* 0x78 - ??? */ 0, 0, 0, 133 | /* 0x7A - ??? */ 0, 0, 0, 134 | /* 0x7B - ??? */ 0, 0, 0, 135 | /* 0x7C - ??? */ 0, 0, 0, 136 | /* 0x7D - ??? */ 0, 0, 0, 137 | /* 0x7E - ??? */ 0, 0, 0, 138 | /* 0x7F - ??? */ 0, 0, 0 139 | }; 140 | 141 | 142 | /* 143 | 回车键: 把光标移到第一列 144 | 换行键: 把光标前进到下一行 145 | */ 146 | 147 | 148 | /*====================================================================================* 149 | Appendix: Scan code set 1 150 | *====================================================================================* 151 | 152 | KEY MAKE BREAK ----- KEY MAKE BREAK ----- KEY MAKE BREAK 153 | -------------------------------------------------------------------------------------- 154 | A 1E 9E 9 0A 8A [ 1A 9A 155 | B 30 B0 ` 29 89 INSERT E0,52 E0,D2 156 | C 2E AE - 0C 8C HOME E0,47 E0,C7 157 | D 20 A0 = 0D 8D PG UP E0,49 E0,C9 158 | E 12 92 \ 2B AB DELETE E0,53 E0,D3 159 | F 21 A1 BKSP 0E 8E END E0,4F E0,CF 160 | G 22 A2 SPACE 39 B9 PG DN E0,51 E0,D1 161 | H 23 A3 TAB 0F 8F U ARROW E0,48 E0,C8 162 | I 17 97 CAPS 3A BA L ARROW E0,4B E0,CB 163 | J 24 A4 L SHFT 2A AA D ARROW E0,50 E0,D0 164 | K 25 A5 L CTRL 1D 9D R ARROW E0,4D E0,CD 165 | L 26 A6 L GUI E0,5B E0,DB NUM 45 C5 166 | M 32 B2 L ALT 38 B8 KP / E0,35 E0,B5 167 | N 31 B1 R SHFT 36 B6 KP * 37 B7 168 | O 18 98 R CTRL E0,1D E0,9D KP - 4A CA 169 | P 19 99 R GUI E0,5C E0,DC KP + 4E CE 170 | Q 10 19 R ALT E0,38 E0,B8 KP EN E0,1C E0,9C 171 | R 13 93 APPS E0,5D E0,DD KP . 53 D3 172 | S 1F 9F ENTER 1C 9C KP 0 52 D2 173 | T 14 94 ESC 01 81 KP 1 4F CF 174 | U 16 96 F1 3B BB KP 2 50 D0 175 | V 2F AF F2 3C BC KP 3 51 D1 176 | W 11 91 F3 3D BD KP 4 4B CB 177 | X 2D AD F4 3E BE KP 5 4C CC 178 | Y 15 95 F5 3F BF KP 6 4D CD 179 | Z 2C AC F6 40 C0 KP 7 47 C7 180 | 0 0B 8B F7 41 C1 KP 8 48 C8 181 | 1 02 82 F8 42 C2 KP 9 49 C9 182 | 2 03 83 F9 43 C3 ] 1B 9B 183 | 3 04 84 F10 44 C4 ; 27 A7 184 | 4 05 85 F11 57 D7 ' 28 A8 185 | 5 06 86 F12 58 D8 , 33 B3 186 | 187 | 6 07 87 PRTSCRN E0,2A E0,B7 . 34 B4 188 | E0,37 E0,AA 189 | 190 | 7 08 88 SCROLL 46 C6 / 35 B5 191 | 192 | 8 09 89 PAUSE E1,1D,45 -NONE- 193 | E1,9D,C5 194 | 195 | 196 | ----------------- 197 | ACPI Scan Codes: 198 | ------------------------------------------- 199 | Key Make Code Break Code 200 | ------------------------------------------- 201 | Power E0, 5E E0, DE 202 | Sleep E0, 5F E0, DF 203 | Wake E0, 63 E0, E3 204 | 205 | 206 | ------------------------------- 207 | Windows Multimedia Scan Codes: 208 | ------------------------------------------- 209 | Key Make Code Break Code 210 | ------------------------------------------- 211 | Next Track E0, 19 E0, 99 212 | Previous Track E0, 10 E0, 90 213 | Stop E0, 24 E0, A4 214 | Play/Pause E0, 22 E0, A2 215 | Mute E0, 20 E0, A0 216 | Volume Up E0, 30 E0, B0 217 | Volume Down E0, 2E E0, AE 218 | Media Select E0, 6D E0, ED 219 | E-Mail E0, 6C E0, EC 220 | Calculator E0, 21 E0, A1 221 | My Computer E0, 6B E0, EB 222 | WWW Search E0, 65 E0, E5 223 | WWW Home E0, 32 E0, B2 224 | WWW Back E0, 6A E0, EA 225 | WWW Forward E0, 69 E0, E9 226 | WWW Stop E0, 68 E0, E8 227 | WWW Refresh E0, 67 E0, E7 228 | WWW Favorites E0, 66 E0, E6 229 | 230 | *=====================================================================================*/ 231 | 232 | 233 | 234 | #endif /* _ORANGES_KEYMAP_H_ */ 235 | 236 | -------------------------------------------------------------------------------- /include/list.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __LIST_H__ 3 | #define __LIST_H__ 4 | 5 | /* 6 | * 关于链表的数据结构 7 | */ 8 | 9 | #include 10 | 11 | struct list_head{ 12 | struct list_head *next, *prev; 13 | }; 14 | 15 | 16 | 17 | #endif 18 | 19 | 20 | -------------------------------------------------------------------------------- /include/memory.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __MEMORY_H__ 4 | #define __MEMORY_H__ 5 | 6 | 7 | /* 8 | * TODO 分配器,对basic,slab等分配器做统一管理 9 | */ 10 | struct memory_allocator_t { 11 | char *name; 12 | 13 | }; 14 | 15 | /* 物理地址 */ 16 | typedef uint32_t phys_addr_t; 17 | 18 | /* 虚拟地址 */ 19 | typedef uint32_t virt_addr_t; 20 | 21 | 22 | 23 | #endif 24 | 25 | -------------------------------------------------------------------------------- /include/page.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __PAGE_H__ 3 | #define __PAGE_H__ 4 | 5 | /* 6 | * 这里定义页相关的变量 7 | * 8 | */ 9 | 10 | #define PAGE_SIZE 4096 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | #endif 20 | 21 | 22 | -------------------------------------------------------------------------------- /include/peripheral.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Peripheral devices 4 | */ 5 | 6 | #include 7 | 8 | /* FDC registers */ 9 | enum FLPYDSK_IO 10 | { 11 | STATUS_REGISTER_A = 0x3F0, // read-only 12 | STATUS_REGISTER_B = 0x3F1, // read-only 13 | FLPYDSK_DOR = 0x3F2, 14 | TAPE_DRIVE_REGISTER = 0x3F3, 15 | FLPYDSK_MSR = 0x3F4, // read-only 16 | DATARATE_SELECT_REGISTER = 0x3F4, // write-only 17 | DATA_FIFO = 0x3F5, 18 | DIGITAL_INPUT_REGISTER = 0x3F7, // read-only 19 | FLPYDSK_CTRL = 0x3F7 // write-only 20 | }; 21 | 22 | enum FLPYDSK_CMD 23 | { 24 | FDC_CMD_READ_TRACK = 2, // generates IRQ6 25 | FDC_CMD_SPECIFY = 3, // * set drive parameters 26 | FDC_CMD_CHECK_STAT = 4, 27 | FDC_CMD_WRITE_SECT = 5, // * write to the disk 28 | FDC_CMD_READ_SECT = 6, // * read from the disk 29 | FDC_CMD_CALIBRATE = 7, // * seek to cylinder 0 30 | FDC_CMD_CHECK_INT = 8, // * ack IRQ6, get status of last command 31 | FDC_CMD_WRITE_DEL_S = 9, 32 | FDC_CMD_READ_ID_S = 10, // generates IRQ6 33 | FDC_CMD_READ_DEL_S = 0xc, 34 | FDC_CMD_FORMAT_TRACK = 0xd, 35 | FDC_CMD_DUMPREG = 14, 36 | FDC_CMD_SEEK = 0xf, 37 | VERSION = 16, // * used during initialization, once 38 | SCAN_EQUAL = 17, 39 | PERPENDICULAR_MODE = 18, // * used during initialization, once, maybe 40 | CONFIGURE = 19, // * set controller parameters 41 | LOCK = 20, // * protect controller params from a reset 42 | VERIFY = 22, 43 | SCAN_LOW_OR_EQUAL = 25, 44 | SCAN_HIGH_OR_EQUAL = 29 45 | }; 46 | 47 | enum FLPYDSK_MSR_MASK 48 | { 49 | FLPYDSK_MSR_MASK_DRIVE1_POS_MODE = 1, //00000001 50 | FLPYDSK_MSR_MASK_DRIVE2_POS_MODE = 2, //00000010 51 | FLPYDSK_MSR_MASK_DRIVE3_POS_MODE = 4, //00000100 52 | FLPYDSK_MSR_MASK_DRIVE4_POS_MODE = 8, //00001000 53 | FLPYDSK_MSR_MASK_BUSY = 16, //00010000 54 | FLPYDSK_MSR_MASK_DMA = 32, //00100000 55 | FLPYDSK_MSR_MASK_DATAIO = 64, //01000000 56 | FLPYDSK_MSR_MASK_DATAREG = 128 //10000000 57 | }; 58 | 59 | enum FLPYDSK_CMD_EXT 60 | { 61 | FDC_CMD_EXT_SKIP = 0x20, //00100000 62 | FDC_CMD_EXT_DENSITY = 0x40, //01000000 63 | FDC_CMD_EXT_MULTITRACK = 0x80 //10000000 64 | }; 65 | 66 | enum FLPYDSK_GAP3_LENGTH 67 | { 68 | FLPYDSK_GAP3_LENGTH_STD = 42, 69 | FLPYDSK_GAP3_LENGTH_5_14 = 32, 70 | FLPYDSK_GAP3_LENGTH_3_5 = 27 71 | }; 72 | 73 | enum FLPYDSK_SECTOR_DTL 74 | { 75 | FLPYDSK_SECTOR_DTL_128 = 0, 76 | FLPYDSK_SECTOR_DTL_256 = 1, 77 | FLPYDSK_SECTOR_DTL_512 = 2, 78 | FLPYDSK_SECTOR_DTL_1024 = 4 79 | }; 80 | 81 | /* for floopy */ 82 | void reset_floppy(int device); 83 | void floppy_init(); 84 | 85 | /* for hard disk */ 86 | void hd_init(); 87 | 88 | -------------------------------------------------------------------------------- /include/pmm.h: -------------------------------------------------------------------------------- 1 | #ifndef __PMM_H__ 2 | #define __PMM_H__ 3 | 4 | #include 5 | 6 | 7 | /* 主内存开始地址 */ 8 | #define MAIN_MEMORY_START (1024*512*9) 9 | #define MAIN_MEMORY_END (1024*1024*128) 10 | 11 | #define PMM_MAX_SIZE (1024*1024*128) // 512MB 12 | #define PMM_START_ADDR (0) // 就从这开始分配每一页 13 | #define PMM_END_ADDR (1024*1024*128) // 128M 14 | #define PAGE_SIZE 0x1000 // 每一页大小为4KB 15 | 16 | /* 总共有多少页 */ 17 | #define PAGE_MAX_COUNT (PMM_MAX_SIZE / PAGE_SIZE) 18 | 19 | extern unsigned int phy_page_count; 20 | extern unsigned int pmm_stack_top; 21 | 22 | void init_pmm(void); 23 | void pmm_free_page(uint32_t p); 24 | uint32_t pmm_alloc_page(void); 25 | void pmm_free_pages(uint32_t p, int count); 26 | uint32_t pmm_alloc_pages(int count); 27 | 28 | void *kmalloc(uint32_t size, int flags); 29 | void kfree(); 30 | 31 | 32 | #endif 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /include/protect.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 关于x86权限相关定义 4 | */ 5 | #ifndef __PROTECT_H__ 6 | #define __PROTECT_H__ 7 | 8 | #define RPL0 0x0 9 | #define RPL1 0x01 10 | #define RPL2 0x02 11 | #define RPL3 0x03 12 | 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /include/schedule.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __SCHEDULE_H__ 3 | #define __SCHEDULE_H__ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | /* 定义与调度相关的变量 */ 10 | #define STACK_SIZE 8192 11 | 12 | enum schedr_index { 13 | PRI_SCHEDR = 0, 14 | MAX_SCHEDR 15 | }; 16 | 17 | extern char kernel_stack[]; 18 | extern long kernel_stack_top; 19 | 20 | void schedule_init(void); 21 | void reschedule(void); 22 | void schedule(void); 23 | void init0_ready(void); 24 | void thread_init1(void); 25 | /* 线程cpu_idle应该是init0 */ 26 | void thread_cpu_idle(void); 27 | void init_thread(void); 28 | 29 | void save_context(pt_regs *regs); 30 | struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next)); 31 | 32 | 33 | /* 在kernel.asm文件中,与_page_dir是相同的含义 */ 34 | #define pg_dir (0) 35 | 36 | /* 37 | * 改变进程权限:从0到3特权级 ss,sp,eflags,cs,ip "lret\n"\ 38 | * 压入ss sp eflags cs ip 39 | * movl $0x17,%%eax RPL=3 TI=1(ldt) SEL=1 40 | */ 41 | void move_to_user_mode(void); 42 | void init(void); 43 | extern struct task_struct *current; 44 | extern union task_union* task_tables[]; 45 | 46 | /* 47 | * 调度器 48 | */ 49 | struct scheduler { 50 | char *name; 51 | void (*fn)(void); 52 | }; 53 | 54 | /* 55 | * 切换进程 56 | * 保存eflags 57 | */ 58 | #define switch_to(prev, next, last) do { \ 59 | unsigned long esi, edi; \ 60 | __asm__ __volatile__("pushfl\n\t" /* 保存eflags */ \ 61 | "pushl %%ebp\n\t" \ 62 | "movl %%esp,%0\n\t" /* 保存ESP */ \ 63 | "movl %5,%%esp\n\t" /* 切换ESP */ \ 64 | "movl $1f,%1\n\t" /* 保存EIP */ \ 65 | "pushl %6\n\t" /* 切换EIP */ \ 66 | "jmp __switch_to\n" \ 67 | "1:\t" /* 下一次切换回到1 */ \ 68 | "popl %%ebp\n\t" \ 69 | "popfl" \ 70 | :"=m" (prev->tss.esp0),"=m" (prev->tss.eip), \ 71 | "=a" (last),"=S" (esi),"=D" (edi) \ 72 | :"m" (next->tss.esp0),"m" (next->tss.eip), \ 73 | "2" (prev), "d" (next)); \ 74 | } while (0); 75 | 76 | #endif 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /include/slab.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __SLAB_H__ 3 | #define __SLAB_H__ 4 | 5 | #include 6 | 7 | void *basic_allocator(uint32_t count); 8 | 9 | typedef struct kmem_cache_struct{ 10 | int a; 11 | } kmem_cache_t; 12 | 13 | 14 | kmem_cache_t *kmem_cache_create(char *name, 15 | size_t size, 16 | int align, 17 | void (*constructor)(void *, size_t), 18 | void (*destructor)(void *, size_t)); 19 | 20 | void kmem_cache_destroy(kmem_cache_t *cp); 21 | 22 | 23 | void *kmem_cache_alloc(kmem_cache_t *cp, int flags); 24 | void kmem_cache_free(kmem_cache_t *cp, void *buf); 25 | 26 | #endif 27 | 28 | 29 | -------------------------------------------------------------------------------- /include/string.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Filename: string.h 4 | * 5 | * Description: 字符串处理函数 6 | * 7 | */ 8 | 9 | #ifndef __STRING_H__ 10 | #define __STRING_H__ 11 | 12 | 13 | static inline void memcpy(unsigned char *dest, const unsigned char *src, unsigned int len) 14 | { 15 | for (; len != 0; len--){ 16 | *dest++ = *src++; 17 | } 18 | } 19 | 20 | static inline void memset(void *dest, unsigned char value, unsigned int len) 21 | { 22 | unsigned char *dst = (unsigned char *)dest; 23 | 24 | for ( ; len != 0; len--) { 25 | *dst++ = value; 26 | } 27 | } 28 | 29 | static inline void bzero(void *dest, unsigned int len) 30 | { 31 | memset(dest, 0, len); 32 | } 33 | 34 | /* 35 | * 描述:比较两个字符串 36 | * 如果相等:返回0 37 | * 如果不等:返回正数,则str1大 38 | * 返回负数,则str2大 39 | */ 40 | static inline int strcmp(const char *str1, const char *str2) 41 | { 42 | while (*str1 && *str2 && *str1 == *str2) { 43 | str1++; 44 | str2++; 45 | } 46 | 47 | return *str1 - *str2; 48 | } 49 | 50 | static inline char *strcpy(char *dest, const char *src) 51 | { 52 | char *tmp = dest; 53 | 54 | while (*src) { 55 | *dest++ = *src++; 56 | } 57 | 58 | *dest = '\0'; 59 | 60 | return tmp; 61 | } 62 | /* 63 | * 描述:将src代表的字符串加到dest代表的字符串后面 64 | */ 65 | static inline char *strcat(char *dest, const char *src) 66 | { 67 | char *cp = dest; 68 | 69 | while(*cp){ 70 | cp++; 71 | } 72 | 73 | while ((*cp++ = *src++)) 74 | ; 75 | 76 | return dest; 77 | } 78 | 79 | static inline int strlen(const char *src) 80 | { 81 | const char *eos = src; 82 | 83 | while (*eos++); 84 | 85 | return (eos - src - 1); 86 | } 87 | 88 | //#define sizeof(char *type) ((type+1)-type) 89 | 90 | 91 | #endif//STRING_H_ 92 | 93 | -------------------------------------------------------------------------------- /include/task.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __TASK_H__ 3 | #define __TASK_H__ 4 | 5 | void kernel_thread_create(int (*fn)(void *), void *args); 6 | 7 | void task_tty(); 8 | 9 | #endif 10 | 11 | 12 | -------------------------------------------------------------------------------- /include/task_struct.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 与进程相关的结构体定义头文件,包括ldt/tss定义 3 | * 4 | * author: 5 | * 6 | */ 7 | #ifndef __TASK_STRUCT_H__ 8 | #define __TASK_STRUCT_H__ 9 | 10 | #include 11 | #include "schedule.h" 12 | 13 | #include "descriptor.h" 14 | #include "page.h" 15 | #include 16 | 17 | #define NR_TASKS 128 18 | #define PG_DIR (0) 19 | 20 | /*进程的五种状态 */ 21 | #define TASK_RUNNING 0 22 | #define TASK_INTERRUPTIBLE 1 23 | #define TASK_UNINTERRUPTIBLE 2 24 | #define TASK_ZOMBIE 3 25 | #define TASK_STOPPED 4 26 | 27 | /* 第一个进程在gdt中的位置 */ 28 | #define FIRST_TASKTSS_INDEX 6 29 | #define FIRST_TASKLDT_INDEX 7 30 | 31 | // 将tss或者ldt相对于第一个tss或者第一个ldt进行编码 32 | 33 | // TR [---selector(16 bit, visible)---/---base(hidden)---/---limit(hidden)---] 34 | #define _TSS(n) ((((unsigned long)n) << 4) + (FIRST_TASKTSS_INDEX << 3)) 35 | #define _LDT(n) ((((unsigned long)n) << 4) + (FIRST_TASKLDT_INDEX << 3)) 36 | 37 | 38 | /* 将tss和ldt地址加载到TR和LDTR寄存器 */ 39 | /* 根据TR寄存器的位图可以看出需要加载一个TSS选择子到TR寄存器 */ 40 | #define ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n))) 41 | #define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n))) 42 | 43 | 44 | 45 | /* 在32位编译器下int 占4个字节 */ 46 | 47 | /* 48 | * tss_struct是一个进程的tss描述符(TSS结构参考Intel 80386 programmer's 49 | * manual 1986) 50 | */ 51 | struct tss_struct{ 52 | long backlink;/* back link to previous TSS */ 53 | long esp0; 54 | long ss0;/* 16位,后续若为16位寄存器则占用低16位,高16位为0 */ 55 | long esp1; 56 | long ss1; 57 | long esp2; 58 | long ss2; 59 | 60 | long cr3; 61 | long eip; 62 | long eflags; 63 | 64 | long eax; 65 | long ecx; 66 | long edx; 67 | long ebx; 68 | 69 | long esp; 70 | long ebp; 71 | long esi; 72 | long edi; 73 | long es;/* 以下皆为16位寄存器 */ 74 | long cs; 75 | long ss; 76 | long ds; 77 | long fs; 78 | long gs; 79 | unsigned int ldt;/* 只取16位 */ 80 | /* tss最后32位中,0:trap,16-31:iobase,其他位为0 */ 81 | long trap; 82 | long iobase; 83 | 84 | }; 85 | 86 | 87 | /* 内核线程上下文 */ 88 | struct context_t{ 89 | uint32_t esp; 90 | uint32_t ebp; 91 | uint32_t ebx; 92 | uint32_t esi; 93 | uint32_t edi; 94 | uint32_t eflags; 95 | }; 96 | 97 | /* task_struct:进程的描述符 */ 98 | struct task_struct{ 99 | long state; /* 进程当前的状态 */ 100 | long counter; /* 时间片 */ 101 | long priority; /* 优先级 */ 102 | long signal; 103 | 104 | long blocked; 105 | int exit_code; 106 | unsigned long start_code,end_code,end_data,brk,start_stack; 107 | long pid,father,pgrp,session,leader; /* pid:进程ID号 */ 108 | unsigned short uid,euid,suid; 109 | unsigned short gid,egid,sgid; 110 | 111 | long alarm; 112 | long utime,stime,cutime,cstime,start_time; 113 | 114 | int nr_tty; /* 自设备号 */ 115 | struct context_t context; 116 | struct task_struct *next; /* 一个进程 */ 117 | /* 接下来需要三个结构体代码该进程执行的对象 */ 118 | // 目前先不设置 119 | 120 | /* 该进程的局部段描述符 */ 121 | struct ldt_struct_t ldt[3]; 122 | /* 该进程的tss */ 123 | struct tss_struct tss; 124 | 125 | }; 126 | 127 | 128 | 129 | /* 利用联合体,一个task_union正好占4K大小 */ 130 | union task_union { 131 | struct task_struct task; 132 | char stack[PAGE_SIZE]; //PAGE_SIZE == 4096 133 | }; 134 | 135 | 136 | 137 | /* 填充一个task0,是所有进程的父进程 */ 138 | #if 0 139 | struct task_struct INIT_TASK={ 140 | .state = TASK_RUNNING, 141 | .counter = 0, 142 | .priority = 0, /* 优先级 */ 143 | .signal = 0, 144 | 145 | 146 | .blocked = 0, 147 | .exit_code = 0, 148 | 149 | .start_code = 0, 150 | .end_code = 0, 151 | .end_data = 0, 152 | .brk = 0, 153 | .start_stack = 0, 154 | 155 | .pid = 0,/* pid:进程ID号 */ 156 | .father = 0, 157 | .pgrp = 0, 158 | .session = 0, 159 | .leader = 0, 160 | 161 | .uid = 0, 162 | .euid = 0, 163 | .suid = 0, 164 | .gid = 0, 165 | .egid = 0, 166 | .sgid = 0, 167 | 168 | .alarm = 0, 169 | .utime = 0, 170 | .stime = 0, 171 | .cutime = 0, 172 | .cstime = 0, 173 | .start_time = 0, 174 | 175 | .tty = 0, /* 自设备号 */ 176 | 177 | /* 填充ldt */ 178 | /* 填充ldt[0] */ 179 | ldt[0].limit0 = 0, 180 | ldt[0].base0 = 0, 181 | ldt[0].base1 = 0, 182 | ldt[0].access = 0, 183 | ldt[0].limit1 = 0, 184 | ldt[0].GD_DB_L_AVL = 0, 185 | ldt[0].base2 = 0, 186 | 187 | /* 填充ldt[1] */ 188 | ldt[1].limit0 = 0, 189 | ldt[1].base0 = 0, 190 | ldt[1].base1 = 0, 191 | ldt[1].access = 0, 192 | ldt[1].limit1 = 0, 193 | ldt[1].GD_DB_L_AVL = 0, 194 | ldt[1].base2 = 0, 195 | 196 | /* 填充ldt[2] */ 197 | ldt[2].limit0 = 0, 198 | ldt[2].base0 = 0, 199 | ldt[2].base1 = 0, 200 | ldt[2].access = 0, 201 | ldt[2].limit1 = 0, 202 | ldt[2].GD_DB_L_AVL = 0, 203 | ldt[2].base2 = 0, 204 | 205 | 206 | /* 填充tss */ 207 | tss.backlink = 0, 208 | tss.esp0 = PAGE_SIZE + (long)&init_task, 209 | tss.ss0 = 0x10, 210 | tss.esp1 = 0, 211 | tss.ss1 = 0, 212 | tss.esp2 = 0, 213 | tss.ss2 = 0, 214 | 215 | tss.cr3 = pg_dir,//进程与内核使用同一个页目录表 216 | tss.eip = 0, 217 | tss.flags = 0, 218 | 219 | tss.eax = 0, 220 | tss.ecx = 0, 221 | tss.edx = 0, 222 | tss.ebx = 0, 223 | 224 | tss.esp = 0, 225 | tss.ebp = 0, 226 | tss.esi = 0, 227 | tss.edi = 0, 228 | tss.es = 0x17, 229 | tss.cs = 0x17, 230 | tss.ss = 0x17, 231 | tss.ds = 0x17, 232 | tss.fs = 0x17, 233 | tss.gs = 0x17, 234 | tss.ldt = _LDT(0), //需要实现 235 | tss.trap = 0x80000000, 236 | tss.iobase = 0,//暂时先留着 237 | 238 | }; 239 | #endif 240 | 241 | 242 | 243 | 244 | /* 使用宏对INIT_TASK进行初始化 */ 245 | /* 246 | {0,0},{0x9f,0xc0fa00},{0x9f,0xc0f200}, 247 | */ 248 | #define INIT_TASK \ 249 | {\ 250 | /* state */ TASK_RUNNING,\ 251 | /* counter */ 1000,\ 252 | /* priority */ 0,\ 253 | /* signal */ 0,\ 254 | \ 255 | /* blocked */ 0,\ 256 | /* exit_code */ 0,\ 257 | \ 258 | /* start_code */ 0,\ 259 | /* end_code */ 0,\ 260 | /* end_data */ 0,\ 261 | /* brk */ 0,\ 262 | /* start_stack */ 0,\ 263 | \ 264 | /* pid */ 0,\ 265 | /* father */ 0,\ 266 | /* pgrp */ 0,\ 267 | /* session */ 0,\ 268 | /* leader */ 0, \ 269 | \ 270 | /* uid */ 0,\ 271 | /* euid */ 0,\ 272 | /* suid */ 0,\ 273 | /* gid */ 0,\ 274 | /* egid */ 0,\ 275 | /* sgid */ 0,\ 276 | \ 277 | /* alarm */ 0,\ 278 | /* utime */ 0,\ 279 | /* stime */ 0,\ 280 | /* cutime */ 0,\ 281 | /* cstime */ 0,\ 282 | /* start_time */ 0,\ 283 | \ 284 | /* tty */ 0,\ 285 | \ 286 | /* 填充ldt(此处需要改进) */\ 287 | /* 填充ldt[0] */\ 288 | {\ 289 | /* ldt[0].limit0 */ {0,\ 290 | /* ldt[0].base0 */ 0,\ 291 | /* ldt[0].base1 */ 0,\ 292 | /* ldt[0].access */ 0,\ 293 | /* ldt[0].limit1 */ 0,\ 294 | /* ldt[0].GD_DB_L_AVL */ 0,\ 295 | /* ldt[0].base2 */ 0},\ 296 | \ 297 | /* 填充ldt[1] */\ 298 | /* ldt[1].limit0 */ {0x9f,\ 299 | /* ldt[1].base0 */ 0,\ 300 | /* ldt[1].base1 */ 0,\ 301 | /* ldt[1].access */ 0xfa,\ 302 | /* ldt[1].limit1 */ 0,\ 303 | /* ldt[1].GD_DB_L_AVL */ 0x0c,\ 304 | /* ldt[1].base2 */ 0},\ 305 | \ 306 | /* 填充ldt[2] */\ 307 | /* ldt[2].limit0 */ {0x9f,\ 308 | /* ldt[2].base0 */ 0,\ 309 | /* ldt[2].base1 */ 0,\ 310 | /* ldt[2].access */ 0xf2,\ 311 | /* ldt[2].limit1 */ 0,\ 312 | /* ldt[2].GD_DB_L_AVL */ 0x0c,\ 313 | /* ldt[2].base2 */ 0},\ 314 | },\ 315 | \ 316 | /* 填充tss */\ 317 | {\ 318 | /* tss.backlink */ 0,\ 319 | /* tss.esp0 */ 0,\ 320 | /* tss.ss0 */ _KERNEL_DS_SELECTOR,\ 321 | /* tss.esp1 */ 0,\ 322 | /* tss.ss1 */ _KERNEL_CS_SELECTOR,\ 323 | /* tss.esp2 */ 0,\ 324 | /* tss.ss2 */ 0,\ 325 | \ 326 | /* 进程与内核使用同一个页目录表 */ \ 327 | /* tss.cr3 */ PG_DIR,\ 328 | /* tss.eip */ 0,\ 329 | /* tss.eflags */0x3202,\ 330 | \ 331 | /* tss.eax */ 0,\ 332 | /* tss.ecx */ 0,\ 333 | /* tss.edx */ 0,\ 334 | /* tss.ebx */ 0,\ 335 | \ 336 | /* tss.esp */ 4096,\ 337 | /* tss.ebp */ 0,\ 338 | /* tss.esi */ 0,\ 339 | /* tss.edi */ 0,\ 340 | /* tss.es */ 0x10,\ 341 | /* tss.cs */ 0x08,\ 342 | /* tss.ss */ 0x10,\ 343 | /* tss.ds */ 0x10,\ 344 | /* tss.fs */ 0x10,\ 345 | /* tss.gs */ 0x10,\ 346 | \ 347 | /* 需要实现 */ \ 348 | /* tss.ldt */ _LDT(0),\ 349 | /* tss.trap */ 0x80000000,\ 350 | \ 351 | /* 暂时先留着 */ \ 352 | /* tss.iobase */ 0,\ 353 | },\ 354 | } 355 | 356 | 357 | //TODO 此处有bug,如果这样写需要INIT_TASK是一个宏,反正不能是一个变量 358 | static union task_union init_task={INIT_TASK,}; 359 | 360 | 361 | 362 | #endif 363 | 364 | 365 | -------------------------------------------------------------------------------- /include/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef __TIMER_H__ 2 | #define __TIMER_H__ 3 | 4 | #include 5 | //extern pt_regs; 6 | 7 | void init_timer(unsigned int frequency); 8 | void timer_callback(pt_regs *regs); 9 | 10 | 11 | #endif 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /include/tty.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __TTY_H__ 4 | #define __TTY_H__ 5 | 6 | #define NR_CONSOLES 3 7 | #define TTY_IN_BYTES 256 8 | 9 | 10 | typedef struct tty_struct 11 | { 12 | unsigned long in_buf[TTY_IN_BYTES]; 13 | unsigned long *inbuf_head; 14 | unsigned long *inbuf_tail; 15 | int inbuf_count; 16 | 17 | struct console_struct* p_console; 18 | }TTY; 19 | 20 | typedef struct console_struct 21 | { 22 | unsigned int current_start_addr; 23 | unsigned int original_addr; 24 | unsigned int mem_limit; 25 | unsigned int cursor; 26 | }CONSOLE; 27 | 28 | extern TTY tty_table[NR_CONSOLES]; 29 | extern CONSOLE console_table[NR_CONSOLES]; 30 | 31 | void tty_write(TTY *tty, char *buf, int len); 32 | 33 | #endif 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /include/unistd.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 实现POSIX标准中对内核的规定,参考POSIX文档完善! 4 | * 5 | * author: Rongwei Wang 6 | * 7 | * 标准符号常量与类型 8 | */ 9 | 10 | #ifndef __UNISTD_H__ 11 | #define __UNISTD_H__ 12 | 13 | 14 | /* 参考POSIX-2001标准 */ 15 | #define _POSIX_VERSION 200112L 16 | #define _POSIX2_VERSION 200112L 17 | #define _XOPEN_VERSION 600 18 | 19 | #define NULL ((void *)0) 20 | #define false 0 21 | #define true 1 22 | 23 | typedef int bool; 24 | typedef unsigned int size_t; 25 | typedef unsigned int uint32_t; 26 | typedef int int32_t; 27 | typedef unsigned short uint16_t; 28 | typedef short int16_t; 29 | typedef unsigned char uint8_t; 30 | typedef char int8_t; 31 | 32 | int fork(void); 33 | static int pause(void); 34 | 35 | int open(const char* filename,int flag,...); 36 | int close(int fd); 37 | 38 | 39 | #define container_of(ptr, type, member) ({\ 40 | const typeof((type *)0->member)*__mptr = (ptr); \ 41 | (type *)((char *)__mptr - offsetof(type, member)) \ 42 | }) 43 | 44 | #endif 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /include/vargs.h: -------------------------------------------------------------------------------- 1 | #ifndef __VARGS_H__ 2 | #define __VARGS_H__ 3 | 4 | 5 | /* 6 | * __builtin***()相关函数是gcc的内置变量和函数 7 | */ 8 | typedef __builtin_va_list va_list; 9 | #define va_start(ap,last) (__builtin_va_start(ap,last)) 10 | #define va_arg(ap,type) (__builtin_va_arg(ap,type)) 11 | #define va_end(ap) 12 | 13 | /* 14 | __builtin_expect 15 | __builtin_clz 16 | __builtin_bswap32 0xaabbccdd---> 0xddccbbaa 17 | __builtin_constant_p 18 | __sync_synchronize 19 | __builtin_fetch_and_add 20 | __builtin_ctz 21 | __builtin_bswap16 22 | 23 | */ 24 | 25 | /* 优化分支预测*/ 26 | #define likely(x) __builtin_expect(!!(x), 1) 27 | #define unlikely(x) __builtin_expect(!!(x), 0) /* x很可能为假 */ 28 | 29 | 30 | 31 | 32 | 33 | 34 | #endif 35 | 36 | 37 | -------------------------------------------------------------------------------- /include/vmm.h: -------------------------------------------------------------------------------- 1 | #ifndef __VMM_H__ 2 | #define __VMM_H__ 3 | 4 | 5 | #define PAGE_DIR_START 0x0 6 | // 页表在页目录的后4k地址处 7 | #define PAGE_TLB_START (PAGE_DIR_START + 0x1000) 8 | 9 | void init_vmm(); 10 | 11 | 12 | 13 | 14 | 15 | #endif 16 | 17 | 18 | -------------------------------------------------------------------------------- /init/console.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 跟显示相关的函数 3 | */ 4 | #include 5 | 6 | //#if 0 7 | static unsigned short *video_memory=(unsigned short*)0xb8000; 8 | //#elif 9 | //static unsigned short *video_memory=(unsigned short*)0xa0000; 10 | //#endif 11 | /* 12 | * 清屏函数 13 | * 给每一行写空格即可 14 | */ 15 | void console_clear() 16 | { 17 | int i; 18 | // 黑底白字的blank看上去就像清屏了 19 | unsigned char attribute = (0 << 4) | (15 & white); 20 | unsigned short blank = (0x20) | (attribute<<8); 21 | for(i=0;i<80*25;i++){ 22 | video_memory[i] = blank; 23 | } 24 | console_movecursor(0,0); 25 | 26 | } 27 | 28 | /* 29 | * 显示一串字符 30 | * string 表示要显示的字符串 31 | * color_b 表示显示字符串的背景颜色 32 | * color_c 表示显示的字符的颜色 33 | */ 34 | void console_puts(unsigned char *string,unsigned char color_b,unsigned char color_c) 35 | { 36 | int i=0,cursor_x=0,cursor_y=0; 37 | unsigned char attribute = (color_b << 4)|(15 & color_c); 38 | unsigned short cursor_xy=0; 39 | 40 | cursor_xy = console_readcursor(); 41 | //console_movecursor(cursor_xy%80,cursor_xy/80); 42 | cursor_x = cursor_xy % 80; 43 | cursor_y = cursor_xy / 80; 44 | while(string[i] != '\0'){ 45 | //检查是否有换行符 46 | do 47 | { 48 | if(string[i] == '\n'){ 49 | cursor_y++; // 纵坐标+1 50 | cursor_x = 0; // 光标移到最开始 51 | i++; // 不显示换行符 52 | } 53 | //if(string[i] == '\0') 54 | // break;// 此处的break只能跳出do{}while 55 | 56 | }while(string[i] == '\n'); 57 | 58 | // 字符串最后的\0不显示 59 | if(string[i] != '\0') 60 | { 61 | video_memory[cursor_y*80+cursor_x] = string[i] | (attribute << 8); 62 | i++; 63 | cursor_x++; 64 | 65 | // 到一行显示完,开始从下一行开始显示 66 | if(cursor_x >= 79) 67 | cursor_y++; 68 | } 69 | console_movecursor(cursor_x,cursor_y); 70 | 71 | 72 | }//结束while(string[i] != '\0') 73 | } 74 | /* 75 | * 说明:移到光标到坐标 (x,y) 76 | */ 77 | void console_movecursor(int x,int y) 78 | { 79 | //组合要移动的光标位置 80 | unsigned short cursor_addr = y*80+x; 81 | //指明下面是设置光标的行 82 | outb(0x3d4,14); 83 | outb(0x3d5,cursor_addr>>8); 84 | //指明下面是设置光标的列 85 | outb(0x3d4,15); 86 | outb(0x3d5,cursor_addr); 87 | 88 | } 89 | /* 90 | * 说明:读取当前光标的位置 91 | */ 92 | unsigned short console_readcursor() 93 | { 94 | unsigned short cursor_xy; 95 | unsigned char cursor_low=0,cursor_high=0; 96 | // 读取光标高八位 97 | outb(0x3d4,14); 98 | cursor_high = inb(0x3d5); 99 | // 读取光标低八位 100 | outb(0x3d4,15); 101 | cursor_low = inb(0x3d5); 102 | 103 | cursor_xy = (unsigned short)cursor_high; 104 | cursor_xy = ((cursor_xy << 8) & 0xff00) | cursor_low; 105 | 106 | // cursor_xy取80的余数就是x值坐标了 107 | return cursor_xy; 108 | 109 | } 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /init/interrupt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 说明:将中断的相关部分分开 3 | * 4 | */ 5 | #include 6 | #include 7 | 8 | #ifdef _DEBUG 9 | #include 10 | #endif 11 | 12 | //#undef _DEBUG 13 | 14 | 15 | void sti() 16 | { 17 | __asm__ __volatile__("sti"); 18 | } 19 | 20 | void cli() 21 | { 22 | __asm__ __volatile__("cli"); 23 | } 24 | 25 | /* 26 | * 中断服务程序 27 | * 函数说明:识别到底是发生了说明中断(通过regs->int_no),然后 28 | * 执行相应的中断服务程序。 29 | * interrupt_handlers[n]是一个数组函数,n代表了具体的中断服务程 30 | * 序,函数参数为regs。 31 | */ 32 | void isr_handler(pt_regs *regs) 33 | { 34 | static count = 0; 35 | if(interrupt_handlers[regs->int_no]){ 36 | interrupt_handlers[regs->int_no](regs); 37 | } 38 | else{ 39 | count++; 40 | if(count != 1) 41 | return; 42 | printk("unhandle interrupt_handler:%d\n",regs->int_no); 43 | //#ifdef _DEBUG 44 | //console_clear(); 45 | printk("ds: 0x%x\n",regs->ds); // 用于保存用户的数据段描述符 46 | //printk("edi:%d\n",regs->edi); // 从 edi 到 eax 由 pusha 指令压入 47 | //printk("esi:%d\n",regs->esi); 48 | //printk("ebp:%d\n",regs->ebp); 49 | //printk("esp:%d\n",regs->esp); 50 | //printk("ebx:%d\n",regs->ebx); 51 | //printk("edx:%d\n",regs->edx); 52 | //printk("ecx:%d\n",regs->ecx); 53 | //printk("eax:%d\n",regs->eax); 54 | printk("int_no: %d\n",regs->int_no); // 中断号 55 | printk("err_code: %d\n",regs->err_code); // 错误代码(有中断错误代码的中断会由CPU压入) 56 | printk("eip: 0x%x\n",regs->eip); // 以下由处理器自动压入 57 | printk("cs: 0x%x\n",regs->cs); 58 | printk("eflags: 0x%x\n",regs->eflags); 59 | printk("useresp: 0x%x\n",regs->useresp); 60 | printk("ss: 0x%x\n",regs->ss); 61 | //#endif 62 | } 63 | } 64 | 65 | void irq_handler(pt_regs *regs) 66 | { 67 | /* 68 | * 从32号开始,为用户自定义中断,单片只能处理八级中断,因此大于40是由从片处理 69 | */ 70 | if(regs->int_no > 40){ 71 | /* 发送重设信号给从片 */ 72 | outb(0xa0,0x20); 73 | } 74 | /* 发送重设信号给主片 */ 75 | outb(0x20,0x20); 76 | if(interrupt_handlers[regs->int_no]){ 77 | interrupt_handlers[regs->int_no](regs); 78 | } 79 | else{ 80 | printk("unhandle irq_handler:%d\n",regs->int_no); 81 | #ifdef _DEBUG 82 | printk("ds:%d\n",regs->ds); // 用于保存用户的数据段描述符 83 | printk("edi:%d\n",regs->edi); // 从 edi 到 eax 由 pusha 指令压入 84 | printk("esi:%d\n",regs->esi); 85 | printk("ebp:%d\n",regs->ebp); 86 | printk("esp:%d\n",regs->esp); 87 | printk("ebx:%d\n",regs->ebx); 88 | printk("edx:%d\n",regs->edx); 89 | printk("ecx:%d\n",regs->ecx); 90 | printk("eax:%d\n",regs->eax); 91 | printk("int_no:%d\n",regs->int_no); // 中断号 92 | printk("err_code:%d\n",regs->err_code); // 错误代码(有中断错误代码的中断会由CPU压入) 93 | printk("eip:%d\n",regs->eip); // 以下由处理器自动压入 94 | printk("cs:%d\n",regs->cs); 95 | printk("eflags:%d\n",regs->eflags); 96 | printk("useresp:%d\n",regs->useresp); 97 | printk("ss:%d\n",regs->ss); 98 | #endif 99 | } 100 | } 101 | 102 | /* 103 | * 函数说明:向中断数组函数加入具体的中断服务程序(相当于注册) 104 | */ 105 | void register_interrupt_handler(unsigned char n, interrupt_handler_t h) 106 | { 107 | interrupt_handlers[n] = h; 108 | //h->int_no = n; 109 | } 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /init/kernel.asm: -------------------------------------------------------------------------------- 1 | 2 | ; UNIX386 3 | ;------------------------------------------------------------------------------- 4 | ; BIOS内存映射 5 | ;------------------------------------------------------------------------------- 6 | ; TAB=4 SP=0x7c00 0x8000=拷贝到启动区 7 | ;------------------------------------------------------------------------------- 8 | ; |中断向量表| |代码存储位置| ...... | 512| 9 | ; | | | | ...... | | 10 | ;------------------------------------------------------------------------------- 11 | ; 0x8200=后边的程序 12 | ; 在某种意义上理解,我们的程序只需要在磁盘的开始512字节就行 13 | ; 然后硬件上自动去读这512,然后执行这段程序 14 | 15 | ; 1-> 读取磁盘后边扇区的数据 16 | ; 2-> 在bootsecond.nas中添加LCD支持 17 | ; 3-> 初始化PIC 18 | ; 4-> 打开A20,进入保护模式 19 | ; 5-> 设置CR0的PE和PG 20 | ; 6-> 跳转到0地址,即执行该程序 21 | ; 7-> 更新D、E、F、G、S,其中数代表的是第几个GDT 22 | ; 8-> 设置页保护机制 23 | ; 9-> 跳转到kernel_start函数 24 | 25 | [bits 32] 26 | global _start 27 | global myprintf 28 | global load_gdtr 29 | global load_idtr 30 | global write_vram 31 | 32 | extern kernel_start; 33 | extern kernel_stack_top; 34 | extern system_call_table; 35 | extern reschedule 36 | extern current 37 | extern state 38 | 39 | 40 | 41 | ;BOOT_INFO信息 42 | CYLS EQU 0x0ff0 43 | LEDS EQU 0x0ff1 44 | LCDMODE EQU 0x0ff2 ; 45 | SCREENX EQU 0x0ff4 ; x 46 | SCREENY EQU 0x0ff6 ; y 47 | LCDRAM EQU 0x0ff8 ; 图像缓冲区的开始地址 48 | ;页信息 49 | ;只有16M,因此只需要4个页目录 50 | _page_dir EQU 0x0000 51 | _page_tab0 EQU 0x1000 52 | _page_tab1 EQU 0x2000 53 | _page_tab2 EQU 0x3000 54 | _page_tab3 EQU 0x4000 55 | 56 | 57 | ; 采用Intel汇编格式 58 | _start: 59 | MOV EAX,0x00000010 60 | MOV DS,AX 61 | MOV ES,AX 62 | MOV FS,AX 63 | MOV GS,AX 64 | MOV SS,AX 65 | ; 设置页目录表和页目录 66 | CALL setup_paging 67 | ; 开始打开分页机制 68 | XOR EAX,EAX 69 | MOV CR3,EAX ;将_page_dir地址0x0000写给CR3 70 | MOV EAX,CR0 71 | OR EAX,0x80000000 72 | MOV CR0,EAX ;PG位置1 73 | ; 设置堆栈 74 | MOV ESP,kernel_stack_top 75 | MOV EBP,ESP 76 | ;AND ESP,0FFFFFFF0H 77 | ;MOV AH,0x0f 78 | ;MOV AL,'V' 79 | ;MOV BYTE [0xb8008],'V' 80 | ; 跳转到C语言部分 81 | MOV EAX,kernel_start 82 | JMP EAX 83 | ;SUB EAX,0x8080 84 | ;CALL EAX 85 | ;-------------------------------------------- 86 | ;-------------------------------------------- 87 | ;设置页目录表和页目录 88 | ; 将页目录表和页目录放在内存的开始地址 89 | ;-------------------------------------------- 90 | setup_paging: 91 | MOV ECX,1024*5 92 | XOR EAX,EAX 93 | XOR EDI,EDI 94 | CLD;EDI往加的方向执行 95 | REP STOSD ;每次移动4个字节,直到ECX==0(目的是将这5K内存清0) 96 | ;页目录表只用到了前面16字节 97 | ;7:表示 U/S R/W P都为1 98 | MOV dword [_page_dir],_page_tab0+7 99 | MOV dword [_page_dir+4],_page_tab1+7 100 | MOV dword [_page_dir+8],_page_tab2+7 101 | MOV dword [_page_dir+12],_page_tab3+7 102 | 103 | MOV EAX,0xFFF007 ;16M-4K位置 104 | MOV EDI,_page_tab3+4092; 105 | STD;EDI往减的方向执行 106 | abcd: STOSD 107 | SUB EAX,0x1000 108 | JGE abcd 109 | 110 | RET 111 | ; 加载gdtr地址需要,后面函数调用 112 | load_gdtr: 113 | MOV EAX,[ESP+4] 114 | LGDT [EAX] 115 | MOV AX,0x10 116 | MOV DS,AX 117 | MOV ES,AX 118 | MOV FS,AX 119 | MOV GS,AX 120 | MOV SS,AX 121 | 122 | JMP 0x08:.flush 123 | .flush: 124 | ret 125 | 126 | load_idtr: 127 | MOV EAX,[ESP+4] 128 | LIDT [EAX] 129 | ret 130 | write_vram: 131 | MOV ECX,[ESP+4] 132 | MOV AL,[ESP+8] 133 | MOV [ECX],AL 134 | RET 135 | 136 | ; 定义两个构造中断处理函数的宏(有的中断有错误代码,有的没有) 137 | ; 用于没有错误代码的中断 138 | %macro ISR_NOERRCODE 1 139 | [GLOBAL isr%1] 140 | isr%1: 141 | cli ; 首先关闭中断 142 | push 0x0 ; push 无效的中断错误代码(起到占位作用,便于所有isr函数统一清栈) 143 | push %1 ; push 中断号 144 | jmp isr_common_stub 145 | %endmacro 146 | 147 | ; 用于有错误代码的中断 148 | %macro ISR_ERRCODE 1 149 | [GLOBAL isr%1] 150 | isr%1: 151 | cli ; 关闭中断 152 | push %1 ; push 中断号 153 | jmp isr_common_stub 154 | %endmacro 155 | 156 | ; 定义中断处理函数 157 | ISR_NOERRCODE 0 ; 0 #DE 除 0 异常 158 | ISR_NOERRCODE 1 ; 1 #DB 调试异常 159 | ISR_NOERRCODE 2 ; 2 NMI 160 | ISR_NOERRCODE 3 ; 3 BP 断点异常 161 | ISR_NOERRCODE 4 ; 4 #OF 溢出 162 | ISR_NOERRCODE 5 ; 5 #BR 对数组的引用超出边界 163 | ISR_NOERRCODE 6 ; 6 #UD 无效或未定义的操作码 164 | ISR_NOERRCODE 7 ; 7 #NM 设备不可用(无数学协处理器) 165 | ISR_ERRCODE 8 ; 8 #DF 双重故障(有错误代码) 166 | ISR_NOERRCODE 9 ; 9 协处理器跨段操作 167 | ISR_ERRCODE 10 ; 10 #TS 无效TSS(有错误代码) 168 | ISR_ERRCODE 11 ; 11 #NP 段不存在(有错误代码) 169 | ISR_ERRCODE 12 ; 12 #SS 栈错误(有错误代码) 170 | ISR_ERRCODE 13 ; 13 #GP 常规保护(有错误代码) 171 | ISR_ERRCODE 14 ; 14 #PF 页故障(有错误代码) 172 | ISR_NOERRCODE 15 ; 15 CPU 保留 173 | ISR_NOERRCODE 16 ; 16 #MF 浮点处理单元错误 174 | ISR_ERRCODE 17 ; 17 #AC 对齐检查 175 | ISR_NOERRCODE 18 ; 18 #MC 机器检查 176 | ISR_NOERRCODE 19 ; 19 #XM SIMD(单指令多数据)浮点异常 177 | 178 | ; 20~31 Intel 保留 179 | ISR_NOERRCODE 20 180 | ISR_NOERRCODE 21 181 | ISR_NOERRCODE 22 182 | ISR_NOERRCODE 23 183 | ISR_NOERRCODE 24 184 | ISR_NOERRCODE 25 185 | ISR_NOERRCODE 26 186 | ISR_NOERRCODE 27 187 | ISR_NOERRCODE 28 188 | ISR_NOERRCODE 29 189 | ISR_NOERRCODE 30 190 | ISR_NOERRCODE 31 191 | ; 32~255 用户自定义 192 | ISR_NOERRCODE 255 193 | 194 | [GLOBAL isr_common_stub] 195 | [EXTERN isr_handler] 196 | ; 中断服务程序 197 | isr_common_stub: 198 | pusha ; Pushes edi, esi, ebp, esp, ebx, edx, ecx, eax 199 | xor eax, eax 200 | mov ax, ds 201 | push eax ; 保存数据段描述符 202 | 203 | mov ax, 0x10 ; 加载内核数据段描述符表 204 | mov ds, ax 205 | mov es, ax 206 | mov fs, ax 207 | mov gs, ax 208 | mov ss, ax 209 | 210 | push esp ; 此时的 esp 寄存器的值等价于 pt_regs 结构体的指针 211 | call isr_handler ; 在 C 语言代码里 212 | add esp, 4 ; 清除压入的参数 213 | 214 | pop ebx ; 恢复原来的数据段描述符 215 | mov ds, bx 216 | mov es, bx 217 | mov fs, bx 218 | mov gs, bx 219 | mov ss, bx 220 | 221 | popa ; Pops edi, esi, ebp, esp, ebx, edx, ecx, eax 222 | add esp, 8 ; 清理栈里的 error code 和 ISR 223 | iret 224 | .end: 225 | 226 | 227 | 228 | ; 构造中断请求的宏 229 | %macro IRQ 2 230 | [GLOBAL irq%1] 231 | irq%1: 232 | cli 233 | push 0 234 | push %2 235 | jmp irq_common_stub 236 | %endmacro 237 | 238 | IRQ 0, 32 ; 电脑系统计时器 239 | IRQ 1, 33 ; 键盘 240 | IRQ 2, 34 ; 与 IRQ9 相接,MPU-401 MD 使用 241 | IRQ 3, 35 ; 串口设备 242 | IRQ 4, 36 ; 串口设备 243 | IRQ 5, 37 ; 建议声卡使用 244 | IRQ 6, 38 ; 软驱传输控制使用 245 | IRQ 7, 39 ; 打印机传输控制使用 246 | IRQ 8, 40 ; 即时时钟 247 | IRQ 9, 41 ; 与 IRQ2 相接,可设定给其他硬件 248 | IRQ 10, 42 ; 建议网卡使用 249 | IRQ 11, 43 ; 建议 AGP 显卡使用 250 | IRQ 12, 44 ; 接 PS/2 鼠标,也可设定给其他硬件 251 | IRQ 13, 45 ; 协处理器使用 252 | IRQ 14, 46 ; IDE0 传输控制使用 253 | IRQ 15, 47 ; IDE1 传输控制使用 254 | 255 | [GLOBAL irq_common_stub] 256 | [EXTERN irq_handler] 257 | irq_common_stub: 258 | pusha ; pushes edi, esi, ebp, esp, ebx, edx, ecx, eax 259 | xor eax, eax 260 | mov ax, ds 261 | push eax ; 保存数据段描述符 262 | 263 | mov ax, 0x10 ; 加载内核数据段描述符 264 | mov ds, ax 265 | mov es, ax 266 | mov fs, ax 267 | mov gs, ax 268 | mov ss, ax 269 | 270 | push esp 271 | call irq_handler 272 | add esp, 4 273 | 274 | pop ebx ; 恢复原来的数据段描述符 275 | mov ds, bx 276 | mov es, bx 277 | mov fs, bx 278 | mov gs, bx 279 | mov ss, bx 280 | 281 | popa ; Pops edi,esi,ebp... 282 | add esp, 8 ; 清理压栈的 错误代码 和 IRQ 编号 283 | iret ; 出栈 CS, EIP, EFLAGS, SS, ESP 284 | .end: 285 | 286 | 287 | ; ============================================================================= 288 | ; sys_call 289 | ; 目前系统调用的函数定义和system_call_table数组在include/i386/sys.h下 290 | ; 291 | ; 进入system_call: 292 | ; eax system number 293 | ; ebx arg1 294 | ; ecx arg2 295 | ; edx arg3 296 | ; esi arg3 297 | ; edi arg3 298 | ; ebp arg4 299 | ; 300 | ; 从系统调用返回是,栈分布如下: 301 | ; esp+0 - %eax 302 | ; esp+4 - %ebx 303 | ; esp+8 - %ecx 304 | ; esp+C - %edx 305 | ; esp+10 - %fs 306 | ; esp+14 - %es 307 | ; esp+18 - %ds 308 | ; esp+1C - %eip 309 | ; esp+20 - %cs 310 | ; esp+24 - %eflags 311 | ; esp+28 - %oldesp 312 | ; esp+2C - %oldss 313 | ; ============================================================================= 314 | ; 系统调用入口函数 315 | [GLOBAL system_call] 316 | system_call: 317 | ; ============================================================================= 318 | ; already on stack: ss,sp,flags,cs,ip 319 | ; next to save general register:EAX ECX EDX EBX ESP EBP ESI EDI and ds es fs gs 320 | ; ============================================================================= 321 | pushad ; \ 322 | push ds ; | 323 | push es ; | 保存原寄存器值 324 | push fs ; | 325 | push gs ; / 326 | 327 | mov esi,esp 328 | 329 | mov edx,0x10 ; 设置ds es段指向当前进程的内核态数据段 330 | mov ds,dx 331 | mov es,dx 332 | 333 | mov edx,0x17 ; 设置fs段指向当前进程用户态数据段 334 | mov fs,dx 335 | 336 | sti 337 | call [system_call_table + eax * 4] 338 | ; why add esi to 11*4 ? --> from EAX to gs has 11*4 339 | mov [esi + 11*4], eax 340 | cli 341 | 342 | ; 检测当前进程是否处于就绪态(state),时间片是否用完 343 | ; if state == TASK_RUNNING, then the task would be rescheduled 344 | .2: mov eax,current 345 | cmp dword [eax],0 346 | jne reschedule 347 | cmp dword [eax+4],0 348 | je reschedule 349 | ret_from_system_call: 350 | ;add esp, 4 * 4 351 | ;pop esi 352 | pop gs 353 | pop fs 354 | pop es 355 | pop ds 356 | popad 357 | 358 | ret 359 | 360 | 361 | ; 362 | ; 保留此处 363 | ;stop: 364 | ; JMP stop 365 | ;stack: 366 | ; times 32768 db 0 367 | ;glb_mboot_ptr: 368 | ; resb 4 369 | 370 | ;STACK_TOP equ $-stack-1 371 | 372 | 373 | 374 | 375 | -------------------------------------------------------------------------------- /init/memory.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #define NR_DIR 32 7 | uint32_t page_dir2[NR_DIR]; 8 | uint32_t page_table2[NR_DIR][1024]; 9 | 10 | /* 11 | * 重新初始化分页 12 | */ 13 | void init_paging() 14 | { 15 | /* 0-128M */ 16 | int i,j; 17 | for(i=0;i 9 | #include 10 | #include 11 | #include 12 | 13 | /* 这个数组存储的就是每一页的开始地址 */ 14 | static unsigned int pmm_stack[PAGE_MAX_COUNT+1]; 15 | unsigned int pmm_stack_top; 16 | 17 | /* phy_page_count仅在init_pmm初始化后,不再变化 */ 18 | unsigned int phy_page_count=0; 19 | 20 | /* 21 | * 函数功能:初始化物理地址,系统的物理内存从0x0---0x9fc00, 22 | * 0x100000---0x7ffe000是RAM区可使用 23 | */ 24 | void init_pmm() 25 | { 26 | unsigned int page_addr = MAIN_MEMORY_START+1024*1024*2; 27 | 28 | printk("physicial memory init\n"); 29 | pmm_stack_top = 0; 30 | // 到0x7ffd000,不在往下分配(128M) 31 | while(page_addr <= (MAIN_MEMORY_END - PAGE_SIZE)){ 32 | if(page_addr <= 0x9e000){ 33 | pmm_free_page(page_addr); 34 | phy_page_count++; 35 | page_addr += PAGE_SIZE; 36 | if(page_addr == 0x9f000){ 37 | page_addr = 0x100000; 38 | } 39 | } 40 | else{ 41 | pmm_free_page(page_addr); 42 | phy_page_count++; 43 | page_addr += PAGE_SIZE; 44 | } 45 | } 46 | 47 | } 48 | 49 | 50 | /* 51 | * 将分配的每一页(4KB)开头地址存储到pmm_stack数组 52 | */ 53 | void pmm_free_page(unsigned int p) 54 | { 55 | pmm_stack[pmm_stack_top++] = p; 56 | //printk("pmm_stack_top = 0x%08X\n",&pmm_stack_top); 57 | } 58 | 59 | /* 60 | * 分配一个页 61 | */ 62 | uint32_t pmm_alloc_page() 63 | { 64 | uint32_t page; 65 | 66 | page = pmm_stack[--pmm_stack_top]; 67 | if(pmm_stack_top == 0){ 68 | return NULL; 69 | } 70 | //printk("pmm_stack = 0x%08X\n",pmm_stack); 71 | return page; 72 | } 73 | 74 | /* 75 | * 释放多个连续页 76 | */ 77 | void pmm_free_pages(unsigned int p, int count) 78 | { 79 | int i; 80 | 81 | for (i=0; i 5 | * time: 2017/05/13 6 | */ 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | extern unsigned char kernel_s[]; 28 | extern unsigned char kernel_e[]; 29 | extern syscall_ptr system_call_table[]; 30 | 31 | void outb(unsigned short port,unsigned short value); 32 | 33 | unsigned char inb(unsigned short port); 34 | 35 | unsigned short inw(unsigned short port); 36 | 37 | 38 | void logo(void); 39 | 40 | /* 41 | * kernel.s------>kernel_start() 42 | * 汇编代码跳入到C语言的第一个函数,需对如下使用C语言重新初始化 43 | * 44 | * 1.初始化全局描述符和中断描述符 45 | * 2.初始化调色板 46 | * 3.初始化键盘 47 | * 4.初始化时钟中断 48 | * 49 | */ 50 | void kernel_start() 51 | { 52 | #if 0 53 | kernel_stack_top = (long)kernel_stack + STACK_SIZE; 54 | __asm__ __volatile__("mov %0,%%esp\n\t"::"r"(kernel_stack_top)); 55 | __asm__ __volatile__("xor %ebp, %ebp"); 56 | #endif 57 | int i; 58 | //字符串存在ELF文件的.stab节和.stabstr节(这部分特别大) 59 | //unsigned char *string = "Hello,welcome to DeeppinkOS\n"; 60 | unsigned int page_addr1 = 0,page_addr2 = 0; 61 | printk("enter the kernel_start function...\n"); 62 | /* 打印内核版本 */ 63 | printk("UNIX386 v0.0.1\n"); 64 | //unsigned char *input = (unsigned char *)0xb8000; 65 | //unsigned char color = (0 << 4) | (15 & white); 66 | //unsigned char *string = "Hello,welcome to DeeppinkOS\n"; 67 | //unsigned int page_addr1=0,page_addr2=0; 68 | //*input++ = 'H'; 69 | //*input++ = color 70 | 71 | //console_clear(); 72 | 73 | //console_puts(string,0,green); 74 | //printk(string); 75 | init_gdt(); 76 | /* 初始化中断/异常/系统调用,填充中断描述符 */ 77 | init_idt(); 78 | init_paging(); 79 | /* 初始化调色板 */ 80 | init_palette(); 81 | /* asm volatile("int $0x3"); */ 82 | /* asm volatile("int $0x4"); */ 83 | 84 | init_keyboard(); 85 | __asm__ __volatile__("cli"); /* 关闭中断 */ 86 | schedule_init(); 87 | printk("kernel start addr = 0x%08X\n", kernel_s); 88 | printk("kernel end addr = 0x%08X\n", kernel_e); 89 | printk("kernel size = %dKB\n", (kernel_e-kernel_s + 1023) / 1024); 90 | 91 | init_pmm(); 92 | printk("The size of key structure:\n"); 93 | printk("task_struct: %d\n",sizeof(struct task_struct)); 94 | printk("tss_struct: %d\n",sizeof(struct tss_struct)); 95 | printk("buddy_element: %d\n",sizeof(struct buddy_element)); 96 | printk("phy_page_count: %d\n",phy_page_count); 97 | #if 1 98 | //page_addr1 = pmm_alloc_page(); 99 | //printk("alloc page1 = 0x%08X\n",page_addr1); 100 | //page_addr2 = pmm_alloc_page(); 101 | //logo(); 102 | /* 其他设备初始化 */ 103 | init_thread(); 104 | init_buddy(); 105 | //init(); 106 | #endif 107 | /* 108 | * 以下代码类似CPU进入idle,即init0 109 | * init0检测是否有其他task需要执行 110 | */ 111 | thread_cpu_idle(); 112 | } 113 | 114 | /* 115 | * 从端口输出一个字节 116 | */ 117 | inline void outb(unsigned short port,unsigned short value) 118 | { 119 | __asm__ __volatile__("outb %1,%0"::"dN"(port),"a"(value)); 120 | } 121 | 122 | /* 123 | * 从端口读一个字节 124 | */ 125 | inline unsigned char inb(unsigned short port) 126 | { 127 | unsigned char retval=0; 128 | __asm__ __volatile__("inb %1,%0":"=a"(retval):"dN"(port)); 129 | return retval; 130 | } 131 | 132 | /* 133 | * 从端口读一个字 134 | */ 135 | inline unsigned short inw(unsigned short port) 136 | { 137 | unsigned short retval=0; 138 | /* retval为输出,port为输入 */ 139 | __asm__ __volatile__("inw %1,%0":"=a"(retval):"dN"(port)); 140 | return retval; 141 | } 142 | 143 | #if 0 144 | /* 145 | * 向显存写数据 146 | * 147 | void write_vram(int address,int data) 148 | { 149 | asm volatile("MOV [%%ESP+4],%%ECX\n\t" 150 | "MOV [%%ESP+8],%%AL\n\t" 151 | "MOV %%AL,[%%ECX]\n\t" 152 | "RET" 153 | : 154 | :"c" 155 | :"ECX" 156 | ); 157 | 158 | } 159 | *********************************************/ 160 | #endif 161 | 162 | /* 163 | * 部分初始化完成以后,开始清屏,再显示 164 | * DeeppinkOS内核的logo 165 | */ 166 | void logo(void) 167 | { 168 | int i,j,x,y; 169 | char pixel; 170 | #if 0 171 | char font_A[16]={ 172 | 0x00,0x18,0x18,0x18,0x18,0x24,0x24,0x24, 173 | 0x24,0x7e,0x42,0x42,0x42,0xe7,0x00,0x00 174 | }; 175 | #endif 176 | x = y = 0; 177 | //pixel = font_A[0]; 178 | for(i=0;i<=15;i++){ 179 | pixel = font_A[i]; 180 | for(j=0;j<=7;j++){ 181 | /* 此处对最高位做判断,分别显示不同颜色 */ 182 | if(pixel & 0x80) 183 | write_vram(0xa0000+j+320*i,1); 184 | else 185 | write_vram(0xa0000+j+320*i,0); 186 | /* pixel向左移动一位 */ 187 | pixel <<= 1; 188 | } 189 | } 190 | 191 | } 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /init/vmm.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 对分页机制的支持的相关函数 4 | * 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | static unsigned int page_dir[1024]; // 1024个页目录项 13 | static unsigned int *page_tlb = PAGE_TLB_START; //页表起始地址在页目录开始地址的4k后 14 | 15 | /* 16 | * 初始化虚拟地址 17 | */ 18 | void init_vmm() 19 | { 20 | int i=0; 21 | for(i=0;i<1024;i++){ 22 | page_dir[i] = page_tlb + i*4096; 23 | } 24 | 25 | } 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /kernel/buddy.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 伙伴系统 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | #define MAX_ORDER 5 13 | 14 | //uint32_t pmm_alloc_page() 15 | static uint32_t average = 20; 16 | static uint32_t nr_free_pages; 17 | static uint32_t nr_pages; 18 | 19 | struct buddy_element *buddy_order[MAX_ORDER]; 20 | static int nr_buddyfree_order[MAX_ORDER]; 21 | 22 | /* 23 | * 初始化buddy system 24 | */ 25 | void init_buddy() 26 | { 27 | /* 一个简单的伙伴系统 */ 28 | int i,j; 29 | struct buddy_element *pr_be=NULL, *pr_prev=NULL, *pr_next=NULL; 30 | 31 | printk("init buddy\n"); 32 | /* phy_page_count代表当前页总数 */ 33 | nr_pages = phy_page_count; 34 | nr_free_pages = phy_page_count; 35 | 36 | /* 37 | * 为buddy系统order数组赋值 38 | */ 39 | for (i=0; iindex = j; 47 | pr_be->data = (uint32_t *)pmm_alloc_pages(1<data == NULL) { 49 | printk("error: 2\n"); 50 | return; 51 | } 52 | 53 | if (pr_prev != NULL) { 54 | pr_prev->order_list_head.next = pr_be; 55 | pr_be->order_list_head.prev = pr_prev; 56 | } else { 57 | /* first element */ 58 | buddy_order[i] = pr_be; 59 | } 60 | pr_prev = pr_be; 61 | nr_free_pages = nr_pages - (1 << i); 62 | } 63 | nr_buddyfree_order[j] = average; 64 | } 65 | } 66 | 67 | /* 68 | * 按照buddy策略,为count数量页选择合适的order分配 69 | * 70 | */ 71 | int buddy_alloc_scheme(int count) 72 | { 73 | int i; 74 | int index = 0; 75 | 76 | /* 77 | * EASY scheme 78 | */ 79 | for (i=0; iorder_list_head.next; 118 | 119 | return ret = (phys_addr_t)be->data; 120 | } 121 | 122 | 123 | -------------------------------------------------------------------------------- /kernel/panic.c: -------------------------------------------------------------------------------- 1 | 2 | #include "console.h" 3 | #include "string.h" 4 | #include "vargs.h" 5 | #include "debug.h" 6 | 7 | /* 8 | * panic 9 | */ 10 | volatile void panic(const char * s) 11 | { 12 | printk("Kernel panic: %s\n\r",s); 13 | /* TODO 待实现打印调用栈 */ 14 | for(;;); 15 | } 16 | 17 | 18 | -------------------------------------------------------------------------------- /kernel/prink.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Filename: printk.c 4 | * 5 | * Description: 内核的打印函数实现,依赖于gcc内置变量和函数: 6 | * (__builtin_va_start(ap,last)) (__builtin_va_arg(ap,type)) 7 | * 8 | */ 9 | 10 | #include "console.h" 11 | #include "string.h" 12 | #include "vargs.h" 13 | #include "debug.h" 14 | 15 | static int vsprintf(char *buff, const char *format, va_list args); 16 | 17 | /* 18 | * 内核打印函数,依赖于vsprintf(...) 19 | */ 20 | void printk(const char *format, ...) 21 | { 22 | // 避免频繁创建临时变量,内核的栈很宝贵 23 | static char buff[1024]; 24 | va_list args; 25 | int i; 26 | 27 | // 按照format格式转换到buff 28 | va_start(args, format); 29 | i = vsprintf(buff, format, args); 30 | va_end(args); 31 | 32 | buff[i] = '\0'; 33 | 34 | console_puts(buff,0,white); 35 | } 36 | 37 | // 判断是否是数字 返回 1:代表是数字 38 | #define is_digit(c) ((c) >= '0' && (c) <= '9') 39 | 40 | /* 41 | * 函数功能:将字符串s转换成数字,如果字符串中有字母,则终止 42 | * 43 | * 例子: s = "12a9aaa", i = 12 44 | * s = "s12aaa", i = 0 45 | */ 46 | static int skip_atoi(const char **s) 47 | { 48 | int i = 0; 49 | 50 | while (is_digit(**s)) { 51 | i = i * 10 + *((*s)++) - '0'; 52 | } 53 | 54 | return i; 55 | } 56 | 57 | #define ZEROPAD 1 // pad with zero 58 | #define SIGN 2 // unsigned/signed long 59 | #define PLUS 4 // show plus 60 | #define SPACE 8 // space if plus 61 | #define LEFT 16 // left justified 62 | #define SPECIAL 32 // 0x 63 | #define SMALL 64 // use 'abcdef' instead of 'ABCDEF' 64 | 65 | #define do_div(n,base) ({ \ 66 | int __res; \ 67 | __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \ 68 | __res; }) 69 | 70 | /* 71 | * 72 | * 73 | */ 74 | static char *number(char *str, int num, int base, int size, int precision, int type) 75 | { 76 | char c, sign, tmp[36]; 77 | const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 78 | int i; 79 | 80 | if (type & SMALL) { 81 | digits ="0123456789abcdefghijklmnopqrstuvwxyz"; 82 | } 83 | if (type & LEFT) { 84 | type &= ~ZEROPAD; 85 | } 86 | if (base < 2 || base > 36) { 87 | return 0; 88 | } 89 | 90 | c = (type & ZEROPAD) ? '0' : ' ' ; 91 | 92 | if (type & SIGN && num < 0) { 93 | sign = '-'; 94 | num = -num; 95 | } 96 | else { 97 | sign = (type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0); 98 | } 99 | 100 | if (sign) { 101 | size--; 102 | } 103 | if (type & SPECIAL) { 104 | if (base == 16) { 105 | size -= 2; 106 | } 107 | else if (base == 8) { 108 | size--; 109 | } 110 | } 111 | 112 | i = 0; 113 | if (num == 0) { 114 | tmp[i++] = '0'; 115 | } 116 | else { 117 | while (num != 0) { 118 | tmp[i++] = digits[do_div(num,base)]; 119 | } 120 | } 121 | 122 | if (i > precision) { 123 | precision = i; 124 | } 125 | size -= precision; 126 | 127 | if (!(type&(ZEROPAD+LEFT))) { 128 | while (size-- > 0) { 129 | *str++ = ' '; 130 | } 131 | } 132 | if (sign) { 133 | *str++ = sign; 134 | } 135 | if (type & SPECIAL) { 136 | if (base == 8) { 137 | *str++ = '0'; 138 | } 139 | else if (base == 16) { 140 | *str++ = '0'; 141 | *str++ = digits[33]; 142 | } 143 | } 144 | if (!(type&LEFT)) { 145 | while (size-- > 0) { 146 | *str++ = c; 147 | } 148 | } 149 | while (i < precision--) { 150 | *str++ = '0'; 151 | } 152 | while (i-- > 0) { 153 | *str++ = tmp[i]; 154 | } 155 | while (size-- > 0) { 156 | *str++ = ' '; 157 | } 158 | 159 | return str; 160 | } 161 | 162 | /* 163 | * 描述:将args按format的格式输入到buff 164 | * 返回:正常返回字符串长度(除去\0) 165 | * 失败返回负数 166 | */ 167 | static int vsprintf(char *buff, const char *format, va_list args) 168 | { 169 | int len; 170 | int i; 171 | char *str; 172 | char *s; 173 | int *ip; 174 | 175 | int flags; // flags to number() 176 | 177 | int field_width; // width of output field 178 | int precision; // min. # of digits for integers; max number of chars for from string 179 | 180 | for (str = buff ; *format ; ++format) { 181 | if (*format != '%') { 182 | //*str++ = *format; //此处代码要改善 183 | *str = *format; 184 | str++; 185 | continue; 186 | } 187 | 188 | flags = 0; 189 | repeat: 190 | ++format; // this also skips first '%' 191 | switch (*format) { 192 | case '-': flags |= LEFT; 193 | goto repeat; 194 | case '+': flags |= PLUS; 195 | goto repeat; 196 | case ' ': flags |= SPACE; 197 | goto repeat; 198 | case '#': flags |= SPECIAL; 199 | goto repeat; 200 | case '0': flags |= ZEROPAD; 201 | goto repeat; 202 | } 203 | // get field width 204 | field_width = -1; 205 | if (is_digit(*format)) { 206 | field_width = skip_atoi(&format); 207 | } 208 | else if (*format == '*') { 209 | // it's the next argument 210 | field_width = va_arg(args, int); 211 | if (field_width < 0) { 212 | field_width = -field_width; 213 | flags |= LEFT; 214 | } 215 | } 216 | 217 | // get the precision 218 | precision = -1; 219 | if (*format == '.') { 220 | ++format; 221 | if (is_digit(*format)) { 222 | precision = skip_atoi(&format); 223 | } 224 | else if (*format == '*') { 225 | // it's the next argument 226 | precision = va_arg(args, int); 227 | } 228 | if (precision < 0) { 229 | precision = 0; 230 | } 231 | } 232 | 233 | // get the conversion qualifier 234 | // int qualifier = -1; // 'h', 'l', or 'L' for integer fields 235 | if (*format == 'h' || *format == 'l' || *format == 'L') { 236 | //qualifier = *format; 237 | ++format; 238 | } 239 | 240 | switch (*format) { 241 | case 'c': 242 | if (!(flags & LEFT)) { 243 | while (--field_width > 0) { 244 | *str++ = ' '; 245 | } 246 | } 247 | *str++ = (unsigned char) va_arg(args, int); 248 | while (--field_width > 0) { 249 | *str++ = ' '; 250 | } 251 | break; 252 | 253 | case 's': 254 | s = va_arg(args, char *); 255 | len = strlen(s); 256 | if (precision < 0) { 257 | precision = len; 258 | } 259 | else if (len > precision) { 260 | len = precision; 261 | } 262 | 263 | if (!(flags & LEFT)) { 264 | while (len < field_width--) { 265 | *str++ = ' '; 266 | } 267 | } 268 | for (i = 0; i < len; ++i) { 269 | *str++ = *s++; 270 | } 271 | while (len < field_width--) { 272 | *str++ = ' '; 273 | } 274 | break; 275 | 276 | case 'o': 277 | str = number(str, va_arg(args, unsigned long), 8, 278 | field_width, precision, flags); 279 | break; 280 | 281 | case 'p': 282 | if (field_width == -1) { 283 | field_width = 8; 284 | flags |= ZEROPAD; 285 | } 286 | str = number(str, (unsigned long) va_arg(args, void *), 16, 287 | field_width, precision, flags); 288 | break; 289 | 290 | case 'x': 291 | flags |= SMALL; 292 | case 'X': 293 | str = number(str, va_arg(args, unsigned long), 16, 294 | field_width, precision, flags); 295 | break; 296 | 297 | case 'd': 298 | case 'i': 299 | flags |= SIGN; 300 | case 'u': 301 | str = number(str, va_arg(args, unsigned long), 10, 302 | field_width, precision, flags); 303 | break; 304 | case 'b': 305 | str = number(str, va_arg(args, unsigned long), 2, 306 | field_width, precision, flags); 307 | break; 308 | 309 | case 'n': 310 | ip = va_arg(args, int *); 311 | *ip = (str - buff); 312 | break; 313 | 314 | default: 315 | if (*format != '%') 316 | *str++ = '%'; 317 | if (*format) { 318 | *str++ = *format; 319 | } else { 320 | --format; 321 | } 322 | break; 323 | } 324 | } 325 | *str = '\0'; 326 | 327 | return (str -buff); 328 | } 329 | 330 | 331 | 332 | 333 | -------------------------------------------------------------------------------- /kernel/sched.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 关于进程调度相关实现 4 | */ 5 | 6 | 7 | #include "schedule.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "unistd.h" 13 | #include 14 | #include 15 | 16 | 17 | extern tss_struct; 18 | extern gdt_struct_t gdt_list[]; 19 | extern syscall_ptr system_call_table[]; 20 | 21 | #define PAGE_SIZE 4096 22 | 23 | union task_union* task_tables[NR_TASKS] = {&init_task,}; 24 | 25 | /* 在kernel.asm需要用到 */ 26 | long user_stack[PAGE_SIZE >> 2]={0}; 27 | char kernel_stack[PAGE_SIZE << 1] __attribute__ ((aligned(16))); 28 | 29 | long *_stack_top = &user_stack[PAGE_SIZE >> 2]; 30 | long kernel_stack_top = (long)kernel_stack + STACK_SIZE; 31 | 32 | /* 一个全局指针,指向当前正在执行的进程的task_struct */ 33 | struct task_struct *current = &(init_task.task); 34 | 35 | /* 所有可以选择的调度器 */ 36 | struct scheduler scheduler_array[] = { 37 | {"primary_sched", schedule}, 38 | {NULL, NULL} 39 | }; 40 | 41 | /* 42 | * 调度初始化,启动进程0 43 | */ 44 | void schedule_init(void) 45 | { 46 | unsigned int base, limit; 47 | printk("scheduler init!\n"); 48 | /* 在gdt表后边加上进程0的tss和ldt */ 49 | //set_tssldt2_gdt(FIRST_TASKTSS_INDEX, &(init_task.task.tss), 0xe9); 50 | //set_tssldt2_gdt(FIRST_TASKLDT_INDEX, &(init_task.task.ldt), 0xe2); 51 | base = &(init_task.task.tss); 52 | limit = &(init_task.task.tss) + sizeof(init_task.task.tss); 53 | set_tssldt2_gdt(FIRST_TASKTSS_INDEX, base, limit, P_SET | (DPL3 << 5) | TYPE_TSS_NOTBUSY); 54 | base = &(init_task.task.ldt); 55 | limit = &(init_task.task.ldt) + sizeof(init_task.task.ldt); 56 | set_tssldt2_gdt(FIRST_TASKLDT_INDEX, base, limit, P_SET | (DPL3 << 5) | TYPE_LDT); 57 | __asm__ __volatile__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); 58 | /* 将tss挂接到TR寄存器 */ 59 | ltr(0); 60 | /* 将LDT挂接到LDTR寄存器 */ 61 | lldt(0); 62 | 63 | /* 初始化时钟 */ 64 | init_timer(HZ); 65 | 66 | /* 设置系统调度总入口 */ 67 | set_system_gate(0x80, &system_call); 68 | printk("scheduler initial end...\n"); 69 | 70 | } 71 | 72 | void move_to_user_mode(void) 73 | { 74 | /* 从ring0转换到ring3 */ 75 | printk("move to user mode: ring0->ring3\n"); 76 | __asm__ __volatile__("cli\n\t"\ 77 | "mov $0x2b,%%ax\n\t"\ 78 | "mov %%ax,%%ds\n\t" \ 79 | "mov %%ax,%%es\n\t" \ 80 | "mov %%ax,%%fs\n\t" \ 81 | "mov %%ax,%%gs\n\t" \ 82 | "movl %%esp,%%eax\n\t"\ 83 | "pushl $0x23\n\t" /* 压入ss */\ 84 | "pushl %%eax\n\t" /* 压入sp */\ 85 | "pushfl\n\t" /* 压入eflags */\ 86 | "pushl $0x23\n\t" /* 压入cs */\ 87 | "pushl $1f\n\t" /* 压入ip */\ 88 | "iret\n"\ 89 | "1:\t"\ 90 | :::"ax"); 91 | 92 | } 93 | 94 | void init() 95 | { 96 | long ss, sp, eflags, cs, ip; 97 | 98 | ss = init_task.task.tss.ss; 99 | sp = init_task.task.tss.esp0; 100 | eflags = init_task.task.tss.eflags; 101 | cs = init_task.task.tss.cs; 102 | ip = init_task.task.tss.eip; 103 | __asm__ __volatile__("cli\n\t"\ 104 | "pushl %0\n\t" /* 压入ss */\ 105 | "pushl %1\n\t" /* 压入sp */\ 106 | "pushl %2\n\t" /* 压入eflags */\ 107 | "pushl %3\n\t" /* 压入cs */\ 108 | "mov %4, %%ecx\n\t" /* 压入ip */\ 109 | "sti\n\t" \ 110 | "jmp *%%ecx\n" /* 压入ip */\ 111 | ::"r"(ss),"r"(sp),"r"(eflags),"r"(cs),"r"(ip)); 112 | 113 | } 114 | 115 | /* 116 | * 重新调度(时间片用完或者current.state==0) 117 | */ 118 | void reschedule(void) 119 | { 120 | /* 重新设置current指针 */ 121 | current->state = TASK_INTERRUPTIBLE; 122 | if(current->pid == 0){ 123 | current = &(task_tables[1]->task); 124 | } 125 | else{ 126 | current = &(task_tables[0]->task); 127 | 128 | } 129 | current->state = TASK_RUNNING; 130 | return; 131 | } 132 | 133 | /* 134 | * 根据调度策略,选择合适的task_struct作为下一个current 135 | */ 136 | void schedule(void) 137 | { 138 | unsigned int eip, esp, ebp; 139 | unsigned int base, limit; 140 | struct task_struct *prev, *next; 141 | int n, pid; 142 | 143 | __asm__ __volatile__("mov %%esp, %0":"=r"(esp)); 144 | __asm__ __volatile__("mov %%ebp, %0":"=r"(ebp)); 145 | prev = current; 146 | if(current->pid == 0){ 147 | current = &task_tables[1]->task; 148 | } 149 | else{ 150 | current = &task_tables[0]->task; 151 | } 152 | next = current; 153 | current->state = TASK_RUNNING; 154 | pid = current->pid; 155 | if(current != NULL){ 156 | /* 在gdt表后边加上进程0的tss和ldt */ 157 | base = &(current->tss); 158 | limit = &(current->tss) + sizeof(current->tss); 159 | set_tssldt2_gdt(FIRST_TASKTSS_INDEX, base, limit, P_SET | (DPL3 << 5) | TYPE_TSS_NOTBUSY); 160 | 161 | base = &(current->ldt); 162 | limit = &(current->ldt) + sizeof(current->ldt); 163 | set_tssldt2_gdt(FIRST_TASKLDT_INDEX, base, limit, P_SET | (DPL3 << 5) | TYPE_LDT); 164 | 165 | //eip = current->tss.eip; 166 | //current->tss.esp = esp; 167 | //current->tss.ebp = ebp; 168 | /* 进程切换 */ 169 | switch_to(prev, next, prev); 170 | } 171 | } 172 | 173 | /* 174 | * 保存上下文 175 | */ 176 | void save_context(pt_regs *regs) 177 | { 178 | current->tss.edi = regs->edi; // 从 edi 到 eax 由 pusha 指令压入 179 | current->tss.esi = regs->esi; 180 | current->tss.ebp = regs->ebp; 181 | current->tss.esp = regs->esp; 182 | current->tss.ebx = regs->ebx; 183 | current->tss.eflags = regs->eflags; 184 | } 185 | 186 | 187 | /* 188 | * 切换到task_[n],首先需要检测n不是当前current,否则不做任何事; 189 | * 如果task_[n]用到math co-processor,需要清空TS-flag; 190 | */ 191 | struct task_struct fastcall * __switch_to(struct task_struct *prev, struct task_struct *next) 192 | { 193 | struct {long a,b;} __tmp; 194 | unsigned int eip,esp,ebp; 195 | esp = next->tss.esp0; 196 | ebp = next->tss.ebp; 197 | eip = next->tss.eip; 198 | __asm__ __volatile__("cli\n\t" \ 199 | "mov %0, %%ecx\n\t" \ 200 | "mov %1, %%esp\n\t" \ 201 | "mov %2, %%ebp\n\t" \ 202 | "mov %3, %%eax\n\t" \ 203 | "mov $0x12345, %%eax\n\t" \ 204 | "sti\n\t" \ 205 | "jmp *%%ecx\t" \ 206 | :: "r"(eip), "r"(esp), "r"(ebp), "r"(current->tss.cr3)); 207 | return prev; 208 | } 209 | 210 | 211 | 212 | /* 213 | * 准备init0 214 | */ 215 | void init0_ready(void) 216 | { 217 | /* 设置栈 */ 218 | struct task_struct *init0_point = &(task_tables[0]->task); 219 | init0_point->tss.esp0 = (long)task_tables + PAGE_SIZE; 220 | init0_point->tss.eip = (long)thread_cpu_idle; 221 | init0_point->tss.eflags = 0x3202; /* 设置IOPL=3 */ 222 | } 223 | 224 | /* 225 | * 初始化开始状态下的两个线程 226 | */ 227 | void init_thread(void) 228 | { 229 | /* 初始化init0 */ 230 | init0_ready(); 231 | #if 1 232 | /* 分配一个task_struct结构体 */ 233 | union task_union *idle_point = (union task_union *)kmalloc(sizeof(union task_union), 0); 234 | if(idle_point == NULL){ 235 | panic("init_thread"); 236 | } 237 | idle_point->task = task_tables[0]->task; 238 | task_tables[1] = idle_point; 239 | idle_point->task.pid = 1; 240 | idle_point->task.tss.esp0 = &task_tables[1] + PAGE_SIZE; 241 | idle_point->task.tss.eip = (long)thread_init1; 242 | idle_point->task.tss.eflags = 0x3202; /* 设置IOPL=3 */ 243 | #endif 244 | } 245 | 246 | 247 | /* 初始化一个函数作为init进程程序体 */ 248 | void thread_init1(void) 249 | { 250 | static int i=0,j=0; 251 | while(1){ 252 | cli(); 253 | i++; 254 | if((i % 3000) == 0){ 255 | printk("1 "); 256 | } 257 | if(i == 10000){ 258 | i = 0; 259 | j++; 260 | 261 | current->state = TASK_INTERRUPTIBLE; 262 | schedule(); 263 | 264 | } 265 | sti(); 266 | }; 267 | } 268 | 269 | 270 | /* 271 | * CPU空闲状态下运行的内核线程 272 | */ 273 | void thread_cpu_idle(void) 274 | { 275 | static int i=0,j=0; 276 | while(1){ 277 | cli(); 278 | i++; 279 | if((i % 3000) == 0){ 280 | printk("0 "); 281 | } 282 | if(i == 10000){ 283 | i = 0; 284 | j++; 285 | 286 | current->state = TASK_INTERRUPTIBLE; 287 | schedule(); 288 | 289 | } 290 | sti(); 291 | }; 292 | } 293 | 294 | -------------------------------------------------------------------------------- /kernel/sched.s: -------------------------------------------------------------------------------- 1 | 2 | sched.o: file format elf32-i386 3 | 4 | 5 | Disassembly of section .text: 6 | 7 | 00000000 : 8 | 0: 55 push %ebp 9 | 1: 89 e5 mov %esp,%ebp 10 | 3: 83 ec 14 sub $0x14,%esp 11 | 6: e8 fc ff ff ff call 7 12 | b: 05 01 00 00 00 add $0x1,%eax 13 | 10: 8b 45 0c mov 0xc(%ebp),%eax 14 | 13: 88 45 ec mov %al,-0x14(%ebp) 15 | 16: 8b 45 08 mov 0x8(%ebp),%eax 16 | 19: 89 45 fc mov %eax,-0x4(%ebp) 17 | 1c: eb 13 jmp 31 18 | 1e: 8b 45 fc mov -0x4(%ebp),%eax 19 | 21: 8d 50 01 lea 0x1(%eax),%edx 20 | 24: 89 55 fc mov %edx,-0x4(%ebp) 21 | 27: 0f b6 55 ec movzbl -0x14(%ebp),%edx 22 | 2b: 88 10 mov %dl,(%eax) 23 | 2d: 83 6d 10 01 subl $0x1,0x10(%ebp) 24 | 31: 83 7d 10 00 cmpl $0x0,0x10(%ebp) 25 | 35: 75 e7 jne 1e 26 | 37: 90 nop 27 | 38: c9 leave 28 | 39: c3 ret 29 | 30 | 0000003a : 31 | 3a: 55 push %ebp 32 | 3b: 89 e5 mov %esp,%ebp 33 | 3d: e8 fc ff ff ff call 3e 34 | 42: 05 01 00 00 00 add $0x1,%eax 35 | 47: ff 75 0c pushl 0xc(%ebp) 36 | 4a: 6a 00 push $0x0 37 | 4c: ff 75 08 pushl 0x8(%ebp) 38 | 4f: e8 ac ff ff ff call 0 39 | 54: 83 c4 0c add $0xc,%esp 40 | 57: 90 nop 41 | 58: c9 leave 42 | 59: c3 ret 43 | 44 | 0000005a : 45 | 5a: 55 push %ebp 46 | 5b: 89 e5 mov %esp,%ebp 47 | 5d: 56 push %esi 48 | 5e: 53 push %ebx 49 | 5f: 83 ec 08 sub $0x8,%esp 50 | 62: e8 fc ff ff ff call 63 51 | 67: 05 01 00 00 00 add $0x1,%eax 52 | 6c: 8b 4d 14 mov 0x14(%ebp),%ecx 53 | 6f: 8b 55 18 mov 0x18(%ebp),%edx 54 | 72: 88 4d f4 mov %cl,-0xc(%ebp) 55 | 75: 88 55 f0 mov %dl,-0x10(%ebp) 56 | 78: 8b 55 10 mov 0x10(%ebp),%edx 57 | 7b: 89 d3 mov %edx,%ebx 58 | 7d: 8b 90 00 00 00 00 mov 0x0(%eax),%edx 59 | 83: 8b 4d 08 mov 0x8(%ebp),%ecx 60 | 86: 66 89 1c ca mov %bx,(%edx,%ecx,8) 61 | 8a: 8b 55 0c mov 0xc(%ebp),%edx 62 | 8d: 89 d3 mov %edx,%ebx 63 | 8f: 8b 90 00 00 00 00 mov 0x0(%eax),%edx 64 | 95: 8b 4d 08 mov 0x8(%ebp),%ecx 65 | 98: 66 89 5c ca 02 mov %bx,0x2(%edx,%ecx,8) 66 | 9d: 8b 55 0c mov 0xc(%ebp),%edx 67 | a0: c1 ea 10 shr $0x10,%edx 68 | a3: 89 d3 mov %edx,%ebx 69 | a5: 8b 90 00 00 00 00 mov 0x0(%eax),%edx 70 | ab: 8b 4d 08 mov 0x8(%ebp),%ecx 71 | ae: 88 5c ca 04 mov %bl,0x4(%edx,%ecx,8) 72 | b2: 8b 90 00 00 00 00 mov 0x0(%eax),%edx 73 | b8: 8b 4d 08 mov 0x8(%ebp),%ecx 74 | bb: 0f b6 5d f4 movzbl -0xc(%ebp),%ebx 75 | bf: 88 5c ca 05 mov %bl,0x5(%edx,%ecx,8) 76 | c3: 8b 55 10 mov 0x10(%ebp),%edx 77 | c6: c1 ea 10 shr $0x10,%edx 78 | c9: 83 e2 0f and $0xf,%edx 79 | cc: 8b 88 00 00 00 00 mov 0x0(%eax),%ecx 80 | d2: 8b 5d 08 mov 0x8(%ebp),%ebx 81 | d5: 89 d6 mov %edx,%esi 82 | d7: 83 e6 0f and $0xf,%esi 83 | da: 0f b6 54 d9 06 movzbl 0x6(%ecx,%ebx,8),%edx 84 | df: 83 e2 f0 and $0xfffffff0,%edx 85 | e2: 09 f2 or %esi,%edx 86 | e4: 88 54 d9 06 mov %dl,0x6(%ecx,%ebx,8) 87 | e8: 0f b6 55 f0 movzbl -0x10(%ebp),%edx 88 | ec: 89 d3 mov %edx,%ebx 89 | ee: 83 e3 0f and $0xf,%ebx 90 | f1: 8b 90 00 00 00 00 mov 0x0(%eax),%edx 91 | f7: 8b 4d 08 mov 0x8(%ebp),%ecx 92 | fa: 89 de mov %ebx,%esi 93 | fc: c1 e6 04 shl $0x4,%esi 94 | ff: 0f b6 5c ca 06 movzbl 0x6(%edx,%ecx,8),%ebx 95 | 104: 83 e3 0f and $0xf,%ebx 96 | 107: 09 f3 or %esi,%ebx 97 | 109: 88 5c ca 06 mov %bl,0x6(%edx,%ecx,8) 98 | 10d: 8b 55 0c mov 0xc(%ebp),%edx 99 | 110: c1 ea 18 shr $0x18,%edx 100 | 113: 89 d1 mov %edx,%ecx 101 | 115: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 102 | 11b: 8b 55 08 mov 0x8(%ebp),%edx 103 | 11e: 88 4c d0 07 mov %cl,0x7(%eax,%edx,8) 104 | 122: 90 nop 105 | 123: 83 c4 08 add $0x8,%esp 106 | 126: 5b pop %ebx 107 | 127: 5e pop %esi 108 | 128: 5d pop %ebp 109 | 129: c3 ret 110 | 111 | 0000012a : 112 | 12a: 55 push %ebp 113 | 12b: 89 e5 mov %esp,%ebp 114 | 12d: 53 push %ebx 115 | 12e: 83 ec 08 sub $0x8,%esp 116 | 131: e8 fc ff ff ff call 132 117 | 136: 05 01 00 00 00 add $0x1,%eax 118 | 13b: 8b 4d 10 mov 0x10(%ebp),%ecx 119 | 13e: 8b 55 14 mov 0x14(%ebp),%edx 120 | 141: 66 89 4d f8 mov %cx,-0x8(%ebp) 121 | 145: 66 89 55 f4 mov %dx,-0xc(%ebp) 122 | 149: 8b 55 0c mov 0xc(%ebp),%edx 123 | 14c: 89 d3 mov %edx,%ebx 124 | 14e: 8b 90 00 00 00 00 mov 0x0(%eax),%edx 125 | 154: 8b 4d 08 mov 0x8(%ebp),%ecx 126 | 157: 66 89 1c ca mov %bx,(%edx,%ecx,8) 127 | 15b: 8b 55 0c mov 0xc(%ebp),%edx 128 | 15e: c1 ea 10 shr $0x10,%edx 129 | 161: 89 d3 mov %edx,%ebx 130 | 163: 8b 90 00 00 00 00 mov 0x0(%eax),%edx 131 | 169: 8b 4d 08 mov 0x8(%ebp),%ecx 132 | 16c: 66 89 5c ca 06 mov %bx,0x6(%edx,%ecx,8) 133 | 171: 8b 90 00 00 00 00 mov 0x0(%eax),%edx 134 | 177: 8b 4d 08 mov 0x8(%ebp),%ecx 135 | 17a: 0f b7 5d f8 movzwl -0x8(%ebp),%ebx 136 | 17e: 66 89 5c ca 02 mov %bx,0x2(%edx,%ecx,8) 137 | 183: 8b 90 00 00 00 00 mov 0x0(%eax),%edx 138 | 189: 8b 4d 08 mov 0x8(%ebp),%ecx 139 | 18c: c6 44 ca 04 00 movb $0x0,0x4(%edx,%ecx,8) 140 | 191: 0f b7 55 f4 movzwl -0xc(%ebp),%edx 141 | 195: 89 d1 mov %edx,%ecx 142 | 197: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 143 | 19d: 8b 55 08 mov 0x8(%ebp),%edx 144 | 1a0: 88 4c d0 05 mov %cl,0x5(%eax,%edx,8) 145 | 1a4: 90 nop 146 | 1a5: 83 c4 08 add $0x8,%esp 147 | 1a8: 5b pop %ebx 148 | 1a9: 5d pop %ebp 149 | 1aa: c3 ret 150 | 151 | 000001ab : 152 | 1ab: 55 push %ebp 153 | 1ac: 89 e5 mov %esp,%ebp 154 | 1ae: 53 push %ebx 155 | 1af: 83 ec 14 sub $0x14,%esp 156 | 1b2: e8 fc ff ff ff call 1b3 157 | 1b7: 81 c3 02 00 00 00 add $0x2,%ebx 158 | 1bd: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp) 159 | 1c4: 83 ec 0c sub $0xc,%esp 160 | 1c7: 8d 83 00 00 00 00 lea 0x0(%ebx),%eax 161 | 1cd: 50 push %eax 162 | 1ce: e8 fc ff ff ff call 1cf 163 | 1d3: 83 c4 10 add $0x10,%esp 164 | 1d6: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 165 | 1dc: 66 c7 00 ff 07 movw $0x7ff,(%eax) 166 | 1e1: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 167 | 1e7: 89 c2 mov %eax,%edx 168 | 1e9: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 169 | 1ef: 89 50 02 mov %edx,0x2(%eax) 170 | 1f2: 83 ec 0c sub $0xc,%esp 171 | 1f5: 6a 00 push $0x0 172 | 1f7: 6a 00 push $0x0 173 | 1f9: 6a 00 push $0x0 174 | 1fb: 6a 00 push $0x0 175 | 1fd: 6a 00 push $0x0 176 | 1ff: e8 56 fe ff ff call 5a 177 | 204: 83 c4 20 add $0x20,%esp 178 | 207: 83 ec 0c sub $0xc,%esp 179 | 20a: 6a 0c push $0xc 180 | 20c: 68 9a 00 00 00 push $0x9a 181 | 211: 68 ff ff 0f 00 push $0xfffff 182 | 216: 6a 00 push $0x0 183 | 218: 6a 01 push $0x1 184 | 21a: e8 3b fe ff ff call 5a 185 | 21f: 83 c4 20 add $0x20,%esp 186 | 222: 83 ec 0c sub $0xc,%esp 187 | 225: 6a 0c push $0xc 188 | 227: 68 92 00 00 00 push $0x92 189 | 22c: 68 ff ff 0f 00 push $0xfffff 190 | 231: 6a 00 push $0x0 191 | 233: 6a 02 push $0x2 192 | 235: e8 20 fe ff ff call 5a 193 | 23a: 83 c4 20 add $0x20,%esp 194 | 23d: 83 ec 0c sub $0xc,%esp 195 | 240: 6a 00 push $0x0 196 | 242: 6a 00 push $0x0 197 | 244: 6a 00 push $0x0 198 | 246: 6a 00 push $0x0 199 | 248: 6a 03 push $0x3 200 | 24a: e8 0b fe ff ff call 5a 201 | 24f: 83 c4 20 add $0x20,%esp 202 | 252: 83 ec 0c sub $0xc,%esp 203 | 255: 6a 0c push $0xc 204 | 257: 68 fa 00 00 00 push $0xfa 205 | 25c: 68 ff ff 0f 00 push $0xfffff 206 | 261: 6a 00 push $0x0 207 | 263: 6a 04 push $0x4 208 | 265: e8 f0 fd ff ff call 5a 209 | 26a: 83 c4 20 add $0x20,%esp 210 | 26d: 83 ec 0c sub $0xc,%esp 211 | 270: 6a 0c push $0xc 212 | 272: 68 f2 00 00 00 push $0xf2 213 | 277: 68 ff ff 0f 00 push $0xfffff 214 | 27c: 6a 00 push $0x0 215 | 27e: 6a 05 push $0x5 216 | 280: e8 d5 fd ff ff call 5a 217 | 285: 83 c4 20 add $0x20,%esp 218 | 288: c7 45 f4 06 00 00 00 movl $0x6,-0xc(%ebp) 219 | 28f: eb 1a jmp 2ab 220 | 291: 83 ec 0c sub $0xc,%esp 221 | 294: 6a 00 push $0x0 222 | 296: 6a 00 push $0x0 223 | 298: 6a 00 push $0x0 224 | 29a: 6a 00 push $0x0 225 | 29c: ff 75 f4 pushl -0xc(%ebp) 226 | 29f: e8 b6 fd ff ff call 5a 227 | 2a4: 83 c4 20 add $0x20,%esp 228 | 2a7: 83 45 f4 01 addl $0x1,-0xc(%ebp) 229 | 2ab: 81 7d f4 ff 00 00 00 cmpl $0xff,-0xc(%ebp) 230 | 2b2: 7e dd jle 291 231 | 2b4: 83 ec 0c sub $0xc,%esp 232 | 2b7: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 233 | 2bd: 50 push %eax 234 | 2be: e8 fc ff ff ff call 2bf 235 | 2c3: 83 c4 10 add $0x10,%esp 236 | 2c6: 90 nop 237 | 2c7: 8b 5d fc mov -0x4(%ebp),%ebx 238 | 2ca: c9 leave 239 | 2cb: c3 ret 240 | 241 | 000002cc : 242 | 2cc: 55 push %ebp 243 | 2cd: 89 e5 mov %esp,%ebp 244 | 2cf: 53 push %ebx 245 | 2d0: 83 ec 04 sub $0x4,%esp 246 | 2d3: e8 fc ff ff ff call 2d4 247 | 2d8: 81 c3 02 00 00 00 add $0x2,%ebx 248 | 2de: 83 ec 0c sub $0xc,%esp 249 | 2e1: 8d 83 13 00 00 00 lea 0x13(%ebx),%eax 250 | 2e7: 50 push %eax 251 | 2e8: e8 fc ff ff ff call 2e9 252 | 2ed: 83 c4 10 add $0x10,%esp 253 | 2f0: 83 ec 08 sub $0x8,%esp 254 | 2f3: 6a 11 push $0x11 255 | 2f5: 6a 20 push $0x20 256 | 2f7: e8 fc ff ff ff call 2f8 257 | 2fc: 83 c4 10 add $0x10,%esp 258 | 2ff: 83 ec 08 sub $0x8,%esp 259 | 302: 6a 11 push $0x11 260 | 304: 68 a0 00 00 00 push $0xa0 261 | 309: e8 fc ff ff ff call 30a 262 | 30e: 83 c4 10 add $0x10,%esp 263 | 311: 83 ec 08 sub $0x8,%esp 264 | 314: 6a 20 push $0x20 265 | 316: 6a 21 push $0x21 266 | 318: e8 fc ff ff ff call 319 267 | 31d: 83 c4 10 add $0x10,%esp 268 | 320: 83 ec 08 sub $0x8,%esp 269 | 323: 6a 28 push $0x28 270 | 325: 68 a1 00 00 00 push $0xa1 271 | 32a: e8 fc ff ff ff call 32b 272 | 32f: 83 c4 10 add $0x10,%esp 273 | 332: 83 ec 08 sub $0x8,%esp 274 | 335: 6a 04 push $0x4 275 | 337: 6a 21 push $0x21 276 | 339: e8 fc ff ff ff call 33a 277 | 33e: 83 c4 10 add $0x10,%esp 278 | 341: 83 ec 08 sub $0x8,%esp 279 | 344: 6a 02 push $0x2 280 | 346: 68 a1 00 00 00 push $0xa1 281 | 34b: e8 fc ff ff ff call 34c 282 | 350: 83 c4 10 add $0x10,%esp 283 | 353: 83 ec 08 sub $0x8,%esp 284 | 356: 6a 01 push $0x1 285 | 358: 6a 21 push $0x21 286 | 35a: e8 fc ff ff ff call 35b 287 | 35f: 83 c4 10 add $0x10,%esp 288 | 362: 83 ec 08 sub $0x8,%esp 289 | 365: 6a 01 push $0x1 290 | 367: 68 a1 00 00 00 push $0xa1 291 | 36c: e8 fc ff ff ff call 36d 292 | 371: 83 c4 10 add $0x10,%esp 293 | 374: 83 ec 08 sub $0x8,%esp 294 | 377: 6a 00 push $0x0 295 | 379: 6a 21 push $0x21 296 | 37b: e8 fc ff ff ff call 37c 297 | 380: 83 c4 10 add $0x10,%esp 298 | 383: 83 ec 08 sub $0x8,%esp 299 | 386: 6a 00 push $0x0 300 | 388: 68 a1 00 00 00 push $0xa1 301 | 38d: e8 fc ff ff ff call 38e 302 | 392: 83 c4 10 add $0x10,%esp 303 | 395: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 304 | 39b: 66 c7 00 ff 07 movw $0x7ff,(%eax) 305 | 3a0: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 306 | 3a6: 89 c2 mov %eax,%edx 307 | 3a8: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 308 | 3ae: 89 50 02 mov %edx,0x2(%eax) 309 | 3b1: 83 ec 08 sub $0x8,%esp 310 | 3b4: 68 00 04 00 00 push $0x400 311 | 3b9: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 312 | 3bf: 50 push %eax 313 | 3c0: e8 75 fc ff ff call 3a 314 | 3c5: 83 c4 10 add $0x10,%esp 315 | 3c8: 83 ec 08 sub $0x8,%esp 316 | 3cb: 68 00 08 00 00 push $0x800 317 | 3d0: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 318 | 3d6: 50 push %eax 319 | 3d7: e8 5e fc ff ff call 3a 320 | 3dc: 83 c4 10 add $0x10,%esp 321 | 3df: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 322 | 3e5: 68 8e 00 00 00 push $0x8e 323 | 3ea: 6a 08 push $0x8 324 | 3ec: 50 push %eax 325 | 3ed: 6a 00 push $0x0 326 | 3ef: e8 36 fd ff ff call 12a 327 | 3f4: 83 c4 10 add $0x10,%esp 328 | 3f7: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 329 | 3fd: 68 8e 00 00 00 push $0x8e 330 | 402: 6a 08 push $0x8 331 | 404: 50 push %eax 332 | 405: 6a 01 push $0x1 333 | 407: e8 1e fd ff ff call 12a 334 | 40c: 83 c4 10 add $0x10,%esp 335 | 40f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 336 | 415: 68 8e 00 00 00 push $0x8e 337 | 41a: 6a 08 push $0x8 338 | 41c: 50 push %eax 339 | 41d: 6a 02 push $0x2 340 | 41f: e8 06 fd ff ff call 12a 341 | 424: 83 c4 10 add $0x10,%esp 342 | 427: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 343 | 42d: 68 8e 00 00 00 push $0x8e 344 | 432: 6a 08 push $0x8 345 | 434: 50 push %eax 346 | 435: 6a 03 push $0x3 347 | 437: e8 ee fc ff ff call 12a 348 | 43c: 83 c4 10 add $0x10,%esp 349 | 43f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 350 | 445: 68 8e 00 00 00 push $0x8e 351 | 44a: 6a 08 push $0x8 352 | 44c: 50 push %eax 353 | 44d: 6a 04 push $0x4 354 | 44f: e8 d6 fc ff ff call 12a 355 | 454: 83 c4 10 add $0x10,%esp 356 | 457: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 357 | 45d: 68 8e 00 00 00 push $0x8e 358 | 462: 6a 08 push $0x8 359 | 464: 50 push %eax 360 | 465: 6a 05 push $0x5 361 | 467: e8 be fc ff ff call 12a 362 | 46c: 83 c4 10 add $0x10,%esp 363 | 46f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 364 | 475: 68 8e 00 00 00 push $0x8e 365 | 47a: 6a 08 push $0x8 366 | 47c: 50 push %eax 367 | 47d: 6a 06 push $0x6 368 | 47f: e8 a6 fc ff ff call 12a 369 | 484: 83 c4 10 add $0x10,%esp 370 | 487: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 371 | 48d: 68 8e 00 00 00 push $0x8e 372 | 492: 6a 08 push $0x8 373 | 494: 50 push %eax 374 | 495: 6a 07 push $0x7 375 | 497: e8 8e fc ff ff call 12a 376 | 49c: 83 c4 10 add $0x10,%esp 377 | 49f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 378 | 4a5: 68 8e 00 00 00 push $0x8e 379 | 4aa: 6a 08 push $0x8 380 | 4ac: 50 push %eax 381 | 4ad: 6a 08 push $0x8 382 | 4af: e8 76 fc ff ff call 12a 383 | 4b4: 83 c4 10 add $0x10,%esp 384 | 4b7: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 385 | 4bd: 68 8e 00 00 00 push $0x8e 386 | 4c2: 6a 08 push $0x8 387 | 4c4: 50 push %eax 388 | 4c5: 6a 09 push $0x9 389 | 4c7: e8 5e fc ff ff call 12a 390 | 4cc: 83 c4 10 add $0x10,%esp 391 | 4cf: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 392 | 4d5: 68 8e 00 00 00 push $0x8e 393 | 4da: 6a 08 push $0x8 394 | 4dc: 50 push %eax 395 | 4dd: 6a 0a push $0xa 396 | 4df: e8 46 fc ff ff call 12a 397 | 4e4: 83 c4 10 add $0x10,%esp 398 | 4e7: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 399 | 4ed: 68 8e 00 00 00 push $0x8e 400 | 4f2: 6a 08 push $0x8 401 | 4f4: 50 push %eax 402 | 4f5: 6a 0b push $0xb 403 | 4f7: e8 2e fc ff ff call 12a 404 | 4fc: 83 c4 10 add $0x10,%esp 405 | 4ff: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 406 | 505: 68 8e 00 00 00 push $0x8e 407 | 50a: 6a 08 push $0x8 408 | 50c: 50 push %eax 409 | 50d: 6a 0c push $0xc 410 | 50f: e8 16 fc ff ff call 12a 411 | 514: 83 c4 10 add $0x10,%esp 412 | 517: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 413 | 51d: 68 8e 00 00 00 push $0x8e 414 | 522: 6a 08 push $0x8 415 | 524: 50 push %eax 416 | 525: 6a 0d push $0xd 417 | 527: e8 fe fb ff ff call 12a 418 | 52c: 83 c4 10 add $0x10,%esp 419 | 52f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 420 | 535: 68 8e 00 00 00 push $0x8e 421 | 53a: 6a 08 push $0x8 422 | 53c: 50 push %eax 423 | 53d: 6a 0e push $0xe 424 | 53f: e8 e6 fb ff ff call 12a 425 | 544: 83 c4 10 add $0x10,%esp 426 | 547: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 427 | 54d: 68 8e 00 00 00 push $0x8e 428 | 552: 6a 08 push $0x8 429 | 554: 50 push %eax 430 | 555: 6a 0f push $0xf 431 | 557: e8 ce fb ff ff call 12a 432 | 55c: 83 c4 10 add $0x10,%esp 433 | 55f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 434 | 565: 68 8e 00 00 00 push $0x8e 435 | 56a: 6a 08 push $0x8 436 | 56c: 50 push %eax 437 | 56d: 6a 10 push $0x10 438 | 56f: e8 b6 fb ff ff call 12a 439 | 574: 83 c4 10 add $0x10,%esp 440 | 577: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 441 | 57d: 68 8e 00 00 00 push $0x8e 442 | 582: 6a 08 push $0x8 443 | 584: 50 push %eax 444 | 585: 6a 11 push $0x11 445 | 587: e8 9e fb ff ff call 12a 446 | 58c: 83 c4 10 add $0x10,%esp 447 | 58f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 448 | 595: 68 8e 00 00 00 push $0x8e 449 | 59a: 6a 08 push $0x8 450 | 59c: 50 push %eax 451 | 59d: 6a 12 push $0x12 452 | 59f: e8 86 fb ff ff call 12a 453 | 5a4: 83 c4 10 add $0x10,%esp 454 | 5a7: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 455 | 5ad: 68 8e 00 00 00 push $0x8e 456 | 5b2: 6a 08 push $0x8 457 | 5b4: 50 push %eax 458 | 5b5: 6a 13 push $0x13 459 | 5b7: e8 6e fb ff ff call 12a 460 | 5bc: 83 c4 10 add $0x10,%esp 461 | 5bf: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 462 | 5c5: 68 8e 00 00 00 push $0x8e 463 | 5ca: 6a 08 push $0x8 464 | 5cc: 50 push %eax 465 | 5cd: 6a 14 push $0x14 466 | 5cf: e8 56 fb ff ff call 12a 467 | 5d4: 83 c4 10 add $0x10,%esp 468 | 5d7: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 469 | 5dd: 68 8e 00 00 00 push $0x8e 470 | 5e2: 6a 08 push $0x8 471 | 5e4: 50 push %eax 472 | 5e5: 6a 15 push $0x15 473 | 5e7: e8 3e fb ff ff call 12a 474 | 5ec: 83 c4 10 add $0x10,%esp 475 | 5ef: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 476 | 5f5: 68 8e 00 00 00 push $0x8e 477 | 5fa: 6a 08 push $0x8 478 | 5fc: 50 push %eax 479 | 5fd: 6a 16 push $0x16 480 | 5ff: e8 26 fb ff ff call 12a 481 | 604: 83 c4 10 add $0x10,%esp 482 | 607: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 483 | 60d: 68 8e 00 00 00 push $0x8e 484 | 612: 6a 08 push $0x8 485 | 614: 50 push %eax 486 | 615: 6a 17 push $0x17 487 | 617: e8 0e fb ff ff call 12a 488 | 61c: 83 c4 10 add $0x10,%esp 489 | 61f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 490 | 625: 68 8e 00 00 00 push $0x8e 491 | 62a: 6a 08 push $0x8 492 | 62c: 50 push %eax 493 | 62d: 6a 18 push $0x18 494 | 62f: e8 f6 fa ff ff call 12a 495 | 634: 83 c4 10 add $0x10,%esp 496 | 637: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 497 | 63d: 68 8e 00 00 00 push $0x8e 498 | 642: 6a 08 push $0x8 499 | 644: 50 push %eax 500 | 645: 6a 19 push $0x19 501 | 647: e8 de fa ff ff call 12a 502 | 64c: 83 c4 10 add $0x10,%esp 503 | 64f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 504 | 655: 68 8e 00 00 00 push $0x8e 505 | 65a: 6a 08 push $0x8 506 | 65c: 50 push %eax 507 | 65d: 6a 1a push $0x1a 508 | 65f: e8 c6 fa ff ff call 12a 509 | 664: 83 c4 10 add $0x10,%esp 510 | 667: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 511 | 66d: 68 8e 00 00 00 push $0x8e 512 | 672: 6a 08 push $0x8 513 | 674: 50 push %eax 514 | 675: 6a 1b push $0x1b 515 | 677: e8 ae fa ff ff call 12a 516 | 67c: 83 c4 10 add $0x10,%esp 517 | 67f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 518 | 685: 68 8e 00 00 00 push $0x8e 519 | 68a: 6a 08 push $0x8 520 | 68c: 50 push %eax 521 | 68d: 6a 1c push $0x1c 522 | 68f: e8 96 fa ff ff call 12a 523 | 694: 83 c4 10 add $0x10,%esp 524 | 697: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 525 | 69d: 68 8e 00 00 00 push $0x8e 526 | 6a2: 6a 08 push $0x8 527 | 6a4: 50 push %eax 528 | 6a5: 6a 1d push $0x1d 529 | 6a7: e8 7e fa ff ff call 12a 530 | 6ac: 83 c4 10 add $0x10,%esp 531 | 6af: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 532 | 6b5: 68 8e 00 00 00 push $0x8e 533 | 6ba: 6a 08 push $0x8 534 | 6bc: 50 push %eax 535 | 6bd: 6a 1e push $0x1e 536 | 6bf: e8 66 fa ff ff call 12a 537 | 6c4: 83 c4 10 add $0x10,%esp 538 | 6c7: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 539 | 6cd: 68 8e 00 00 00 push $0x8e 540 | 6d2: 6a 08 push $0x8 541 | 6d4: 50 push %eax 542 | 6d5: 6a 1f push $0x1f 543 | 6d7: e8 4e fa ff ff call 12a 544 | 6dc: 83 c4 10 add $0x10,%esp 545 | 6df: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 546 | 6e5: 68 8e 00 00 00 push $0x8e 547 | 6ea: 6a 08 push $0x8 548 | 6ec: 50 push %eax 549 | 6ed: 6a 20 push $0x20 550 | 6ef: e8 36 fa ff ff call 12a 551 | 6f4: 83 c4 10 add $0x10,%esp 552 | 6f7: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 553 | 6fd: 68 8e 00 00 00 push $0x8e 554 | 702: 6a 08 push $0x8 555 | 704: 50 push %eax 556 | 705: 6a 21 push $0x21 557 | 707: e8 1e fa ff ff call 12a 558 | 70c: 83 c4 10 add $0x10,%esp 559 | 70f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 560 | 715: 68 8e 00 00 00 push $0x8e 561 | 71a: 6a 08 push $0x8 562 | 71c: 50 push %eax 563 | 71d: 6a 22 push $0x22 564 | 71f: e8 06 fa ff ff call 12a 565 | 724: 83 c4 10 add $0x10,%esp 566 | 727: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 567 | 72d: 68 8e 00 00 00 push $0x8e 568 | 732: 6a 08 push $0x8 569 | 734: 50 push %eax 570 | 735: 6a 23 push $0x23 571 | 737: e8 ee f9 ff ff call 12a 572 | 73c: 83 c4 10 add $0x10,%esp 573 | 73f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 574 | 745: 68 8e 00 00 00 push $0x8e 575 | 74a: 6a 08 push $0x8 576 | 74c: 50 push %eax 577 | 74d: 6a 24 push $0x24 578 | 74f: e8 d6 f9 ff ff call 12a 579 | 754: 83 c4 10 add $0x10,%esp 580 | 757: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 581 | 75d: 68 8e 00 00 00 push $0x8e 582 | 762: 6a 08 push $0x8 583 | 764: 50 push %eax 584 | 765: 6a 25 push $0x25 585 | 767: e8 be f9 ff ff call 12a 586 | 76c: 83 c4 10 add $0x10,%esp 587 | 76f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 588 | 775: 68 8e 00 00 00 push $0x8e 589 | 77a: 6a 08 push $0x8 590 | 77c: 50 push %eax 591 | 77d: 6a 26 push $0x26 592 | 77f: e8 a6 f9 ff ff call 12a 593 | 784: 83 c4 10 add $0x10,%esp 594 | 787: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 595 | 78d: 68 8e 00 00 00 push $0x8e 596 | 792: 6a 08 push $0x8 597 | 794: 50 push %eax 598 | 795: 6a 27 push $0x27 599 | 797: e8 8e f9 ff ff call 12a 600 | 79c: 83 c4 10 add $0x10,%esp 601 | 79f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 602 | 7a5: 68 8e 00 00 00 push $0x8e 603 | 7aa: 6a 08 push $0x8 604 | 7ac: 50 push %eax 605 | 7ad: 6a 28 push $0x28 606 | 7af: e8 76 f9 ff ff call 12a 607 | 7b4: 83 c4 10 add $0x10,%esp 608 | 7b7: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 609 | 7bd: 68 8e 00 00 00 push $0x8e 610 | 7c2: 6a 08 push $0x8 611 | 7c4: 50 push %eax 612 | 7c5: 6a 29 push $0x29 613 | 7c7: e8 5e f9 ff ff call 12a 614 | 7cc: 83 c4 10 add $0x10,%esp 615 | 7cf: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 616 | 7d5: 68 8e 00 00 00 push $0x8e 617 | 7da: 6a 08 push $0x8 618 | 7dc: 50 push %eax 619 | 7dd: 6a 2a push $0x2a 620 | 7df: e8 46 f9 ff ff call 12a 621 | 7e4: 83 c4 10 add $0x10,%esp 622 | 7e7: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 623 | 7ed: 68 8e 00 00 00 push $0x8e 624 | 7f2: 6a 08 push $0x8 625 | 7f4: 50 push %eax 626 | 7f5: 6a 2b push $0x2b 627 | 7f7: e8 2e f9 ff ff call 12a 628 | 7fc: 83 c4 10 add $0x10,%esp 629 | 7ff: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 630 | 805: 68 8e 00 00 00 push $0x8e 631 | 80a: 6a 08 push $0x8 632 | 80c: 50 push %eax 633 | 80d: 6a 2c push $0x2c 634 | 80f: e8 16 f9 ff ff call 12a 635 | 814: 83 c4 10 add $0x10,%esp 636 | 817: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 637 | 81d: 68 8e 00 00 00 push $0x8e 638 | 822: 6a 08 push $0x8 639 | 824: 50 push %eax 640 | 825: 6a 2d push $0x2d 641 | 827: e8 fe f8 ff ff call 12a 642 | 82c: 83 c4 10 add $0x10,%esp 643 | 82f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 644 | 835: 68 8e 00 00 00 push $0x8e 645 | 83a: 6a 08 push $0x8 646 | 83c: 50 push %eax 647 | 83d: 6a 2e push $0x2e 648 | 83f: e8 e6 f8 ff ff call 12a 649 | 844: 83 c4 10 add $0x10,%esp 650 | 847: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 651 | 84d: 68 8e 00 00 00 push $0x8e 652 | 852: 6a 08 push $0x8 653 | 854: 50 push %eax 654 | 855: 6a 2f push $0x2f 655 | 857: e8 ce f8 ff ff call 12a 656 | 85c: 83 c4 10 add $0x10,%esp 657 | 85f: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 658 | 865: 68 8e 00 00 00 push $0x8e 659 | 86a: 6a 08 push $0x8 660 | 86c: 50 push %eax 661 | 86d: 68 ff 00 00 00 push $0xff 662 | 872: e8 b3 f8 ff ff call 12a 663 | 877: 83 c4 10 add $0x10,%esp 664 | 87a: 83 ec 0c sub $0xc,%esp 665 | 87d: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax 666 | 883: 50 push %eax 667 | 884: e8 fc ff ff ff call 885 668 | 889: 83 c4 10 add $0x10,%esp 669 | 88c: 90 nop 670 | 88d: 8b 5d fc mov -0x4(%ebp),%ebx 671 | 890: c9 leave 672 | 891: c3 ret 673 | 674 | 00000892 : 675 | 892: 55 push %ebp 676 | 893: 89 e5 mov %esp,%ebp 677 | 895: 83 ec 10 sub $0x10,%esp 678 | 898: e8 fc ff ff ff call 899 679 | 89d: 05 01 00 00 00 add $0x1,%eax 680 | 8a2: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp) 681 | 8a9: 83 45 fc 01 addl $0x1,-0x4(%ebp) 682 | 8ad: eb fe jmp 8ad 683 | 684 | 000008af : 685 | 8af: 55 push %ebp 686 | 8b0: 89 e5 mov %esp,%ebp 687 | 8b2: 57 push %edi 688 | 8b3: 56 push %esi 689 | 8b4: 53 push %ebx 690 | 8b5: 83 ec 1c sub $0x1c,%esp 691 | 8b8: e8 fc ff ff ff call 8b9 692 | 8bd: 05 01 00 00 00 add $0x1,%eax 693 | 8c2: 89 45 e4 mov %eax,-0x1c(%ebp) 694 | 8c5: 83 ec 0c sub $0xc,%esp 695 | 8c8: 8b 45 e4 mov -0x1c(%ebp),%eax 696 | 8cb: 8d 80 24 00 00 00 lea 0x24(%eax),%eax 697 | 8d1: 50 push %eax 698 | 8d2: 8b 5d e4 mov -0x1c(%ebp),%ebx 699 | 8d5: e8 fc ff ff ff call 8d6 700 | 8da: 83 c4 10 add $0x10,%esp 701 | 8dd: 8b 45 e4 mov -0x1c(%ebp),%eax 702 | 8e0: 8d 80 80 00 00 00 lea 0x80(%eax),%eax 703 | 8e6: 89 45 e0 mov %eax,-0x20(%ebp) 704 | 8e9: 8b 45 e4 mov -0x1c(%ebp),%eax 705 | 8ec: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 706 | 8f2: 8d 40 20 lea 0x20(%eax),%eax 707 | 8f5: 89 c6 mov %eax,%esi 708 | 8f7: 8b 45 e4 mov -0x1c(%ebp),%eax 709 | 8fa: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 710 | 900: 8d 40 22 lea 0x22(%eax),%eax 711 | 903: 89 c7 mov %eax,%edi 712 | 905: 8b 45 e4 mov -0x1c(%ebp),%eax 713 | 908: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 714 | 90e: 8d 40 24 lea 0x24(%eax),%eax 715 | 911: 89 45 dc mov %eax,-0x24(%ebp) 716 | 914: 8b 45 e4 mov -0x1c(%ebp),%eax 717 | 917: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 718 | 91d: 8d 50 25 lea 0x25(%eax),%edx 719 | 920: 8b 45 e4 mov -0x1c(%ebp),%eax 720 | 923: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 721 | 929: 8d 48 26 lea 0x26(%eax),%ecx 722 | 92c: 8b 45 e4 mov -0x1c(%ebp),%eax 723 | 92f: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 724 | 935: 8d 40 27 lea 0x27(%eax),%eax 725 | 938: 89 c3 mov %eax,%ebx 726 | 93a: 89 d0 mov %edx,%eax 727 | 93c: 89 ca mov %ecx,%edx 728 | 93e: 89 f1 mov %esi,%ecx 729 | 940: 89 fe mov %edi,%esi 730 | 942: 8b 7d dc mov -0x24(%ebp),%edi 731 | 945: 66 c7 01 68 00 movw $0x68,(%ecx) 732 | 94a: 66 89 06 mov %ax,(%esi) 733 | 94d: c1 c8 10 ror $0x10,%eax 734 | 950: 88 07 mov %al,(%edi) 735 | 952: c6 00 89 movb $0x89,(%eax) 736 | 955: c6 02 00 movb $0x0,(%edx) 737 | 958: 88 23 mov %ah,(%ebx) 738 | 95a: c1 c8 10 ror $0x10,%eax 739 | 95d: 8b 45 e4 mov -0x1c(%ebp),%eax 740 | 960: 8d 80 68 00 00 00 lea 0x68(%eax),%eax 741 | 966: 89 45 e0 mov %eax,-0x20(%ebp) 742 | 969: 8b 45 e4 mov -0x1c(%ebp),%eax 743 | 96c: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 744 | 972: 8d 40 28 lea 0x28(%eax),%eax 745 | 975: 89 c6 mov %eax,%esi 746 | 977: 8b 45 e4 mov -0x1c(%ebp),%eax 747 | 97a: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 748 | 980: 8d 40 2a lea 0x2a(%eax),%eax 749 | 983: 89 c7 mov %eax,%edi 750 | 985: 8b 45 e4 mov -0x1c(%ebp),%eax 751 | 988: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 752 | 98e: 8d 40 2c lea 0x2c(%eax),%eax 753 | 991: 89 45 dc mov %eax,-0x24(%ebp) 754 | 994: 8b 45 e4 mov -0x1c(%ebp),%eax 755 | 997: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 756 | 99d: 8d 50 2d lea 0x2d(%eax),%edx 757 | 9a0: 8b 45 e4 mov -0x1c(%ebp),%eax 758 | 9a3: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 759 | 9a9: 8d 48 2e lea 0x2e(%eax),%ecx 760 | 9ac: 8b 45 e4 mov -0x1c(%ebp),%eax 761 | 9af: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 762 | 9b5: 8d 40 2f lea 0x2f(%eax),%eax 763 | 9b8: 89 c3 mov %eax,%ebx 764 | 9ba: 89 d0 mov %edx,%eax 765 | 9bc: 89 ca mov %ecx,%edx 766 | 9be: 89 f1 mov %esi,%ecx 767 | 9c0: 89 fe mov %edi,%esi 768 | 9c2: 8b 7d dc mov -0x24(%ebp),%edi 769 | 9c5: 66 c7 01 68 00 movw $0x68,(%ecx) 770 | 9ca: 66 89 06 mov %ax,(%esi) 771 | 9cd: c1 c8 10 ror $0x10,%eax 772 | 9d0: 88 07 mov %al,(%edi) 773 | 9d2: c6 00 82 movb $0x82,(%eax) 774 | 9d5: c6 02 00 movb $0x0,(%edx) 775 | 9d8: 88 23 mov %ah,(%ebx) 776 | 9da: c1 c8 10 ror $0x10,%eax 777 | 9dd: 83 ec 0c sub $0xc,%esp 778 | 9e0: 8b 45 e4 mov -0x1c(%ebp),%eax 779 | 9e3: 8d 80 38 00 00 00 lea 0x38(%eax),%eax 780 | 9e9: 50 push %eax 781 | 9ea: 8b 5d e4 mov -0x1c(%ebp),%ebx 782 | 9ed: e8 fc ff ff ff call 9ee 783 | 9f2: 83 c4 10 add $0x10,%esp 784 | 9f5: b8 20 00 00 00 mov $0x20,%eax 785 | 9fa: 0f 00 d8 ltr %ax 786 | 9fd: b8 28 00 00 00 mov $0x28,%eax 787 | a02: 0f 00 d0 lldt %ax 788 | a05: 83 ec 0c sub $0xc,%esp 789 | a08: 6a 64 push $0x64 790 | a0a: 8b 5d e4 mov -0x1c(%ebp),%ebx 791 | a0d: e8 fc ff ff ff call a0e 792 | a12: 83 c4 10 add $0x10,%esp 793 | a15: 8b 45 e4 mov -0x1c(%ebp),%eax 794 | a18: 8b 80 00 00 00 00 mov 0x0(%eax),%eax 795 | a1e: 68 8e 00 00 00 push $0x8e 796 | a23: 6a 08 push $0x8 797 | a25: 50 push %eax 798 | a26: 68 80 00 00 00 push $0x80 799 | a2b: e8 fa f6 ff ff call 12a 800 | a30: 83 c4 10 add $0x10,%esp 801 | a33: 83 ec 0c sub $0xc,%esp 802 | a36: 8b 45 e4 mov -0x1c(%ebp),%eax 803 | a39: 8d 80 4b 00 00 00 lea 0x4b(%eax),%eax 804 | a3f: 50 push %eax 805 | a40: 8b 5d e4 mov -0x1c(%ebp),%ebx 806 | a43: e8 fc ff ff ff call a44 807 | a48: 83 c4 10 add $0x10,%esp 808 | a4b: 90 nop 809 | a4c: 8d 65 f4 lea -0xc(%ebp),%esp 810 | a4f: 5b pop %ebx 811 | a50: 5e pop %esi 812 | a51: 5f pop %edi 813 | a52: 5d pop %ebp 814 | a53: c3 ret 815 | 816 | 00000a54 : 817 | a54: 55 push %ebp 818 | a55: 89 e5 mov %esp,%ebp 819 | a57: e8 fc ff ff ff call a58 820 | a5c: 05 01 00 00 00 add $0x1,%eax 821 | a61: 90 nop 822 | a62: 5d pop %ebp 823 | a63: c3 ret 824 | 825 | Disassembly of section .text.__x86.get_pc_thunk.ax: 826 | 827 | 00000000 <__x86.get_pc_thunk.ax>: 828 | 0: 8b 04 24 mov (%esp),%eax 829 | 3: c3 ret 830 | 831 | Disassembly of section .text.__x86.get_pc_thunk.bx: 832 | 833 | 00000000 <__x86.get_pc_thunk.bx>: 834 | 0: 8b 1c 24 mov (%esp),%ebx 835 | 3: c3 ret 836 | -------------------------------------------------------------------------------- /kernel/slab.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * slab分配器 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | long BASIC_FREE_START = MAIN_MEMORY_START; 11 | 12 | #define BASIC_MEMORY_START MAIN_MEMORY_START 13 | #define BASIC_MEMORY_END (MAIN_MEMORY_START+1024*1024*2) 14 | 15 | /* 16 | * basic allocator(在伙伴系统未初始化前负责内存管理) 17 | */ 18 | void *basic_allocator(uint32_t size) 19 | { 20 | /* 从主内存中取出2M用于basic allocator管理 */ 21 | long free = BASIC_FREE_START; 22 | BASIC_FREE_START += size; 23 | if(BASIC_FREE_START >= BASIC_MEMORY_END){ 24 | return NULL; 25 | } 26 | return free; 27 | } 28 | 29 | /* 30 | * TODO 构建kmem_cache 31 | */ 32 | kmem_cache_t *kmem_cache_create(char *name, size_t size, int align, 33 | void (*constructor)(void *, size_t), 34 | void (*destructor)(void *, size_t)) 35 | { 36 | return NULL; 37 | } 38 | 39 | 40 | /* 41 | * TODO 释放kmem_cache 42 | */ 43 | void kmem_cache_destroy(kmem_cache_t *cp) 44 | { 45 | return; 46 | } 47 | 48 | /* 49 | * TODO 从一个kmem_cache中分配一个object 50 | */ 51 | void *kmem_cache_alloc(kmem_cache_t *cp, int flags) 52 | { 53 | return NULL; 54 | } 55 | 56 | /* 57 | * TODO 与kmem_cache_alloc动作相反 58 | */ 59 | void kmem_cache_free(kmem_cache_t *cp, void *buf) 60 | { 61 | return; 62 | } 63 | 64 | -------------------------------------------------------------------------------- /kernel/tty.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 实现tty 4 | */ 5 | 6 | #include "tty.h" 7 | #include "console.h" 8 | 9 | TTY tty_table[NR_CONSOLES]; 10 | CONSOLE console_table[NR_CONSOLES]; 11 | 12 | 13 | void tty_write(TTY *tty, char *buf, int len) 14 | { 15 | char *p=buf; 16 | int i=len; 17 | 18 | while(1){ 19 | //out_char(tty->p_console, *p++); 20 | /* 暂时用console_puts表示 */ 21 | console_puts(buf,0,red); 22 | i--; 23 | } 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /qemu_run_os.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | qemu-system-i386 \ 4 | -hdb hd.img \ 5 | -fda os.img \ 6 | -boot a 7 | 8 | -------------------------------------------------------------------------------- /scripts/kernel.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel.ld -- 针对 kernel 格式所写的链接脚本 3 | * 4 | * 首先,我们声明了内核程序的入口地址是符号 "start",这个脚本告诉 ld 程序 如何构造我们的内核映像文件。 5 | * 然后,我们声明了第一个段 .text 段(代码段)以及它的起始地址 0x100000(1MB)。 6 | * 接着是 已初始化数据段 .data 和 未初始化数据段 .bss 以及它们采用的4096的页对齐方式。 7 | * Linux GCC 增加了额外的数据段 .rodata,这是一个只读的已初始化数据段,放置常量什么的。 8 | * 简单起见,我们把和 .data 段放在一起好了。 9 | * 10 | * 修改<2017/08/23> 11 | * 由于kernel.bin是一个elf文件,所以这里的0x9000地址指明的是_start的加载地址 12 | * 但是在生成的kernel.bin文件里前面还有这个elf文件的属性,尽管把这个.bin文件拷贝到 13 | * 0x8000,但是可执行段是从0x9000开始 14 | * 15 | * 修改<2017/11/17> 16 | * (已更改,使用objcopy删掉了包括elf头在内的信息,可直接从0x8000执行) 17 | * 18 | * 修改<2017/11/18> 19 | * 删掉.stab节和.stabstr节(这部分特别大) 20 | * .stab : 21 | * { 22 | * *(.stab) 23 | * . = ALIGN(4); 24 | * } 25 | * .stabstr : 26 | * { 27 | * *(.stabstr) 28 | * . = ALIGN(4); 29 | * } 30 | * 31 | */ 32 | 33 | ENTRY(_start) 34 | SECTIONS 35 | { 36 | . = 0x5000; 37 | PROVIDE(kernel_s = .); 38 | .text : 39 | { 40 | *(.text) 41 | . = ALIGN(4); 42 | } 43 | .data : 44 | { 45 | *(.data) 46 | *(.rodata) 47 | . = ALIGN(4); 48 | } 49 | .bss : 50 | { 51 | *(.bss) 52 | . = ALIGN(4); 53 | } 54 | PROVIDE(kernel_e = .); 55 | 56 | } 57 | 58 | --------------------------------------------------------------------------------